From 9a88085739d8a99ffc5eb89e88c2276d4a521002 Mon Sep 17 00:00:00 2001 From: Ken Murchison Date: Fri, 8 May 2009 00:43:44 +0000 Subject: [PATCH 001/796] add missing include for USHRT_MAX --- lib/checkpw.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/checkpw.c b/lib/checkpw.c index f91e2e7a..d371f3f2 100644 --- a/lib/checkpw.c +++ b/lib/checkpw.c @@ -1,7 +1,7 @@ /* SASL server API implementation * Rob Siemborski * Tim Martin - * $Id: checkpw.c,v 1.78 2009/03/10 14:10:52 mel Exp $ + * $Id: checkpw.c,v 1.79 2009/05/08 00:43:44 murch Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -74,6 +74,7 @@ #include #endif +#include #include #include From 781eed86253541f5f3bf9577d5e359ac518110e5 Mon Sep 17 00:00:00 2001 From: Ken Murchison Date: Wed, 20 May 2009 12:24:48 +0000 Subject: [PATCH 002/796] Fixes to allow static libs to be built in the CMU build environment --- ChangeLog | 6 ++++++ config/kerberos_v4.m4 | 2 +- config/plain.m4 | 2 +- config/sasldb.m4 | 6 +++--- configure.in | 22 +++++++++++----------- lib/Makefile.am | 6 ++++-- 6 files changed, 26 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index e6761fec..4a6b8622 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2009-05-20 Ken Murchison + * configure.in, cmulocal/sasl2.m4, + config/kerberos_v4.m4, config/plain.m4, config/sasldb.m4, + lib/Makefile.am: Fixes to allow static libs to be built in the + CMU build environment + 2009-05-07 Ken Murchison * configure.in, include/sasl.h, lib/Makefile.am, plugins/Makefile.am, saslauthd/configure.in, sasldb/Makefile.am, diff --git a/config/kerberos_v4.m4 b/config/kerberos_v4.m4 index a4d84e11..78847439 100644 --- a/config/kerberos_v4.m4 +++ b/config/kerberos_v4.m4 @@ -140,7 +140,7 @@ AC_DEFUN([SASL_KERBEROS_V4_CHK], [ if test "$krb4" != no; then AC_MSG_RESULT(enabled) SASL_MECHS="$SASL_MECHS libkerberos4.la" - SASL_STATIC_SRCS="$SASL_STATIC_SRCS ../plugins/kerberos4.c" + SASL_STATIC_SRCS="$SASL_STATIC_SRCS \$(top_srcdir)/plugins/kerberos4.c" SASL_STATIC_OBJS="$SASL_STATIC_OBJS kerberos4.o" AC_DEFINE(STATIC_KERBEROS4,[],[User KERBEROS_V4 Staticly]) AC_DEFINE(HAVE_KRB,[],[Do we have Kerberos 4 Support?]) diff --git a/config/plain.m4 b/config/plain.m4 index fd1fdd34..ee9e0c48 100644 --- a/config/plain.m4 +++ b/config/plain.m4 @@ -23,7 +23,7 @@ dnl PLAIN SASL_MECHS="$SASL_MECHS libplain.la" if test "$enable_static" = yes; then SASL_STATIC_OBJS="$SASL_STATIC_OBJS plain.o" - SASL_STATIC_SRCS="$SASL_STATIC_SRCS ../plugins/plain.c" + SASL_STATIC_SRCS="$SASL_STATIC_SRCS \$(top_srcdir)/plugins/plain.c" AC_DEFINE(STATIC_PLAIN,[],[Link PLAIN Staticly]) fi else diff --git a/config/sasldb.m4 b/config/sasldb.m4 index 2a812f5c..b28b087f 100644 --- a/config/sasldb.m4 +++ b/config/sasldb.m4 @@ -97,7 +97,7 @@ AC_MSG_RESULT($dblib) SASL_DB_BACKEND="db_${dblib}.lo" SASL_DB_BACKEND_STATIC="db_${dblib}.o allockey.o" -SASL_DB_BACKEND_STATIC_SRCS="../sasldb/db_${dblib}.c ../sasldb/allockey.c" +SASL_DB_BACKEND_STATIC_SRCS="\$(top_srcdir)/sasldb/db_${dblib}.c \$(top_srcdir)/sasldb/allockey.c" SASL_DB_UTILS="saslpasswd2 sasldblistusers2" SASL_DB_MANS="saslpasswd2.8 sasldblistusers2.8" @@ -120,7 +120,7 @@ case "$dblib" in dnl will just fail to load anyway. SASL_DB_BACKEND="db_none.lo" SASL_DB_BACKEND_STATIC="db_none.o" - SASL_DB_BACKEND_STATIC_SRCS="../sasldb/db_none.c" + SASL_DB_BACKEND_STATIC_SRCS="\$(top_srcdir)/sasldb/db_none.c" SASL_DB_UTILS="" SASL_DB_MANS="" SASL_DB_LIB="" @@ -129,7 +129,7 @@ esac if test "$enable_static" = yes; then if test "$dblib" != "none"; then - SASL_STATIC_SRCS="$SASL_STATIC_SRCS ../plugins/sasldb.c $SASL_DB_BACKEND_STATIC_SRCS" + SASL_STATIC_SRCS="$SASL_STATIC_SRCS \$(top_srcdir)/plugins/sasldb.c $SASL_DB_BACKEND_STATIC_SRCS" SASL_STATIC_OBJS="$SASL_STATIC_OBJS sasldb.o $SASL_DB_BACKEND_STATIC" AC_DEFINE(STATIC_SASLDB,[],[Link SASLdb Staticly]) else diff --git a/configure.in b/configure.in index 6d82c85b..47138d96 100644 --- a/configure.in +++ b/configure.in @@ -1,7 +1,7 @@ dnl configure.in for the SASL library dnl Rob Siemborski dnl Rob Earhart -dnl $Id: configure.in,v 1.217 2009/05/07 13:49:31 murch Exp $ +dnl $Id: configure.in,v 1.218 2009/05/20 12:24:48 murch Exp $ dnl dnl Copyright (c) 2001 Carnegie Mellon University. All rights reserved. dnl @@ -384,7 +384,7 @@ if test "$cram" != no; then SASL_MECHS="$SASL_MECHS libcrammd5.la" if test "$enable_static" = yes; then SASL_STATIC_OBJS="$SASL_STATIC_OBJS cram.o" - SASL_STATIC_SRCS="$SASL_STATIC_SRCS ../plugins/cram.c" + SASL_STATIC_SRCS="$SASL_STATIC_SRCS \$(top_srcdir)/plugins/cram.c" AC_DEFINE(STATIC_CRAMMD5, [], [Link CRAM-MD5 Staticly]) fi else @@ -418,7 +418,7 @@ if test "$digest" != no; then AC_MSG_RESULT(enabled) SASL_MECHS="$SASL_MECHS libdigestmd5.la" if test "$enable_static" = yes; then - SASL_STATIC_SRCS="$SASL_STATIC_SRCS ../plugins/digestmd5.c" + SASL_STATIC_SRCS="$SASL_STATIC_SRCS \$(top_srcdir)/plugins/digestmd5.c" SASL_STATIC_OBJS="$SASL_STATIC_OBJS digestmd5.o" AC_DEFINE(STATIC_DIGESTMD5, [], [Link DIGEST-MD5 Staticly]) fi @@ -443,7 +443,7 @@ if test "$otp" != no; then SASL_MECHS="$SASL_MECHS libotp.la" if test "$enable_static" = yes; then - SASL_STATIC_SRCS="$SASL_STATIC_SRCS ../plugins/otp.c" + SASL_STATIC_SRCS="$SASL_STATIC_SRCS \$(top_srcdir)/plugins/otp.c" SASL_STATIC_OBJS="$SASL_STATIC_OBJS otp.o" AC_DEFINE(STATIC_OTP, [], [Link OTP Staticly]) fi @@ -500,7 +500,7 @@ if test "$srp" != no; then SASL_MECHS="$SASL_MECHS libsrp.la" if test "$enable_static" = yes; then - SASL_STATIC_SRCS="$SASL_STATIC_SRCS ../plugins/srp.c" + SASL_STATIC_SRCS="$SASL_STATIC_SRCS \$(top_srcdir)/plugins/srp.c" SASL_STATIC_OBJS="$SASL_STATIC_OBJS srp.o" AC_DEFINE(STATIC_SRP, [], [Link SRP Staticly]) fi @@ -557,7 +557,7 @@ if test "$anon" != no; then SASL_MECHS="$SASL_MECHS libanonymous.la" if test "$enable_static" = yes; then SASL_STATIC_OBJS="$SASL_STATIC_OBJS anonymous.o" - SASL_STATIC_SRCS="$SASL_STATIC_SRCS ../plugins/anonymous.c" + SASL_STATIC_SRCS="$SASL_STATIC_SRCS \$(top_srcdir)/plugins/anonymous.c" AC_DEFINE(STATIC_ANONYMOUS, [], [Link ANONYMOUS Staticly]) fi else @@ -574,7 +574,7 @@ if test "$login" != no; then AC_MSG_RESULT(enabled) SASL_MECHS="$SASL_MECHS liblogin.la" if test "$enable_static" = yes; then - SASL_STATIC_SRCS="$SASL_STATIC_SRCS ../plugins/login.c" + SASL_STATIC_SRCS="$SASL_STATIC_SRCS \$(top_srcdir)/plugins/login.c" SASL_STATIC_OBJS="$SASL_STATIC_OBJS login.o" AC_DEFINE(STATIC_LOGIN,[],[Link LOGIN Staticly]) fi @@ -600,7 +600,7 @@ if test "$ntlm" != no; then SASL_MECHS="$SASL_MECHS libntlm.la" if test "$enable_static" = yes; then - SASL_STATIC_SRCS="$SASL_STATIC_SRCS ../plugins/ntlm.c" + SASL_STATIC_SRCS="$SASL_STATIC_SRCS \$(top_srcdir)/plugins/ntlm.c" SASL_STATIC_OBJS="$SASL_STATIC_OBJS ntlm.o" AC_DEFINE(STATIC_NTLM,[],[Link NTLM Staticly]) fi @@ -627,7 +627,7 @@ if test "$passdss" != no; then SASL_MECHS="$SASL_MECHS libpassdss.la" if test "$enable_static" = yes; then SASL_STATIC_OBJS="$SASL_STATIC_OBJS passdss.o" - SASL_STATIC_SRCS="$SASL_STATIC_SRCS ../plugins/passdss.c" + SASL_STATIC_SRCS="$SASL_STATIC_SRCS \$(top_srcdir)/plugins/passdss.c" AC_DEFINE(STATIC_PASSDSS,[],[Link PASSDSS Staticly]) fi else @@ -657,7 +657,7 @@ if test "$sql" != no; then AC_MSG_RESULT(enabled) SASL_MECHS="$SASL_MECHS libsql.la" if test "$enable_static" = yes; then - SASL_STATIC_SRCS="$SASL_STATIC_SRCS ../plugins/sql.c" + SASL_STATIC_SRCS="$SASL_STATIC_SRCS \$(top_srcdir)/plugins/sql.c" SASL_STATIC_OBJS="$SASL_STATIC_OBJS sql.o" AC_DEFINE(STATIC_SQL,[],[Link SQL plugin staticly]) fi @@ -949,7 +949,7 @@ if test "$ldapdb" != no; then SASL_MECHS="$SASL_MECHS libldapdb.la" if test "$enable_static" = yes; then - SASL_STATIC_SRCS="$SASL_STATIC_SRCS ../plugins/ldapdb.c" + SASL_STATIC_SRCS="$SASL_STATIC_SRCS \$(top_srcdir)/plugins/ldapdb.c" SASL_STATIC_OBJS="$SASL_STATIC_OBJS ldapdb.o" AC_DEFINE(STATIC_LDAPDB,[],[Link ldapdb plugin Staticly]) fi diff --git a/lib/Makefile.am b/lib/Makefile.am index ae2608c8..b73e45cd 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1,6 +1,6 @@ # Makefile.am for the SASL library # Rob Earhart -# $Id: Makefile.am,v 1.86 2009/05/07 13:49:31 murch Exp $ +# $Id: Makefile.am,v 1.87 2009/05/20 12:24:49 murch Exp $ # Copyright (c) 2000 Carnegie Mellon University. All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -50,6 +50,8 @@ EXTRA_LIBRARIES = libsasl2.a noinst_LIBRARIES = @SASL_STATIC_LIBS@ libsasl2_a_SOURCES= +BUILT_SOURCES = $(SASL_STATIC_SRCS) + common_headers = saslint.h common_sources = auxprop.c canonusr.c checkpw.c client.c common.c config.c external.c md5.c saslutil.c server.c seterror.c dlopen.c ../plugins/plugin_common.c @@ -93,7 +95,7 @@ libsasl2.a: libsasl2.la $(SASL_STATIC_OBJS) rm -f $@ ln -s .libs/$@ $@ -$(SASL_STATIC_OBJS): linksrcs +$(SASL_STATIC_SRCS): linksrcs linksrcs: -ln -s $(SASL_STATIC_SRCS) . From d5b65450c5a04c7198a850d28fbf2654bf3c6db5 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Wed, 10 Jun 2009 15:58:38 +0000 Subject: [PATCH 003/796] Reformatted a part of server code. --- plugins/plain.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/plugins/plain.c b/plugins/plain.c index 227ce5fc..8fadd524 100644 --- a/plugins/plain.c +++ b/plugins/plain.c @@ -1,7 +1,7 @@ /* Plain SASL plugin * Rob Siemborski * Tim Martin - * $Id: plain.c,v 1.65 2008/10/19 21:44:48 mel Exp $ + * $Id: plain.c,v 1.66 2009/06/10 15:58:38 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -57,7 +57,7 @@ /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: plain.c,v 1.65 2008/10/19 21:44:48 mel Exp $"; +static const char plugin_id[] = "$Id: plain.c,v 1.66 2009/06/10 15:58:38 mel Exp $"; /***************************** Server Section *****************************/ @@ -146,11 +146,15 @@ static int plain_server_mech_step(void *conn_context __attribute__((unused)), /* Canonicalize userid first, so that password verification is only * against the canonical id */ - if (!author || !*author) + if (!author || !*author) { author = authen; - + } + result = params->canon_user(params->utils->conn, - authen, 0, SASL_CU_AUTHID, oparams); + authen, + 0, + SASL_CU_AUTHID, + oparams); if (result != SASL_OK) { _plug_free_string(params->utils, &passcopy); return result; @@ -158,8 +162,10 @@ static int plain_server_mech_step(void *conn_context __attribute__((unused)), /* verify password - return sasl_ok on success*/ result = params->utils->checkpass(params->utils->conn, - oparams->authid, oparams->alen, - passcopy, password_len); + oparams->authid, + oparams->alen, + passcopy, + password_len); _plug_free_string(params->utils, &passcopy); @@ -173,7 +179,10 @@ static int plain_server_mech_step(void *conn_context __attribute__((unused)), /* We need to do this after calling verify_user just in case verify_user * needed to get auxprops itself */ result = params->canon_user(params->utils->conn, - author, 0, SASL_CU_AUTHZID, oparams); + author, + 0, + SASL_CU_AUTHZID, + oparams); if (result != SASL_OK) return result; /* set oparams */ From 3327bd131dca6232e5b6dcdf8ed0b892cc7c86ea Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Wed, 10 Jun 2009 16:05:19 +0000 Subject: [PATCH 004/796] Fixed proxy auth by making sure that proper values are fetched for the authorization identity. --- plugins/plain.c | 58 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 13 deletions(-) diff --git a/plugins/plain.c b/plugins/plain.c index 8fadd524..ddbc1f89 100644 --- a/plugins/plain.c +++ b/plugins/plain.c @@ -1,7 +1,7 @@ /* Plain SASL plugin * Rob Siemborski * Tim Martin - * $Id: plain.c,v 1.66 2009/06/10 15:58:38 mel Exp $ + * $Id: plain.c,v 1.67 2009/06/10 16:05:19 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -57,7 +57,7 @@ /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: plain.c,v 1.66 2009/06/10 15:58:38 mel Exp $"; +static const char plugin_id[] = "$Id: plain.c,v 1.67 2009/06/10 16:05:19 mel Exp $"; /***************************** Server Section *****************************/ @@ -90,10 +90,11 @@ static int plain_server_mech_step(void *conn_context __attribute__((unused)), const char *authen; const char *password; unsigned password_len; - unsigned lup=0; + unsigned lup = 0; int result; char *passcopy; - + unsigned canon_flags = 0; + *serverout = NULL; *serveroutlen = 0; @@ -148,19 +149,26 @@ static int plain_server_mech_step(void *conn_context __attribute__((unused)), * against the canonical id */ if (!author || !*author) { author = authen; + canon_flags = SASL_CU_AUTHZID; + } else if (strcmp(author, authen) == 0) { + /* While this isn't going to find out that and @ + are the same thing, this is good enough for many cases */ + canon_flags = SASL_CU_AUTHZID; } result = params->canon_user(params->utils->conn, authen, 0, - SASL_CU_AUTHID, + SASL_CU_AUTHID | canon_flags, oparams); if (result != SASL_OK) { _plug_free_string(params->utils, &passcopy); return result; } - - /* verify password - return sasl_ok on success*/ + + /* verify password (and possibly fetch both authentication and + authorization identity related properties) - return SASL_OK + on success */ result = params->utils->checkpass(params->utils->conn, oparams->authid, oparams->alen, @@ -178,13 +186,37 @@ static int plain_server_mech_step(void *conn_context __attribute__((unused)), /* Canonicalize and store the authorization ID */ /* We need to do this after calling verify_user just in case verify_user * needed to get auxprops itself */ - result = params->canon_user(params->utils->conn, - author, - 0, - SASL_CU_AUTHZID, - oparams); - if (result != SASL_OK) return result; + if (canon_flags == 0) { + const struct propval *pr; + int i; + + pr = params->utils->prop_get(params->propctx); + if (!pr) { + return SASL_FAIL; + } + + /* params->utils->checkpass() might have fetched authorization identity related properties + for the wrong user name. Free these values. */ + for (i = 0; pr[i].name; i++) { + if (pr[i].name[0] == '*') { + continue; + } + if (pr[i].values) { + params->utils->prop_erase(params->propctx, pr[i].name); + } + } + + result = params->canon_user(params->utils->conn, + author, + 0, + SASL_CU_AUTHZID, + oparams); + if (result != SASL_OK) { + return result; + } + } + /* set oparams */ oparams->doneflag = 1; oparams->mech_ssf = 0; From 75dcddb609b810419b7ca43ec9c6ff4047a9f27d Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Tue, 14 Jul 2009 15:21:46 +0000 Subject: [PATCH 005/796] Code reformatting --- plugins/gssapi.c | 82 ++++++++++++++++++++++++++---------------------- 1 file changed, 45 insertions(+), 37 deletions(-) diff --git a/plugins/gssapi.c b/plugins/gssapi.c index a9472460..333eaeed 100644 --- a/plugins/gssapi.c +++ b/plugins/gssapi.c @@ -1,7 +1,7 @@ /* GSSAPI SASL plugin * Leif Johansson * Rob Siemborski (SASL v2 Conversion) - * $Id: gssapi.c,v 1.97 2009/03/10 16:27:52 mel Exp $ + * $Id: gssapi.c,v 1.98 2009/07/14 15:21:46 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -82,7 +82,7 @@ /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: gssapi.c,v 1.97 2009/03/10 16:27:52 mel Exp $"; +static const char plugin_id[] = "$Id: gssapi.c,v 1.98 2009/07/14 15:21:46 mel Exp $"; static const char * GSSAPI_BLANK_STRING = ""; @@ -320,9 +320,9 @@ sasl_gss_encode(void *context, const struct iovec *invec, unsigned numiov, if(!output) return SASL_BADPARAM; - if(numiov > 1) { + if (numiov > 1) { ret = _plug_iovec_to_buf(text->utils, invec, numiov, &text->enc_in_buf); - if(ret != SASL_OK) return ret; + if (ret != SASL_OK) return ret; inblob = text->enc_in_buf; } else { bufinfo.data = invec[0].iov_base; @@ -351,16 +351,15 @@ sasl_gss_encode(void *context, const struct iovec *invec, unsigned numiov, output_token); GSS_UNLOCK_MUTEX(text->utils); - if (GSS_ERROR(maj_stat)) - { - sasl_gss_seterror(text->utils, maj_stat, min_stat); - if (output_token->value) { - GSS_LOCK_MUTEX(text->utils); - gss_release_buffer(&min_stat, output_token); - GSS_UNLOCK_MUTEX(text->utils); - } - return SASL_FAIL; + if (GSS_ERROR(maj_stat)) { + sasl_gss_seterror(text->utils, maj_stat, min_stat); + if (output_token->value) { + GSS_LOCK_MUTEX(text->utils); + gss_release_buffer(&min_stat, output_token); + GSS_UNLOCK_MUTEX(text->utils); } + return SASL_FAIL; + } if (output_token->value && output) { int len; @@ -390,7 +389,8 @@ sasl_gss_encode(void *context, const struct iovec *invec, unsigned numiov, GSS_LOCK_MUTEX(text->utils); gss_release_buffer(&min_stat, output_token); GSS_UNLOCK_MUTEX(text->utils); - } + } + return SASL_OK; } @@ -408,9 +408,12 @@ static int gssapi_integrity_encode(void *context, const struct iovec *invec, return sasl_gss_encode(context,invec,numiov,output,outputlen,0); } -static int gssapi_decode_packet(void *context, - const char *input, unsigned inputlen, - char **output, unsigned *outputlen) +static int +gssapi_decode_packet(void *context, + const char *input, + unsigned inputlen, + char **output, + unsigned *outputlen) { context_t *text = (context_t *) context; OM_uint32 maj_stat, min_stat; @@ -440,26 +443,26 @@ static int gssapi_decode_packet(void *context, NULL); GSS_UNLOCK_MUTEX(text->utils); - if (GSS_ERROR(maj_stat)) - { - sasl_gss_seterror(text->utils,maj_stat,min_stat); - if (output_token->value) { - GSS_LOCK_MUTEX(text->utils); - gss_release_buffer(&min_stat, output_token); - GSS_UNLOCK_MUTEX(text->utils); - } - return SASL_FAIL; + if (GSS_ERROR(maj_stat)) { + sasl_gss_seterror(text->utils,maj_stat,min_stat); + if (output_token->value) { + GSS_LOCK_MUTEX(text->utils); + gss_release_buffer(&min_stat, output_token); + GSS_UNLOCK_MUTEX(text->utils); } + return SASL_FAIL; + } - if (outputlen) + if (outputlen) { *outputlen = output_token->length; + } if (output_token->value) { if (output) { result = _plug_buf_alloc(text->utils, &text->decode_once_buf, &text->decode_once_buf_len, *outputlen); - if(result != SASL_OK) { + if (result != SASL_OK) { GSS_LOCK_MUTEX(text->utils); gss_release_buffer(&min_stat, output_token); GSS_UNLOCK_MUTEX(text->utils); @@ -1145,7 +1148,8 @@ gssapi_server_mech_step(void *conn_context, text->state = SASL_GSSAPI_STATE_AUTHENTICATED; /* used by layers */ - _plug_decode_init(&text->decode_context, text->utils, + _plug_decode_init(&text->decode_context, + text->utils, (params->props.maxbufsize > 0xFFFFFF) ? 0xFFFFFF : params->props.maxbufsize); @@ -1576,7 +1580,7 @@ static int gssapi_client_mech_step(void *conn_context, /* good to go */ need = 0; } - + /* bit mask of server support */ serverhas = ((char *)output_token->value)[0]; @@ -1611,7 +1615,7 @@ static int gssapi_client_mech_step(void *conn_context, (((unsigned char *) output_token->value)[2] << 8) | (((unsigned char *) output_token->value)[3] << 0); - if(oparams->mech_ssf) { + if (oparams->mech_ssf) { maj_stat = gss_wrap_size_limit( &min_stat, text->gss_ctx, 1, @@ -1619,7 +1623,7 @@ static int gssapi_client_mech_step(void *conn_context, (OM_uint32) oparams->maxoutbuf, &max_input); - if(max_input > oparams->maxoutbuf) { + if (max_input > oparams->maxoutbuf) { /* Heimdal appears to get this wrong */ oparams->maxoutbuf -= (max_input - oparams->maxoutbuf); } else { @@ -1636,10 +1640,11 @@ static int gssapi_client_mech_step(void *conn_context, * Make sure the client actually requested it though, by checking * if our context was set. */ - if (text->user && text->user[0]) + if (text->user && text->user[0]) { alen = strlen(oparams->user); - else + } else { alen = 0; + } input_token->length = 4 + alen; input_token->value = @@ -1693,12 +1698,15 @@ static int gssapi_client_mech_step(void *conn_context, return SASL_FAIL; } - if (clientoutlen) + if (clientoutlen) { *clientoutlen = output_token->length; + } if (output_token->value) { if (clientout) { - ret = _plug_buf_alloc(text->utils, &(text->out_buf), - &(text->out_buf_len), *clientoutlen); + ret = _plug_buf_alloc(text->utils, + &(text->out_buf), + &(text->out_buf_len), + *clientoutlen); if (ret != SASL_OK) { GSS_LOCK_MUTEX(params->utils); gss_release_buffer(&min_stat, output_token); From 2332ed0360d448f1479610941d8a7099c9897605 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Thu, 16 Jul 2009 13:43:50 +0000 Subject: [PATCH 006/796] Formatting change --- lib/client.c | 68 ++++++++++++++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/lib/client.c b/lib/client.c index 44a973ff..c7ea8a76 100644 --- a/lib/client.c +++ b/lib/client.c @@ -1,7 +1,7 @@ /* SASL client API implementation * Rob Siemborski * Tim Martin - * $Id: client.c,v 1.74 2009/04/08 19:36:20 mel Exp $ + * $Id: client.c,v 1.75 2009/07/16 13:43:50 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -142,50 +142,50 @@ static int client_done(void) { int sasl_client_add_plugin(const char *plugname, sasl_client_plug_init_t *entry_point) { - int plugcount; - sasl_client_plug_t *pluglist; - cmechanism_t *mech; - int result; - int version; - int lupe; + int plugcount; + sasl_client_plug_t *pluglist; + cmechanism_t *mech; + int result; + int version; + int lupe; - if(!plugname || !entry_point) return SASL_BADPARAM; - - result = entry_point(cmechlist->utils, SASL_CLIENT_PLUG_VERSION, &version, - &pluglist, &plugcount); + if (!plugname || !entry_point) return SASL_BADPARAM; - if (result != SASL_OK) - { - _sasl_log(NULL, SASL_LOG_WARN, + result = entry_point(cmechlist->utils, SASL_CLIENT_PLUG_VERSION, &version, + &pluglist, &plugcount); + + if (result != SASL_OK) + { + _sasl_log(NULL, SASL_LOG_WARN, "entry_point failed in sasl_client_add_plugin for %s", plugname); - return result; - } + return result; + } - if (version != SASL_CLIENT_PLUG_VERSION) - { - _sasl_log(NULL, SASL_LOG_WARN, + if (version != SASL_CLIENT_PLUG_VERSION) + { + _sasl_log(NULL, SASL_LOG_WARN, "version conflict in sasl_client_add_plugin for %s", plugname); - return SASL_BADVERS; - } + return SASL_BADVERS; + } - for (lupe=0;lupe< plugcount ;lupe++) + for (lupe=0; lupe< plugcount ;lupe++) { - mech = sasl_ALLOC(sizeof(cmechanism_t)); - if (! mech) return SASL_NOMEM; + mech = sasl_ALLOC(sizeof(cmechanism_t)); + if (!mech) return SASL_NOMEM; - mech->m.plug=pluglist++; - if(_sasl_strdup(plugname, &mech->m.plugname, NULL) != SASL_OK) { - sasl_FREE(mech); - return SASL_NOMEM; - } - mech->m.version = version; - mech->next = cmechlist->mech_list; - cmechlist->mech_list = mech; - cmechlist->mech_length++; + mech->m.plug = pluglist++; + if (_sasl_strdup(plugname, &mech->m.plugname, NULL) != SASL_OK) { + sasl_FREE(mech); + return SASL_NOMEM; + } + mech->m.version = version; + mech->next = cmechlist->mech_list; + cmechlist->mech_list = mech; + cmechlist->mech_length++; } - return SASL_OK; + return SASL_OK; } static int From f16192a2ef647dd2282104bc146efd8d08095532 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Fri, 24 Jul 2009 11:30:20 +0000 Subject: [PATCH 007/796] Don't send maxbuf, if no security layer can be established. Added additional checks for buffer lengths. --- plugins/gssapi.c | 97 ++++++++++++++++++++++++++++++------------------ 1 file changed, 61 insertions(+), 36 deletions(-) diff --git a/plugins/gssapi.c b/plugins/gssapi.c index 333eaeed..c96ea62a 100644 --- a/plugins/gssapi.c +++ b/plugins/gssapi.c @@ -1,7 +1,7 @@ /* GSSAPI SASL plugin * Leif Johansson * Rob Siemborski (SASL v2 Conversion) - * $Id: gssapi.c,v 1.98 2009/07/14 15:21:46 mel Exp $ + * $Id: gssapi.c,v 1.99 2009/07/24 11:30:20 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -82,7 +82,7 @@ /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: gssapi.c,v 1.98 2009/07/14 15:21:46 mel Exp $"; +static const char plugin_id[] = "$Id: gssapi.c,v 1.99 2009/07/24 11:30:20 mel Exp $"; static const char * GSSAPI_BLANK_STRING = ""; @@ -933,15 +933,22 @@ gssapi_server_mech_step(void *conn_context, } /* build up our security properties token */ - if (params->props.maxbufsize > 0xFFFFFF) { - /* make sure maxbufsize isn't too large */ - /* maxbufsize = 0xFFFFFF */ - sasldata[1] = sasldata[2] = sasldata[3] = 0xFF; - } else { - sasldata[1] = (params->props.maxbufsize >> 16) & 0xFF; - sasldata[2] = (params->props.maxbufsize >> 8) & 0xFF; - sasldata[3] = (params->props.maxbufsize >> 0) & 0xFF; - } + if (text->requiressf != 0) { + if (params->props.maxbufsize > 0xFFFFFF) { + /* make sure maxbufsize isn't too large */ + /* maxbufsize = 0xFFFFFF */ + sasldata[1] = sasldata[2] = sasldata[3] = 0xFF; + } else { + sasldata[1] = (params->props.maxbufsize >> 16) & 0xFF; + sasldata[2] = (params->props.maxbufsize >> 8) & 0xFF; + sasldata[3] = (params->props.maxbufsize >> 0) & 0xFF; + } + } else { + /* From RFC 4752: "The client verifies that the server maximum buffer is 0 + if the server does not advertise support for any security layer." */ + sasldata[1] = sasldata[2] = sasldata[3] = 0; + } + sasldata[0] = 0; if(text->requiressf != 0 && !params->props.maxbufsize) { params->utils->seterror(params->utils->conn, 0, @@ -1033,6 +1040,16 @@ gssapi_server_mech_step(void *conn_context, sasl_gss_free_context_contents(text); return SASL_FAIL; } + + if (output_token->length < 4) { + SETERROR(text->utils, + "token too short"); + GSS_LOCK_MUTEX(params->utils); + gss_release_buffer(&min_stat, output_token); + GSS_UNLOCK_MUTEX(params->utils); + sasl_gss_free_context_contents(text); + return SASL_FAIL; + } layerchoice = (int)(((char *)(output_token->value))[0]); if (layerchoice == 1 && text->requiressf == 0) { /* no encryption */ @@ -1086,7 +1103,7 @@ gssapi_server_mech_step(void *conn_context, sasl_gss_free_context_contents(text); return ret; } - } else if(output_token->length == 4) { + } else /* if (output_token->length == 4) */ { /* null authzid */ int ret; @@ -1099,16 +1116,8 @@ gssapi_server_mech_step(void *conn_context, if (ret != SASL_OK) { sasl_gss_free_context_contents(text); return ret; - } - } else { - SETERROR(text->utils, - "token too short"); - GSS_LOCK_MUTEX(params->utils); - gss_release_buffer(&min_stat, output_token); - GSS_UNLOCK_MUTEX(params->utils); - sasl_gss_free_context_contents(text); - return SASL_FAIL; - } + } + } /* No matter what, set the rest of the oparams */ @@ -1561,6 +1570,16 @@ static int gssapi_client_mech_step(void *conn_context, return SASL_FAIL; } + if (output_token->length != 4) { + SETERROR(text->utils, + (output_token->length < 4) ? "token too short" : "token too long"); + GSS_LOCK_MUTEX(params->utils); + gss_release_buffer(&min_stat, output_token); + GSS_UNLOCK_MUTEX(params->utils); + sasl_gss_free_context_contents(text); + return SASL_FAIL; + } + /* taken from kerberos.c */ if (secprops->min_ssf > (K5_MAX_SSF + external)) { return SASL_TOOWEAK; @@ -1658,20 +1677,26 @@ static int gssapi_client_mech_step(void *conn_context, memcpy((char *)input_token->value+4,oparams->user,alen); /* build up our security properties token */ - if (params->props.maxbufsize > 0xFFFFFF) { - /* make sure maxbufsize isn't too large */ - /* maxbufsize = 0xFFFFFF */ - ((unsigned char *)input_token->value)[1] = 0xFF; - ((unsigned char *)input_token->value)[2] = 0xFF; - ((unsigned char *)input_token->value)[3] = 0xFF; - } else { - ((unsigned char *)input_token->value)[1] = - (params->props.maxbufsize >> 16) & 0xFF; - ((unsigned char *)input_token->value)[2] = - (params->props.maxbufsize >> 8) & 0xFF; - ((unsigned char *)input_token->value)[3] = - (params->props.maxbufsize >> 0) & 0xFF; - } + if (mychoice > 1) { + if (params->props.maxbufsize > 0xFFFFFF) { + /* make sure maxbufsize isn't too large */ + /* maxbufsize = 0xFFFFFF */ + ((unsigned char *)input_token->value)[1] = 0xFF; + ((unsigned char *)input_token->value)[2] = 0xFF; + ((unsigned char *)input_token->value)[3] = 0xFF; + } else { + ((unsigned char *)input_token->value)[1] = + (params->props.maxbufsize >> 16) & 0xFF; + ((unsigned char *)input_token->value)[2] = + (params->props.maxbufsize >> 8) & 0xFF; + ((unsigned char *)input_token->value)[3] = + (params->props.maxbufsize >> 0) & 0xFF; + } + } else { + ((unsigned char *)input_token->value)[1] = 0; + ((unsigned char *)input_token->value)[2] = 0; + ((unsigned char *)input_token->value)[3] = 0; + } ((unsigned char *)input_token->value)[0] = mychoice; GSS_LOCK_MUTEX(params->utils); From da52ae52660f04114f670a0efb11e20f3ec77ce7 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Tue, 4 Aug 2009 17:13:51 +0000 Subject: [PATCH 008/796] Reformatting change --- lib/client.c | 74 +++++++++++++++++++++++++++------------------------- 1 file changed, 39 insertions(+), 35 deletions(-) diff --git a/lib/client.c b/lib/client.c index c7ea8a76..08903663 100644 --- a/lib/client.c +++ b/lib/client.c @@ -1,7 +1,7 @@ /* SASL client API implementation * Rob Siemborski * Tim Martin - * $Id: client.c,v 1.75 2009/07/16 13:43:50 mel Exp $ + * $Id: client.c,v 1.76 2009/08/04 17:13:51 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -104,39 +104,40 @@ int sasl_client_done(void) } static int client_done(void) { - cmechanism_t *cm; - cmechanism_t *cprevm; + cmechanism_t *cm; + cmechanism_t *cprevm; - if(!_sasl_client_active) - return SASL_NOTINIT; - else - _sasl_client_active--; - - if(_sasl_client_active) { - /* Don't de-init yet! Our refcount is nonzero. */ - return SASL_CONTINUE; - } - - cm=cmechlist->mech_list; /* m point to beggining of the list */ - while (cm!=NULL) - { - cprevm=cm; - cm=cm->next; - - if (cprevm->m.plug->mech_free) { - cprevm->m.plug->mech_free(cprevm->m.plug->glob_context, - cmechlist->utils); + if (!_sasl_client_active) { + return SASL_NOTINIT; + } else { + _sasl_client_active--; } - sasl_FREE(cprevm->m.plugname); - sasl_FREE(cprevm); - } - _sasl_free_utils(&cmechlist->utils); - sasl_FREE(cmechlist); + if(_sasl_client_active) { + /* Don't de-init yet! Our refcount is nonzero. */ + return SASL_CONTINUE; + } - cmechlist = NULL; + cm = cmechlist->mech_list; /* m point to beggining of the list */ + while (cm!=NULL) + { + cprevm = cm; + cm = cm->next; - return SASL_OK; + if (cprevm->m.plug->mech_free) { + cprevm->m.plug->mech_free(cprevm->m.plug->glob_context, + cmechlist->utils); + } + + sasl_FREE(cprevm->m.plugname); + sasl_FREE(cprevm); + } + _sasl_free_utils(&cmechlist->utils); + sasl_FREE(cmechlist); + + cmechlist = NULL; + + return SASL_OK; } int sasl_client_add_plugin(const char *plugname, @@ -151,8 +152,11 @@ int sasl_client_add_plugin(const char *plugname, if (!plugname || !entry_point) return SASL_BADPARAM; - result = entry_point(cmechlist->utils, SASL_CLIENT_PLUG_VERSION, &version, - &pluglist, &plugcount); + result = entry_point(cmechlist->utils, + SASL_CLIENT_PLUG_VERSION, + &version, + &pluglist, + &plugcount); if (result != SASL_OK) { @@ -739,16 +743,16 @@ int _sasl_client_listmech(sasl_conn_t *conn, unsigned *plen, int *pcount) { - cmechanism_t *m=NULL; + cmechanism_t *m = NULL; sasl_ssf_t minssf = 0; int ret; size_t resultlen; int flag; const char *mysep; - if(_sasl_client_active == 0) return SASL_NOTINIT; + if (_sasl_client_active == 0) return SASL_NOTINIT; if (!conn) return SASL_BADPARAM; - if(conn->type != SASL_CONN_CLIENT) PARAMERROR(conn); + if (conn->type != SASL_CONN_CLIENT) PARAMERROR(conn); if (! result) PARAMERROR(conn); @@ -764,7 +768,7 @@ int _sasl_client_listmech(sasl_conn_t *conn, mysep = " "; } - if(conn->props.min_ssf < conn->external.ssf) { + if (conn->props.min_ssf < conn->external.ssf) { minssf = 0; } else { minssf = conn->props.min_ssf - conn->external.ssf; From 2dc96f278fd10776cd04004f80fd1f716120a589 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Tue, 4 Aug 2009 17:17:26 +0000 Subject: [PATCH 009/796] Properly set serveroutlen in one place. Don't send empty challenge once server context establishment is done, as this is in violation of the RFC --- plugins/gssapi.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/plugins/gssapi.c b/plugins/gssapi.c index c96ea62a..25ab2de0 100644 --- a/plugins/gssapi.c +++ b/plugins/gssapi.c @@ -1,7 +1,7 @@ /* GSSAPI SASL plugin * Leif Johansson * Rob Siemborski (SASL v2 Conversion) - * $Id: gssapi.c,v 1.99 2009/07/24 11:30:20 mel Exp $ + * $Id: gssapi.c,v 1.100 2009/08/04 17:17:26 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -82,7 +82,7 @@ /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: gssapi.c,v 1.99 2009/07/24 11:30:20 mel Exp $"; +static const char plugin_id[] = "$Id: gssapi.c,v 1.100 2009/08/04 17:17:26 mel Exp $"; static const char * GSSAPI_BLANK_STRING = ""; @@ -777,15 +777,24 @@ gssapi_server_mech_step(void *conn_context, } else { /* No output token, send an empty string */ *serverout = GSSAPI_BLANK_STRING; - serveroutlen = 0; + *serveroutlen = 0; } - + if (maj_stat == GSS_S_COMPLETE) { /* Switch to ssf negotiation */ text->state = SASL_GSSAPI_STATE_SSFCAP; + + if (*serveroutlen != 0) { + return SASL_CONTINUE; + } + + /* Pretend that we just got an empty response from the client */ + clientinlen = 0; + + /* fall through */ + } else { + return SASL_CONTINUE; } - - return SASL_CONTINUE; case SASL_GSSAPI_STATE_SSFCAP: { unsigned char sasldata[4]; @@ -797,7 +806,11 @@ gssapi_server_mech_step(void *conn_context, name_token.value = NULL; name_without_realm.value = NULL; - /* We ignore whatever the client sent us at this stage */ + if (clientinlen != 0) { + SETERROR(text->utils, "GSSAPI server is not expecting data at this stage"); + sasl_gss_free_context_contents(text); + return SASL_BADAUTH; + } GSS_LOCK_MUTEX(params->utils); maj_stat = gss_display_name (&min_stat, From 551bc57b1dd691b6125344656e21170c3223c410 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Tue, 4 Aug 2009 17:45:55 +0000 Subject: [PATCH 010/796] Corrected a comment, reformatted some code --- lib/server.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/lib/server.c b/lib/server.c index 83111c0c..4bd987ce 100644 --- a/lib/server.c +++ b/lib/server.c @@ -1,7 +1,7 @@ /* SASL server API implementation * Rob Siemborski * Tim Martin - * $Id: server.c,v 1.160 2009/04/08 19:36:20 mel Exp $ + * $Id: server.c,v 1.161 2009/08/04 17:45:55 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -1351,8 +1351,8 @@ int sasl_server_start(sasl_conn_t *conn, if (!mech || ((clientin==NULL) && (clientinlen>0))) PARAMERROR(conn); - if(serverout) *serverout = NULL; - if(serveroutlen) *serveroutlen = 0; + if (serverout) *serverout = NULL; + if (serveroutlen) *serveroutlen = 0; /* make sure mech is valid mechanism if not return appropriate error */ @@ -1476,8 +1476,10 @@ int sasl_server_start(sasl_conn_t *conn, } else { /* Mech wants client-first, so let them have it */ result = sasl_server_step(conn, - clientin, clientinlen, - serverout, serveroutlen); + clientin, + clientinlen, + serverout, + serveroutlen); } } else { if(s_conn->mech->m.plug->features & SASL_FEAT_WANT_CLIENT_FIRST) { @@ -1488,8 +1490,10 @@ int sasl_server_start(sasl_conn_t *conn, } else { /* Mech wants server-first, so let them have it */ result = sasl_server_step(conn, - clientin, clientinlen, - serverout, serveroutlen); + clientin, + clientinlen, + serverout, + serveroutlen); } } } @@ -1510,9 +1514,9 @@ int sasl_server_start(sasl_conn_t *conn, /* perform one step of the SASL exchange - * inputlen & input -- client data + * clientinlen & clientin -- client data * NULL on first step if no optional client step - * outputlen & output -- set to the server data to transmit + * serveroutlen & serverout -- set to the server data to transmit * to the client in the next step * (library handles freeing this) * @@ -1542,7 +1546,7 @@ int sasl_server_step(sasl_conn_t *conn, PARAMERROR(conn); /* If we've already done the last send, return! */ - if(s_conn->sent_last == 1) { + if (s_conn->sent_last == 1) { return SASL_OK; } @@ -1552,8 +1556,8 @@ int sasl_server_step(sasl_conn_t *conn, return SASL_FAIL; } - if(serverout) *serverout = NULL; - if(serveroutlen) *serveroutlen = 0; + if (serverout) *serverout = NULL; + if (serveroutlen) *serveroutlen = 0; ret = s_conn->mech->m.plug->mech_step(conn->context, s_conn->sparams, From c5f28bab3fe10e7625182bb801a7a449352fd96d Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Tue, 4 Aug 2009 18:02:26 +0000 Subject: [PATCH 011/796] Updated as per recent GSSAPI plugin fixes. --- ChangeLog | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/ChangeLog b/ChangeLog index 4a6b8622..6fb89175 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2009-08-04 Alexey Melnikov + * plugins/gssapi.c: Properly set serveroutlen to 0 in one place. + Don't send empty challenge once server context establishment is done, + as this is in violation of the RFC 2222 and its successor. + +2009-07-24 Alexey Melnikov + * plugins/gssapi.c: Don't send maxbuf, if no security layer + can be established. Added additional checks for buffer lengths. + 2009-05-20 Ken Murchison * configure.in, cmulocal/sasl2.m4, config/kerberos_v4.m4, config/plain.m4, config/sasldb.m4, From 417473582c5e4c9725af752bdf21d798d36cab72 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Fri, 14 Aug 2009 14:55:51 +0000 Subject: [PATCH 012/796] Removed _XOPEN_SOURCE, as this breaks Solaris 8 build --- saslauthd/auth_shadow.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/saslauthd/auth_shadow.c b/saslauthd/auth_shadow.c index c3f749d7..e7393524 100644 --- a/saslauthd/auth_shadow.c +++ b/saslauthd/auth_shadow.c @@ -1,4 +1,3 @@ -#define _XOPEN_SOURCE #define PWBUFSZ 256 /***SWB***/ /* MODULE: auth_shadow */ @@ -31,7 +30,7 @@ * END COPYRIGHT */ #ifdef __GNUC__ -#ident "$Id: auth_shadow.c,v 1.10 2009/02/20 21:59:50 mel Exp $" +#ident "$Id: auth_shadow.c,v 1.11 2009/08/14 14:55:51 mel Exp $" #endif /* PUBLIC DEPENDENCIES */ From e6da446a502577051ee01329072617638a7c83b9 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Fri, 14 Aug 2009 14:58:38 +0000 Subject: [PATCH 013/796] Moved PWBUFSZ definition to a better place --- saslauthd/auth_shadow.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/saslauthd/auth_shadow.c b/saslauthd/auth_shadow.c index e7393524..714e1481 100644 --- a/saslauthd/auth_shadow.c +++ b/saslauthd/auth_shadow.c @@ -1,5 +1,3 @@ -#define PWBUFSZ 256 /***SWB***/ - /* MODULE: auth_shadow */ /* COPYRIGHT @@ -30,7 +28,7 @@ * END COPYRIGHT */ #ifdef __GNUC__ -#ident "$Id: auth_shadow.c,v 1.11 2009/08/14 14:55:51 mel Exp $" +#ident "$Id: auth_shadow.c,v 1.12 2009/08/14 14:58:38 mel Exp $" #endif /* PUBLIC DEPENDENCIES */ @@ -38,6 +36,8 @@ #ifdef AUTH_SHADOW +#define PWBUFSZ 256 /***SWB***/ + # include # include # include From 1055236a1f807adf9d90474ec7ca1d1ab270d792 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Fri, 14 Aug 2009 15:00:29 +0000 Subject: [PATCH 014/796] Updated as per auth_shadow.c change. --- ChangeLog | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ChangeLog b/ChangeLog index 6fb89175..d09d8cfc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2009-08-14 Alexey Melnikov + * saslauthd/auth_shadow.c: Rolled back the previous commit + (#define _XOPEN_SOURCE before including unistd.h), + as this seems to break Solaris 8 build. Note that crypt.h + should be present on a Solaris 8 machine, as well is on Debian, + so this shouldn't be a problem. + 2009-08-04 Alexey Melnikov * plugins/gssapi.c: Properly set serveroutlen to 0 in one place. Don't send empty challenge once server context establishment is done, From 9426f13567fc491dfc317120a40c62d199cc695b Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Tue, 18 Aug 2009 12:23:57 +0000 Subject: [PATCH 015/796] Code reformatting change --- lib/client.c | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/lib/client.c b/lib/client.c index 08903663..0daf1d7c 100644 --- a/lib/client.c +++ b/lib/client.c @@ -1,7 +1,7 @@ /* SASL client API implementation * Rob Siemborski * Tim Martin - * $Id: client.c,v 1.76 2009/08/04 17:13:51 mel Exp $ + * $Id: client.c,v 1.77 2009/08/18 12:23:57 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -334,7 +334,7 @@ int sasl_client_new(const char *service, sasl_client_conn_t *conn; sasl_utils_t *utils; - if(_sasl_client_active==0) return SASL_NOTINIT; + if (_sasl_client_active == 0) return SASL_NOTINIT; /* Remember, serverFQDN, iplocalport and ipremoteport can be NULL and be valid! */ if (!pconn || !service) @@ -365,9 +365,10 @@ int sasl_client_new(const char *service, prompt_supp, &global_callbacks_client); if (result != SASL_OK) RETURN(*pconn, result); - utils=_sasl_alloc_utils(*pconn, &global_callbacks_client); - if (utils==NULL) + utils = _sasl_alloc_utils(*pconn, &global_callbacks_client); + if (utils == NULL) { MEMERROR(*pconn); + } utils->conn= *pconn; @@ -386,7 +387,7 @@ int sasl_client_new(const char *service, result = _sasl_strdup(name, &conn->clientFQDN, NULL); - if(result == SASL_OK) return SASL_OK; + if (result == SASL_OK) return SASL_OK; /* result isn't SASL_OK */ _sasl_conn_dispose(*pconn); @@ -453,7 +454,7 @@ int sasl_client_start(sasl_conn_t *conn, unsigned *clientoutlen, const char **mech) { - sasl_client_conn_t *c_conn= (sasl_client_conn_t *) conn; + sasl_client_conn_t *c_conn = (sasl_client_conn_t *) conn; char name[SASL_MECHNAMEMAX + 1]; cmechanism_t *m=NULL,*bestm=NULL; size_t pos=0,place; @@ -461,13 +462,14 @@ int sasl_client_start(sasl_conn_t *conn, sasl_ssf_t bestssf = 0, minssf = 0; int result; - if(_sasl_client_active==0) return SASL_NOTINIT; + if (_sasl_client_active == 0) return SASL_NOTINIT; if (!conn) return SASL_BADPARAM; /* verify parameters */ - if (mechlist == NULL) + if (mechlist == NULL) { PARAMERROR(conn); + } /* if prompt_need != NULL we've already been here and just need to do the continue step again */ @@ -478,7 +480,7 @@ int sasl_client_start(sasl_conn_t *conn, goto dostep; } - if(conn->props.min_ssf < conn->external.ssf) { + if (conn->props.min_ssf < conn->external.ssf) { minssf = 0; } else { minssf = conn->props.min_ssf - conn->external.ssf; @@ -623,7 +625,7 @@ int sasl_client_start(sasl_conn_t *conn, result = c_conn->mech->m.plug->mech_new(c_conn->mech->m.plug->glob_context, c_conn->cparams, &(conn->context)); - if(result != SASL_OK) goto done; + if (result != SASL_OK) goto done; /* do a step -- but only if we can do a client-send-first */ dostep: @@ -774,8 +776,9 @@ int _sasl_client_listmech(sasl_conn_t *conn, minssf = conn->props.min_ssf - conn->external.ssf; } - if (! cmechlist || cmechlist->mech_length <= 0) + if (! cmechlist || cmechlist->mech_length <= 0) { INTERROR(conn, SASL_NOMECH); + } resultlen = (prefix ? strlen(prefix) : 0) + (strlen(mysep) * (cmechlist->mech_length - 1)) @@ -783,23 +786,27 @@ int _sasl_client_listmech(sasl_conn_t *conn, + (suffix ? strlen(suffix) : 0) + 1; ret = _buf_alloc(&conn->mechlist_buf, - &conn->mechlist_buf_len, resultlen); - if(ret != SASL_OK) MEMERROR(conn); + &conn->mechlist_buf_len, + resultlen); + if (ret != SASL_OK) MEMERROR(conn); - if (prefix) + if (prefix) { strcpy (conn->mechlist_buf,prefix); - else + } else { *(conn->mechlist_buf) = '\0'; + } flag = 0; for (m = cmechlist->mech_list; m != NULL; m = m->next) { /* do we have the prompts for it? */ - if (!have_prompts(conn, m->m.plug)) + if (!have_prompts(conn, m->m.plug)) { continue; + } /* is it strong enough? */ - if (minssf > m->m.plug->max_ssf) + if (minssf > m->m.plug->max_ssf) { continue; + } /* does it meet our security properties? */ if (((conn->props.security_flags ^ m->m.plug->security_flags) From 93fba81fe6d12590fcb249f8f1bde1451eb36225 Mon Sep 17 00:00:00 2001 From: Ken Murchison Date: Fri, 22 Jan 2010 15:14:53 +0000 Subject: [PATCH 016/796] make sure we tell the caller how much data has been decoded in the SASL_CONTINUE case --- lib/saslutil.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/saslutil.c b/lib/saslutil.c index c9ccc2d4..6b43d6d7 100644 --- a/lib/saslutil.c +++ b/lib/saslutil.c @@ -1,7 +1,7 @@ /* saslutil.c * Rob Siemborski * Tim Martin - * $Id: saslutil.c,v 1.49 2009/04/27 13:26:27 murch Exp $ + * $Id: saslutil.c,v 1.50 2010/01/22 15:14:53 murch Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -231,6 +231,10 @@ int sasl_decode64(const char *in, } } + *out = '\0'; /* NUL terminate the output string */ + + if (outlen) *outlen = len; + if (inlen != 0) { if (saw_equal) { /* Unless there is CRLF at the end? */ @@ -240,10 +244,6 @@ int sasl_decode64(const char *in, } } - *out = '\0'; /* NUL terminate the output string */ - - if (outlen) *outlen = len; - return SASL_OK; } From 4af2b405d648e0c95c469d442b0eab256825c703 Mon Sep 17 00:00:00 2001 From: Ken Murchison Date: Mon, 25 Jan 2010 15:45:46 +0000 Subject: [PATCH 017/796] properly check value of ntlm_v2 option --- plugins/ntlm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/ntlm.c b/plugins/ntlm.c index 5188d696..e121f8fa 100644 --- a/plugins/ntlm.c +++ b/plugins/ntlm.c @@ -1,6 +1,6 @@ /* NTLM SASL plugin * Ken Murchison - * $Id: ntlm.c,v 1.33 2008/10/30 14:19:46 mel Exp $ + * $Id: ntlm.c,v 1.34 2010/01/25 15:45:46 murch Exp $ * * References: * http://www.innovation.ch/java/ntlm.html @@ -100,7 +100,7 @@ /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: ntlm.c,v 1.33 2008/10/30 14:19:46 mel Exp $"; +static const char plugin_id[] = "$Id: ntlm.c,v 1.34 2010/01/25 15:45:46 murch Exp $"; #ifdef WIN32 static ssize_t writev (SOCKET fd, const struct iovec *iov, size_t iovcnt); @@ -2018,8 +2018,8 @@ static int ntlm_client_mech_step2(client_context_t *text, params->utils->getopt(params->utils->getopt_context, "NTLM", "ntlm_v2", &sendv2, NULL); if (sendv2 && - (*sendv2 == '1' || *sendv2 == 'y' || - (*sendv2 == 'o' && *sendv2 == 'n') || *sendv2 == 't')) { + (sendv2[0] == '1' || sendv2[0] == 'y' || + (sendv2[0] == 'o' && sendv2[1] == 'n') || sendv2[0] == 't')) { /* put the cnonce in place after the LMv2 HMAC */ char *cnonce = resp + MD5_DIGEST_LENGTH; From b6fc0bb13b243c6ae97492bb696b47824c9e4f8b Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Mon, 15 Feb 2010 12:12:13 +0000 Subject: [PATCH 018/796] Minor formatting change --- plugins/gssapi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/gssapi.c b/plugins/gssapi.c index 25ab2de0..ea20d706 100644 --- a/plugins/gssapi.c +++ b/plugins/gssapi.c @@ -1,7 +1,7 @@ /* GSSAPI SASL plugin * Leif Johansson * Rob Siemborski (SASL v2 Conversion) - * $Id: gssapi.c,v 1.100 2009/08/04 17:17:26 mel Exp $ + * $Id: gssapi.c,v 1.101 2010/02/15 12:12:13 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -82,7 +82,7 @@ /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: gssapi.c,v 1.100 2009/08/04 17:17:26 mel Exp $"; +static const char plugin_id[] = "$Id: gssapi.c,v 1.101 2010/02/15 12:12:13 mel Exp $"; static const char * GSSAPI_BLANK_STRING = ""; @@ -318,7 +318,7 @@ sasl_gss_encode(void *context, const struct iovec *invec, unsigned numiov, int ret; struct buffer_info *inblob, bufinfo; - if(!output) return SASL_BADPARAM; + if (!output) return SASL_BADPARAM; if (numiov > 1) { ret = _plug_iovec_to_buf(text->utils, invec, numiov, &text->enc_in_buf); @@ -931,7 +931,7 @@ gssapi_server_mech_step(void *conn_context, if (name_without_realm.value) { params->utils->free(name_without_realm.value); } - + /* we have to decide what sort of encryption/integrity/etc., we support */ if (params->props.max_ssf < params->external_ssf) { From a65ade3ef5d44d86f8bdc3ea18fcf9c2ff21aafa Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Mon, 15 Feb 2010 12:14:47 +0000 Subject: [PATCH 019/796] Avoid use of htonl() as this is not entirely portable between different architectures. --- plugins/gssapi.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/plugins/gssapi.c b/plugins/gssapi.c index ea20d706..712b0962 100644 --- a/plugins/gssapi.c +++ b/plugins/gssapi.c @@ -1,7 +1,7 @@ /* GSSAPI SASL plugin * Leif Johansson * Rob Siemborski (SASL v2 Conversion) - * $Id: gssapi.c,v 1.101 2010/02/15 12:12:13 mel Exp $ + * $Id: gssapi.c,v 1.102 2010/02/15 12:14:47 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -82,7 +82,7 @@ /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: gssapi.c,v 1.101 2010/02/15 12:12:13 mel Exp $"; +static const char plugin_id[] = "$Id: gssapi.c,v 1.102 2010/02/15 12:14:47 mel Exp $"; static const char * GSSAPI_BLANK_STRING = ""; @@ -362,10 +362,12 @@ sasl_gss_encode(void *context, const struct iovec *invec, unsigned numiov, } if (output_token->value && output) { - int len; + unsigned char * p = (unsigned char *) text->encode_buf; - ret = _plug_buf_alloc(text->utils, &(text->encode_buf), - &(text->encode_buf_len), output_token->length + 4); + ret = _plug_buf_alloc(text->utils, + &(text->encode_buf), + &(text->encode_buf_len), + output_token->length + 4); if (ret != SASL_OK) { GSS_LOCK_MUTEX(text->utils); @@ -374,8 +376,11 @@ sasl_gss_encode(void *context, const struct iovec *invec, unsigned numiov, return ret; } - len = htonl(output_token->length); - memcpy(text->encode_buf, &len, 4); + p[0] = (output_token->length>>24) & 0xFF; + p[1] = (output_token->length>>16) & 0xFF; + p[2] = (output_token->length>>8) & 0xFF; + p[3] = output_token->length & 0xFF; + memcpy(text->encode_buf + 4, output_token->value, output_token->length); } From 080e51c7fa0421eb2f0210d34cf0ac48a228b1e9 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Mon, 15 Feb 2010 12:23:45 +0000 Subject: [PATCH 020/796] Updated the list of GSS-API flags passed to gss_init_sec_context() as per RFC 4752. --- plugins/gssapi.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/plugins/gssapi.c b/plugins/gssapi.c index 712b0962..1da8cfca 100644 --- a/plugins/gssapi.c +++ b/plugins/gssapi.c @@ -1,7 +1,7 @@ /* GSSAPI SASL plugin * Leif Johansson * Rob Siemborski (SASL v2 Conversion) - * $Id: gssapi.c,v 1.102 2010/02/15 12:14:47 mel Exp $ + * $Id: gssapi.c,v 1.103 2010/02/15 12:23:45 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -82,7 +82,7 @@ /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: gssapi.c,v 1.102 2010/02/15 12:14:47 mel Exp $"; +static const char plugin_id[] = "$Id: gssapi.c,v 1.103 2010/02/15 12:23:45 mel Exp $"; static const char * GSSAPI_BLANK_STRING = ""; @@ -1423,23 +1423,24 @@ static int gssapi_client_mech_step(void *conn_context, GSS_UNLOCK_MUTEX(params->utils); text->gss_ctx = GSS_C_NO_CONTEXT; } - + /* Setup req_flags properly */ - req_flags = GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG; - if(params->props.max_ssf > params->external_ssf) { + req_flags = GSS_C_INTEG_FLAG; + if (params->props.max_ssf > params->external_ssf) { /* We are requesting a security layer */ - req_flags |= GSS_C_INTEG_FLAG; + req_flags |= GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG; /* Any SSF bigger than 1 is confidentiality. */ /* Let's check if the client of the API requires confidentiality, and it wasn't already provided by an external layer */ - if(params->props.max_ssf - params->external_ssf > 1) { + if (params->props.max_ssf - params->external_ssf > 1) { /* We want to try for privacy */ req_flags |= GSS_C_CONF_FLAG; } } - - if (params->props.security_flags & SASL_SEC_PASS_CREDENTIALS) + + if (params->props.security_flags & SASL_SEC_PASS_CREDENTIALS) { req_flags = req_flags | GSS_C_DELEG_FLAG; + } GSS_LOCK_MUTEX(params->utils); maj_stat = gss_init_sec_context(&min_stat, From bbe52c3b05b6b86927208c9a03839a6d21e341e8 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Mon, 15 Feb 2010 12:32:12 +0000 Subject: [PATCH 021/796] Check resulting GSS-API security flags upon successful client or server authentication. Cleanup of the code handling security layer negotiation. --- plugins/gssapi.c | 107 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 81 insertions(+), 26 deletions(-) diff --git a/plugins/gssapi.c b/plugins/gssapi.c index 1da8cfca..5e745fc8 100644 --- a/plugins/gssapi.c +++ b/plugins/gssapi.c @@ -1,7 +1,7 @@ /* GSSAPI SASL plugin * Leif Johansson * Rob Siemborski (SASL v2 Conversion) - * $Id: gssapi.c,v 1.103 2010/02/15 12:23:45 mel Exp $ + * $Id: gssapi.c,v 1.104 2010/02/15 12:32:12 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -82,7 +82,7 @@ /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: gssapi.c,v 1.103 2010/02/15 12:23:45 mel Exp $"; +static const char plugin_id[] = "$Id: gssapi.c,v 1.104 2010/02/15 12:32:12 mel Exp $"; static const char * GSSAPI_BLANK_STRING = ""; @@ -150,6 +150,8 @@ typedef struct context { sasl_ssf_t limitssf, requiressf; /* application defined bounds, for the server */ + unsigned char qop; /* as allowed by GSSAPI */ + const sasl_utils_t *utils; /* layers buffering */ @@ -177,6 +179,10 @@ enum { SASL_GSSAPI_STATE_AUTHENTICATED = 4 }; +#define LAYER_CONFIDENTIALITY 4 +#define LAYER_INTEGRITY 2 +#define LAYER_NONE 1 + /* sasl_gss_log: only logs status string returned from gss_display_status() */ #define sasl_gss_log(x,y,z) sasl_gss_seterror_(x,y,z,1) #define sasl_gss_seterror(x,y,z) sasl_gss_seterror_(x,y,z,0) @@ -749,7 +755,26 @@ gssapi_server_mech_step(void *conn_context, sasl_gss_free_context_contents(text); return SASL_BADAUTH; } - + + /* When GSS_Accept_sec_context returns GSS_S_COMPLETE, the server + examines the context to ensure that it provides a level of protection + permitted by the server's security policy. In particular, if the + integ_avail flag is not set in the context, then no security layer + can be offered or accepted. If the conf_avail flag is not set in the + context, then no security layer with confidentiality can be offered + or accepted. */ + if ((out_flags & GSS_C_INTEG_FLAG) == 0) { + /* if the integ_avail flag is not set in the context, + then no security layer can be offered or accepted. */ + text->qop = LAYER_NONE; + } else if ((out_flags & GSS_C_CONF_FLAG) == 0) { + /* If the conf_avail flag is not set in the context, + then no security layer with confidentiality can be offered + or accepted. */ + text->qop = LAYER_NONE | LAYER_INTEGRITY; + } else { + text->qop = LAYER_NONE | LAYER_INTEGRITY | LAYER_CONFIDENTIALITY; + } if ((params->props.security_flags & SASL_SEC_PASS_CREDENTIALS) && (!(out_flags & GSS_C_DELEG_FLAG) || @@ -951,7 +976,8 @@ gssapi_server_mech_step(void *conn_context, } /* build up our security properties token */ - if (text->requiressf != 0) { + if (text->requiressf != 0 && + (text->qop & (LAYER_INTEGRITY|LAYER_CONFIDENTIALITY))) { if (params->props.maxbufsize > 0xFFFFFF) { /* make sure maxbufsize isn't too large */ /* maxbufsize = 0xFFFFFF */ @@ -975,15 +1001,19 @@ gssapi_server_mech_step(void *conn_context, } if (text->requiressf == 0) { - sasldata[0] |= 1; /* authentication */ + sasldata[0] |= LAYER_NONE; /* authentication */ } - if (text->requiressf <= 1 && text->limitssf >= 1 - && params->props.maxbufsize) { - sasldata[0] |= 2; + if ((text->qop & LAYER_INTEGRITY) && + text->requiressf <= 1 && + text->limitssf >= 1 && + params->props.maxbufsize) { + sasldata[0] |= LAYER_INTEGRITY; } - if (text->requiressf <= K5_MAX_SSF && text->limitssf >= K5_MAX_SSF - && params->props.maxbufsize) { - sasldata[0] |= 4; + if ((text->qop & LAYER_CONFIDENTIALITY) && + text->requiressf <= K5_MAX_SSF && + text->limitssf >= K5_MAX_SSF && + params->props.maxbufsize) { + sasldata[0] |= LAYER_CONFIDENTIALITY; } real_input_token.value = (void *)sasldata; @@ -1032,6 +1062,9 @@ gssapi_server_mech_step(void *conn_context, GSS_UNLOCK_MUTEX(params->utils); } + /* Remember what we want and can offer */ + text->qop = sasldata[0]; + /* Wait for ssf request and authid */ text->state = SASL_GSSAPI_STATE_SSFREQ; @@ -1070,17 +1103,20 @@ gssapi_server_mech_step(void *conn_context, } layerchoice = (int)(((char *)(output_token->value))[0]); - if (layerchoice == 1 && text->requiressf == 0) { /* no encryption */ + if (layerchoice == LAYER_NONE && + (text->qop & LAYER_NONE)) { /* no encryption */ oparams->encode = NULL; oparams->decode = NULL; oparams->mech_ssf = 0; - } else if (layerchoice == 2 && text->requiressf <= 1 && - text->limitssf >= 1) { /* integrity */ - oparams->encode=&gssapi_integrity_encode; - oparams->decode=&gssapi_decode; - oparams->mech_ssf=1; - } else if (layerchoice == 4 && text->requiressf <= K5_MAX_SSF && - text->limitssf >= K5_MAX_SSF) { /* privacy */ + } else if (layerchoice == LAYER_INTEGRITY && + (text->qop & LAYER_INTEGRITY)) { /* integrity */ + oparams->encode = &gssapi_integrity_encode; + oparams->decode = &gssapi_decode; + oparams->mech_ssf = 1; + } else if ((layerchoice == LAYER_CONFIDENTIALITY || + /* For compatibility with broken clients setting both bits */ + layerchoice == (LAYER_CONFIDENTIALITY|LAYER_INTEGRITY)) && + (context->qop & LAYER_CONFIDENTIALITY)) { /* privacy */ oparams->encode = &gssapi_privacy_encode; oparams->decode = &gssapi_decode; /* FIX ME: Need to extract the proper value here */ @@ -1469,6 +1505,19 @@ static int gssapi_client_mech_step(void *conn_context, return SASL_FAIL; } + if ((out_req_flags & GSS_C_INTEG_FLAG) == 0) { + /* if the integ_avail flag is not set in the context, + then no security layer can be offered or accepted. */ + text->qop = LAYER_NONE; + } else if ((out_req_flags & GSS_C_CONF_FLAG) == 0) { + /* If the conf_avail flag is not set in the context, + then no security layer with confidentiality can be offered + or accepted. */ + text->qop = LAYER_NONE | LAYER_INTEGRITY; + } else { + text->qop = LAYER_NONE | LAYER_INTEGRITY | LAYER_CONFIDENTIALITY; + } + if ((out_req_flags & GSS_C_DELEG_FLAG) != (req_flags & GSS_C_DELEG_FLAG)) { text->utils->seterror(text->utils->conn, SASL_LOG_WARN, "GSSAPI warning: no credentials were passed"); /* not a fatal error */ @@ -1622,26 +1671,32 @@ static int gssapi_client_mech_step(void *conn_context, /* bit mask of server support */ serverhas = ((char *)output_token->value)[0]; - /* if client didn't set use strongest layer available */ - if (allowed >= K5_MAX_SSF && need <= K5_MAX_SSF && (serverhas & 4)) { + /* use the strongest layer available */ + if ((context->qop & LAYER_CONFIDENTIALITY) && + allowed >= K5_MAX_SSF && + need <= K5_MAX_SSF && + (serverhas & LAYER_CONFIDENTIALITY)) { /* encryption */ oparams->encode = &gssapi_privacy_encode; oparams->decode = &gssapi_decode; /* FIX ME: Need to extract the proper value here */ oparams->mech_ssf = K5_MAX_SSF; - mychoice = 4; - } else if (allowed >= 1 && need <= 1 && (serverhas & 2)) { + mychoice = LAYER_CONFIDENTIALITY; + } else if ((context->qop & LAYER_INTEGRITY) && + allowed >= 1 && + need <= 1 && + (serverhas & LAYER_INTEGRITY)) { /* integrity */ oparams->encode = &gssapi_integrity_encode; oparams->decode = &gssapi_decode; oparams->mech_ssf = 1; - mychoice = 2; - } else if (need <= 0 && (serverhas & 1)) { + mychoice = LAYER_INTEGRITY; + } else if (need <= 0 && (serverhas & LAYER_NONE)) { /* no layer */ oparams->encode = NULL; oparams->decode = NULL; oparams->mech_ssf = 0; - mychoice = 1; + mychoice = LAYER_NONE; } else { /* there's no appropriate layering for us! */ sasl_gss_free_context_contents(text); From 4724ae85299d40ea89134266fdd66da8fff080e2 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Wed, 24 Feb 2010 19:41:59 +0000 Subject: [PATCH 022/796] Renamed the local sasl_getopt function to be plugview_sasl_getopt, otherwise there is a conflict with sasl_getopt() defined in sasl.h --- utils/pluginviewer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/utils/pluginviewer.c b/utils/pluginviewer.c index a8c3bae6..7e5f2a4c 100644 --- a/utils/pluginviewer.c +++ b/utils/pluginviewer.c @@ -1,7 +1,7 @@ /* pluginviewer.c -- Plugin Viewer for CMU SASL * Alexey Melnikov, Isode Ltd. * - * $Id: pluginviewer.c,v 1.7 2009/02/14 14:42:46 mel Exp $ + * $Id: pluginviewer.c,v 1.8 2010/02/24 19:41:59 mel Exp $ */ /* * Copyright (c) 2004 Carnegie Mellon University. All rights reserved. @@ -216,7 +216,7 @@ getpath(void *context, } static int -sasl_getopt ( +plugview_sasl_getopt ( void *context, const char *plugin_name, const char *option, @@ -582,7 +582,7 @@ main(int argc, char *argv[]) /* NOTE: this will return "sasl_mech" option, however this HAS NO EFFECT on client side SASL plugins, which just never query this option */ callback->id = SASL_CB_GETOPT; - callback->proc = &sasl_getopt; + callback->proc = &plugview_sasl_getopt; callback->context = NULL; ++callback; From 2f261dd68e7fd2269605fed58c1db8a6ed6c21ad Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Wed, 24 Feb 2010 22:15:06 +0000 Subject: [PATCH 023/796] Fixed the last commit to compiled --- plugins/gssapi.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/gssapi.c b/plugins/gssapi.c index 5e745fc8..6e4b2b8d 100644 --- a/plugins/gssapi.c +++ b/plugins/gssapi.c @@ -1,7 +1,7 @@ /* GSSAPI SASL plugin * Leif Johansson * Rob Siemborski (SASL v2 Conversion) - * $Id: gssapi.c,v 1.104 2010/02/15 12:32:12 mel Exp $ + * $Id: gssapi.c,v 1.105 2010/02/24 22:15:06 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -82,7 +82,7 @@ /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: gssapi.c,v 1.104 2010/02/15 12:32:12 mel Exp $"; +static const char plugin_id[] = "$Id: gssapi.c,v 1.105 2010/02/24 22:15:06 mel Exp $"; static const char * GSSAPI_BLANK_STRING = ""; @@ -1116,7 +1116,7 @@ gssapi_server_mech_step(void *conn_context, } else if ((layerchoice == LAYER_CONFIDENTIALITY || /* For compatibility with broken clients setting both bits */ layerchoice == (LAYER_CONFIDENTIALITY|LAYER_INTEGRITY)) && - (context->qop & LAYER_CONFIDENTIALITY)) { /* privacy */ + (text->qop & LAYER_CONFIDENTIALITY)) { /* privacy */ oparams->encode = &gssapi_privacy_encode; oparams->decode = &gssapi_decode; /* FIX ME: Need to extract the proper value here */ @@ -1672,7 +1672,7 @@ static int gssapi_client_mech_step(void *conn_context, serverhas = ((char *)output_token->value)[0]; /* use the strongest layer available */ - if ((context->qop & LAYER_CONFIDENTIALITY) && + if ((text->qop & LAYER_CONFIDENTIALITY) && allowed >= K5_MAX_SSF && need <= K5_MAX_SSF && (serverhas & LAYER_CONFIDENTIALITY)) { @@ -1682,7 +1682,7 @@ static int gssapi_client_mech_step(void *conn_context, /* FIX ME: Need to extract the proper value here */ oparams->mech_ssf = K5_MAX_SSF; mychoice = LAYER_CONFIDENTIALITY; - } else if ((context->qop & LAYER_INTEGRITY) && + } else if ((text->qop & LAYER_INTEGRITY) && allowed >= 1 && need <= 1 && (serverhas & LAYER_INTEGRITY)) { From a898cddd706dbebd6e1468869c79e7f7872490c7 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Wed, 24 Feb 2010 22:19:20 +0000 Subject: [PATCH 024/796] Return SASL_NOMEM consistently when printing error messages --- plugins/gssapi.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/plugins/gssapi.c b/plugins/gssapi.c index 6e4b2b8d..c8f2f0d4 100644 --- a/plugins/gssapi.c +++ b/plugins/gssapi.c @@ -1,7 +1,7 @@ /* GSSAPI SASL plugin * Leif Johansson * Rob Siemborski (SASL v2 Conversion) - * $Id: gssapi.c,v 1.105 2010/02/24 22:15:06 mel Exp $ + * $Id: gssapi.c,v 1.106 2010/02/24 22:19:20 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -82,7 +82,7 @@ /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: gssapi.c,v 1.105 2010/02/24 22:15:06 mel Exp $"; +static const char plugin_id[] = "$Id: gssapi.c,v 1.106 2010/02/24 22:19:20 mel Exp $"; static const char * GSSAPI_BLANK_STRING = ""; @@ -198,10 +198,12 @@ sasl_gss_seterror_(const sasl_utils_t *utils, OM_uint32 maj, OM_uint32 min, char *out = NULL; size_t len, curlen = 0; const char prefix[] = "GSSAPI Error: "; + + if (!utils) return SASL_OK; len = sizeof(prefix); ret = _plug_buf_alloc(utils, &out, &curlen, 256); - if(ret != SASL_OK) return SASL_OK; + if (ret != SASL_OK) return SASL_NOMEM; strcpy(out, prefix); @@ -231,7 +233,7 @@ sasl_gss_seterror_(const sasl_utils_t *utils, OM_uint32 maj, OM_uint32 min, if(ret != SASL_OK) { utils->free(out); - return SASL_OK; + return SASL_NOMEM; } strcat(out, msg.value); From 3969990b9221da9bb87baa59b90390bd7f92f690 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Wed, 24 Feb 2010 22:23:29 +0000 Subject: [PATCH 025/796] Check for params->serverFQDN being NULL --- plugins/gssapi.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/plugins/gssapi.c b/plugins/gssapi.c index c8f2f0d4..98548e52 100644 --- a/plugins/gssapi.c +++ b/plugins/gssapi.c @@ -1,7 +1,7 @@ /* GSSAPI SASL plugin * Leif Johansson * Rob Siemborski (SASL v2 Conversion) - * $Id: gssapi.c,v 1.106 2010/02/24 22:19:20 mel Exp $ + * $Id: gssapi.c,v 1.107 2010/02/24 22:23:29 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -82,7 +82,7 @@ /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: gssapi.c,v 1.106 2010/02/24 22:19:20 mel Exp $"; +static const char plugin_id[] = "$Id: gssapi.c,v 1.107 2010/02/24 22:23:29 mel Exp $"; static const char * GSSAPI_BLANK_STRING = ""; @@ -675,6 +675,12 @@ gssapi_server_mech_step(void *conn_context, case SASL_GSSAPI_STATE_AUTHNEG: if (text->server_name == GSS_C_NO_NAME) { /* only once */ + if (params->serverFQDN == NULL + || strlen(params->serverFQDN) == 0) { + SETERROR(text->utils, "GSSAPI Failure: no serverFQDN"); + sasl_gss_free_context_contents(text); + return SASL_FAIL; + } name_token.length = strlen(params->service) + 1 + strlen(params->serverFQDN); name_token.value = (char *)params->utils->malloc((name_token.length + 1) * sizeof(char)); if (name_token.value == NULL) { @@ -1416,6 +1422,7 @@ static int gssapi_client_mech_step(void *conn_context, if (params->serverFQDN == NULL || strlen(params->serverFQDN) == 0) { SETERROR(text->utils, "GSSAPI Failure: no serverFQDN"); + sasl_gss_free_context_contents(text); return SASL_FAIL; } name_token.length = strlen(params->service) + 1 + strlen(params->serverFQDN); From cccc5a5a87a74cd434fbdf5e87c4158e21ebcf19 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Wed, 24 Feb 2010 22:32:30 +0000 Subject: [PATCH 026/796] Added ad_compat client side SASL option that controls compatibility with AD or similar servers that require both integrity and confidentiality bits selected during security layer negotiation --- plugins/gssapi.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/plugins/gssapi.c b/plugins/gssapi.c index 98548e52..ec88a068 100644 --- a/plugins/gssapi.c +++ b/plugins/gssapi.c @@ -1,7 +1,7 @@ /* GSSAPI SASL plugin * Leif Johansson * Rob Siemborski (SASL v2 Conversion) - * $Id: gssapi.c,v 1.107 2010/02/24 22:23:29 mel Exp $ + * $Id: gssapi.c,v 1.108 2010/02/24 22:32:30 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -82,7 +82,7 @@ /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: gssapi.c,v 1.107 2010/02/24 22:23:29 mel Exp $"; +static const char plugin_id[] = "$Id: gssapi.c,v 1.108 2010/02/24 22:32:30 mel Exp $"; static const char * GSSAPI_BLANK_STRING = ""; @@ -1685,12 +1685,30 @@ static int gssapi_client_mech_step(void *conn_context, allowed >= K5_MAX_SSF && need <= K5_MAX_SSF && (serverhas & LAYER_CONFIDENTIALITY)) { + + const char *ad_compat; + /* encryption */ oparams->encode = &gssapi_privacy_encode; oparams->decode = &gssapi_decode; /* FIX ME: Need to extract the proper value here */ oparams->mech_ssf = K5_MAX_SSF; mychoice = LAYER_CONFIDENTIALITY; + + if (serverhas & LAYER_INTEGRITY) { + /* should we send an AD compatible choice of security layers? */ + params->utils->getopt(params->utils->getopt_context, + "GSSAPI", + "ad_compat", + &ad_compat, + NULL); + if (ad_compat && + (ad_compat[0] == '1' || ad_compat[0] == 'y' || + (ad_compat[0] == 'o' && ad_compat[1] == 'n') || + ad_compat[0] == 't')) { + mychoice = LAYER_INTEGRITY|LAYER_CONFIDENTIALITY; + } + } } else if ((text->qop & LAYER_INTEGRITY) && allowed >= 1 && need <= 1 && From 487c2152fe4a3f39027fe53da3964cf25b8d1c03 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Wed, 24 Feb 2010 22:41:18 +0000 Subject: [PATCH 027/796] Be defensive about calling sasl_server_step once authentication has already failed --- plugins/gssapi.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/plugins/gssapi.c b/plugins/gssapi.c index ec88a068..8091eeb2 100644 --- a/plugins/gssapi.c +++ b/plugins/gssapi.c @@ -1,7 +1,7 @@ /* GSSAPI SASL plugin * Leif Johansson * Rob Siemborski (SASL v2 Conversion) - * $Id: gssapi.c,v 1.108 2010/02/24 22:32:30 mel Exp $ + * $Id: gssapi.c,v 1.109 2010/02/24 22:41:18 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -82,7 +82,7 @@ /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: gssapi.c,v 1.108 2010/02/24 22:32:30 mel Exp $"; +static const char plugin_id[] = "$Id: gssapi.c,v 1.109 2010/02/24 22:41:18 mel Exp $"; static const char * GSSAPI_BLANK_STRING = ""; @@ -671,6 +671,10 @@ gssapi_server_mech_step(void *conn_context, *serverout = NULL; *serveroutlen = 0; + if (text == NULL) { + return SASL_BADPROT; + } + switch (text->state) { case SASL_GSSAPI_STATE_AUTHNEG: From 99a952cb79875ae5c3bc119b81ffdbd9247c92ba Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Sat, 27 Feb 2010 19:24:56 +0000 Subject: [PATCH 028/796] corrected a couple of error messages --- utils/pluginviewer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/utils/pluginviewer.c b/utils/pluginviewer.c index 7e5f2a4c..29534eca 100644 --- a/utils/pluginviewer.c +++ b/utils/pluginviewer.c @@ -1,7 +1,7 @@ /* pluginviewer.c -- Plugin Viewer for CMU SASL * Alexey Melnikov, Isode Ltd. * - * $Id: pluginviewer.c,v 1.8 2010/02/24 19:41:59 mel Exp $ + * $Id: pluginviewer.c,v 1.9 2010/02/27 19:24:56 mel Exp $ */ /* * Copyright (c) 2004 Carnegie Mellon University. All rights reserved. @@ -706,7 +706,7 @@ main(int argc, char *argv[]) &len, &count); if (result != SASL_OK) { - saslfail(result, "Setting security properties", NULL); + saslfail(result, "Listing SASL mechanisms", NULL); } /* NOTE: available_mechs contains subset of sasl_mech */ @@ -788,7 +788,7 @@ main(int argc, char *argv[]) &len, &count); if (result != SASL_OK) { - saslfail(result, "Setting security properties", NULL); + saslfail(result, "Listing SASL mechanisms", NULL); } if (count > 0) { From af9f1f612de4d9b7c2f9e5dfe83c545b5cd76bc2 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Wed, 12 May 2010 21:28:19 +0000 Subject: [PATCH 029/796] Added support for SASL_GSS_CREDS property to GSSAPI plugin (patch by Howard Chu). --- include/saslplug.h | 8 ++++++-- lib/common.c | 17 ++++++++++++++++- plugins/gssapi.c | 44 +++++++++++++++++++++++++------------------- 3 files changed, 47 insertions(+), 22 deletions(-) diff --git a/include/saslplug.h b/include/saslplug.h index 5b540717..e8e8f08c 100755 --- a/include/saslplug.h +++ b/include/saslplug.h @@ -253,8 +253,10 @@ typedef struct sasl_client_params { sasl_security_properties_t props; sasl_ssf_t external_ssf; /* external SSF active */ + /* GSS credentials */ + void *gss_creds; + /* for additions which don't require a version upgrade; set to 0 */ - void *spare_ptr1; void *spare_ptr2; void *spare_ptr3; void *spare_ptr4; @@ -552,8 +554,10 @@ typedef struct sasl_server_params { */ struct propctx *propctx; + /* GSS credentials */ + void *gss_creds; + /* for additions which don't require a version upgrade; set to 0 */ - void *spare_ptr1; void *spare_ptr2; void *spare_ptr3; void *spare_ptr4; diff --git a/lib/common.c b/lib/common.c index b76df23b..a814792d 100644 --- a/lib/common.c +++ b/lib/common.c @@ -1,7 +1,7 @@ /* common.c - Functions that are common to server and clinet * Rob Siemborski * Tim Martin - * $Id: common.c,v 1.124 2009/02/20 23:10:53 mel Exp $ + * $Id: common.c,v 1.125 2010/05/12 21:28:19 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -1027,6 +1027,14 @@ int sasl_getprop(sasl_conn_t *conn, int propnum, const void **pvalue) case SASL_SEC_PROPS: *((const sasl_security_properties_t **)pvalue) = &conn->props; break; + case SASL_GSS_CREDS: + if(conn->type == SASL_CONN_CLIENT) + *(void **)pvalue = + ((sasl_client_conn_t *)conn)->cparams->gss_creds; + else + *(void **)pvalue = + ((sasl_server_conn_t *)conn)->sparams->gss_creds; + break; default: result = SASL_BADPARAM; } @@ -1238,6 +1246,13 @@ int sasl_setprop(sasl_conn_t *conn, int propnum, const void *value) } break; + case SASL_GSS_CREDS: + if(conn->type == SASL_CONN_CLIENT) + ((sasl_client_conn_t *)conn)->cparams->gss_creds = value; + else + ((sasl_server_conn_t *)conn)->sparams->gss_creds = value; + break; + default: sasl_seterror(conn, 0, "Unknown parameter type"); result = SASL_BADPARAM; diff --git a/plugins/gssapi.c b/plugins/gssapi.c index 8091eeb2..b501410c 100644 --- a/plugins/gssapi.c +++ b/plugins/gssapi.c @@ -1,7 +1,7 @@ /* GSSAPI SASL plugin * Leif Johansson * Rob Siemborski (SASL v2 Conversion) - * $Id: gssapi.c,v 1.109 2010/02/24 22:41:18 mel Exp $ + * $Id: gssapi.c,v 1.110 2010/05/12 21:28:19 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -82,7 +82,7 @@ /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: gssapi.c,v 1.109 2010/02/24 22:41:18 mel Exp $"; +static const char plugin_id[] = "$Id: gssapi.c,v 1.110 2010/05/12 21:28:19 mel Exp $"; static const char * GSSAPI_BLANK_STRING = ""; @@ -657,6 +657,7 @@ gssapi_server_mech_step(void *conn_context, OM_uint32 max_input; gss_buffer_desc name_token; int ret, out_flags = 0 ; + gss_cred_id_t server_creds = params->gss_creds; input_token = &real_input_token; output_token = &real_output_token; @@ -716,22 +717,26 @@ gssapi_server_mech_step(void *conn_context, GSS_UNLOCK_MUTEX(params->utils); text->server_creds = GSS_C_NO_CREDENTIAL; } + + /* If caller didn't provide creds already */ + if ( server_creds == GSS_C_NO_CREDENTIAL) { + GSS_LOCK_MUTEX(params->utils); + maj_stat = gss_acquire_cred(&min_stat, + text->server_name, + GSS_C_INDEFINITE, + GSS_C_NO_OID_SET, + GSS_C_ACCEPT, + &text->server_creds, + NULL, + NULL); + GSS_UNLOCK_MUTEX(params->utils); - GSS_LOCK_MUTEX(params->utils); - maj_stat = gss_acquire_cred(&min_stat, - text->server_name, - GSS_C_INDEFINITE, - GSS_C_NO_OID_SET, - GSS_C_ACCEPT, - &text->server_creds, - NULL, - NULL); - GSS_UNLOCK_MUTEX(params->utils); - - if (GSS_ERROR(maj_stat)) { - sasl_gss_seterror(text->utils, maj_stat, min_stat); - sasl_gss_free_context_contents(text); - return SASL_FAIL; + if (GSS_ERROR(maj_stat)) { + sasl_gss_seterror(text->utils, maj_stat, min_stat); + sasl_gss_free_context_contents(text); + return SASL_FAIL; + } + server_creds = text->server-creds; } } @@ -745,7 +750,7 @@ gssapi_server_mech_step(void *conn_context, maj_stat = gss_accept_sec_context(&min_stat, &(text->gss_ctx), - text->server_creds, + server_creds, input_token, GSS_C_NO_CHANNEL_BINDINGS, &text->client_name, @@ -1380,6 +1385,7 @@ static int gssapi_client_mech_step(void *conn_context, output_token->value = NULL; input_token->value = NULL; input_token->length = 0; + gss_cred_id_t client_creds = (gss_cred_id_t)params->gss_creds; *clientout = NULL; *clientoutlen = 0; @@ -1493,7 +1499,7 @@ static int gssapi_client_mech_step(void *conn_context, GSS_LOCK_MUTEX(params->utils); maj_stat = gss_init_sec_context(&min_stat, - GSS_C_NO_CREDENTIAL, + client_creds, /* GSS_C_NO_CREDENTIAL */ &text->gss_ctx, text->server_name, GSS_C_NO_OID, From 6e641a54f243af3df006b6bc21b065693101ceee Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Thu, 10 Jun 2010 10:45:35 +0000 Subject: [PATCH 030/796] Check for a buffer overflow in ldapdb_canon_client() [Lars Duesing/Howard Chu] --- plugins/ldapdb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/ldapdb.c b/plugins/ldapdb.c index 18c0c261..f86b73bf 100644 --- a/plugins/ldapdb.c +++ b/plugins/ldapdb.c @@ -430,6 +430,8 @@ ldapdb_canon_client(void *glob_context, { if(!cparams || !user) return SASL_BADPARAM; + if (ulen > out_umax) return SASL_BUFOVER; + /* Trim whitespace */ while(isspace(*(unsigned char *)user)) { user++; From 675b6796472bd4ad6de0cd3c66a02842eae1fe92 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Thu, 10 Jun 2010 11:08:05 +0000 Subject: [PATCH 031/796] Moved the length check in ldapdb_canon_client() just before the memcpy --- plugins/ldapdb.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/ldapdb.c b/plugins/ldapdb.c index f86b73bf..1217ddc8 100644 --- a/plugins/ldapdb.c +++ b/plugins/ldapdb.c @@ -430,8 +430,6 @@ ldapdb_canon_client(void *glob_context, { if(!cparams || !user) return SASL_BADPARAM; - if (ulen > out_umax) return SASL_BUFOVER; - /* Trim whitespace */ while(isspace(*(unsigned char *)user)) { user++; @@ -446,6 +444,9 @@ ldapdb_canon_client(void *glob_context, "All-whitespace username."); return SASL_FAIL; } + + if (ulen > out_umax) return SASL_BUFOVER; + memcpy(out, user, ulen); out[ulen] = '\0'; *out_ulen = ulen; From 5d606a68bc1bbdbd23b5c7dc7ffd3b3b8fe1af2c Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Fri, 24 Sep 2010 19:54:43 +0000 Subject: [PATCH 032/796] Reimplementation of SCRAM as specified in RFC 5802. Implemented by Alexey with some improvements by Dave Cridland. --- plugins/scram.c | 2085 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2085 insertions(+) create mode 100644 plugins/scram.c diff --git a/plugins/scram.c b/plugins/scram.c new file mode 100644 index 00000000..567d628b --- /dev/null +++ b/plugins/scram.c @@ -0,0 +1,2085 @@ +/* SCRAM-SHA-1 SASL plugin + * Alexey Melnikov + * $Id: scram.c,v 1.18 2010/09/24 19:54:43 mel Exp $ + */ +/* + * Copyright (c) 2009-2010 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any other legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include +#ifndef macintosh +#include +#endif +#include +#include + +#include +#include +#include + +#include "plugin_common.h" + +#ifdef macintosh +#include +#endif + +#include +#include +#include + +/***************************** Common Section *****************************/ + +static const char plugin_id[] = "$Id: scram.c,v 1.18 2010/09/24 19:54:43 mel Exp $"; + +#define NONCE_SIZE (32) /* arbitrary */ +#define SALT_SIZE (16) /* arbitrary */ + +/* TODO: make this a configurable option? */ +#define DEFAULT_ITERATION_COUNTER 4096 +#define MIN_ITERATION_COUNTER 4096 + +#define MAX_ITERATION_COUNTER 0x10000 + +/* maximum length of the iteration_counter (as a string). Assume it is 32bits */ +#define ITERATION_COUNTER_BUF_LEN 20 + +#define SCRAM_HASH_SIZE 20 + +#define MAX_CLIENTIN_LEN 2048 +#define MAX_SERVERIN_LEN 2048 + +#define STRINGIZE(x) #x +#define MAX_CLIENTIN_LEN_STR STRINGIZE((MAX_CLIENTIN_LEN)) +#define MAX_SERVERIN_LEN_STR STRINGIZE((MAX_SERVERIN_LEN)) + +#define CLIENT_KEY_CONSTANT "Client Key" +#define SERVER_KEY_CONSTANT "Server Key" +#define CLIENT_KEY_CONSTANT_LEN sizeof(CLIENT_KEY_CONSTANT)-1 +#define SERVER_KEY_CONSTANT_LEN sizeof(SERVER_KEY_CONSTANT)-1 + +#ifdef SCRAM_DEBUG +#define PRINT_HASH(func,hash) print_hash(func,hash) +#else +#define PRINT_HASH(func,hash) +#endif + +/* NB: A temporary mapping for "internal errors". It would be better to add + a new SASL error code for that */ +#define SASL_SCRAM_INTERNAL SASL_NOMEM + +/* Holds the core salt to avoid regenerating salt each auth. */ +static unsigned char g_salt_key[SALT_SIZE]; + +/* Convert saslname = 1*(value-safe-char / "=2C" / "=3D") in place. + Returns SASL_FAIL if the encoding is invalid, otherwise SASL_OK */ +static int +decode_saslname (char *buf) +{ + char * inp; + char * outp; + + inp = outp = buf; + + while (*inp) { + if (*inp == '=') { + inp++; + if (*inp == '\0') { + return SASL_FAIL; + } + if (inp[0] == '2' && inp[1] == 'C') { + *outp = ','; + inp += 2; + } else if (inp[0] == '3' && inp[1] == 'D') { + *outp = '='; + inp += 2; + } else { + return SASL_FAIL; + } + } else { + *outp = *inp; + inp++; + } + outp++; + } + + return SASL_OK; +} + +/* Convert a username to saslname = 1*(value-safe-char / "=2C" / "=3D") + and return an allocated copy. + "freeme" contains pointer to the allocated output, or NULL, + if encoded_saslname just points to saslname. + Returns SASL_NOMEM if can't allocate memory for the output, otherwise SASL_OK */ +static int +encode_saslname (const char *saslname, + const char **encoded_saslname, + char **freeme) +{ + const char * inp; + char * outp; + int special_chars = 0; + + /* Found out if anything needs encoding */ + for (inp = saslname; *inp; inp++) { + if (*inp == ',' || *inp == '=') { + special_chars++; + } + } + + if (special_chars == 0) { + *encoded_saslname = saslname; + *freeme = NULL; + return SASL_OK; + } + + outp = malloc(strlen(saslname) + special_chars * 2 + 1); + *encoded_saslname = outp; + *freeme = outp; + if (outp == NULL) { + return SASL_NOMEM; + } + + for (inp = saslname; *inp; inp++) { + switch (*inp) { + case ',': + *outp++ = '='; + *outp++ = '2'; + *outp++ = 'C'; + break; + + case '=': + *outp++ = '='; + *outp++ = '3'; + *outp++ = 'D'; + break; + + default: + *outp++ = *inp; + } + } + + *outp = '\0'; + + return SASL_OK; +} + +static char * +create_nonce(const sasl_utils_t * utils, + char *buffer, + size_t buflen) /* Including the terminating NUL */ +{ + char *intbuf; + unsigned int estimated; + + if ((buflen - 1) % 4 != 0) { + /* NB: the algorithm below doesn't work for such length. + It needs to be adjusted to allocate + 4 bytes, + encode the last 4 bytes to a separate buffer and + then copy the necessary number of bytes to the end of the output */ + return NULL; + } + + estimated = (unsigned int)((buflen - 1) / 4 * 3); + intbuf = (char *) utils->malloc(estimated + 1); + if (intbuf == NULL) { + return NULL; + } + + utils->rand(utils->rpool, intbuf, estimated); + + /* base 64 encode it so it has valid chars */ + if (utils->encode64(intbuf, + estimated, + buffer, + (unsigned int)buflen, + NULL) != SASL_OK) { + utils->free(intbuf); + return NULL; + } + + utils->free(intbuf); + + buffer[buflen-1] = '\0'; + + return buffer; +} + +/* Useful for debugging interop issues */ +static void +print_hash (const char * func, const char * hash) +{ + int i; + + printf (" HASH in %s:", func); + for (i = 0; i < SCRAM_HASH_SIZE; i++) { + printf (" %.2X", (unsigned char)hash[i]); + } + printf ("\n"); +} + + +/* The result variable need to point to a buffer big enough for the [SHA-1] hash */ +static void +Hi (const sasl_utils_t * utils, + char * str, + size_t str_len, + char * salt, + size_t salt_len, + unsigned int iteration_count, + char * result) +{ + char * initial_key = NULL; + unsigned int i; + int k; + char * temp_result; + unsigned int hash_len = 0; + + initial_key = utils->malloc(salt_len + 4); + memcpy (initial_key, salt, salt_len); + initial_key[salt_len] = 0; + initial_key[salt_len+1] = 0; + initial_key[salt_len+2] = 0; + initial_key[salt_len+3] = 1; + + temp_result = utils->malloc(SCRAM_HASH_SIZE); + + /* U1 := HMAC(str, salt || INT(1)) */ + + if (HMAC(EVP_sha1(), + (const unsigned char *) str, + (int)str_len, + initial_key, + (int)salt_len + 4, + (unsigned char *)result, + &hash_len) == NULL) { + } + + memcpy(temp_result, result, SCRAM_HASH_SIZE); + + PRINT_HASH ("first HMAC in Hi()", temp_result); + + /* On each loop iteration j "temp_result" contains Uj, + while "result" contains "U1 XOR ... XOR Uj" */ + for (i = 2; i <= iteration_count; i++) { + if (HMAC(EVP_sha1(), + (const unsigned char *) str, + (int)str_len, + temp_result, + SCRAM_HASH_SIZE, + (unsigned char *)temp_result, + &hash_len) == NULL) { + } + + PRINT_HASH ("Hi() HMAC inside loop", temp_result); + + for (k = 0; k < SCRAM_HASH_SIZE; k++) { + result[k] ^= temp_result[k]; + } + + PRINT_HASH ("Hi() - accumulated result inside loop", result); + } + + utils->free(initial_key); + utils->free(temp_result); +} + +/** + * User salt is Hi(username,salt_key); + * This is fixed per reboot, to allow caching of SCRAM + * SaltedPassword. + */ +static unsigned char * +scram_server_user_salt(const sasl_utils_t * utils, + const char * username) +{ + char * result = utils->malloc(SCRAM_HASH_SIZE); + Hi(utils, username, strlen(username), g_salt_key, SALT_SIZE, 20, result); + return result; +} + +/***************************** Server Section *****************************/ + +typedef struct server_context { + int state; + + char * authentication_id; + char * authorization_id; + + char * out_buf; + char * auth_message; + size_t auth_message_len; + char * nonce; + /* in binary form */ + char * salt; + unsigned int iteration_count; +} server_context_t; + +static int +scram_server_mech_new(void *glob_context __attribute__((unused)), + sasl_server_params_t *sparams, + const char *challenge __attribute__((unused)), + unsigned challen __attribute__((unused)), + void **conn_context) +{ + server_context_t *text; + + /* holds state are in */ + text = sparams->utils->malloc(sizeof(server_context_t)); + if (text == NULL) { + MEMERROR( sparams->utils ); + return SASL_NOMEM; + } + + memset(text, 0, sizeof(server_context_t)); + /* text->state = 0; */ + + *conn_context = text; + + return SASL_OK; +} + +static int +scram_server_mech_step1(server_context_t *text, + sasl_server_params_t *sparams, + const char *clientin, + unsigned clientinlen, + const char **serverout, + unsigned *serveroutlen, + sasl_out_params_t *oparams __attribute__((unused))) +{ + char * authentication_id; + char * p; + char * nonce; + size_t client_nonce_len; + char * base64_salt = NULL; + size_t base64len; + size_t estimated_challenge_len; + size_t gs2_header_length = 0; + size_t pure_scram_length; + char * inbuf = NULL; + int result; + + if (clientinlen == 0) { + SETERROR(sparams->utils, "SCRAM-SHA-1 input expected"); + return SASL_BADPROT; + } + + /* Expecting: 'gs2-cbind-flag "," [ authzid ] "," [reserved-mext ","] + username "," nonce ["," extensions]' */ + + if (clientinlen < 10) { + SETERROR(sparams->utils, "Invalid SCRAM-SHA-1 input"); + return SASL_BADPROT; + } + + inbuf = sparams->utils->malloc (clientinlen + 1); + + if (inbuf == NULL) { + MEMERROR( sparams->utils ); + return SASL_NOMEM; + } + + memcpy(inbuf, clientin, clientinlen); + inbuf[clientinlen] = 0; + + if (strlen(inbuf) != clientinlen) { + SETERROR(sparams->utils, "NULs found in SCRAM-SHA-1 input"); + result = SASL_BADPROT; + goto cleanup; + } + + p = inbuf; + + /* gs2-cbind-flag = "p=" cb-name / "n" / "y" + ;; "n" -> client doesn't support channel binding + ;; "y" -> client does support channel binding + ;; but thinks the server does not. + ;; "p" -> client requires channel binding. + ;; The selected channel binding follows "p=". */ + switch (p[0]) { + case 'p': + if (clientin[1] != '=') { + SETERROR(sparams->utils, "The initial 'p' needs to be followed by '=' in SCRAM-SHA-1 input"); + result = SASL_BADPROT; + goto cleanup; + } + break; + + case 'n': + /* We always have at least 10 bytes, so this is safe */ + p++; + break; + + case 'y': + /* We always have at least 10 bytes, so this is safe */ + p++; + break; + + default: + SETERROR(sparams->utils, "The initial SCRAM-SHA-1 client response needs to start with 'y', 'n' or 'p'"); + result = SASL_BADPROT; + goto cleanup; + } + + if (p[0] != ',') { + SETERROR(sparams->utils, "',' expected in SCRAM-SHA-1 input"); + result = SASL_BADPROT; + goto cleanup; + } + p++; + + if (p[0] == 'a' && p[1] == '=') { + text->authorization_id = p + 2; + + p = strchr (text->authorization_id, ','); + if (p == NULL) { + text->authorization_id = NULL; + + SETERROR(sparams->utils, "At least nonce is expected in SCRAM-SHA-1 input"); + result = SASL_BADPROT; + goto cleanup; + } + + /* End of the GS2 header */ + p[0] = '\0'; + /* The GS2 header length DOES include the terminating comma */ + gs2_header_length = p - inbuf + 1; + + p++; + + /* Make a read-write copy we can modify */ + _plug_strdup(sparams->utils, text->authorization_id, &text->authorization_id, NULL); + + if (decode_saslname(text->authorization_id) != SASL_OK) { + SETERROR(sparams->utils, "Invalid authorization identity encoding in SCRAM-SHA-1 input"); + result = SASL_BADPROT; + goto cleanup; + } + } else if (p[0] != ',') { + SETERROR(sparams->utils, "',' expected in SCRAM-SHA-1 input"); + result = SASL_BADPROT; + goto cleanup; + } else { + /* End of the GS2 header */ + p[0] = '\0'; + /* The GS2 header length DOES include the terminating comma */ + gs2_header_length = p - inbuf + 1; + + p++; + } + + if (p[1] != '=') { + SETERROR(sparams->utils, "Invalid SCRAM-SHA-1 input"); + result = SASL_BADPROT; + goto cleanup; + } + + if (p[0] == 'm') { + SETERROR(sparams->utils, "Unsupported mandatory extension to SCRAM-SHA-1"); + result = SASL_BADPROT; + goto cleanup; + } + + if (p[0] != 'n') { + SETERROR(sparams->utils, "Username (n=) expected in SCRAM-SHA-1 input"); + result = SASL_BADPROT; + goto cleanup; + } + + authentication_id = p + 2; + p = strchr (authentication_id, ','); + + /* MUST be followed by a nonce */ + if (p == NULL) { + SETERROR(sparams->utils, "Nonce expected after the username in SCRAM-SHA-1 input"); + result = SASL_BADPROT; + goto cleanup; + } + + *p = '\0'; + p++; + + if (decode_saslname(authentication_id) != SASL_OK) { + SETERROR(sparams->utils, "Invalid username encoding in SCRAM-SHA-1 input"); + result = SASL_BADPROT; + goto cleanup; + } + + _plug_strdup(sparams->utils, authentication_id, &text->authentication_id, NULL); + + if (strncmp(p, "r=", 2) != 0) { + SETERROR(sparams->utils, "Nonce expected after the username in SCRAM-SHA-1 input"); + result = SASL_BADPROT; + goto cleanup; + } + + p += 2; + nonce = p; + p = strchr (nonce, ','); + + if (p == NULL) { + p = nonce + strlen(nonce); + } else { + *p = '\0'; + } + + /* Generate server nonce, by appending some random stuff to the client nonce */ + client_nonce_len = strlen(nonce); + text->nonce = sparams->utils->malloc (client_nonce_len + NONCE_SIZE + 1); + + if (text->nonce == NULL) { + MEMERROR( sparams->utils ); + result = SASL_NOMEM; + goto cleanup; + } + + strcpy (text->nonce, nonce); + + if (create_nonce(sparams->utils, + text->nonce + client_nonce_len, + NONCE_SIZE + 1) == NULL) { + MEMERROR( sparams->utils ); + result = SASL_NOMEM; + goto cleanup; + } + + /* NOTE: The following would change, if we start storing salt + and iteration_count in a SCRAM specific attribute */ + + text->salt = scram_server_user_salt(sparams->utils, text->authentication_id); + + text->iteration_count = DEFAULT_ITERATION_COUNTER; + + + + /* base 64 encode it so it has valid chars */ + base64len = (SALT_SIZE / 3 * 4) + ((SALT_SIZE % 3) ? 4 : 0); + + base64_salt = (char *) sparams->utils->malloc(base64len + 1); + if (base64_salt == NULL) { + MEMERROR( sparams->utils ); + result = SASL_NOMEM; + goto cleanup; + } + + /* + * Returns SASL_OK on success, SASL_BUFOVER if result won't fit + */ + if (sparams->utils->encode64(text->salt, + SALT_SIZE, + base64_salt, + (unsigned int)base64len + 1, + NULL) != SASL_OK) { + MEMERROR( sparams->utils ); + result = SASL_NOMEM; + goto cleanup; + } + + base64_salt[base64len] = '\0'; + + /* Now we generate server challenge */ + estimated_challenge_len = client_nonce_len + NONCE_SIZE + + base64len + + ITERATION_COUNTER_BUF_LEN + + strlen("r=,s=,i="); + text->out_buf = (char *) sparams->utils->malloc(estimated_challenge_len + 1); + if (text->out_buf == NULL) { + MEMERROR( sparams->utils ); + result = SASL_NOMEM; + goto cleanup; + } + + sprintf(text->out_buf, + "r=%s,s=%s,i=%u", + text->nonce, + base64_salt, + text->iteration_count); + + + /* Save the (client response, ",", server challenge, ","). + Note, we skip the GS2 prefix here */ + pure_scram_length = clientinlen - gs2_header_length; + text->auth_message_len = pure_scram_length + 1 + estimated_challenge_len + 1; + text->auth_message = sparams->utils->malloc (text->auth_message_len + 1); + if (text->auth_message == NULL) { + MEMERROR( sparams->utils ); + result = SASL_NOMEM; + goto cleanup; + } + + memcpy(text->auth_message, clientin + gs2_header_length, pure_scram_length); + text->auth_message[pure_scram_length] = ','; + strcpy (text->auth_message + pure_scram_length + 1, text->out_buf); + strcat (text->auth_message + pure_scram_length + 1, ","); + + /* Now remember the exact length, not the estimated one */ + text->auth_message_len = strlen(text->auth_message); + + *serverout = text->out_buf; + *serveroutlen = (unsigned) strlen(text->out_buf); + + result = SASL_CONTINUE; + text->state = 2; + +cleanup: + if (inbuf != NULL) { + sparams->utils->free(inbuf); + } + if (base64_salt != NULL) { + sparams->utils->free(base64_salt); + } + return result; +} + +static int +scram_server_mech_step2(server_context_t *text, + sasl_server_params_t *sparams, + const char *clientin, + unsigned clientinlen, + const char **serverout, + unsigned *serveroutlen, + sasl_out_params_t *oparams) +{ + char *channel_binding = NULL; + char *client_proof = NULL; + char *inbuf = NULL; + char *p; + int canon_flags; + sasl_secret_t *sec = NULL; + size_t len; + int result = SASL_FAIL; + const char *password_request[] = { SASL_AUX_PASSWORD, + NULL }; + struct propval auxprop_values[3]; + char StoredKey[SCRAM_HASH_SIZE]; + char ServerKey[SCRAM_HASH_SIZE]; + size_t proof_offset; + char * full_auth_message; + char ReceivedClientKey[SCRAM_HASH_SIZE]; + char DecodedClientProof[SCRAM_HASH_SIZE + 1]; + char CalculatedStoredKey[SCRAM_HASH_SIZE]; + char ClientSignature[SCRAM_HASH_SIZE]; + char ServerSignature[SCRAM_HASH_SIZE]; + char * nonce; + size_t client_proof_len; + size_t server_proof_len; + unsigned exact_client_proof_len; + int k; + unsigned int hash_len = 0; + + if (clientinlen == 0) { + SETERROR(sparams->utils, "SCRAM-SHA-1 input expected"); + return SASL_BADPROT; + } + + if (clientinlen < 3 || clientin[1] != '=') { + SETERROR(sparams->utils, "Invalid SCRAM-SHA-1 input"); + return SASL_BADPROT; + } + + inbuf = sparams->utils->malloc (clientinlen + 1); + + if (inbuf == NULL) { + MEMERROR( sparams->utils ); + return SASL_NOMEM; + } + + memcpy(inbuf, clientin, clientinlen); + inbuf[clientinlen] = 0; + + if (strlen(inbuf) != clientinlen) { + SETERROR(sparams->utils, "NULs found in SCRAM-SHA-1 input"); + result = SASL_BADPROT; + goto cleanup; + } + + /* Expecting: channel-binding "," nonce ["," extensions] "," proof */ + + p = inbuf; + + if (strncmp(p, "c=", 2) != 0) { + SETERROR(sparams->utils, "Channel binding expected in SCRAM-SHA-1 input"); + result = SASL_BADPROT; + goto cleanup; + } + + channel_binding = p + 2; + + p = strchr (channel_binding, ','); + if (p == NULL) { + SETERROR(sparams->utils, "At least nonce is expected in SCRAM-SHA-1 input"); + result = SASL_BADPROT; + goto cleanup; + } + *p = '\0'; + p++; + + if (strncmp(p, "r=", 2) != 0) { + SETERROR(sparams->utils, "Nonce expected in SCRAM-SHA-1 input"); + result = SASL_BADPROT; + goto cleanup; + } + + nonce = p + 2; + + p = strchr (nonce, ','); + if (p == NULL) { + SETERROR(sparams->utils, "At least proof is expected in SCRAM-SHA-1 input"); + result = SASL_BADPROT; + goto cleanup; + } + *p = '\0'; + p++; + + if (strcmp(nonce, text->nonce) != 0) { + SETERROR(sparams->utils, "Nonce mismatch SCRAM-SHA-1 input"); + result = SASL_BADPROT; + goto cleanup; + } + + while (p[0] != '\0') { + if (strncmp(p, "p=", 2) == 0) { + client_proof = p + 2; + proof_offset = p - inbuf - 1; + break; + } + + p = strchr (p, ','); + if (p == NULL) { + break; + } + p++; + } + + if (client_proof == NULL) { + SETERROR(sparams->utils, "Client proof is expected in SCRAM-SHA-1 input"); + result = SASL_BADPROT; + goto cleanup; + } + + /* Check that no extension data exists after the proof */ + p = strchr (client_proof, ','); + if (p != NULL) { + SETERROR(sparams->utils, "No extension data is allowed after the client proof in SCRAM-SHA-1 input"); + result = SASL_BADPROT; + goto cleanup; + } + + if (strlen(client_proof) != (SCRAM_HASH_SIZE / 3 * 4 + (SCRAM_HASH_SIZE % 3 ? 4 : 0))) { + SETERROR(sparams->utils, "Invalid client proof length in SCRAM-SHA-1 input"); + result = SASL_BADPROT; + goto cleanup; + } + + /* Now we fetch user's password and calculate our secret */ + result = sparams->utils->prop_request(sparams->propctx, password_request); + if (result != SASL_OK) { + goto cleanup; + } + + /* this will trigger the getting of the aux properties */ + canon_flags = SASL_CU_AUTHID; + if (text->authorization_id == NULL || *text->authorization_id == '\0') { + canon_flags |= SASL_CU_AUTHZID; + } + + result = sparams->canon_user(sparams->utils->conn, + text->authentication_id, + 0, + canon_flags, + oparams); + if (result != SASL_OK) { + SETERROR(sparams->utils, "unable to canonify user and get auxprops"); + goto cleanup; + } + + if (text->authorization_id != NULL && *text->authorization_id != '\0') { + result = sparams->canon_user(sparams->utils->conn, + text->authorization_id, + 0, + SASL_CU_AUTHZID, + oparams); + } + if (result != SASL_OK) { + SETERROR(sparams->utils, "unable to canonify authorization ID"); + goto cleanup; + } + + result = sparams->utils->prop_getnames(sparams->propctx, + password_request, + auxprop_values); + if (result < 0 || + ((!auxprop_values[0].name || !auxprop_values[0].values) && + (!auxprop_values[1].name || !auxprop_values[1].values))) { + /* We didn't find this username */ + sparams->utils->seterror(sparams->utils->conn,0, + "no secret in database"); + result = sparams->transition ? SASL_TRANS : SASL_NOUSER; + goto cleanup; + } + + if (auxprop_values[0].name && auxprop_values[0].values) { + char SaltedPassword[SCRAM_HASH_SIZE]; + char ClientKey[SCRAM_HASH_SIZE]; + + len = strlen(auxprop_values[0].values[0]); + if (len == 0) { + sparams->utils->seterror(sparams->utils->conn,0, + "empty secret"); + result = SASL_FAIL; + goto cleanup; + } + + sec = sparams->utils->malloc(sizeof(sasl_secret_t) + len); + if (sec == NULL) { + MEMERROR( sparams->utils ); + result = SASL_NOMEM; + goto cleanup; + } + + sec->len = (unsigned) len; + strncpy((char *)sec->data, auxprop_values[0].values[0], len + 1); + + /* SaltedPassword := Hi(password, salt) */ + Hi (sparams->utils, + sec->data, + sec->len, + text->salt, + SALT_SIZE, + text->iteration_count, + SaltedPassword); + + /* ClientKey := HMAC(SaltedPassword, "Client Key") */ + if (HMAC(EVP_sha1(), + (const unsigned char *) SaltedPassword, + SCRAM_HASH_SIZE, + CLIENT_KEY_CONSTANT, + CLIENT_KEY_CONSTANT_LEN, + (unsigned char *)ClientKey, + &hash_len) == NULL) { + sparams->utils->seterror(sparams->utils->conn,0, + "HMAC-SHA1 call failed"); + result = SASL_SCRAM_INTERNAL; + goto cleanup; + } + + /* StoredKey := H(ClientKey) */ + if (SHA1(ClientKey, SCRAM_HASH_SIZE, StoredKey) == NULL) { + sparams->utils->seterror(sparams->utils->conn,0, + "SHA1 call failed"); + result = SASL_SCRAM_INTERNAL; + goto cleanup; + + } + + /* ServerKey := HMAC(SaltedPassword, "Server Key") */ + if (HMAC(EVP_sha1(), + (const unsigned char *) SaltedPassword, + SCRAM_HASH_SIZE, + SERVER_KEY_CONSTANT, + SERVER_KEY_CONSTANT_LEN, + (unsigned char *)ServerKey, + &hash_len) == NULL) { + sparams->utils->seterror(sparams->utils->conn,0, + "HMAC-SHA1 call failed"); + result = SASL_SCRAM_INTERNAL; + goto cleanup; + } + +#ifdef NOT_YET + } else if (auxprop_values[1].name && auxprop_values[1].values) { + /* We have a precomputed secret */ + memcpy(&md5state, auxprop_values[1].values[0], + sizeof(HMAC_SHA1_STATE)); +#endif + } else { + sparams->utils->seterror(sparams->utils->conn, 0, + "Have neither type of secret"); + return SASL_FAIL; + } + + /* erase the plaintext password */ + sparams->utils->prop_erase(sparams->propctx, password_request[0]); + + + + /* Construct the full AuthMessage */ + full_auth_message = sparams->utils->realloc(text->auth_message, + text->auth_message_len + proof_offset + 1); + if (full_auth_message == NULL) { + MEMERROR( sparams->utils ); + result = SASL_NOMEM; + goto cleanup; + } + text->auth_message = full_auth_message; + + memcpy(text->auth_message + text->auth_message_len, clientin, proof_offset); + + text->auth_message_len += proof_offset; + text->auth_message[text->auth_message_len] = '\0'; + + + /* ClientSignature := HMAC(StoredKey, AuthMessage) */ + if (HMAC(EVP_sha1(), + (const unsigned char *) StoredKey, + SCRAM_HASH_SIZE, + text->auth_message, + (int)text->auth_message_len, + (unsigned char *)ClientSignature, + &hash_len) == NULL) { + sparams->utils->seterror(sparams->utils->conn,0, + "HMAC-SHA1 call failed"); + result = SASL_SCRAM_INTERNAL; + goto cleanup; + } + + client_proof_len = strlen(client_proof); + if (sparams->utils->decode64(client_proof, + (unsigned int)client_proof_len, + DecodedClientProof, + SCRAM_HASH_SIZE + 1, + &exact_client_proof_len) != SASL_OK) { + SETERROR(sparams->utils, "Invalid base64 encoding of the client proof in SCRAM-SHA-1 input"); + result = SASL_BADPROT; + goto cleanup; + } + + if (exact_client_proof_len != SCRAM_HASH_SIZE) { + SETERROR(sparams->utils, "Invalid client proof (truncated) in SCRAM-SHA-1 input"); + result = SASL_BADPROT; + goto cleanup; + } + + for (k = 0; k < SCRAM_HASH_SIZE; k++) { + ReceivedClientKey[k] = DecodedClientProof[k] ^ ClientSignature[k]; + } + + /* StoredKey := H(ClientKey) */ + if (SHA1(ReceivedClientKey, SCRAM_HASH_SIZE, CalculatedStoredKey) == NULL) { + sparams->utils->seterror(sparams->utils->conn,0, + "SHA1 call failed"); + result = SASL_SCRAM_INTERNAL; + goto cleanup; + } + + for (k = 0; k < SCRAM_HASH_SIZE; k++) { + if (CalculatedStoredKey[k] != StoredKey[k]) { + SETERROR(sparams->utils, "StoredKey mismatch"); + result = SASL_BADPROT; + goto cleanup; + } + } + + /* ServerSignature := HMAC(ServerKey, AuthMessage) */ + if (HMAC(EVP_sha1(), + (const unsigned char *) ServerKey, + SCRAM_HASH_SIZE, + text->auth_message, + (int)text->auth_message_len, + (unsigned char *)ServerSignature, + &hash_len) == NULL) { + sparams->utils->seterror(sparams->utils->conn,0, + "HMAC-SHA1 call failed"); + result = SASL_SCRAM_INTERNAL; + goto cleanup; + } + + server_proof_len = (SCRAM_HASH_SIZE / 3 * 4 + (SCRAM_HASH_SIZE % 3 ? 4 : 0)); + text->out_buf = (char *) sparams->utils->malloc(server_proof_len + strlen("v=") + 1); + if (text->out_buf == NULL) { + MEMERROR( sparams->utils ); + result = SASL_NOMEM; + goto cleanup; + } + + text->out_buf[0] = 'v'; + text->out_buf[1] = '='; + + + if (sparams->utils->encode64(ServerSignature, + SCRAM_HASH_SIZE, + text->out_buf+2, + (unsigned int)server_proof_len + 1, + NULL) != SASL_OK) { + SETERROR(sparams->utils, "Internal error"); + /* This is not quite right, but better than alternatives */ + result = SASL_NOMEM; + goto cleanup; + } + + text->out_buf[server_proof_len + 2] = '\0'; + + *serverout = text->out_buf; + *serveroutlen = (unsigned) strlen(text->out_buf); + + + /* set oparams */ + oparams->doneflag = 1; + oparams->mech_ssf = 0; + oparams->maxoutbuf = 0; + oparams->encode_context = NULL; + oparams->encode = NULL; + oparams->decode_context = NULL; + oparams->decode = NULL; + oparams->param_version = 0; + + result = SASL_OK; + +cleanup: + if (sec) _plug_free_secret(sparams->utils, &sec); + + return result; +} + +static int scram_server_mech_step(void *conn_context, + sasl_server_params_t *sparams, + const char *clientin, + unsigned clientinlen, + const char **serverout, + unsigned *serveroutlen, + sasl_out_params_t *oparams) +{ + server_context_t *text = (server_context_t *) conn_context; + + *serverout = NULL; + *serveroutlen = 0; + + if (text == NULL) { + return SASL_BADPROT; + } + + /* this should be well more than is ever needed */ + if (clientinlen > MAX_CLIENTIN_LEN) { + SETERROR(sparams->utils, "SCRAM-SHA-1 input longer than " STRINGIZE((MAX_CLIENTIN_LEN)) " bytes"); + return SASL_BADPROT; + } + + switch (text->state) { + case 0: + text->state++; + /* Assume the protocol doesn't support initial client response */ + if (clientinlen == 0) { + return SASL_CONTINUE; + } + /* fall through */ + + case 1: + return scram_server_mech_step1(text, + sparams, + clientin, + clientinlen, + serverout, + serveroutlen, + oparams); + + case 2: + text->state++; + return scram_server_mech_step2(text, + sparams, + clientin, + clientinlen, + serverout, + serveroutlen, + oparams); + + default: /* should never get here */ + sparams->utils->log(NULL, SASL_LOG_ERR, + "Invalid SCRAM-SHA-1 server step %d\n", text->state); + return SASL_FAIL; + } + + return SASL_FAIL; /* should never get here */ +} + +static void scram_server_mech_dispose(void *conn_context, + const sasl_utils_t *utils) +{ + server_context_t *text = (server_context_t *) conn_context; + + if (!text) return; + + if (text->authentication_id) _plug_free_string(utils,&(text->authentication_id)); + if (text->authorization_id) _plug_free_string(utils,&(text->authorization_id)); + if (text->out_buf) _plug_free_string(utils,&(text->out_buf)); + if (text->auth_message) _plug_free_string(utils,&(text->auth_message)); + if (text->nonce) _plug_free_string(utils,&(text->nonce)); + if (text->salt) utils->free(text->salt); + + utils->free(text); +} + +static sasl_server_plug_t scram_server_plugins[] = +{ + { + "SCRAM-SHA-1", /* mech_name */ + 0, /* max_ssf */ + SASL_SEC_NOPLAINTEXT + | SASL_SEC_NOACTIVE + | SASL_SEC_NOANONYMOUS + | SASL_SEC_MUTUAL_AUTH, /* security_flags */ + SASL_FEAT_ALLOWS_PROXY, /* features */ + NULL, /* glob_context */ + &scram_server_mech_new, /* mech_new */ + &scram_server_mech_step, /* mech_step */ + &scram_server_mech_dispose, /* mech_dispose */ + NULL, /* mech_free */ + NULL, /* setpass */ + NULL, /* user_query */ + NULL, /* idle */ + NULL, /* mech avail */ + NULL /* spare */ + } +}; + +int scram_server_plug_init(const sasl_utils_t *utils, + int maxversion, + int *out_version, + sasl_server_plug_t **pluglist, + int *plugcount) +{ + if (maxversion < SASL_SERVER_PLUG_VERSION) { + SETERROR( utils, "SCRAM version mismatch"); + return SASL_BADVERS; + } + + *out_version = SASL_SERVER_PLUG_VERSION; + *pluglist = scram_server_plugins; + *plugcount = 1; + utils->rand(utils->rpool, (char *)g_salt_key, SALT_SIZE); + + return SASL_OK; +} + +/***************************** Client Section *****************************/ + +typedef struct client_context { + int state; + + sasl_secret_t *password; /* user password */ + unsigned int free_password; /* set if we need to free the password */ + + char * gs2_header; + size_t gs2_header_length; + char * out_buf; + unsigned out_buf_len; + char * auth_message; + size_t auth_message_len; + char * nonce; + /* in binary form */ + char * salt; + size_t salt_len; + unsigned int iteration_count; + char SaltedPassword[SCRAM_HASH_SIZE]; +} client_context_t; + +static int scram_client_mech_new(void *glob_context __attribute__((unused)), + sasl_client_params_t *params, + void **conn_context) +{ + client_context_t *text; + + /* holds state are in */ + text = params->utils->malloc(sizeof(client_context_t)); + if (text == NULL) { + MEMERROR(params->utils); + return SASL_NOMEM; + } + + memset(text, 0, sizeof(client_context_t)); + + *conn_context = text; + + return SASL_OK; +} + +static int +scram_client_mech_step1(client_context_t *text, + sasl_client_params_t *params, + const char *serverin __attribute__((unused)), + unsigned serverinlen __attribute__((unused)), + sasl_interact_t **prompt_need, + const char **clientout, + unsigned *clientoutlen, + sasl_out_params_t *oparams) +{ + const char *authid = NULL; + const char *userid = NULL; + int user_result = SASL_OK; + int auth_result = SASL_OK; + int pass_result = SASL_OK; + int result; + size_t maxsize; + char * encoded_authcid; + char * freeme = NULL; + char * freeme2 = NULL; + char channel_binding_state = 'n'; + char * channel_binding_name = NULL; + char * encoded_authorization_id = NULL; + + /* check if sec layer strong enough */ + if (params->props.min_ssf > params->external_ssf) { + SETERROR( params->utils, "SSF requested of SCRAM-SHA-1 plugin"); + return SASL_TOOWEAK; + } + + /* try to get the userid */ + if (oparams->authid == NULL) { + auth_result=_plug_get_authid(params->utils, &authid, prompt_need); + + if ((auth_result != SASL_OK) && (auth_result != SASL_INTERACT)) + return auth_result; + } + + /* try to get the userid */ + if (oparams->user == NULL) { + user_result = _plug_get_userid(params->utils, &userid, prompt_need); + + if ((user_result != SASL_OK) && (user_result != SASL_INTERACT)) { + return user_result; + } + } + + /* try to get the password */ + if (text->password == NULL) { + pass_result = _plug_get_password(params->utils, + &text->password, + &text->free_password, + prompt_need); + if ((pass_result != SASL_OK) && (pass_result != SASL_INTERACT)) { + return pass_result; + } + } + + /* free prompts we got */ + if (prompt_need && *prompt_need) { + params->utils->free(*prompt_need); + *prompt_need = NULL; + } + + /* if there are prompts not filled in */ + if ((auth_result == SASL_INTERACT) || + (user_result == SASL_INTERACT) || + (pass_result == SASL_INTERACT)) { + /* make the prompt list */ + result = + _plug_make_prompts(params->utils, + prompt_need, + user_result == SASL_INTERACT ? + "Please enter your authorization name" : NULL, + NULL, + auth_result == SASL_INTERACT ? + "Please enter your authentication name" : NULL, + NULL, + pass_result == SASL_INTERACT ? + "Please enter your password" : NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL); + + if (result != SASL_OK) { + goto cleanup; + } + + return SASL_INTERACT; + } + + if (!text->password) { + PARAMERROR(params->utils); + return SASL_BADPARAM; + } + + if (oparams->authid == NULL) { + if (!userid || !*userid) { + result = params->canon_user(params->utils->conn, + authid, + 0, + SASL_CU_AUTHID | SASL_CU_AUTHZID, + oparams); + } + else { + result = params->canon_user(params->utils->conn, + authid, + 0, + SASL_CU_AUTHID, + oparams); + if (result != SASL_OK) { + goto cleanup; + } + + result = params->canon_user(params->utils->conn, + userid, + 0, + SASL_CU_AUTHZID, + oparams); + } + if (result != SASL_OK) { + goto cleanup; + } + } + + text->nonce = params->utils->malloc (NONCE_SIZE + 1); + + if (text->nonce == NULL) { + MEMERROR( params->utils ); + result = SASL_NOMEM; + goto cleanup; + } + + if (create_nonce(params->utils, + text->nonce, + NONCE_SIZE + 1) == NULL) { + MEMERROR( params->utils ); + result = SASL_NOMEM; + goto cleanup; + } + + if (userid != NULL && *userid != '\0') { + result = encode_saslname (oparams->user, + &encoded_authorization_id, + &freeme2); + + if (result != SASL_OK) { + MEMERROR( params->utils ); + result = SASL_NOMEM; + goto cleanup; + } + } + + result = encode_saslname (oparams->authid, + &encoded_authcid, + &freeme); + if (result != SASL_OK) { + MEMERROR( params->utils ); + result = SASL_NOMEM; + goto cleanup; + } + + maxsize = strlen("p=,a=,n=,r=") + + ((channel_binding_name != NULL) ? strlen(channel_binding_name) : 0) + + ((encoded_authorization_id != NULL) ? strlen(encoded_authorization_id) : 0) + + strlen(encoded_authcid) + + strlen(text->nonce); + result = _plug_buf_alloc(params->utils, + &(text->out_buf), + &(text->out_buf_len), + (unsigned) maxsize + 1); + if (result != SASL_OK) { + MEMERROR( params->utils ); + result = SASL_NOMEM; + goto cleanup; + } + + snprintf(text->out_buf, + maxsize + 1, + "%c%s%s,%s%s,", + channel_binding_state, + (channel_binding_name != NULL) ? "=" : "", + (channel_binding_name != NULL) ? channel_binding_name : "", + (encoded_authorization_id != NULL) ? "a=" : "", + (encoded_authorization_id != NULL) ? encoded_authorization_id : ""); + + text->gs2_header_length = strlen(text->out_buf); + _plug_strdup(params->utils, text->out_buf, &text->gs2_header, NULL); + + snprintf(text->out_buf + text->gs2_header_length, + maxsize + 1, + "n=%s,r=%s", + encoded_authcid, + text->nonce); + + + /* Save the copy of the client-first-message */ + + /* Need to skip the GS2 prefix here */ + _plug_strdup(params->utils, + text->out_buf + text->gs2_header_length, + &text->auth_message, + NULL); + if (text->auth_message == NULL) { + MEMERROR( params->utils ); + result = SASL_NOMEM; + goto cleanup; + } + + text->auth_message_len = strlen(text->auth_message); + + *clientout = text->out_buf; + *clientoutlen = (unsigned) strlen(*clientout); + + result = SASL_CONTINUE; + +cleanup: + if (freeme != NULL) _plug_free_string(params->utils, &freeme); + if (freeme2 != NULL) _plug_free_string(params->utils, &freeme2); + + return result; +} + +static int +scram_client_mech_step2(client_context_t *text, + sasl_client_params_t *params, + const char *serverin, + unsigned serverinlen, + sasl_interact_t **prompt_need __attribute__((unused)), + const char **clientout, + unsigned *clientoutlen, + sasl_out_params_t *oparams __attribute__((unused))) +{ + char * p; + char * nonce; + size_t server_nonce_len; + char * base64_salt = NULL; + size_t base64_salt_len; + unsigned exact_salt_len; + char * counter; + char * end; + char * inbuf = NULL; + size_t estimated_response_len; + size_t length_no_proof; + char * full_auth_message; + size_t cb_bin_length; + size_t cb_encoded_length; + char * channel_binding_data = NULL; + char * cb_encoded = NULL; + int result; + char ClientKey[SCRAM_HASH_SIZE]; + char StoredKey[SCRAM_HASH_SIZE]; + char ClientSignature[SCRAM_HASH_SIZE]; + char ClientProof[SCRAM_HASH_SIZE]; + char * client_proof = NULL; + size_t client_proof_len; + int k; + unsigned int hash_len = 0; + + if (serverinlen == 0) { + SETERROR(params->utils, "SCRAM-SHA-1 input expected"); + return SASL_BADPROT; + } + + /* [reserved-mext ","] nonce "," salt "," iteration-count ["," extensions] */ + + if (serverinlen < 3 || serverin[1] != '=') { + SETERROR(params->utils, "Invalid SCRAM-SHA-1 input"); + return SASL_BADPROT; + } + + if (serverin[0] == 'm') { + SETERROR(params->utils, "Unsupported mandatory extension to SCRAM-SHA-1"); + return SASL_BADPROT; + } + + if (serverin[0] != 'r') { + SETERROR(params->utils, "Nonce (r=) expected in SCRAM-SHA-1 input"); + return SASL_BADPROT; + } + + inbuf = params->utils->malloc (serverinlen + 1); + if (inbuf == NULL) { + MEMERROR( params->utils ); + return SASL_NOMEM; + } + + memcpy(inbuf, serverin, serverinlen); + inbuf[serverinlen] = 0; + + if (strlen(inbuf) != serverinlen) { + SETERROR(params->utils, "NULs found in SCRAM-SHA-1 input"); + result = SASL_BADPROT; + goto cleanup; + } + + nonce = inbuf + 2; + p = strchr (nonce, ','); + + /* MUST be followed by a salt */ + if (p == NULL) { + SETERROR(params->utils, "Salt expected after the nonce in SCRAM-SHA-1 input"); + result = SASL_BADPROT; + goto cleanup; + } + + *p = '\0'; + p++; + + if (strncmp(p, "s=", 2) != 0) { + SETERROR(params->utils, "Salt expected after the nonce in SCRAM-SHA-1 input"); + result = SASL_BADPROT; + goto cleanup; + } + + p += 2; + base64_salt = p; + + p = strchr (base64_salt, ','); + + /* MUST be followed by an iteration-count */ + if (p == NULL) { + SETERROR(params->utils, "iteration-count expected after the salt in SCRAM-SHA-1 input"); + result = SASL_BADPROT; + goto cleanup; + } + + *p = '\0'; + p++; + + if (strncmp(p, "i=", 2) != 0) { + SETERROR(params->utils, "iteration-count expected after the salt in SCRAM-SHA-1 input"); + result = SASL_BADPROT; + goto cleanup; + } + + p += 2; + counter = p; + p = strchr (counter, ','); + + if (p == NULL) { + p = counter + strlen(counter); + } else { + *p = '\0'; + } + + errno = 0; + text->iteration_count = strtoul(counter, &end, 10); + if (counter == end || *end != '\0' || errno != 0) { + SETERROR(params->utils, "Invalid iteration-count in SCRAM-SHA-1 input"); + result = SASL_BADPROT; + goto cleanup; + } + + if (text->iteration_count < MIN_ITERATION_COUNTER) { + } + + if (text->iteration_count > MAX_ITERATION_COUNTER) { + SETERROR(params->utils, "iteration-count is too big, refusing to compute"); + result = SASL_BADPROT; + goto cleanup; + } + + /* The client MUST verify that the initial part of the nonce + used in subsequent messages is the same as the nonce it + initially specified. */ + server_nonce_len = strlen(nonce); + + if (server_nonce_len <= NONCE_SIZE || + strncmp(nonce, text->nonce, NONCE_SIZE) != 0) { + SETERROR(params->utils, "The nonce received from the server doesn't start from the nonce sent by the client"); + result = SASL_BADPROT; + goto cleanup; + } + + /* Now we can forget about our nonce */ + params->utils->free(text->nonce); + + _plug_strdup(params->utils, nonce, &text->nonce, NULL); + + if (text->nonce == NULL) { + MEMERROR( params->utils ); + result = SASL_NOMEM; + goto cleanup; + } + + /* base64 decode salt */ + base64_salt_len = strlen(base64_salt); + + if (base64_salt_len == 0) { + SETERROR(params->utils, "The salt can't be empty"); + result = SASL_BADPROT; + goto cleanup; + } + + if (base64_salt_len % 4 != 0) { + SETERROR(params->utils, "Invalid base64 encoding of the salt"); + result = SASL_BADPROT; + goto cleanup; + } + + text->salt_len = base64_salt_len / 4 * 3; + + text->salt = (char *) params->utils->malloc(text->salt_len + 1); + if (text->salt == NULL) { + MEMERROR( params->utils ); + result = SASL_NOMEM; + goto cleanup; + } + + if (params->utils->decode64(base64_salt, + (unsigned int)base64_salt_len, + text->salt, + (unsigned int)text->salt_len + 1, + &exact_salt_len) != SASL_OK) { + SETERROR(params->utils, "Invalid base64 encoding of the salt in SCRAM-SHA-1 input"); + result = SASL_BADPROT; + goto cleanup; + } + + text->salt_len = exact_salt_len; + + /* Now we generate client response */ + + if (text->gs2_header[0] == 'p') { + } + + cb_bin_length = text->gs2_header_length + + ((channel_binding_data != NULL) ? strlen(channel_binding_data) : 0); + cb_encoded_length = (cb_bin_length / 3 * 4) + ((cb_bin_length % 3) ? 4 : 0); + + cb_encoded = (char *) params->utils->malloc(cb_encoded_length + 1); + if (cb_encoded == NULL) { + MEMERROR( params->utils ); + result = SASL_NOMEM; + goto cleanup; + } + + /* + * Returns SASL_OK on success, SASL_BUFOVER if result won't fit + */ + if (params->utils->encode64( + text->gs2_header, + (unsigned int)cb_bin_length, + cb_encoded, + (unsigned int)cb_encoded_length + 1, + NULL) != SASL_OK) { + MEMERROR( params->utils ); + result = SASL_NOMEM; + goto cleanup; + } + + cb_encoded[cb_encoded_length] = '\0'; + + client_proof_len = SCRAM_HASH_SIZE / 3 * 4 + ((SCRAM_HASH_SIZE % 3) ? 4 : 0); + estimated_response_len = strlen(cb_encoded)+ + strlen(text->nonce)+ + client_proof_len + + strlen("c=,r=,p="); + text->out_buf = (char *) params->utils->malloc(estimated_response_len + 1); + if (text->out_buf == NULL) { + MEMERROR( params->utils ); + result = SASL_NOMEM; + goto cleanup; + } + + /* channel-binding "," nonce ["," extensions] */ + sprintf(text->out_buf, + "c=%s,r=%s", + cb_encoded, + text->nonce); + + length_no_proof = strlen(text->out_buf); + + /* Build AuthMessage */ + full_auth_message = params->utils->realloc(text->auth_message, + text->auth_message_len + 1 + + serverinlen + 1 + + length_no_proof + 1); + if (full_auth_message == NULL) { + MEMERROR( params->utils ); + result = SASL_NOMEM; + goto cleanup; + } + + text->auth_message = full_auth_message; + + text->auth_message[text->auth_message_len] = ','; + memcpy(text->auth_message + text->auth_message_len + 1, serverin, serverinlen); + text->auth_message[text->auth_message_len + 1 + serverinlen] = ','; + memcpy(text->auth_message + text->auth_message_len + 1 + serverinlen + 1, + text->out_buf, + length_no_proof); + text->auth_message_len += serverinlen + 2 + length_no_proof; + text->auth_message[text->auth_message_len] = '\0'; + + /* Calculate ClientProof */ + + /* SaltedPassword := Hi(password, salt) */ + Hi (params->utils, + text->password->data, + text->password->len, + text->salt, + text->salt_len, + text->iteration_count, + text->SaltedPassword); + + PRINT_HASH ("SaltedPassword", text->SaltedPassword); + + /* ClientKey := HMAC(SaltedPassword, "Client Key") */ + if (HMAC(EVP_sha1(), + (const unsigned char *) text->SaltedPassword, + SCRAM_HASH_SIZE, + CLIENT_KEY_CONSTANT, + CLIENT_KEY_CONSTANT_LEN, + (unsigned char *)ClientKey, + &hash_len) == NULL) { + params->utils->seterror(params->utils->conn,0, + "HMAC-SHA1 call failed"); + result = SASL_SCRAM_INTERNAL; + goto cleanup; + } + + PRINT_HASH ("ClientKey", ClientKey); + + /* StoredKey := H(ClientKey) */ + if (SHA1(ClientKey, SCRAM_HASH_SIZE, StoredKey) == NULL) { + params->utils->seterror(params->utils->conn,0, + "SHA1 call failed"); + result = SASL_SCRAM_INTERNAL; + goto cleanup; + } + + PRINT_HASH ("StoredKey", StoredKey); + + /* ClientSignature := HMAC(StoredKey, AuthMessage) */ + if (HMAC(EVP_sha1(), + (const unsigned char *)StoredKey, + SCRAM_HASH_SIZE, + text->auth_message, + (int)text->auth_message_len, + (unsigned char *)ClientSignature, + &hash_len) == NULL) { + params->utils->seterror(params->utils->conn,0, + "HMAC-SHA1 call failed"); + result = SASL_SCRAM_INTERNAL; + goto cleanup; + } + + PRINT_HASH ("ClientSignature", ClientSignature); + + /* ClientProof := ClientKey XOR ClientSignature */ + for (k = 0; k < SCRAM_HASH_SIZE; k++) { + ClientProof[k] = ClientKey[k] ^ ClientSignature[k]; + } + + PRINT_HASH ("ClientProof", ClientProof); + + /* base64-encode ClientProof */ + client_proof = (char *) params->utils->malloc(client_proof_len + 1); + if (client_proof == NULL) { + MEMERROR( params->utils ); + result = SASL_NOMEM; + goto cleanup; + } + + result = params->utils->encode64(ClientProof, + SCRAM_HASH_SIZE, + client_proof, + (unsigned int)client_proof_len + 1, + NULL); + + if (result != SASL_OK) { + goto cleanup; + } + + client_proof[client_proof_len] = '\0'; + + sprintf(text->out_buf + length_no_proof, + ",p=%s", + client_proof); + + *clientout = text->out_buf; + *clientoutlen = (unsigned) strlen(text->out_buf); + + result = SASL_CONTINUE; + +cleanup: + if (inbuf != NULL) { + params->utils->free(inbuf); + } + + if (client_proof != NULL) { + params->utils->free(client_proof); + } + + if (cb_encoded != NULL) { + params->utils->free(cb_encoded); + } + + return result; +} + + +static int +scram_client_mech_step3(client_context_t *text, + sasl_client_params_t *params, + const char *serverin, + unsigned serverinlen, + sasl_interact_t **prompt_need __attribute__((unused)), + const char **clientout __attribute__((unused)), + unsigned *clientoutlen __attribute__((unused)), + sasl_out_params_t *oparams) +{ + char * p; + int result; + size_t server_proof_len; + unsigned exact_server_proof_len; + char DecodedServerProof[SCRAM_HASH_SIZE + 1]; + char ServerKey[SCRAM_HASH_SIZE]; + char ServerSignature[SCRAM_HASH_SIZE]; + int k; + unsigned int hash_len = 0; + + if (serverinlen < 3) { + SETERROR(params->utils, "Invalid SCRAM-SHA-1 input expected"); + return SASL_BADPROT; + } + + /* Expecting: 'verifier ["," extensions]' */ + + if (strncmp(serverin, "v=", 2) != 0) { + SETERROR(params->utils, "ServerSignature expected in SCRAM-SHA-1 input"); + return SASL_BADPROT; + } + + p = strchr (serverin + 2, ','); + if (p != NULL) { + server_proof_len = p - (serverin + 2) - 1; + } else { + server_proof_len = serverinlen - 2; + } + + if (params->utils->decode64(serverin + 2, /* ServerProof */ + (unsigned int)server_proof_len, + DecodedServerProof, + SCRAM_HASH_SIZE + 1, + &exact_server_proof_len) != SASL_OK) { + SETERROR(params->utils, "Invalid base64 encoding of the server proof in SCRAM-SHA-1 input"); + result = SASL_BADPROT; + goto cleanup; + } + + if (exact_server_proof_len != SCRAM_HASH_SIZE) { + SETERROR(params->utils, "Invalid server proof (truncated) in SCRAM-SHA-1 input"); + result = SASL_BADPROT; + goto cleanup; + } + + /* ServerKey := HMAC(SaltedPassword, "Server Key") */ + if (HMAC(EVP_sha1(), + (const unsigned char *)text->SaltedPassword, + SCRAM_HASH_SIZE, + SERVER_KEY_CONSTANT, + SERVER_KEY_CONSTANT_LEN, + (unsigned char *)ServerKey, + &hash_len) == NULL) { + params->utils->seterror(params->utils->conn,0, + "HMAC-SHA1 call failed"); + result = SASL_SCRAM_INTERNAL; + goto cleanup; + } + + /* ServerSignature := HMAC(ServerKey, AuthMessage) */ + if (HMAC(EVP_sha1(), + (const unsigned char *)ServerKey, + SCRAM_HASH_SIZE, + text->auth_message, + (int)text->auth_message_len, + (unsigned char *)ServerSignature, + &hash_len) == NULL) { + params->utils->seterror(params->utils->conn,0, + "HMAC-SHA1 call failed"); + result = SASL_SCRAM_INTERNAL; + goto cleanup; + } + + for (k = 0; k < SCRAM_HASH_SIZE; k++) { + if (DecodedServerProof[k] != ServerSignature[k]) { + SETERROR(params->utils, "ServerSignature mismatch"); + result = SASL_BADAUTH; + goto cleanup; + } + } + + /* set oparams */ + oparams->doneflag = 1; + oparams->mech_ssf = 0; + oparams->maxoutbuf = 0; + oparams->encode_context = NULL; + oparams->encode = NULL; + oparams->decode_context = NULL; + oparams->decode = NULL; + oparams->param_version = 0; + + result = SASL_OK; + +cleanup: + return result; +} + +static int scram_client_mech_step(void *conn_context, + sasl_client_params_t *params, + const char *serverin, + unsigned serverinlen, + sasl_interact_t **prompt_need, + const char **clientout, + unsigned *clientoutlen, + sasl_out_params_t *oparams) +{ + int result = SASL_FAIL; + client_context_t *text = (client_context_t *) conn_context; + + *clientout = NULL; + *clientoutlen = 0; + + /* this should be well more than is ever needed */ + if (serverinlen > MAX_SERVERIN_LEN) { + SETERROR(params->utils, "SCRAM-SHA-1 input longer than " STRINGIZE((MAX_SERVERIN_LEN)) " bytes"); + return SASL_BADPROT; + } + + switch (text->state) { + case 0: + result = scram_client_mech_step1(text, + params, + serverin, + serverinlen, + prompt_need, + clientout, + clientoutlen, + oparams); + break; + + case 1: + result = scram_client_mech_step2(text, + params, + serverin, + serverinlen, + prompt_need, + clientout, + clientoutlen, + oparams); + break; + + case 2: + result = scram_client_mech_step3(text, + params, + serverin, + serverinlen, + prompt_need, + clientout, + clientoutlen, + oparams); + break; + + default: /* should never get here */ + params->utils->log(NULL, SASL_LOG_ERR, + "Invalid SCRAM-SHA-1 client step %d\n", text->state); + return SASL_FAIL; + } + + if (result != SASL_INTERACT) { + text->state++; + } + return result; +} + +static void scram_client_mech_dispose(void *conn_context, + const sasl_utils_t *utils) +{ + client_context_t *text = (client_context_t *) conn_context; + + if (!text) return; + + /* get rid of all sensitive info */ + if (text->free_password) { + _plug_free_secret(utils, &text->password); + text->free_password = 0; + } + + if (text->gs2_header) { + utils->free(text->gs2_header); + text->gs2_header = NULL; + } + + if (text->out_buf) { + utils->free(text->out_buf); + text->out_buf = NULL; + } + + if (text->auth_message) _plug_free_string(utils,&(text->auth_message)); + if (text->nonce) _plug_free_string(utils,&(text->nonce)); + if (text->salt) utils->free(text->salt); + + utils->free(text); +} + +static sasl_client_plug_t scram_client_plugins[] = +{ + { + "SCRAM-SHA-1", /* mech_name */ + 0, /* max_ssf */ + SASL_SEC_NOPLAINTEXT + | SASL_SEC_NOANONYMOUS + | SASL_SEC_NOACTIVE + | SASL_SEC_MUTUAL_AUTH, /* security_flags */ + SASL_FEAT_ALLOWS_PROXY, /* features */ + NULL, /* required_prompts */ + NULL, /* glob_context */ + &scram_client_mech_new, /* mech_new */ + &scram_client_mech_step, /* mech_step */ + &scram_client_mech_dispose, /* mech_dispose */ + NULL, /* mech_free */ + NULL, /* idle */ + NULL, /* spare */ + NULL /* spare */ + } +}; + +int scram_client_plug_init(const sasl_utils_t *utils, + int maxversion, + int *out_version, + sasl_client_plug_t **pluglist, + int *plugcount) +{ + if (maxversion < SASL_CLIENT_PLUG_VERSION) { + SETERROR( utils, "SCRAM version mismatch"); + return SASL_BADVERS; + } + + *out_version = SASL_CLIENT_PLUG_VERSION; + *pluglist = scram_client_plugins; + *plugcount = 1; + + return SASL_OK; +} From ed8a44c36ef1d89f2341100b05495d28d6e89fef Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Tue, 26 Oct 2010 11:08:02 +0000 Subject: [PATCH 033/796] Fixed a typo that prevented the code from compiling --- plugins/gssapi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/gssapi.c b/plugins/gssapi.c index b501410c..c555a196 100644 --- a/plugins/gssapi.c +++ b/plugins/gssapi.c @@ -1,7 +1,7 @@ /* GSSAPI SASL plugin * Leif Johansson * Rob Siemborski (SASL v2 Conversion) - * $Id: gssapi.c,v 1.110 2010/05/12 21:28:19 mel Exp $ + * $Id: gssapi.c,v 1.111 2010/10/26 11:08:02 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -82,7 +82,7 @@ /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: gssapi.c,v 1.110 2010/05/12 21:28:19 mel Exp $"; +static const char plugin_id[] = "$Id: gssapi.c,v 1.111 2010/10/26 11:08:02 mel Exp $"; static const char * GSSAPI_BLANK_STRING = ""; @@ -736,7 +736,7 @@ gssapi_server_mech_step(void *conn_context, sasl_gss_free_context_contents(text); return SASL_FAIL; } - server_creds = text->server-creds; + server_creds = text->server_creds; } } From 9d8c7182d9dc8f448873f33a2ee6aa59b3552310 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Tue, 16 Nov 2010 15:12:10 +0000 Subject: [PATCH 034/796] Updated/fixed dependencies for .c files --- lib/NTMakefile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/NTMakefile b/lib/NTMakefile index 7a857639..14d485a1 100755 --- a/lib/NTMakefile +++ b/lib/NTMakefile @@ -58,9 +58,11 @@ plugin_common.c: ..\plugins\plugin_common.c plugin_common.h plugin_common.h: ..\plugins\plugin_common.h copy ..\plugins\plugin_common.h . -auxprop.c checkpw.c client.c common.c external.c plugin_common.c server.c seterror.c: ..\include\saslplug.h +auxprop.obj checkpw.obj client.obj common.obj external.obj plugin_common.obj server.obj seterror.obj: ..\include\saslplug.h -auxprop.c canonusr.c checkpw.c client.c common.c config.c external.c getsubopt.c md5.c plugin_common.c server.c seterror.c windlopen.c: ..\include\sasl.h +auxprop.obj canonusr.obj checkpw.obj client.obj common.obj config.obj external.obj getsubopt.obj md5.obj plugin_common.obj server.obj seterror.obj windlopen.obj: ..\include\sasl.h ..\include\prop.h + +auxprop.obj canonusr.obj checkpw.obj client.obj common.obj config.obj dlopen.obj external.obj saslutil.obj server.obj seterror.obj windlopen.obj: saslint.h CLEAN : -@erase $(all_objs) From f3af629eaf4f4ffd153fb34f003d6b92082aeafa Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Tue, 30 Nov 2010 11:34:17 +0000 Subject: [PATCH 035/796] Fixed an interop problem with some LDAP clients ignoring server advertised realm and providing their own --- plugins/digestmd5.c | 56 +++++++++++++++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 14 deletions(-) diff --git a/plugins/digestmd5.c b/plugins/digestmd5.c index 53b2dd14..c34e3d5d 100644 --- a/plugins/digestmd5.c +++ b/plugins/digestmd5.c @@ -3,7 +3,7 @@ * Rob Siemborski * Tim Martin * Alexey Melnikov - * $Id: digestmd5.c,v 1.190 2009/02/20 22:55:58 mel Exp $ + * $Id: digestmd5.c,v 1.191 2010/11/30 11:34:17 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -122,7 +122,7 @@ extern int gethostname(char *, int); /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: digestmd5.c,v 1.190 2009/02/20 22:55:58 mel Exp $"; +static const char plugin_id[] = "$Id: digestmd5.c,v 1.191 2010/11/30 11:34:17 mel Exp $"; /* Definitions */ #define NONCE_SIZE (32) /* arbitrary */ @@ -2098,7 +2098,10 @@ static int digestmd5_server_mech_step2(server_context_t *stext, unsigned int n = 0; HASH Secret; - + int client_ignores_realm = 0; + char *full_username = NULL; + char *internal_username = NULL; + /* password prop_request */ const char *password_request[] = { SASL_AUX_PASSWORD, "*cmusaslsecretDIGEST-MD5", @@ -2344,12 +2347,20 @@ static int digestmd5_server_mech_step2(server_context_t *stext, } /* CLAIM: realm is not NULL below */ + } else if (text->realm == NULL) { + sparams->utils->log(sparams->utils->conn, SASL_LOG_DEBUG, + "The client specifies a realm when the server hasn't provided one. Using client's realm."); + _plug_strdup(sparams->utils, realm, &text->realm, NULL); } else if ((strcmp(realm, text->realm) != 0) && - (text->realm[0] != 0)) { - SETERROR(sparams->utils, - "realm changed: authentication aborted"); - result = SASL_BADAUTH; - goto FreeAllMem; + /* XXX - Not sure why the check for text->realm not being empty is needed, + as it should always be non-empty */ + (text->realm[0] != 0)) { + + client_ignores_realm = 1; + sparams->utils->log(sparams->utils->conn, SASL_LOG_DEBUG, + "The client tries to override server provided realm"); + if (text->realm) sparams->utils->free(text->realm); + _plug_strdup(sparams->utils, realm, &text->realm, NULL); } if (strcmp((char *) nonce, (char *) text->nonce) != 0) { SETERROR(sparams->utils, @@ -2378,24 +2389,38 @@ static int digestmd5_server_mech_step2(server_context_t *stext, /* this will trigger the getting of the aux properties */ /* Note that if we don't have an authorization id, we don't use it... */ + + if (client_ignores_realm) { + if (strlen(text->realm) == 0) { + /* Don't put @ at the end of the username, if the realm is empty */ + _plug_strdup(sparams->utils, username, &full_username, NULL); + } else { + full_username = (char *) sparams->utils->malloc(strlen(username) + + strlen(text->realm) + 2); + full_username[0] = '\0'; + sprintf (full_username, "%s@%s", username, text->realm); + } + internal_username = full_username; + } else { + internal_username = username; + } result = sparams->canon_user(sparams->utils->conn, - username, 0, SASL_CU_AUTHID, oparams); + internal_username, 0, SASL_CU_AUTHID, oparams); if (result != SASL_OK) { - SETERROR(sparams->utils, "unable canonify user and get auxprops"); + SETERROR(sparams->utils, "unable to canonify user and get auxprops"); goto FreeAllMem; } if (!authorization_id || !*authorization_id) { result = sparams->canon_user(sparams->utils->conn, - username, 0, SASL_CU_AUTHZID, oparams); + internal_username, 0, SASL_CU_AUTHZID, oparams); } else { result = sparams->canon_user(sparams->utils->conn, authorization_id, 0, SASL_CU_AUTHZID, oparams); } - if (result != SASL_OK) { - SETERROR(sparams->utils, "unable authorization ID"); + SETERROR(sparams->utils, "unable to canonify authorization ID"); goto FreeAllMem; } @@ -2658,7 +2683,8 @@ static int digestmd5_server_mech_step2(server_context_t *stext, FreeAllMem: if (text->reauth->timeout && sparams->utils->mutex_lock(text->reauth->mutex) == SASL_OK) { /* LOCK */ - unsigned val = hash(username) % text->reauth->size; + /* Look for an entry for our "internal username" */ + unsigned val = hash(internal_username) % text->reauth->size; switch (result) { case SASL_OK: @@ -2695,6 +2721,8 @@ static int digestmd5_server_mech_step2(server_context_t *stext, /* free everything */ if (in_start) sparams->utils->free (in_start); + if (full_username != NULL) + sparams->utils->free (full_username); if (username != NULL) sparams->utils->free (username); if (authorization_id != NULL) From b6222b0fe71d2d2114a0c49ba64b8db447dd5620 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Tue, 30 Nov 2010 11:38:42 +0000 Subject: [PATCH 036/796] Test against broken utf-8 based hashes if calculation using special iso-8859-1 code fails. This affected some XMPP clients. Patch by Dave Cridland. --- plugins/digestmd5.c | 132 +++++++++++++++++++++++++++++++++----------- 1 file changed, 101 insertions(+), 31 deletions(-) diff --git a/plugins/digestmd5.c b/plugins/digestmd5.c index c34e3d5d..b412adfd 100644 --- a/plugins/digestmd5.c +++ b/plugins/digestmd5.c @@ -3,7 +3,7 @@ * Rob Siemborski * Tim Martin * Alexey Melnikov - * $Id: digestmd5.c,v 1.191 2010/11/30 11:34:17 mel Exp $ + * $Id: digestmd5.c,v 1.192 2010/11/30 11:38:42 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -122,7 +122,7 @@ extern int gethostname(char *, int); /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: digestmd5.c,v 1.191 2010/11/30 11:34:17 mel Exp $"; +static const char plugin_id[] = "$Id: digestmd5.c,v 1.192 2010/11/30 11:38:42 mel Exp $"; /* Definitions */ #define NONCE_SIZE (32) /* arbitrary */ @@ -429,15 +429,19 @@ static void MD5_UTF8_8859_1(const sasl_utils_t * utils, while (base < end); } -static void DigestCalcSecret(const sasl_utils_t * utils, - unsigned char *pszUserName, - unsigned char *pszRealm, - unsigned char *Password, - int PasswordLen, - HASH HA1) +/** + * Returns true if it mangled the username. + */ +static bool DigestCalcSecret(const sasl_utils_t * utils, + unsigned char *pszUserName, + unsigned char *pszRealm, + unsigned char *Password, + int PasswordLen, + bool Ignore_8859, + HASH HA1) { bool In_8859_1; - + bool Any_8859_1 = FALSE; MD5_CTX Md5Ctx; /* Chris Newman clarified that the following text in DIGEST-MD5 spec @@ -447,28 +451,44 @@ static void DigestCalcSecret(const sasl_utils_t * utils, utils->MD5Init(&Md5Ctx); /* We have to convert UTF-8 to ISO-8859-1 if possible */ - In_8859_1 = UTF8_In_8859_1(pszUserName, strlen((char *) pszUserName)); - MD5_UTF8_8859_1(utils, &Md5Ctx, In_8859_1, - pszUserName, (unsigned) strlen((char *) pszUserName)); + if (Ignore_8859 == FALSE) { + In_8859_1 = UTF8_In_8859_1(pszUserName, strlen((char *) pszUserName)); + MD5_UTF8_8859_1(utils, &Md5Ctx, In_8859_1, + pszUserName, (unsigned) strlen((char *) pszUserName)); + Any_8859_1 |= In_8859_1; + } else { + utils->MD5Update(&Md5Ctx, pszUserName, (unsigned) strlen((char *) pszUserName)); + } utils->MD5Update(&Md5Ctx, COLON, 1); /* a NULL realm is equivalent to the empty string */ if (pszRealm != NULL && pszRealm[0] != '\0') { - /* We have to convert UTF-8 to ISO-8859-1 if possible */ - In_8859_1 = UTF8_In_8859_1(pszRealm, strlen((char *) pszRealm)); - MD5_UTF8_8859_1(utils, &Md5Ctx, In_8859_1, - pszRealm, (unsigned) strlen((char *) pszRealm)); - } + if (Ignore_8859 == FALSE) { + /* We have to convert UTF-8 to ISO-8859-1 if possible */ + In_8859_1 = UTF8_In_8859_1(pszRealm, strlen((char *) pszRealm)); + MD5_UTF8_8859_1(utils, &Md5Ctx, In_8859_1, + pszRealm, (unsigned) strlen((char *) pszRealm)); + Any_8859_1 |= In_8859_1; + } else { + utils->MD5Update(&Md5Ctx, pszRealm, (unsigned) strlen((char *) pszRealm)); + } + } utils->MD5Update(&Md5Ctx, COLON, 1); - - /* We have to convert UTF-8 to ISO-8859-1 if possible */ - In_8859_1 = UTF8_In_8859_1(Password, PasswordLen); - MD5_UTF8_8859_1(utils, &Md5Ctx, In_8859_1, - Password, PasswordLen); - + + if (Ignore_8859 == FALSE) { + /* We have to convert UTF-8 to ISO-8859-1 if possible */ + In_8859_1 = UTF8_In_8859_1(Password, PasswordLen); + MD5_UTF8_8859_1(utils, &Md5Ctx, In_8859_1, + Password, PasswordLen); + Any_8859_1 |= In_8859_1; + } else { + utils->MD5Update(&Md5Ctx, Password, PasswordLen); + } utils->MD5Final(HA1, &Md5Ctx); + + return Any_8859_1; } static unsigned char *create_nonce(const sasl_utils_t * utils) @@ -2098,6 +2118,8 @@ static int digestmd5_server_mech_step2(server_context_t *stext, unsigned int n = 0; HASH Secret; + HASH SecretBogus; + bool Try_8859_1 = FALSE; int client_ignores_realm = 0; char *full_username = NULL; char *internal_username = NULL; @@ -2470,13 +2492,30 @@ static int digestmd5_server_mech_step2(server_context_t *stext, * (used to build A1) */ + Try_8859_1 = DigestCalcSecret(sparams->utils, + (unsigned char *) username, + (unsigned char *) text->realm, + sec->data, + sec->len, + FALSE, + Secret); + Secret[HASHLEN] = '\0'; + } + if (Try_8859_1) { + /* + * Secret = { H( { username-value, ":", realm-value, ":", passwd } ) } + * + * (used to build A1) + */ + DigestCalcSecret(sparams->utils, (unsigned char *) username, (unsigned char *) text->realm, sec->data, sec->len, - Secret); - Secret[HASHLEN] = '\0'; + TRUE, + SecretBogus); + SecretBogus[HASHLEN] = '\0'; } /* We're done with sec now. Let's get rid of it */ @@ -2561,7 +2600,7 @@ static int digestmd5_server_mech_step2(server_context_t *stext, result = SASL_FAIL; goto FreeAllMem; } - + serverresponse = create_response(text, sparams->utils, text->nonce, @@ -2581,11 +2620,41 @@ static int digestmd5_server_mech_step2(server_context_t *stext, /* if ok verified */ if (strcmp(serverresponse, response) != 0) { - SETERROR(sparams->utils, - "client response doesn't match what we generated"); - result = SASL_BADAUTH; - - goto FreeAllMem; + if (Try_8859_1) { + + serverresponse = create_response(text, + sparams->utils, + text->nonce, + text->nonce_count, + cnonce, + qop, + digesturi, + SecretBogus, + authorization_id, + &text->response_value); + + if (serverresponse == NULL) { + SETERROR(sparams->utils, "internal error: unable to create response"); + result = SASL_NOMEM; + goto FreeAllMem; + } + + /* if ok verified */ + if (strcmp(serverresponse, response) != 0) { + SETERROR(sparams->utils, + "client response doesn't match what we generated (tried bogus)"); + result = SASL_BADAUTH; + + goto FreeAllMem; + } + + } else { + SETERROR(sparams->utils, + "client response doesn't match what we generated"); + result = SASL_BADAUTH; + + goto FreeAllMem; + } } /* see if our nonce expired */ @@ -2949,6 +3018,7 @@ static void DigestCalcHA1(context_t * text, pszRealm, (unsigned char *) pszPassword->data, pszPassword->len, + FALSE, HA1); /* calculate the session key */ From 269224b2f2843c53ace7886e272dc9c2bd44c4b1 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Tue, 30 Nov 2010 11:41:47 +0000 Subject: [PATCH 037/796] Be protective against calling sasl_server_step once authentication has failed. --- plugins/cram.c | 12 ++++++++---- plugins/login.c | 8 ++++++-- plugins/ntlm.c | 8 ++++++-- plugins/otp.c | 8 ++++++-- plugins/srp.c | 16 ++++++++++------ 5 files changed, 36 insertions(+), 16 deletions(-) diff --git a/plugins/cram.c b/plugins/cram.c index 20f6e840..6da3fb07 100644 --- a/plugins/cram.c +++ b/plugins/cram.c @@ -1,7 +1,7 @@ /* CRAM-MD5 SASL plugin * Rob Siemborski * Tim Martin - * $Id: cram.c,v 1.85 2004/09/08 10:57:56 mel Exp $ + * $Id: cram.c,v 1.86 2010/11/30 11:41:47 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -65,7 +65,7 @@ /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: cram.c,v 1.85 2004/09/08 10:57:56 mel Exp $"; +static const char plugin_id[] = "$Id: cram.c,v 1.86 2010/11/30 11:41:47 mel Exp $"; /* convert a string of 8bit chars to it's representation in hex * using lowercase letters @@ -174,7 +174,7 @@ crammd5_server_mech_step1(server_context_t *text, /* we shouldn't have received anything */ if (clientinlen != 0) { - SETERROR(sparams->utils, "CRAM-MD5 does not accpet inital data"); + SETERROR(sparams->utils, "CRAM-MD5 does not accept inital data"); return SASL_BADPROT; } @@ -370,7 +370,11 @@ static int crammd5_server_mech_step(void *conn_context, *serverout = NULL; *serveroutlen = 0; - + + if (text == NULL) { + return SASL_BADPROT; + } + /* this should be well more than is ever needed */ if (clientinlen > 1024) { SETERROR(sparams->utils, "CRAM-MD5 input longer than 1024 bytes"); diff --git a/plugins/login.c b/plugins/login.c index 1957eec0..ee44be64 100644 --- a/plugins/login.c +++ b/plugins/login.c @@ -2,7 +2,7 @@ * Rob Siemborski (SASLv2 Conversion) * contributed by Rainer Schoepf * based on PLAIN, by Tim Martin - * $Id: login.c,v 1.30 2008/10/30 14:19:46 mel Exp $ + * $Id: login.c,v 1.31 2010/11/30 11:41:47 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -54,7 +54,7 @@ /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: login.c,v 1.30 2008/10/30 14:19:46 mel Exp $"; +static const char plugin_id[] = "$Id: login.c,v 1.31 2010/11/30 11:41:47 mel Exp $"; /***************************** Server Section *****************************/ @@ -105,6 +105,10 @@ static int login_server_mech_step(void *conn_context, *serverout = NULL; *serveroutlen = 0; + if (text == NULL) { + return SASL_BADPROT; + } + switch (text->state) { case 1: diff --git a/plugins/ntlm.c b/plugins/ntlm.c index e121f8fa..2d6523bc 100644 --- a/plugins/ntlm.c +++ b/plugins/ntlm.c @@ -1,6 +1,6 @@ /* NTLM SASL plugin * Ken Murchison - * $Id: ntlm.c,v 1.34 2010/01/25 15:45:46 murch Exp $ + * $Id: ntlm.c,v 1.35 2010/11/30 11:41:47 mel Exp $ * * References: * http://www.innovation.ch/java/ntlm.html @@ -100,7 +100,7 @@ /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: ntlm.c,v 1.34 2010/01/25 15:45:46 murch Exp $"; +static const char plugin_id[] = "$Id: ntlm.c,v 1.35 2010/11/30 11:41:47 mel Exp $"; #ifdef WIN32 static ssize_t writev (SOCKET fd, const struct iovec *iov, size_t iovcnt); @@ -1689,6 +1689,10 @@ static int ntlm_server_mech_step(void *conn_context, *serverout = NULL; *serveroutlen = 0; + if (text == NULL) { + return SASL_BADPROT; + } + sparams->utils->log(NULL, SASL_LOG_DEBUG, "NTLM server step %d\n", text->state); diff --git a/plugins/otp.c b/plugins/otp.c index 8a486b88..58e01a31 100644 --- a/plugins/otp.c +++ b/plugins/otp.c @@ -1,6 +1,6 @@ /* OTP SASL plugin * Ken Murchison - * $Id: otp.c,v 1.41 2009/02/14 12:45:29 mel Exp $ + * $Id: otp.c,v 1.42 2010/11/30 11:41:47 mel Exp $ */ /* * Copyright (c) 1998-2009 Carnegie Mellon University. All rights reserved. @@ -68,7 +68,7 @@ /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: otp.c,v 1.41 2009/02/14 12:45:29 mel Exp $"; +static const char plugin_id[] = "$Id: otp.c,v 1.42 2010/11/30 11:41:47 mel Exp $"; #define OTP_SEQUENCE_MAX 9999 #define OTP_SEQUENCE_DEFAULT 499 @@ -350,6 +350,10 @@ static int opie_server_mech_step(void *conn_context, *serverout = NULL; *serveroutlen = 0; + if (text == NULL) { + return SASL_BADPROT; + } + switch (text->state) { case 1: { diff --git a/plugins/srp.c b/plugins/srp.c index 2f72d7f4..cc012d52 100644 --- a/plugins/srp.c +++ b/plugins/srp.c @@ -1,7 +1,7 @@ /* SRP SASL plugin * Ken Murchison * Tim Martin 3/17/00 - * $Id: srp.c,v 1.58 2006/04/24 19:21:44 mel Exp $ + * $Id: srp.c,v 1.59 2010/11/30 11:41:47 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -101,7 +101,7 @@ typedef unsigned short uint32; /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: srp.c,v 1.58 2006/04/24 19:21:44 mel Exp $"; +static const char plugin_id[] = "$Id: srp.c,v 1.59 2010/11/30 11:41:47 mel Exp $"; /* Size limit of cipher block size */ #define SRP_MAXBLOCKSIZE 16 @@ -2161,12 +2161,16 @@ static int srp_server_mech_step(void *conn_context, || !oparams) return SASL_BADPARAM; - sparams->utils->log(NULL, SASL_LOG_DEBUG, - "SRP server step %d\n", text->state); - *serverout = NULL; *serveroutlen = 0; - + + if (text == NULL) { + return SASL_BADPROT; + } + + sparams->utils->log(NULL, SASL_LOG_DEBUG, + "SRP server step %d\n", text->state); + switch (text->state) { case 1: From 9fa54801372fb0ebf2097d8bd3ff81c63fc8b9b2 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Tue, 30 Nov 2010 11:53:10 +0000 Subject: [PATCH 038/796] Fixed some memory leaks on failed plugin initialization. Prevent potential race condition when freeding plugin state. Set the freed reauthentication cache mutex to NULL, to make errors due to mutex access after free more obvious. --- plugins/digestmd5.c | 39 +++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/plugins/digestmd5.c b/plugins/digestmd5.c index b412adfd..64cf8e77 100644 --- a/plugins/digestmd5.c +++ b/plugins/digestmd5.c @@ -3,7 +3,7 @@ * Rob Siemborski * Tim Martin * Alexey Melnikov - * $Id: digestmd5.c,v 1.192 2010/11/30 11:38:42 mel Exp $ + * $Id: digestmd5.c,v 1.193 2010/11/30 11:53:10 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -122,7 +122,7 @@ extern int gethostname(char *, int); /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: digestmd5.c,v 1.192 2010/11/30 11:38:42 mel Exp $"; +static const char plugin_id[] = "$Id: digestmd5.c,v 1.193 2010/11/30 11:53:10 mel Exp $"; /* Definitions */ #define NONCE_SIZE (32) /* arbitrary */ @@ -1647,20 +1647,26 @@ static void digestmd5_common_mech_free(void *glob_context, (digest_glob_context_t *) glob_context; reauth_cache_t *reauth_cache = my_glob_context->reauth; size_t n; - + utils->log(utils->conn, SASL_LOG_DEBUG, "DIGEST-MD5 common mech free"); + + /* Prevent anybody else from freeing this as well */ + my_glob_context->reauth = NULL; if (!reauth_cache) return; - for (n = 0; n < reauth_cache->size; n++) + for (n = 0; n < reauth_cache->size; n++) { clear_reauth_entry(&reauth_cache->e[n], reauth_cache->i_am, utils); + } if (reauth_cache->e) utils->free(reauth_cache->e); - if (reauth_cache->mutex) utils->mutex_free(reauth_cache->mutex); + if (reauth_cache->mutex) { + utils->mutex_free(reauth_cache->mutex); + reauth_cache->mutex = NULL; + } utils->free(reauth_cache); - my_glob_context->reauth = NULL; } /***************************** Server Section *****************************/ @@ -2942,36 +2948,45 @@ int digestmd5_server_plug_init(sasl_utils_t *utils, const char *timeout = NULL; unsigned int len; - if (maxversion < SASL_SERVER_PLUG_VERSION) + if (maxversion < SASL_SERVER_PLUG_VERSION) { return SASL_BADVERS; + } /* reauth cache */ reauth_cache = utils->malloc(sizeof(reauth_cache_t)); - if (reauth_cache == NULL) + if (reauth_cache == NULL) { return SASL_NOMEM; + } memset(reauth_cache, 0, sizeof(reauth_cache_t)); reauth_cache->i_am = SERVER; /* fetch and canonify the reauth_timeout */ utils->getopt(utils->getopt_context, "DIGEST-MD5", "reauth_timeout", &timeout, &len); - if (timeout) + if (timeout) { reauth_cache->timeout = (time_t) 60 * strtol(timeout, NULL, 10); - if (reauth_cache->timeout < 0) + } + if (reauth_cache->timeout < 0) { reauth_cache->timeout = 0; + } if (reauth_cache->timeout) { /* mutex */ reauth_cache->mutex = utils->mutex_alloc(); - if (!reauth_cache->mutex) + if (!reauth_cache->mutex) { + utils->free(reauth_cache); return SASL_FAIL; + } /* entries */ reauth_cache->size = 100; reauth_cache->e = utils->malloc(reauth_cache->size * sizeof(reauth_entry_t)); - if (reauth_cache->e == NULL) + if (reauth_cache->e == NULL) { + utils->mutex_free(reauth_cache->mutex); + utils->free(reauth_cache); return SASL_NOMEM; + } memset(reauth_cache->e, 0, reauth_cache->size * sizeof(reauth_entry_t)); } From f5e758e0f1ffeaf5f2fbbf2988510db9bd628c18 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Tue, 30 Nov 2010 11:57:00 +0000 Subject: [PATCH 039/796] Updated digestmd5_server_mech_step2() to be more defensive against empty client input --- plugins/digestmd5.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/plugins/digestmd5.c b/plugins/digestmd5.c index 64cf8e77..89e9c69e 100644 --- a/plugins/digestmd5.c +++ b/plugins/digestmd5.c @@ -3,7 +3,7 @@ * Rob Siemborski * Tim Martin * Alexey Melnikov - * $Id: digestmd5.c,v 1.193 2010/11/30 11:53:10 mel Exp $ + * $Id: digestmd5.c,v 1.194 2010/11/30 11:57:00 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -122,7 +122,7 @@ extern int gethostname(char *, int); /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: digestmd5.c,v 1.193 2010/11/30 11:53:10 mel Exp $"; +static const char plugin_id[] = "$Id: digestmd5.c,v 1.194 2010/11/30 11:57:00 mel Exp $"; /* Definitions */ #define NONCE_SIZE (32) /* arbitrary */ @@ -2145,6 +2145,12 @@ static int digestmd5_server_mech_step2(server_context_t *stext, sparams->utils->log(sparams->utils->conn, SASL_LOG_DEBUG, "DIGEST-MD5 server step 2"); + if (clientinlen == 0) { + SETERROR(sparams->utils, "input expected in DIGEST-MD5, step 2"); + result = SASL_BADAUTH; + goto FreeAllMem; + } + in = sparams->utils->malloc(clientinlen + 1); memcpy(in, clientin, clientinlen); @@ -2756,7 +2762,8 @@ static int digestmd5_server_mech_step2(server_context_t *stext, result = SASL_OK; FreeAllMem: - if (text->reauth->timeout && + if (clientinlen > 0 && + text->reauth->timeout && sparams->utils->mutex_lock(text->reauth->mutex) == SASL_OK) { /* LOCK */ /* Look for an entry for our "internal username" */ unsigned val = hash(internal_username) % text->reauth->size; From 184b843be42be83d0d4f02f746c92554dccf68f8 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Tue, 30 Nov 2010 12:04:50 +0000 Subject: [PATCH 040/796] Minimize the number of auxprop lookups in the server side DIGEST-MD5 plugin for the most common case when authentication and authorization identities are the same. --- plugins/digestmd5.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/plugins/digestmd5.c b/plugins/digestmd5.c index 89e9c69e..ab85e859 100644 --- a/plugins/digestmd5.c +++ b/plugins/digestmd5.c @@ -3,7 +3,7 @@ * Rob Siemborski * Tim Martin * Alexey Melnikov - * $Id: digestmd5.c,v 1.194 2010/11/30 11:57:00 mel Exp $ + * $Id: digestmd5.c,v 1.195 2010/11/30 12:04:50 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -122,7 +122,7 @@ extern int gethostname(char *, int); /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: digestmd5.c,v 1.194 2010/11/30 11:57:00 mel Exp $"; +static const char plugin_id[] = "$Id: digestmd5.c,v 1.195 2010/11/30 12:04:50 mel Exp $"; /* Definitions */ #define NONCE_SIZE (32) /* arbitrary */ @@ -2129,6 +2129,7 @@ static int digestmd5_server_mech_step2(server_context_t *stext, int client_ignores_realm = 0; char *full_username = NULL; char *internal_username = NULL; + int canon_flags; /* password prop_request */ const char *password_request[] = { SASL_AUX_PASSWORD, @@ -2438,17 +2439,23 @@ static int digestmd5_server_mech_step2(server_context_t *stext, } else { internal_username = username; } + + canon_flags = SASL_CU_AUTHID; + if (!authorization_id || !*authorization_id) { + canon_flags |= SASL_CU_AUTHZID; + } + result = sparams->canon_user(sparams->utils->conn, - internal_username, 0, SASL_CU_AUTHID, oparams); + internal_username, + 0, + canon_flags, + oparams); if (result != SASL_OK) { SETERROR(sparams->utils, "unable to canonify user and get auxprops"); goto FreeAllMem; } - if (!authorization_id || !*authorization_id) { - result = sparams->canon_user(sparams->utils->conn, - internal_username, 0, SASL_CU_AUTHZID, oparams); - } else { + if (authorization_id != NULL && *authorization_id != '\0') { result = sparams->canon_user(sparams->utils->conn, authorization_id, 0, SASL_CU_AUTHZID, oparams); From 55cab88b568cfff93a6665b4131a366aaa4edb9a Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Tue, 30 Nov 2010 12:08:24 +0000 Subject: [PATCH 041/796] Be protective against calling sasl_server_step once authentication has failed. --- plugins/digestmd5.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/plugins/digestmd5.c b/plugins/digestmd5.c index ab85e859..3473dc93 100644 --- a/plugins/digestmd5.c +++ b/plugins/digestmd5.c @@ -3,7 +3,7 @@ * Rob Siemborski * Tim Martin * Alexey Melnikov - * $Id: digestmd5.c,v 1.195 2010/11/30 12:04:50 mel Exp $ + * $Id: digestmd5.c,v 1.196 2010/11/30 12:08:24 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -122,7 +122,7 @@ extern int gethostname(char *, int); /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: digestmd5.c,v 1.195 2010/11/30 12:04:50 mel Exp $"; +static const char plugin_id[] = "$Id: digestmd5.c,v 1.196 2010/11/30 12:08:24 mel Exp $"; /* Definitions */ #define NONCE_SIZE (32) /* arbitrary */ @@ -2851,11 +2851,15 @@ static int digestmd5_server_mech_step(void *conn_context, context_t *text = (context_t *) conn_context; server_context_t *stext = (server_context_t *) conn_context; - if (clientinlen > 4096) return SASL_BADPROT; - *serverout = NULL; *serveroutlen = 0; + if (clientinlen > 4096) return SASL_BADPROT; + + if (text == NULL) { + return SASL_BADPROT; + } + switch (text->state) { case 1: From bf4c4de872e4aabd6bce31a67c1106b01b1bf2a4 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Tue, 30 Nov 2010 12:09:17 +0000 Subject: [PATCH 042/796] Eliminated some warnings --- plugins/digestmd5.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/digestmd5.c b/plugins/digestmd5.c index 3473dc93..f0e520b6 100644 --- a/plugins/digestmd5.c +++ b/plugins/digestmd5.c @@ -3,7 +3,7 @@ * Rob Siemborski * Tim Martin * Alexey Melnikov - * $Id: digestmd5.c,v 1.196 2010/11/30 12:08:24 mel Exp $ + * $Id: digestmd5.c,v 1.197 2010/11/30 12:09:17 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -122,7 +122,7 @@ extern int gethostname(char *, int); /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: digestmd5.c,v 1.196 2010/11/30 12:08:24 mel Exp $"; +static const char plugin_id[] = "$Id: digestmd5.c,v 1.197 2010/11/30 12:09:17 mel Exp $"; /* Definitions */ #define NONCE_SIZE (32) /* arbitrary */ @@ -337,7 +337,7 @@ DigestCalcResponse(const sasl_utils_t * utils, HASH HA2; HASH RespHash; HASHHEX HA2Hex; - char ncvalue[10]; + unsigned char ncvalue[10]; /* calculate H(A2) */ utils->MD5Init(&Md5Ctx); @@ -345,7 +345,7 @@ DigestCalcResponse(const sasl_utils_t * utils, if (pszMethod != NULL) { utils->MD5Update(&Md5Ctx, pszMethod, (unsigned) strlen((char *) pszMethod)); } - utils->MD5Update(&Md5Ctx, COLON, 1); + utils->MD5Update(&Md5Ctx, (unsigned char *) COLON, 1); /* utils->MD5Update(&Md5Ctx, (unsigned char *) "AUTHENTICATE:", 13); */ utils->MD5Update(&Md5Ctx, pszDigestUri, (unsigned) strlen((char *) pszDigestUri)); @@ -364,8 +364,8 @@ DigestCalcResponse(const sasl_utils_t * utils, utils->MD5Update(&Md5Ctx, pszNonce, (unsigned) strlen((char *) pszNonce)); utils->MD5Update(&Md5Ctx, COLON, 1); if (*pszQop) { - sprintf(ncvalue, "%08x", pszNonceCount); - utils->MD5Update(&Md5Ctx, (unsigned char *) ncvalue, (unsigned) strlen(ncvalue)); + sprintf((char *)ncvalue, "%08x", pszNonceCount); + utils->MD5Update(&Md5Ctx, ncvalue, (unsigned) strlen((char *)ncvalue)); utils->MD5Update(&Md5Ctx, COLON, 1); utils->MD5Update(&Md5Ctx, pszCNonce, (unsigned) strlen((char *) pszCNonce)); utils->MD5Update(&Md5Ctx, COLON, 1); From 73cfb752f20c294f917e9ab3dfc4815529a124d3 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Tue, 30 Nov 2010 13:31:20 +0000 Subject: [PATCH 043/796] Updated ChangeLog for DIGEST-MD5 (and some other plugin) changes merged today --- ChangeLog | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/ChangeLog b/ChangeLog index d09d8cfc..4a4028a5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,41 @@ +2010-11-30 Alexey Melnikov + * plugins/digestmd5.c: Eliminated some "signed/unsigned mismatch" + warnings. + +2010-11-30 Alexey Melnikov + * plugins/digestmd5.c, plugins/srp.c, plugins/otp.c, + plugins/ntlm.c, plugins/login.c, plugins/cram.c: + Be protective against calling sasl_server_step + once authentication has failed. + +2010-11-30 Alexey Melnikov + * plugins/digestmd5.c: Minimize the number of auxprop lookups + in the server side DIGEST-MD5 plugin for the most common + case when authentication and authorization identities are + the same. + +2010-11-30 Alexey Melnikov + * plugins/digestmd5.c: Updated digestmd5_server_mech_step2() + to be more defensive against empty client input. + +2010-11-30 Alexey Melnikov + * plugins/digestmd5.c: Fixed some memory leaks on failed + plugin initialization. Prevent potential race condition + when freeding plugin state. Set the freed reauthentication + cache mutex to NULL, to make errors due to mutex access + after free more obvious. + +2010-11-30 Alexey Melnikov + * plugins/digestmd5.c: Test against broken UTF-8 based hashes + if calculation using special ISO-8859-1 code fails. + This affected some XMPP clients. Patch by Dave Cridland + . + +2010-11-30 Alexey Melnikov + * plugins/digestmd5.c: Fixed an interop problem with some + LDAP clients ignoring server advertised realm + and providing their own. + 2009-08-14 Alexey Melnikov * saslauthd/auth_shadow.c: Rolled back the previous commit (#define _XOPEN_SOURCE before including unistd.h), From d93fa6a9335f591ce29bae58c1253f928d0991a6 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Wed, 1 Dec 2010 14:24:21 +0000 Subject: [PATCH 044/796] Updated textual messages for various SASL error codes --- lib/common.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/common.c b/lib/common.c index a814792d..a39c9c63 100644 --- a/lib/common.c +++ b/lib/common.c @@ -1,7 +1,7 @@ /* common.c - Functions that are common to server and clinet * Rob Siemborski * Tim Martin - * $Id: common.c,v 1.125 2010/05/12 21:28:19 mel Exp $ + * $Id: common.c,v 1.126 2010/12/01 14:24:21 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -1287,11 +1287,11 @@ const char *sasl_errstring(int saslerr, case SASL_BUFOVER: return "overflowed buffer"; case SASL_NOMECH: return "no mechanism available"; case SASL_BADPROT: return "bad protocol / cancel"; - case SASL_NOTDONE: return "can't request info until later in exchange"; + case SASL_NOTDONE: return "can't request information until later in exchange"; case SASL_BADPARAM: return "invalid parameter supplied"; case SASL_TRYAGAIN: return "transient failure (e.g., weak key)"; case SASL_BADMAC: return "integrity check failed"; - case SASL_NOTINIT: return "SASL library not initialized"; + case SASL_NOTINIT: return "SASL library is not initialized"; /* -- client only codes -- */ case SASL_INTERACT: return "needs user interaction"; case SASL_BADSERV: return "server failed mutual authentication step"; From 0704d0460a33e90b7d5abf8f84490faed7556ba9 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Wed, 1 Dec 2010 14:25:53 +0000 Subject: [PATCH 045/796] Fixed random number generator on Windows --- lib/saslutil.c | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/lib/saslutil.c b/lib/saslutil.c index 6b43d6d7..035c718f 100644 --- a/lib/saslutil.c +++ b/lib/saslutil.c @@ -1,7 +1,7 @@ /* saslutil.c * Rob Siemborski * Tim Martin - * $Id: saslutil.c,v 1.50 2010/01/22 15:14:53 murch Exp $ + * $Id: saslutil.c,v 1.51 2010/12/01 14:25:53 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -45,6 +45,11 @@ #include #include + +#if defined(WIN32) +#define _CRT_RAND_S +#endif + #include #include #include @@ -431,6 +436,11 @@ static void randinit(sasl_rand_t *rpool) srandom(*foo); } #endif /* HAVE_JRAND48 */ +#else if defined(WIN32) + { + unsigned int *foo = (unsigned int *)rpool->pool; + srand(*foo); + } #endif /* WIN32 */ } @@ -439,24 +449,33 @@ static void randinit(sasl_rand_t *rpool) void sasl_rand (sasl_rand_t *rpool, char *buf, unsigned len) { unsigned int lup; +#if defined(WIN32) + unsigned int randomValue; +#endif + /* check params */ if (!rpool || !buf) return; /* init if necessary */ randinit(rpool); - -#if (defined(WIN32)||defined(macintosh)) - for (lup=0;lup> 8); +#elif defined(macintosh) buf[lup] = (char) (rand() >> 8); -#else /* WIN32 */ +#else /* !WIN32 && !macintosh */ #ifdef HAVE_JRAND48 - for (lup=0; luppool) >> 8); #else - for (lup=0;lup> 8); #endif /* HAVE_JRAND48 */ #endif /* WIN32 */ + } } /* this function is just a bad idea all around, since we're not trying to From 5ef1ca79db8e2cd2c0994b139cc597068051f2b2 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Wed, 1 Dec 2010 14:51:53 +0000 Subject: [PATCH 046/796] Added support for channel bindings (patch by Luke Howard) --- include/sasl.h | 13 ++- include/saslplug.h | 42 ++++++--- lib/client.c | 202 ++++++++++++++++++++++++++++++++++++-------- lib/common.c | 42 ++++++++- lib/saslint.h | 15 +++- lib/server.c | 105 ++++++++++++++++++----- sample/Makefile.am | 10 +-- sample/client.c | 42 +++++++-- sample/server.c | 206 +++++++++++++++++++++++++++++++++++++++++++-- 9 files changed, 580 insertions(+), 97 deletions(-) diff --git a/include/sasl.h b/include/sasl.h index dfc4d6a1..d5af6bfb 100755 --- a/include/sasl.h +++ b/include/sasl.h @@ -176,6 +176,8 @@ #define SASL_CONSTRAINT_VIOLAT -30 /* a property can't be stored, because of some constrains/policy violation */ +#define SASL_BADBINDING -32 /* channel binding failure */ + /* max size of a sasl mechanism name */ #define SASL_MECHNAMEMAX 20 @@ -796,7 +798,7 @@ LIBSASL_API int sasl_getprop(sasl_conn_t *conn, int propnum, * is returned by the mechanism. The user will probably need to know * which mechanism was used to actually known how to make use of them * currently only implemented for the gssapi mechanism */ -#define SASL_DELEGATEDCREDS 11 +#define SASL_DELEGATEDCREDS 11 #define SASL_SERVICE 12 /* service passed to sasl_*_new */ #define SASL_SERVERFQDN 13 /* serverFQDN passed to sasl_*_new */ @@ -823,6 +825,15 @@ LIBSASL_API int sasl_getprop(sasl_conn_t *conn, int propnum, * is particularly useful for servers that respond to multiple names. */ #define SASL_GSS_LOCAL_NAME 20 +/* Channel binding information. Memory is managed by the caller. */ +typedef struct sasl_channel_binding { + const char *name; + int critical; + unsigned long len; + const unsigned char *data; +} sasl_channel_binding_t; + +#define SASL_CHANNEL_BINDING 21 /* set property in SASL connection state * returns: diff --git a/include/saslplug.h b/include/saslplug.h index e8e8f08c..9c7fdc25 100755 --- a/include/saslplug.h +++ b/include/saslplug.h @@ -193,12 +193,12 @@ typedef struct sasl_out_params { void *client_creds; /* for additions which don't require a version upgrade; set to 0 */ - void *spare_ptr2; - void *spare_ptr3; - void *spare_ptr4; + const void *gss_peer_name; + const void *gss_local_name; + const char *cbindingname; /* channel binding name from packet */ int (*spare_fptr1)(); int (*spare_fptr2)(); - int spare_int1; + unsigned int cbindingdisp; /* channel binding disposition from client */ int spare_int2; int spare_int3; int spare_int4; @@ -219,7 +219,21 @@ typedef enum { SASL_INFO_LIST_END } sasl_info_callback_stage_t; +/****************************** + * Channel binding macros ** + ******************************/ + +typedef enum { + SASL_CB_DISP_NONE = 0, /* client did not support CB */ + SASL_CB_DISP_USED, /* client supports and used CB */ + SASL_CB_DISP_WANT /* client supports CB, thinks server does not */ +} sasl_cbinding_disp_t; +/* TRUE if channel binding is non-NULL */ +#define SASL_CB_PRESENT(params) ((params)->cbinding != NULL) +/* TRUE if channel binding is marked critical */ +#define SASL_CB_CRITICAL(params) (SASL_CB_PRESENT(params) && \ + (params)->cbinding->critical) /****************************** * Client Mechanism Functions * @@ -253,11 +267,9 @@ typedef struct sasl_client_params { sasl_security_properties_t props; sasl_ssf_t external_ssf; /* external SSF active */ - /* GSS credentials */ - void *gss_creds; - /* for additions which don't require a version upgrade; set to 0 */ - void *spare_ptr2; + const void *gss_creds; /* GSS credential handle */ + const sasl_channel_binding_t *cbinding; /* client channel binding */ void *spare_ptr3; void *spare_ptr4; @@ -291,7 +303,7 @@ typedef struct sasl_client_params { int (*spare_fptr1)(); - int spare_int1; + unsigned int cbindingdisp; int spare_int2; int spare_int3; @@ -334,6 +346,12 @@ typedef struct sasl_client_params { /* server plugin don't use cleartext userPassword attribute */ #define SASL_FEAT_DONTUSE_USERPASSWD 0x0080 +/* Underlying mechanism uses GSS framing */ +#define SASL_FEAT_GSS_FRAMING 0x0100 + +/* Underlying mechanism supports channel binding */ +#define SASL_FEAT_CHANNEL_BINDING 0x0200 + /* client plug-in features */ #define SASL_FEAT_NEEDSERVERFQDN 0x0001 @@ -554,11 +572,9 @@ typedef struct sasl_server_params { */ struct propctx *propctx; - /* GSS credentials */ - void *gss_creds; - /* for additions which don't require a version upgrade; set to 0 */ - void *spare_ptr2; + const void *gss_creds; /* GSS credential handle */ + const sasl_channel_binding_t *cbinding; /* server channel binding */ void *spare_ptr3; void *spare_ptr4; int (*spare_fptr1)(); diff --git a/lib/client.c b/lib/client.c index 0daf1d7c..8c7bff75 100644 --- a/lib/client.c +++ b/lib/client.c @@ -1,7 +1,7 @@ /* SASL client API implementation * Rob Siemborski * Tim Martin - * $Id: client.c,v 1.77 2009/08/18 12:23:57 mel Exp $ + * $Id: client.c,v 1.78 2010/12/01 14:51:53 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -424,6 +424,114 @@ static int have_prompts(sasl_conn_t *conn, return 1; /* we have all the prompts */ } +static int +_mech_plus_p(const char *mech, size_t len) +{ + return (len > 5 && strncasecmp(&mech[len - 5], "-PLUS", 5) == 0); +} + +/* + * Order PLUS mechanisms first. Returns NUL separated list of + * *count items. + */ +static int +_sasl_client_order_mechs(const sasl_utils_t *utils, + const char *mechs, + int has_cb_data, + char **ordered_mechs, + size_t *count, + int *server_can_cb) +{ + char *list, *listp; + size_t i, mechslen, start; + + *count = 0; + *server_can_cb = 0; + + if (mechs == NULL || mechs[0] == '\0') + return SASL_NOMECH; + + mechslen = strlen(mechs); + + listp = list = utils->malloc(mechslen + 1); + if (list == NULL) + return SASL_NOMEM; + + /* xxx confirm this with rfc 2222 + * SASL mechanism allowable characters are "AZaz-_" + * seperators can be any other characters and of any length + * even variable lengths between + * + * Apps should be encouraged to simply use space or comma space + * though + */ +#define ismechchar(c) (isalnum((c)) || (c) == '_' || (c) == '-') + do { + for (i = start = 0; i <= mechslen; i++) { + if (!ismechchar(mechs[i])) { + const char *mechp = &mechs[start]; + size_t len = i - start; + + if (len != 0 && + _mech_plus_p(mechp, len) == has_cb_data) { + memcpy(listp, mechp, len); + listp[len] = '\0'; + listp += len + 1; + (*count)++; + if (*server_can_cb == 0 && has_cb_data) + *server_can_cb = 1; + } + start = ++i; + } + } + if (has_cb_data) + has_cb_data = 0; + else + break; + } while (1); + + if (*count == 0) { + utils->free(list); + return SASL_NOMECH; + } + + *ordered_mechs = list; + + return SASL_OK; +} + +static INLINE int +_sasl_cbinding_disp(sasl_client_params_t *cparams, + int mech_nego, + int server_can_cb, + sasl_cbinding_disp_t *cbindingdisp) +{ + /* + * If negotiating mechanisms, then we fail immediately if the + * client requires channel binding and the server does not + * advertise support. Otherwise we send "y" (which later will + * become "p" if we select a supporting mechanism). + * + * If the client explicitly selected a mechanism, then we only + * send channel bindings if they're marked critical. + */ + + *cbindingdisp = SASL_CB_DISP_NONE; + + if (SASL_CB_PRESENT(cparams)) { + if (mech_nego) { + if (!server_can_cb && SASL_CB_CRITICAL(cparams)) + return SASL_NOMECH; + else + *cbindingdisp = SASL_CB_DISP_WANT; + } else if (SASL_CB_CRITICAL(cparams)) { + *cbindingdisp = SASL_CB_DISP_USED; + } + } + + return SASL_OK; +} + /* select a mechanism for a connection * mechlist -- mechanisms server has available (punctuation ignored) * secret -- optional secret from previous session @@ -439,10 +547,12 @@ static int have_prompts(sasl_conn_t *conn, * SASL_INTERACT -- user interaction needed to fill in prompt_need list */ -/* xxx confirm this with rfc 2222 - * SASL mechanism allowable characters are "AZaz-_" +/* + * SASL mechanism allowable characters are "AZ-_" * separators can be any other characters and of any length - * even variable lengths between + * even variable lengths between. + * + * But for convenience we accept lowercase ASCII. * * Apps should be encouraged to simply use space or comma space * though @@ -455,12 +565,12 @@ int sasl_client_start(sasl_conn_t *conn, const char **mech) { sasl_client_conn_t *c_conn = (sasl_client_conn_t *) conn; - char name[SASL_MECHNAMEMAX + 1]; + char *ordered_mechs = NULL, *name; cmechanism_t *m=NULL,*bestm=NULL; - size_t pos=0,place; - size_t list_len; + size_t i, list_len; sasl_ssf_t bestssf = 0, minssf = 0; - int result; + int result, server_can_cb = 0; + sasl_cbinding_disp_t cbindingdisp; if (_sasl_client_active == 0) return SASL_NOTINIT; @@ -486,38 +596,33 @@ int sasl_client_start(sasl_conn_t *conn, minssf = conn->props.min_ssf - conn->external.ssf; } - /* parse mechlist */ - list_len = strlen(mechlist); - - while (poscparams->utils, + mechlist, + SASL_CB_PRESENT(c_conn->cparams), + &ordered_mechs, + &list_len, + &server_can_cb); + if (result != 0) + goto done; - if (! place) continue; + /* + * Determine channel binding disposition based on whether we + * are doing mechanism negotiation and whether server supports + * channel bindings. + */ + result = _sasl_cbinding_disp(c_conn->cparams, (list_len > 1), + server_can_cb, &cbindingdisp); + if (result != 0) + goto done; + for (i = 0, name = ordered_mechs; i < list_len; i++) { /* foreach in client list */ for (m = cmechlist->mech_list; m != NULL; m = m->next) { - int myflags; - - /* Is this the mechanism the server is suggesting? */ - if (strcasecmp(m->m.plug->mech_name, name)) - continue; /* no */ + int myflags, plus; + + if (!_sasl_is_equal_mech(name, m->m.plug->mech_name, &plus)) + continue; /* Do we have the prompts for it? */ if (!have_prompts(conn, m->m.plug)) @@ -541,6 +646,11 @@ int sasl_client_start(sasl_conn_t *conn, } /* Can we meet it's features? */ + if (cbindingdisp != SASL_CB_DISP_NONE && + !(m->m.plug->features & SASL_FEAT_CHANNEL_BINDING)) { + break; + } + if ((m->m.plug->features & SASL_FEAT_NEEDSERVERFQDN) && !conn->serverFQDN) { break; @@ -551,7 +661,7 @@ int sasl_client_start(sasl_conn_t *conn, !(m->m.plug->features & SASL_FEAT_ALLOWS_PROXY)) { break; } - + #ifdef PREFER_MECH if (strcasecmp(m->m.plug->mech_name, PREFER_MECH) && bestm && m->m.plug->max_ssf <= bestssf) { @@ -590,6 +700,10 @@ int sasl_client_start(sasl_conn_t *conn, break; } + if (SASL_CB_PRESENT(c_conn->cparams) && plus) { + cbindingdisp = SASL_CB_DISP_USED; + } + if (mech) { *mech = m->m.plug->mech_name; } @@ -597,6 +711,7 @@ int sasl_client_start(sasl_conn_t *conn, bestm = m; break; } + name += strlen(name) + 1; } if (bestm == NULL) { @@ -619,6 +734,7 @@ int sasl_client_start(sasl_conn_t *conn, c_conn->cparams->external_ssf = conn->external.ssf; c_conn->cparams->props = conn->props; + c_conn->cparams->cbindingdisp = cbindingdisp; c_conn->mech = bestm; /* init that plugin */ @@ -643,6 +759,8 @@ int sasl_client_start(sasl_conn_t *conn, result = SASL_CONTINUE; done: + if (ordered_mechs != NULL) + c_conn->cparams->utils->free(ordered_mechs); RETURN(conn, result); } @@ -984,6 +1102,16 @@ _sasl_print_mechanism ( printf ("%cNEED_SERVER_FQDN", delimiter); delimiter = '|'; } + + if (m->plug->features & SASL_FEAT_GSS_FRAMING) { + printf ("%cGSS_FRAMING", delimiter); + delimiter = '|'; + } + + if (m->plug->features & SASL_FEAT_CHANNEL_BINDING) { + printf ("%cCHANNEL_BINDING", delimiter); + delimiter = '|'; + } } /* Delay loading is not supported for the client side plugins: diff --git a/lib/common.c b/lib/common.c index a39c9c63..d8d2fb7e 100644 --- a/lib/common.c +++ b/lib/common.c @@ -1,7 +1,7 @@ /* common.c - Functions that are common to server and clinet * Rob Siemborski * Tim Martin - * $Id: common.c,v 1.126 2010/12/01 14:24:21 mel Exp $ + * $Id: common.c,v 1.127 2010/12/01 14:51:53 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -1018,6 +1018,18 @@ int sasl_getprop(sasl_conn_t *conn, int propnum, const void **pvalue) else *((const char **)pvalue) = conn->oparams.client_creds; break; + case SASL_GSS_PEER_NAME: + if(! conn->oparams.gss_peer_name) + result = SASL_NOTDONE; + else + *((const char **)pvalue) = conn->oparams.gss_peer_name; + break; + case SASL_GSS_LOCAL_NAME: + if(! conn->oparams.gss_peer_name) + result = SASL_NOTDONE; + else + *((const char **)pvalue) = conn->oparams.gss_local_name; + break; case SASL_SSF_EXTERNAL: *((const sasl_ssf_t **)pvalue) = &conn->external.ssf; break; @@ -1253,6 +1265,15 @@ int sasl_setprop(sasl_conn_t *conn, int propnum, const void *value) ((sasl_server_conn_t *)conn)->sparams->gss_creds = value; break; + case SASL_CHANNEL_BINDING: { + const struct sasl_channel_binding *cb = (const struct sasl_channel_binding *)value; + + if (conn->type == SASL_CONN_SERVER) + ((sasl_server_conn_t *)conn)->sparams->cbinding = cb; + else + ((sasl_client_conn_t *)conn)->cparams->cbinding = cb; + break; + } default: sasl_seterror(conn, 0, "Unknown parameter type"); result = SASL_BADPARAM; @@ -1316,6 +1337,7 @@ const char *sasl_errstring(int saslerr, "to perform password change"; case SASL_CONSTRAINT_VIOLAT: return "sasl_setpass can't store a property because " "of a constraint violation"; + case SASL_BADBINDING: return "channel binding failure"; default: return "undefined error!"; } @@ -2366,6 +2388,24 @@ int sasl_listmech(sasl_conn_t *conn, PARAMERROR(conn); } +int _sasl_is_equal_mech(const char *req_mech, + const char *plug_mech, + int *plus) +{ + size_t len = strlen(req_mech); + size_t n; + + if (len > 5 && + strcasecmp(&req_mech[len - 5], "-PLUS") == 0) { + n = len - 5; + *plus = 1; + } else { + n = len; + *plus = 0; + } + + return (strncasecmp(req_mech, plug_mech, n) == 0); +} #ifndef WIN32 static char * diff --git a/lib/saslint.h b/lib/saslint.h index b4ef0836..95dc47c7 100644 --- a/lib/saslint.h +++ b/lib/saslint.h @@ -1,7 +1,7 @@ /* saslint.h - internal SASL library definitions * Rob Siemborski * Tim Martin - * $Id: saslint.h,v 1.69 2009/02/21 20:07:45 mel Exp $ + * $Id: saslint.h,v 1.70 2010/12/01 14:51:53 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -52,6 +52,15 @@ #include "saslutil.h" #include "prop.h" +#ifndef INLINE +#if defined (WIN32) +/* Visual Studio: "inline" keyword is not available in C, only in C++ */ +#define INLINE __inline +#else +#define INLINE inline +#endif +#endif + /* #define'd constants */ #define CANON_BUF_SIZE 1024 @@ -306,6 +315,10 @@ extern int _sasl_allocation_locked; void sasl_common_done(void); +extern int _sasl_is_equal_mech(const char *req_mech, + const char *plug_mech, + int *plus); + /* * checkpw.c */ diff --git a/lib/server.c b/lib/server.c index 4bd987ce..a7170c44 100644 --- a/lib/server.c +++ b/lib/server.c @@ -1,7 +1,7 @@ /* SASL server API implementation * Rob Siemborski * Tim Martin - * $Id: server.c,v 1.161 2009/08/04 17:45:55 mel Exp $ + * $Id: server.c,v 1.162 2010/12/01 14:51:53 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -1342,6 +1342,7 @@ int sasl_server_start(sasl_conn_t *conn, int result; context_list_t *cur, **prev; mechanism_t *m; + int plus = 0; if (_sasl_server_active==0) return SASL_NOTINIT; @@ -1358,13 +1359,11 @@ int sasl_server_start(sasl_conn_t *conn, if not return appropriate error */ m = s_conn->mech_list; - while (m!=NULL) - { - if ( strcasecmp(mech, m->m.plug->mech_name)==0) - { + while (m != NULL) { + if (_sasl_is_equal_mech(mech, m->m.plug->mech_name, &plus)) break; - } - m=m->next; + + m = m->next; } if (m==NULL) { @@ -1586,7 +1585,39 @@ int sasl_server_step(sasl_conn_t *conn, conn->oparams.maxoutbuf = conn->props.maxbufsize; } - if(conn->oparams.user == NULL || conn->oparams.authid == NULL) { + /* Validate channel bindings */ + switch (conn->oparams.cbindingdisp) { + case SASL_CB_DISP_NONE: + if (SASL_CB_CRITICAL(s_conn->sparams)) { + sasl_seterror(conn, 0, + "server requires channel binding but client provided none"); + ret = SASL_BADBINDING; + } + break; + case SASL_CB_DISP_WANT: + if (SASL_CB_PRESENT(s_conn->sparams)) { + sasl_seterror(conn, 0, + "client incorrectly assumed server had no channel binding"); + ret = SASL_BADAUTH; + } + break; + case SASL_CB_DISP_USED: + if (!SASL_CB_PRESENT(s_conn->sparams)) { + sasl_seterror(conn, 0, + "client provided channel binding but server had none"); + ret = SASL_BADBINDING; + } else if (strcmp(conn->oparams.cbindingname, + s_conn->sparams->cbinding->name) != 0) { + sasl_seterror(conn, 0, + "client channel binding %s does not match server %s", + conn->oparams.cbindingname, s_conn->sparams->cbinding->name); + ret = SASL_BADBINDING; + } + break; + } + + if (ret == SASL_OK && + (conn->oparams.user == NULL || conn->oparams.authid == NULL)) { sasl_seterror(conn, 0, "mech did not call canon_user for both authzid " \ "and authid"); @@ -1637,7 +1668,7 @@ int _sasl_server_listmech(sasl_conn_t *conn, unsigned *plen, int *pcount) { - sasl_server_conn_t *s_conn = (sasl_server_conn_t *)conn; + sasl_server_conn_t *s_conn = (sasl_server_conn_t *) conn; /* cast */ int lup; mechanism_t *listptr; int ret; @@ -1668,10 +1699,12 @@ int _sasl_server_listmech(sasl_conn_t *conn, INTERROR(conn, SASL_NOMECH); resultlen = (prefix ? strlen(prefix) : 0) - + (strlen(mysep) * (s_conn->mech_length - 1)) - + mech_names_len(s_conn->mech_list) + + (strlen(mysep) * (s_conn->mech_length - 1) * 2) + + (mech_names_len(s_conn->mech_list) * 2) /* including -PLUS variant */ + + (s_conn->mech_length * (sizeof("-PLUS") - 1)) + (suffix ? strlen(suffix) : 0) + 1; + ret = _buf_alloc(&conn->mechlist_buf, &conn->mechlist_buf_len, resultlen); if(ret != SASL_OK) MEMERROR(conn); @@ -1688,18 +1721,38 @@ int _sasl_server_listmech(sasl_conn_t *conn, for (lup = 0; lup < s_conn->mech_length; lup++) { /* currently, we don't use the "user" parameter for anything */ if (mech_permitted(conn, listptr) == SASL_OK) { - if (pcount != NULL) + /* + * If the server would never succeed in the authentication of + * he non-PLUS-variant due to policy reasons, it MUST advertise + * only the PLUS-variant. + */ + if (!SASL_CB_PRESENT(s_conn->sparams) || + !SASL_CB_CRITICAL(s_conn->sparams)) { + if (pcount != NULL) (*pcount)++; - - /* print separator */ - if (flag) { - strcat(conn->mechlist_buf, mysep); - } else { - flag = 1; + if (flag) + strcat(conn->mechlist_buf, mysep); + else + flag = 1; + strcat(conn->mechlist_buf, listptr->m.plug->mech_name); + } + /* + * If the server cannot support channel binding, it SHOULD + * advertise only the non-PLUS-variant. Here, supporting channel + * binding means the underlying SASL mechanism supports it and + * the application has set some channel binding data. + */ + if ((listptr->m.plug->features & SASL_FEAT_CHANNEL_BINDING) && + SASL_CB_PRESENT(s_conn->sparams)) { + if (pcount != NULL) + (*pcount)++; + if (flag) + strcat(conn->mechlist_buf, mysep); + else + flag = 1; + strcat(conn->mechlist_buf, listptr->m.plug->mech_name); + strcat(conn->mechlist_buf, "-PLUS"); } - - /* now print the mechanism name */ - strcat(conn->mechlist_buf, listptr->m.plug->mech_name); } listptr = listptr->next; @@ -2187,6 +2240,16 @@ _sasl_print_mechanism ( printf ("%cNEED_GETSECRET", delimiter); delimiter = '|'; } + + if (m->plug->features & SASL_FEAT_GSS_FRAMING) { + printf ("%cGSS_FRAMING", delimiter); + delimiter = '|'; + } + + if (m->plug->features & SASL_FEAT_CHANNEL_BINDING) { + printf ("%cCHANNEL_BINDING", delimiter); + delimiter = '|'; + } } if (m->f) { diff --git a/sample/Makefile.am b/sample/Makefile.am index 0e18483c..f00579db 100644 --- a/sample/Makefile.am +++ b/sample/Makefile.am @@ -54,10 +54,8 @@ sample_server_SOURCES = sample-server.c server_SOURCES = server.c common.c common.h client_SOURCES = client.c common.c common.h -server_LDADD = ../lib/libsasl2.la $(LIB_SOCKET) -client_LDADD = ../lib/libsasl2.la $(LIB_SOCKET) +server_LDADD = ../lib/libsasl2.la $(GSSAPIBASE_LIBS) $(GSSAPI_LIBS) $(LIB_SOCKET) +client_LDADD = ../lib/libsasl2.la $(GSSAPIBASE_LIBS) $(GSSAPI_LIBS) $(LIB_SOCKET) -sample_client_LDADD = ../lib/libsasl2.la $(LIB_SOCKET) -sample_server_LDADD = ../lib/libsasl2.la $(LIB_SOCKET) - -EXTRA_DIST = NTMakefile +sample_client_LDADD = ../lib/libsasl2.la $(GSSAPIBASE_LIBS) $(GSSAPI_LIBS) $(LIB_SOCKET) +sample_server_LDADD = ../lib/libsasl2.la $(GSSAPIBASE_LIBS) $(GSSAPI_LIBS) $(LIB_SOCKET) diff --git a/sample/client.c b/sample/client.c index 0ddb16c7..e0cf2e27 100644 --- a/sample/client.c +++ b/sample/client.c @@ -1,4 +1,4 @@ -/* $Id: client.c,v 1.7 2004/03/09 17:35:32 rjs3 Exp $ */ +/* $Id: client.c,v 1.8 2010/12/01 14:51:53 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. * @@ -108,7 +108,9 @@ static int simple(void *context __attribute__((unused)), const char **result, unsigned *len) { - static char buf[1024]; + static char bufU[1024]; + static char bufA[1024]; + char *b; /* paranoia check */ if (! result) @@ -117,18 +119,20 @@ static int simple(void *context __attribute__((unused)), switch (id) { case SASL_CB_USER: printf("please enter an authorization id: "); + b = bufU; break; case SASL_CB_AUTHNAME: printf("please enter an authentication id: "); + b = bufA; break; default: return SASL_BADPARAM; } - fgets(buf, sizeof buf, stdin); - chop(buf); - *result = buf; - if (len) *len = strlen(buf); + fgets(b, 1024, stdin); + chop(b); + *result = b; + if (len) *len = strlen(b); return SASL_OK; } @@ -317,7 +321,7 @@ int mysasl_negotiate(FILE *in, FILE *out, sasl_conn_t *conn) void usage(void) { - fprintf(stderr, "usage: client [-p port] [-s service] [-m mech] host\n"); + fprintf(stderr, "usage: client [-c|-C] [-p port] [-s service] [-m mech] host\n"); exit(EX_USAGE); } @@ -337,9 +341,19 @@ int main(int argc, char *argv[]) int salen; int niflags, error; struct sockaddr_storage local_ip, remote_ip; + int cb_flag = 0; + sasl_channel_binding_t cb; - while ((c = getopt(argc, argv, "p:s:m:")) != EOF) { + while ((c = getopt(argc, argv, "Ccp:s:m:")) != EOF) { switch(c) { + case 'C': + cb_flag = 2; /* channel bindings are critical */ + break; + + case 'c': + cb_flag = 1; /* channel bindings are optional */ + break; + case 'p': port = optarg; break; @@ -415,12 +429,22 @@ int main(int argc, char *argv[]) r = sasl_client_new(service, host, localaddr, remoteaddr, NULL, 0, &conn); if (r != SASL_OK) saslfail(r, "allocating connection state"); + if (cb_flag) { + cb.name = "sasl-sample"; + cb.critical = cb_flag > 1; + cb.data = "this is a test of channel binding"; + cb.len = strlen(cb.data); + + sasl_setprop(conn, SASL_CHANNEL_BINDING, &cb); + } + /* set external properties here sasl_setprop(conn, SASL_SSF_EXTERNAL, &extprops); */ /* set required security properties here sasl_setprop(conn, SASL_SEC_PROPS, &secprops); */ + in = fdopen(fd, "r"); out = fdopen(fd, "w"); @@ -439,5 +463,5 @@ int main(int argc, char *argv[]) sasl_done(); - return 0; + return r; } diff --git a/sample/server.c b/sample/server.c index e0af99c8..f5aff680 100644 --- a/sample/server.c +++ b/sample/server.c @@ -1,4 +1,4 @@ -/* $Id: server.c,v 1.9 2004/03/29 14:56:40 rjs3 Exp $ */ +/* $Id: server.c,v 1.10 2010/12/01 14:51:53 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. * @@ -38,6 +38,30 @@ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +/* + * Copyright 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ #include @@ -59,6 +83,11 @@ #include +#ifdef HAVE_GSS_GET_NAME_ATTRIBUTE +#include +#include +#endif + #include "common.h" #if !defined(IPV6_BINDV6ONLY) && defined(IN6P_IPV6_V6ONLY) @@ -71,6 +100,13 @@ #undef IPV6_V6ONLY #endif +#ifdef HAVE_GSS_GET_NAME_ATTRIBUTE +static OM_uint32 +enumerateAttributes(OM_uint32 *minor, + gss_name_t name, + int noisy); +#endif + /* create a socket listening on port 'port' */ /* if af is PF_UNSPEC more than one socket may be returned */ /* the returned list is dynamically allocated, so caller needs to free it */ @@ -154,7 +190,7 @@ int *listensock(const char *port, const int af) void usage(void) { - fprintf(stderr, "usage: server [-p port] [-s service] [-m mech]\n"); + fprintf(stderr, "usage: server [-C|-c] [-h hostname] [-p port] [-s service] [-m mech]\n"); exit(EX_USAGE); } @@ -170,6 +206,9 @@ int mysasl_negotiate(FILE *in, FILE *out, sasl_conn_t *conn) int len; int r = SASL_FAIL; const char *userid; +#ifdef HAVE_GSS_GET_NAME_ATTRIBUTE + gss_name_t peer = GSS_C_NO_NAME; +#endif /* generate the capability list */ if (mech) { @@ -273,6 +312,14 @@ int mysasl_negotiate(FILE *in, FILE *out, sasl_conn_t *conn) r = sasl_getprop(conn, SASL_USERNAME, (const void **) &userid); printf("successful authentication '%s'\n", userid); +#ifdef HAVE_GSS_GET_NAME_ATTRIBUTE + r = sasl_getprop(conn, SASL_GSS_PEER_NAME, (const void **) &peer); + if (peer != GSS_C_NO_NAME) { + OM_uint32 minor; + enumerateAttributes(&minor, peer, 1); + } +#endif + return 0; } @@ -281,12 +328,26 @@ int main(int argc, char *argv[]) int c; char *port = "12345"; char *service = "rcmd"; + char *hostname = NULL; int *l, maxfd=0; int r, i; sasl_conn_t *conn; + int cb_flag = 0; - while ((c = getopt(argc, argv, "p:s:m:")) != EOF) { + while ((c = getopt(argc, argv, "Cch:p:s:m:")) != EOF) { switch(c) { + case 'C': + cb_flag = 2; /* channel bindings are critical */ + break; + + case 'c': + cb_flag = 1; /* channel bindings are present */ + break; + + case 'h': + hostname = optarg; + break; + case 'p': port = optarg; break; @@ -330,6 +391,7 @@ int main(int argc, char *argv[]) int nfds, fd = -1; FILE *in, *out; fd_set readfds; + sasl_channel_binding_t cb; FD_ZERO(&readfds); for (i = 1; i <= l[0]; i++) @@ -394,18 +456,30 @@ int main(int argc, char *argv[]) } snprintf(remoteaddr, sizeof(remoteaddr), "%s;%s", hbuf, pbuf); - r = gethostname(myhostname, sizeof(myhostname)-1); - if(r == -1) saslfail(r, "getting hostname"); + if (hostname == NULL) { + r = gethostname(myhostname, sizeof(myhostname)-1); + if(r == -1) saslfail(r, "getting hostname"); + hostname = myhostname; + } - r = sasl_server_new(service, myhostname, NULL, localaddr, remoteaddr, + r = sasl_server_new(service, hostname, NULL, localaddr, remoteaddr, NULL, 0, &conn); if (r != SASL_OK) saslfail(r, "allocating connection state"); + cb.name = "sasl-sample"; + cb.critical = cb_flag > 1; + cb.data = "this is a test of channel binding"; + cb.len = strlen(cb.data); + + if (cb_flag) { + sasl_setprop(conn, SASL_CHANNEL_BINDING, &cb); + } + /* set external properties here - sasl_setprop(conn, SASL_SSF_EXTERNAL, &extprops); */ + sasl_setprop(conn, SASL_SSF_EXTERNAL, &extprops); */ /* set required security properties here - sasl_setprop(conn, SASL_SEC_PROPS, &secprops); */ + sasl_setprop(conn, SASL_SEC_PROPS, &secprops); */ in = fdopen(fd, "r"); out = fdopen(fd, "w"); @@ -426,3 +500,119 @@ int main(int argc, char *argv[]) sasl_done(); } + +#ifdef HAVE_GSS_GET_NAME_ATTRIBUTE +static void displayStatus_1(m, code, type) + char *m; + OM_uint32 code; + int type; +{ + OM_uint32 maj_stat, min_stat; + gss_buffer_desc msg; + OM_uint32 msg_ctx; + + msg_ctx = 0; + while (1) { + maj_stat = gss_display_status(&min_stat, code, + type, GSS_C_NULL_OID, + &msg_ctx, &msg); + fprintf(stderr, "%s: %s\n", m, (char *)msg.value); + (void) gss_release_buffer(&min_stat, &msg); + + if (!msg_ctx) + break; + } +} + +static void displayStatus(msg, maj_stat, min_stat) + char *msg; + OM_uint32 maj_stat; + OM_uint32 min_stat; +{ + displayStatus_1(msg, maj_stat, GSS_C_GSS_CODE); + displayStatus_1(msg, min_stat, GSS_C_MECH_CODE); +} + +static void +dumpAttribute(OM_uint32 *minor, + gss_name_t name, + gss_buffer_t attribute, + int noisy) +{ + OM_uint32 major, tmp; + gss_buffer_desc value; + gss_buffer_desc display_value; + int authenticated = 0; + int complete = 0; + int more = -1; + unsigned int i; + + while (more != 0) { + value.value = NULL; + display_value.value = NULL; + + major = gss_get_name_attribute(minor, + name, + attribute, + &authenticated, + &complete, + &value, + &display_value, + &more); + if (GSS_ERROR(major)) { + displayStatus("gss_get_name_attribute", major, *minor); + break; + } + + printf("Attribute %.*s %s %s\n\n%.*s\n", + (int)attribute->length, (char *)attribute->value, + authenticated ? "Authenticated" : "", + complete ? "Complete" : "", + (int)display_value.length, (char *)display_value.value); + + if (noisy) { + for (i = 0; i < value.length; i++) { + if ((i % 32) == 0) + printf("\n"); + printf("%02x", ((char *)value.value)[i] & 0xFF); + } + printf("\n\n"); + } + + gss_release_buffer(&tmp, &value); + gss_release_buffer(&tmp, &display_value); + } +} + +static OM_uint32 +enumerateAttributes(OM_uint32 *minor, + gss_name_t name, + int noisy) +{ + OM_uint32 major, tmp; + int name_is_MN; + gss_OID mech = GSS_C_NO_OID; + gss_buffer_set_t attrs = GSS_C_NO_BUFFER_SET; + unsigned int i; + + major = gss_inquire_name(minor, + name, + &name_is_MN, + &mech, + &attrs); + if (GSS_ERROR(major)) { + displayStatus("gss_inquire_name", major, *minor); + return major; + } + + if (attrs != GSS_C_NO_BUFFER_SET) { + for (i = 0; i < attrs->count; i++) + dumpAttribute(minor, name, &attrs->elements[i], noisy); + } + + gss_release_oid(&tmp, &mech); + gss_release_buffer_set(&tmp, &attrs); + + return major; +} +#endif From 8427a1ff6342a6caf7101170e46e8d81a903401c Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Wed, 1 Dec 2010 15:08:00 +0000 Subject: [PATCH 047/796] Added support for ordering mechanisms by strength (on the client side), or using the client_mech_list option. --- lib/client.c | 168 +++++++++++++++++++++++++++++++++++++++++++------- lib/saslint.h | 4 +- 2 files changed, 148 insertions(+), 24 deletions(-) diff --git a/lib/client.c b/lib/client.c index 8c7bff75..2e0e652e 100644 --- a/lib/client.c +++ b/lib/client.c @@ -1,7 +1,7 @@ /* SASL client API implementation * Rob Siemborski * Tim Martin - * $Id: client.c,v 1.78 2010/12/01 14:51:53 mel Exp $ + * $Id: client.c,v 1.79 2010/12/01 15:08:00 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -118,9 +118,8 @@ static int client_done(void) { return SASL_CONTINUE; } - cm = cmechlist->mech_list; /* m point to beggining of the list */ - while (cm!=NULL) - { + cm = cmechlist->mech_list; /* m point to beginning of the list */ + while (cm != NULL) { cprevm = cm; cm = cm->next; @@ -140,12 +139,44 @@ static int client_done(void) { return SASL_OK; } +/* This is nearly identical to the version in server.c. + Keep in sync. */ +static int mech_compare(const sasl_client_plug_t *a, + const sasl_client_plug_t *b) +{ + unsigned sec_diff; + + if (a->max_ssf > b->max_ssf) return 1; + if (a->max_ssf < b->max_ssf) return -1; + + /* XXX the following is fairly arbitrary, but its independent + of the order in which the plugins are loaded + */ + sec_diff = a->security_flags ^ b->security_flags; + if (sec_diff & a->security_flags & SASL_SEC_FORWARD_SECRECY) return 1; + if (sec_diff & b->security_flags & SASL_SEC_FORWARD_SECRECY) return -1; + if (sec_diff & a->security_flags & SASL_SEC_NOACTIVE) return 1; + if (sec_diff & b->security_flags & SASL_SEC_NOACTIVE) return -1; + if (sec_diff & a->security_flags & SASL_SEC_NODICTIONARY) return 1; + if (sec_diff & b->security_flags & SASL_SEC_NODICTIONARY) return -1; + if (sec_diff & a->security_flags & SASL_SEC_MUTUAL_AUTH) return 1; + if (sec_diff & b->security_flags & SASL_SEC_MUTUAL_AUTH) return -1; + if (sec_diff & a->security_flags & SASL_SEC_NOANONYMOUS) return 1; + if (sec_diff & b->security_flags & SASL_SEC_NOANONYMOUS) return -1; + if (sec_diff & a->security_flags & SASL_SEC_NOPLAINTEXT) return 1; + if (sec_diff & b->security_flags & SASL_SEC_NOPLAINTEXT) return -1; + if (sec_diff & a->security_flags & SASL_SEC_PASS_CREDENTIALS) return 1; + if (sec_diff & b->security_flags & SASL_SEC_PASS_CREDENTIALS) return -1; + + return 0; +} + int sasl_client_add_plugin(const char *plugname, sasl_client_plug_init_t *entry_point) { int plugcount; sasl_client_plug_t *pluglist; - cmechanism_t *mech; + cmechanism_t *mech, *mp; int result; int version; int lupe; @@ -173,19 +204,32 @@ int sasl_client_add_plugin(const char *plugname, return SASL_BADVERS; } - for (lupe=0; lupe< plugcount ;lupe++) + for (lupe=0; lupe < plugcount; lupe++, pluglist++) { mech = sasl_ALLOC(sizeof(cmechanism_t)); if (!mech) return SASL_NOMEM; - mech->m.plug = pluglist++; + mech->m.plug = pluglist; if (_sasl_strdup(plugname, &mech->m.plugname, NULL) != SASL_OK) { sasl_FREE(mech); return SASL_NOMEM; } mech->m.version = version; - mech->next = cmechlist->mech_list; - cmechlist->mech_list = mech; + + /* sort mech_list by relative "strength" */ + mp = cmechlist->mech_list; + if (!mp || mech_compare(pluglist, mp->m.plug) >= 0) { + /* add mech to head of list */ + mech->next = cmechlist->mech_list; + cmechlist->mech_list = mech; + } else { + /* find where to insert mech into list */ + while (mp->next && + mech_compare(pluglist, mp->next->m.plug) <= 0) mp = mp->next; + mech->next = mp->next; + mp->next = mech; + } + cmechlist->mech_length++; } @@ -296,6 +340,19 @@ static void client_dispose(sasl_conn_t *pconn) sasl_FREE(c_conn->cparams); } + if (c_conn->mech_list != cmechlist->mech_list) { + /* free connection-specific mech_list */ + cmechanism_t *m, *prevm; + + m = c_conn->mech_list; /* m point to beginning of the list */ + + while (m) { + prevm = m; + m = m->next; + sasl_FREE(prevm); + } + } + _sasl_conn_dispose(pconn); } @@ -333,6 +390,9 @@ int sasl_client_new(const char *service, char name[MAXHOSTNAMELEN]; sasl_client_conn_t *conn; sasl_utils_t *utils; + sasl_getopt_t *getopt; + void *context; + const char *mlist = NULL; if (_sasl_client_active == 0) return SASL_NOTINIT; @@ -371,10 +431,68 @@ int sasl_client_new(const char *service, } utils->conn= *pconn; + conn->cparams->utils = utils; + + if(_sasl_getcallback(*pconn, SASL_CB_GETOPT, (sasl_callback_ft *)&getopt, &context) == SASL_OK) { + getopt(context, NULL, "client_mech_list", &mlist, NULL); + } + + /* if we have a client_mech_list, create ordered list of + available mechanisms for this conn */ + if (mlist) { + const char *cp; + cmechanism_t *mptr, *tail = NULL; + cmechanism_t *new; + + while (*mlist) { + /* find end of current mech name */ + for (cp = mlist; *cp && !isspace((int) *cp); cp++); + + /* search for mech name in loaded plugins */ + for (mptr = cmechlist->mech_list; mptr; mptr = mptr->next) { + const sasl_client_plug_t *plug = mptr->m.plug; + + if (((size_t) (cp - mlist) == strlen(plug->mech_name)) && + !strncasecmp(mlist, plug->mech_name, strlen(plug->mech_name))) + /* found a match */ + break; + } + if (mptr) { + new = sasl_ALLOC(sizeof(cmechanism_t)); + if (!new) { + result = SASL_NOMEM; + goto failed_client_new; + } + memcpy(&new->m, &mptr->m, sizeof(client_sasl_mechanism_t)); + new->next = NULL; + + if (!conn->mech_list) { + conn->mech_list = new; + tail = conn->mech_list; + } else { + tail->next = new; + tail = new; + } + conn->mech_length++; + } + + /* find next mech name */ + mlist = cp; + while (*mlist && isspace((int) *mlist)) mlist++; + } + } else { + conn->mech_list = cmechlist->mech_list; + conn->mech_length = cmechlist->mech_length; + } + + if (conn->mech_list == NULL) { + sasl_seterror(*pconn, 0, "No worthy mechs found"); + result = SASL_NOMECH; + goto failed_client_new; + } /* Setup the non-lazy parts of cparams, the rest is done in * sasl_client_start */ - conn->cparams->utils = utils; conn->cparams->canon_user = &_sasl_canon_user_lookup; conn->cparams->flags = flags; conn->cparams->prompt_supp = (*pconn)->callbacks; @@ -389,6 +507,7 @@ int sasl_client_new(const char *service, if (result == SASL_OK) return SASL_OK; +failed_client_new: /* result isn't SASL_OK */ _sasl_conn_dispose(*pconn); sasl_FREE(*pconn); @@ -457,10 +576,12 @@ _sasl_client_order_mechs(const sasl_utils_t *utils, if (list == NULL) return SASL_NOMEM; - /* xxx confirm this with rfc 2222 - * SASL mechanism allowable characters are "AZaz-_" - * seperators can be any other characters and of any length - * even variable lengths between + /* As per RFC 4422: + * SASL mechanism allowable characters are "AZ-_" + * separators can be any other characters and of any length + * even variable lengths between. + * + * But for convenience we accept lowercase ASCII. * * Apps should be encouraged to simply use space or comma space * though @@ -605,7 +726,7 @@ int sasl_client_start(sasl_conn_t *conn, &server_can_cb); if (result != 0) goto done; - + /* * Determine channel binding disposition based on whether we * are doing mechanism negotiation and whether server supports @@ -617,8 +738,8 @@ int sasl_client_start(sasl_conn_t *conn, goto done; for (i = 0, name = ordered_mechs; i < list_len; i++) { - /* foreach in client list */ - for (m = cmechlist->mech_list; m != NULL; m = m->next) { + /* for each mechanism in client's list */ + for (m = c_conn->mech_list; m != NULL; m = m->next) { int myflags, plus; if (!_sasl_is_equal_mech(name, m->m.plug->mech_name, &plus)) @@ -841,12 +962,12 @@ int sasl_client_step(sasl_conn_t *conn, * added up */ -static unsigned mech_names_len() +static unsigned mech_names_len(cmechanism_t *mech_list) { cmechanism_t *listptr; unsigned result = 0; - for (listptr = cmechlist->mech_list; + for (listptr = mech_list; listptr; listptr = listptr->next) result += (unsigned) strlen(listptr->m.plug->mech_name); @@ -863,6 +984,7 @@ int _sasl_client_listmech(sasl_conn_t *conn, unsigned *plen, int *pcount) { + sasl_client_conn_t *c_conn = (sasl_client_conn_t *)conn; cmechanism_t *m = NULL; sasl_ssf_t minssf = 0; int ret; @@ -894,13 +1016,13 @@ int _sasl_client_listmech(sasl_conn_t *conn, minssf = conn->props.min_ssf - conn->external.ssf; } - if (! cmechlist || cmechlist->mech_length <= 0) { + if (!c_conn->mech_list || c_conn->mech_length <= 0) { INTERROR(conn, SASL_NOMECH); } resultlen = (prefix ? strlen(prefix) : 0) - + (strlen(mysep) * (cmechlist->mech_length - 1)) - + mech_names_len() + + (strlen(mysep) * (c_conn->mech_length - 1)) + + mech_names_len(c_conn->mech_list) + (suffix ? strlen(suffix) : 0) + 1; ret = _buf_alloc(&conn->mechlist_buf, @@ -915,7 +1037,7 @@ int _sasl_client_listmech(sasl_conn_t *conn, } flag = 0; - for (m = cmechlist->mech_list; m != NULL; m = m->next) { + for (m = c_conn->mech_list; m != NULL; m = m->next) { /* do we have the prompts for it? */ if (!have_prompts(conn, m->m.plug)) { continue; diff --git a/lib/saslint.h b/lib/saslint.h index 95dc47c7..869b4204 100644 --- a/lib/saslint.h +++ b/lib/saslint.h @@ -1,7 +1,7 @@ /* saslint.h - internal SASL library definitions * Rob Siemborski * Tim Martin - * $Id: saslint.h,v 1.70 2010/12/01 14:51:53 mel Exp $ + * $Id: saslint.h,v 1.71 2010/12/01 15:08:00 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -261,6 +261,8 @@ typedef struct sasl_client_conn { char *clientFQDN; + cmechanism_t *mech_list; /* list of available mechanisms */ + int mech_length; /* number of available mechanisms */ } sasl_client_conn_t; typedef struct sasl_allocation_utils { From 4c9aacc9802cd4083cd8a01cb3bcb4257821f53d Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Wed, 1 Dec 2010 15:18:12 +0000 Subject: [PATCH 048/796] Mostly reformatting changes --- lib/server.c | 58 +++++++++++++++++++++++++++------------------------- 1 file changed, 30 insertions(+), 28 deletions(-) diff --git a/lib/server.c b/lib/server.c index a7170c44..c26c8311 100644 --- a/lib/server.c +++ b/lib/server.c @@ -1,7 +1,7 @@ /* SASL server API implementation * Rob Siemborski * Tim Martin - * $Id: server.c,v 1.162 2010/12/01 14:51:53 mel Exp $ + * $Id: server.c,v 1.163 2010/12/01 15:18:12 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -363,8 +363,8 @@ static int init_mechlist(void) newutils->checkpass = &_sasl_checkpass; mechlist->utils = newutils; - mechlist->mech_list=NULL; - mechlist->mech_length=0; + mechlist->mech_list = NULL; + mechlist->mech_length = 0; return SASL_OK; } @@ -530,7 +530,7 @@ static int server_done(void) { mechlist->utils); } - sasl_FREE(prevm->m.plugname); + sasl_FREE(prevm->m.plugname); sasl_FREE(prevm); } _sasl_free_utils(&mechlist->utils); @@ -1205,13 +1205,14 @@ static int mech_permitted(sasl_conn_t *conn, } context = NULL; - if(plug->mech_avail - && (ret = plug->mech_avail(plug->glob_context, - s_conn->sparams, (void **)&context)) != SASL_OK ) { - if(ret == SASL_NOMECH) { + if (plug->mech_avail + && (ret = plug->mech_avail(plug->glob_context, + s_conn->sparams, + (void **)&context)) != SASL_OK ) { + if (ret == SASL_NOMECH) { /* Mark this mech as no good for this connection */ cur = sasl_ALLOC(sizeof(context_list_t)); - if(!cur) { + if (!cur) { MEMERROR(conn); return SASL_NOMECH; } @@ -1225,10 +1226,10 @@ static int mech_permitted(sasl_conn_t *conn, /* Error should be set by mech_avail call */ return SASL_NOMECH; - } else if(context) { + } else if (context) { /* Save this context */ cur = sasl_ALLOC(sizeof(context_list_t)); - if(!cur) { + if (!cur) { MEMERROR(conn); return SASL_NOMECH; } @@ -1277,7 +1278,7 @@ static int mech_permitted(sasl_conn_t *conn, } /* Check Features */ - if(plug->features & SASL_FEAT_GETSECRET) { + if (plug->features & SASL_FEAT_GETSECRET) { /* We no longer support sasl_server_{get,put}secret */ sasl_seterror(conn, 0, "mech %s requires unprovided secret facility", @@ -1349,7 +1350,7 @@ int sasl_server_start(sasl_conn_t *conn, /* check parameters */ if(!conn) return SASL_BADPARAM; - if (!mech || ((clientin==NULL) && (clientinlen>0))) + if (!mech || ((clientin == NULL) && (clientinlen > 0))) PARAMERROR(conn); if (serverout) *serverout = NULL; @@ -1366,7 +1367,7 @@ int sasl_server_start(sasl_conn_t *conn, m = m->next; } - if (m==NULL) { + if (m == NULL) { sasl_seterror(conn, 0, "Couldn't find mech %s", mech); result = SASL_NOMECH; goto done; @@ -1452,24 +1453,25 @@ int sasl_server_start(sasl_conn_t *conn, s_conn->mech = m; - if(!conn->context) { + if (!conn->context) { /* Note that we don't hand over a new challenge */ result = s_conn->mech->m.plug->mech_new(s_conn->mech->m.plug->glob_context, - s_conn->sparams, - NULL, - 0, - &(conn->context)); + s_conn->sparams, + NULL, + 0, + &(conn->context)); } else { /* the work was already done by mech_avail! */ result = SASL_OK; } if (result == SASL_OK) { - if(clientin) { - if(s_conn->mech->m.plug->features & SASL_FEAT_SERVER_FIRST) { + if (clientin) { + if (s_conn->mech->m.plug->features & SASL_FEAT_SERVER_FIRST) { /* Remote sent first, but mechanism does not support it. * RFC 2222 says we fail at this point. */ - sasl_seterror(conn, 0, + sasl_seterror(conn, + 0, "Remote sent first but mech does not allow it."); result = SASL_BADPROT; } else { @@ -1481,10 +1483,10 @@ int sasl_server_start(sasl_conn_t *conn, serveroutlen); } } else { - if(s_conn->mech->m.plug->features & SASL_FEAT_WANT_CLIENT_FIRST) { + if (s_conn->mech->m.plug->features & SASL_FEAT_WANT_CLIENT_FIRST) { /* Mech wants client first anyway, so we should do that */ - *serverout = ""; - *serveroutlen = 0; + if (serverout) *serverout = ""; + if (serveroutlen) *serveroutlen = 0; result = SASL_CONTINUE; } else { /* Mech wants server-first, so let them have it */ @@ -1498,12 +1500,12 @@ int sasl_server_start(sasl_conn_t *conn, } done: - if( result != SASL_OK + if ( result != SASL_OK && result != SASL_CONTINUE && result != SASL_INTERACT) { - if(conn->context) { + if (conn->context) { s_conn->mech->m.plug->mech_dispose(conn->context, - s_conn->sparams->utils); + s_conn->sparams->utils); conn->context = NULL; } } From d381965922dd2583c6a2dd52154cb013f673b346 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Wed, 1 Dec 2010 15:19:52 +0000 Subject: [PATCH 049/796] server_idle needs to be using server's list of available SASL mechanisms --- lib/server.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/lib/server.c b/lib/server.c index c26c8311..ab07a448 100644 --- a/lib/server.c +++ b/lib/server.c @@ -1,7 +1,7 @@ /* SASL server API implementation * Rob Siemborski * Tim Martin - * $Id: server.c,v 1.163 2010/12/01 15:18:12 mel Exp $ + * $Id: server.c,v 1.164 2010/12/01 15:19:52 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -549,18 +549,23 @@ static int server_done(void) { static int server_idle(sasl_conn_t *conn) { + sasl_server_conn_t *s_conn = (sasl_server_conn_t *) conn; mechanism_t *m; - if (! mechlist) + + if (! mechlist) { return 0; - - for (m = mechlist->mech_list; + } + + for (m = s_conn->mech_list; m != NULL; - m = m->next) + m = m->next) { if (m->m.plug->idle && m->m.plug->idle(m->m.plug->glob_context, - conn, - conn ? ((sasl_server_conn_t *)conn)->sparams : NULL)) + conn, + conn ? ((sasl_server_conn_t *)conn)->sparams : NULL)) { return 1; + } + } return 0; } From 97988f40ae4ff66541ad035c6d5eb1aeb2a0d9cf Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Wed, 1 Dec 2010 15:30:45 +0000 Subject: [PATCH 050/796] Some reformatting and safer handling of 'free after SASL server shutdown' condition in server_dispose --- lib/server.c | 88 +++++++++++++++++++++++++++++----------------------- 1 file changed, 50 insertions(+), 38 deletions(-) diff --git a/lib/server.c b/lib/server.c index ab07a448..b8694c91 100644 --- a/lib/server.c +++ b/lib/server.c @@ -1,7 +1,7 @@ /* SASL server API implementation * Rob Siemborski * Tim Martin - * $Id: server.c,v 1.164 2010/12/01 15:19:52 mel Exp $ + * $Id: server.c,v 1.165 2010/12/01 15:30:45 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -303,52 +303,64 @@ int sasl_setpass(sasl_conn_t *conn, /* local mechanism which disposes of server */ static void server_dispose(sasl_conn_t *pconn) { - sasl_server_conn_t *s_conn= (sasl_server_conn_t *) pconn; - context_list_t *cur, *cur_next; - - if (s_conn->mech - && s_conn->mech->m.plug->mech_dispose) { - s_conn->mech->m.plug->mech_dispose(pconn->context, - s_conn->sparams->utils); - } - pconn->context = NULL; - - for(cur = s_conn->mech_contexts; cur; cur=cur_next) { - cur_next = cur->next; - if(cur->context) - cur->mech->m.plug->mech_dispose(cur->context, s_conn->sparams->utils); - sasl_FREE(cur); - } - s_conn->mech_contexts = NULL; + sasl_server_conn_t *s_conn= (sasl_server_conn_t *) pconn; + context_list_t *cur, *cur_next; + + /* Just sanity check that sasl_server_done wasn't called yet */ + if (_sasl_server_active != 0) { + if (s_conn->mech) { + void (*mech_dispose)(void *conn_context, const sasl_utils_t *utils); + + mech_dispose = s_conn->mech->m.plug->mech_dispose; + + if (mech_dispose) { + mech_dispose(pconn->context, s_conn->sparams->utils); + } + } + pconn->context = NULL; + + for(cur = s_conn->mech_contexts; cur; cur=cur_next) { + cur_next = cur->next; + if (cur->context) { + cur->mech->m.plug->mech_dispose(cur->context, s_conn->sparams->utils); + } + sasl_FREE(cur); + } + s_conn->mech_contexts = NULL; + } - _sasl_free_utils(&s_conn->sparams->utils); + _sasl_free_utils(&s_conn->sparams->utils); - if (s_conn->sparams->propctx) - prop_dispose(&s_conn->sparams->propctx); + if (s_conn->sparams->propctx) { + prop_dispose(&s_conn->sparams->propctx); + } - if (s_conn->appname) - sasl_FREE(s_conn->appname); + if (s_conn->appname) { + sasl_FREE(s_conn->appname); + } - if (s_conn->user_realm) - sasl_FREE(s_conn->user_realm); + if (s_conn->user_realm) { + sasl_FREE(s_conn->user_realm); + } - if (s_conn->sparams) - sasl_FREE(s_conn->sparams); + if (s_conn->sparams) { + sasl_FREE(s_conn->sparams); + } - if (s_conn->mech_list != mechlist->mech_list) { - /* free connection-specific mech_list */ - mechanism_t *m, *prevm; + if (s_conn->mech_list != mechlist->mech_list) { + /* free connection-specific mech_list */ + mechanism_t *m, *prevm; - m = s_conn->mech_list; /* m point to beginning of the list */ + m = s_conn->mech_list; /* m point to beginning of the list */ - while (m) { - prevm = m; - m = m->next; - sasl_FREE(prevm); - } - } + while (m) { + prevm = m; + m = m->next; + sasl_FREE(prevm); + } + } - _sasl_conn_dispose(pconn); + _sasl_conn_dispose(pconn); } static int init_mechlist(void) From 5e68ebcb5b7c381c70acff01b7916be535905c53 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Wed, 1 Dec 2010 15:34:21 +0000 Subject: [PATCH 051/796] Updated for major todays commits --- ChangeLog | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/ChangeLog b/ChangeLog index 4a4028a5..6df26f3d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,30 @@ +2010-12-01 Alexey Melnikov + * lib/server.c: Some reformatting and safer handling of 'free + after SASL server shutdown' condition in server_dispose. + +2010-12-01 Alexey Melnikov + * lib/server.c: server_idle needs to obey server's SASL mechanism + list from the server context. + +2010-12-01 Alexey Melnikov + * lib/client.c, lib/saslint.h: Added support for ordering + SASL mechanisms by strength (on the client side), + or using the client_mech_list option. + +2010-12-01 Alexey Melnikov + * include/sasl.h, include/saslplug.h, lib/client.c, lib/common.c, + lib/saslint.h, lib/server.c, sample/Makefile.am, sample/client.c, + sample/server.c: Added support for channel bindings + (patch by Luke Howard). + +2010-12-01 Alexey Melnikov + * lib/saslutil.c: Fixed the random number generator on Windows + to actually produce random output on each run. + +2010-12-01 Alexey Melnikov + * lib/common.c: Updated textual representations of some error + messages + 2010-11-30 Alexey Melnikov * plugins/digestmd5.c: Eliminated some "signed/unsigned mismatch" warnings. From e7402fdbf24aa866dc71b928a81641ddb1a92878 Mon Sep 17 00:00:00 2001 From: Ken Murchison Date: Wed, 1 Dec 2010 15:49:25 +0000 Subject: [PATCH 052/796] Fix typo --- lib/client.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/client.c b/lib/client.c index 2e0e652e..84c0004a 100644 --- a/lib/client.c +++ b/lib/client.c @@ -1,7 +1,7 @@ /* SASL client API implementation * Rob Siemborski * Tim Martin - * $Id: client.c,v 1.79 2010/12/01 15:08:00 mel Exp $ + * $Id: client.c,v 1.80 2010/12/01 15:49:25 murch Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -433,7 +433,7 @@ int sasl_client_new(const char *service, utils->conn= *pconn; conn->cparams->utils = utils; - if(_sasl_getcallback(*pconn, SASL_CB_GETOPT, (sasl_callback_ft *)&getopt, &context) == SASL_OK) { + if(_sasl_getcallback(*pconn, SASL_CB_GETOPT, (sasl_callback_t *)&getopt, &context) == SASL_OK) { getopt(context, NULL, "client_mech_list", &mlist, NULL); } From 55f5317a0453d9e158161695931a73f3a54d1b53 Mon Sep 17 00:00:00 2001 From: Ken Murchison Date: Thu, 2 Dec 2010 16:26:17 +0000 Subject: [PATCH 053/796] - Changed SASL_FEAT_CHANNEL_BINDING value so it doesn't conflict with SASL_FEAT_SERVICE - Aligned SASL_FEAT values so they are easier to read --- include/saslplug.h | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/include/saslplug.h b/include/saslplug.h index 9c7fdc25..6a15d519 100755 --- a/include/saslplug.h +++ b/include/saslplug.h @@ -322,38 +322,40 @@ typedef struct sasl_client_params { /* This indicates that the mechanism prefers to do client-send-first * if the protocol allows it. */ -#define SASL_FEAT_WANT_CLIENT_FIRST 0x0002 +#define SASL_FEAT_WANT_CLIENT_FIRST 0x0002 -/* This feature is deprecated, instead, plugins should set *serverout to +/* This feature is deprecated. Instead, plugins should set *serverout to * non-NULL and return SASL_OK intelligently to allow flexible use of - * server-last semantics */ -/* #define SASL_FEAT_WANT_SERVER_LAST 0x0004 */ + * server-last semantics +#define SASL_FEAT_WANT_SERVER_LAST 0x0004 +*/ -/* This feature is deprecated, instead plugins should correctly set - * SASL_FEAT_SERVER_FIRST as needed */ -/* #define SASL_FEAT_INTERNAL_CLIENT_FIRST 0x0008 */ +/* This feature is deprecated. Instead, plugins should correctly set + * SASL_FEAT_SERVER_FIRST as needed +#define SASL_FEAT_INTERNAL_CLIENT_FIRST 0x0008 +*/ /* This indicates that the plugin is server-first only. * Not defining either of SASL_FEAT_SERVER_FIRST or - * SASL_FEAT_WANT_CLIENT_FIRST indicates that the mechanism will take care - * of the client-first situation internally. + * SASL_FEAT_WANT_CLIENT_FIRST indicates that the mechanism + * will handle the client-first situation internally. */ -#define SASL_FEAT_SERVER_FIRST 0x0010 +#define SASL_FEAT_SERVER_FIRST 0x0010 /* This plugin allows proxying */ -#define SASL_FEAT_ALLOWS_PROXY 0x0020 +#define SASL_FEAT_ALLOWS_PROXY 0x0020 /* server plugin don't use cleartext userPassword attribute */ -#define SASL_FEAT_DONTUSE_USERPASSWD 0x0080 +#define SASL_FEAT_DONTUSE_USERPASSWD 0x0080 /* Underlying mechanism uses GSS framing */ -#define SASL_FEAT_GSS_FRAMING 0x0100 +#define SASL_FEAT_GSS_FRAMING 0x0100 /* Underlying mechanism supports channel binding */ -#define SASL_FEAT_CHANNEL_BINDING 0x0200 +#define SASL_FEAT_CHANNEL_BINDING 0x0800 /* client plug-in features */ -#define SASL_FEAT_NEEDSERVERFQDN 0x0001 +#define SASL_FEAT_NEEDSERVERFQDN 0x0001 /* a C object for a client mechanism */ From 2c2a372b0469ae0611ee610108010fab8e717921 Mon Sep 17 00:00:00 2001 From: Ken Murchison Date: Fri, 3 Dec 2010 17:42:33 +0000 Subject: [PATCH 054/796] use add_to_challenge() to construct final server challenge (rspauth) --- plugins/digestmd5.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/plugins/digestmd5.c b/plugins/digestmd5.c index f0e520b6..815d715a 100644 --- a/plugins/digestmd5.c +++ b/plugins/digestmd5.c @@ -3,7 +3,7 @@ * Rob Siemborski * Tim Martin * Alexey Melnikov - * $Id: digestmd5.c,v 1.197 2010/11/30 12:09:17 mel Exp $ + * $Id: digestmd5.c,v 1.198 2010/12/03 17:42:33 murch Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -122,7 +122,7 @@ extern int gethostname(char *, int); /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: digestmd5.c,v 1.197 2010/11/30 12:09:17 mel Exp $"; +static const char plugin_id[] = "$Id: digestmd5.c,v 1.198 2010/12/03 17:42:33 murch Exp $"; /* Definitions */ #define NONCE_SIZE (32) /* arbitrary */ @@ -2745,17 +2745,17 @@ static int digestmd5_server_mech_step2(server_context_t *stext, /* add to challenge */ { - unsigned resplen = (unsigned) - (strlen(text->response_value) + strlen("rspauth") + 3); - - result = _plug_buf_alloc(sparams->utils, &(text->out_buf), - &(text->out_buf_len), resplen); - if(result != SASL_OK) { + unsigned resplen = 0; + + if (add_to_challenge(sparams->utils, + &text->out_buf, &text->out_buf_len, &resplen, + "rspauth", (unsigned char *) text->response_value, + FALSE) != SASL_OK) { + SETERROR(sparams->utils, "internal error: add_to_challenge failed"); + result = SASL_FAIL; goto FreeAllMem; } - sprintf(text->out_buf, "rspauth=%s", text->response_value); - /* self check */ if (strlen(text->out_buf) > 2048) { result = SASL_FAIL; From 486e650ed0fc1eb8d323f12a2850c51b8cd4f803 Mon Sep 17 00:00:00 2001 From: Ken Murchison Date: Fri, 3 Dec 2010 18:05:29 +0000 Subject: [PATCH 055/796] fix for multiple reauths (was flushing cache after first reauth) --- plugins/digestmd5.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/digestmd5.c b/plugins/digestmd5.c index 815d715a..c49aba5e 100644 --- a/plugins/digestmd5.c +++ b/plugins/digestmd5.c @@ -3,7 +3,7 @@ * Rob Siemborski * Tim Martin * Alexey Melnikov - * $Id: digestmd5.c,v 1.198 2010/12/03 17:42:33 murch Exp $ + * $Id: digestmd5.c,v 1.199 2010/12/03 18:05:29 murch Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -122,7 +122,7 @@ extern int gethostname(char *, int); /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: digestmd5.c,v 1.198 2010/12/03 17:42:33 murch Exp $"; +static const char plugin_id[] = "$Id: digestmd5.c,v 1.199 2010/12/03 18:05:29 murch Exp $"; /* Definitions */ #define NONCE_SIZE (32) /* arbitrary */ @@ -2786,7 +2786,7 @@ static int digestmd5_server_mech_step2(server_context_t *stext, text->reauth->e[val].nonce = text->nonce; text->nonce = NULL; text->reauth->e[val].cnonce = cnonce; cnonce = NULL; } - if (text->nonce_count <= text->reauth->e[val].nonce_count) { + if (text->nonce_count < text->reauth->e[val].nonce_count) { /* paranoia. prevent replay attacks */ clear_reauth_entry(&text->reauth->e[val], SERVER, sparams->utils); } From 66dbb2a280f440e8ddb219c3fffc0b34ef69a5fa Mon Sep 17 00:00:00 2001 From: Ken Murchison Date: Fri, 14 Jan 2011 14:33:21 +0000 Subject: [PATCH 056/796] Allow DIGEST-MD5 plugin to be used for server-side HTTP Digest (RFC 2617) --- ChangeLog | 6 +++ include/sasl.h | 4 ++ include/saslplug.h | 5 +- lib/common.c | 19 +++++++- lib/server.c | 6 ++- plugins/digestmd5.c | 112 +++++++++++++++++++++++++++++++++++--------- 6 files changed, 126 insertions(+), 26 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6df26f3d..d30b139f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-01-14 Ken Murchison + * include/sasl.h, include/saslplug.h, + lib/common.c, lib/server.c, plugins/digest-md5.c: + Allow DIGEST-MD5 plugin to be used for server-side + HTTP Digest (RFC 2617) + 2010-12-01 Alexey Melnikov * lib/server.c: Some reformatting and safer handling of 'free after SASL server shutdown' condition in server_dispose. diff --git a/include/sasl.h b/include/sasl.h index d5af6bfb..b7ea9014 100755 --- a/include/sasl.h +++ b/include/sasl.h @@ -273,6 +273,7 @@ typedef unsigned sasl_ssf_t; */ #define SASL_SUCCESS_DATA 0x0004 /* server supports data on success */ #define SASL_NEED_PROXY 0x0008 /* require a mech that allows proxying */ +#define SASL_NEED_HTTP 0x0010 /* require a mech that can do HTTP auth */ /*************************** * Security Property Types * @@ -835,6 +836,9 @@ typedef struct sasl_channel_binding { #define SASL_CHANNEL_BINDING 21 +/* HTTP request method (RFC 2616) - ONLY used for HTTP Digest auth (RFC 2617) */ +#define SASL_HTTP_METHOD 22 + /* set property in SASL connection state * returns: * SASL_OK -- value set diff --git a/include/saslplug.h b/include/saslplug.h index 6a15d519..7151e553 100755 --- a/include/saslplug.h +++ b/include/saslplug.h @@ -354,6 +354,9 @@ typedef struct sasl_client_params { /* Underlying mechanism supports channel binding */ #define SASL_FEAT_CHANNEL_BINDING 0x0800 +/* This plugin can be used for HTTP authentication */ +#define SASL_FEAT_SUPPORTS_HTTP 0x1000 + /* client plug-in features */ #define SASL_FEAT_NEEDSERVERFQDN 0x0001 @@ -577,7 +580,7 @@ typedef struct sasl_server_params { /* for additions which don't require a version upgrade; set to 0 */ const void *gss_creds; /* GSS credential handle */ const sasl_channel_binding_t *cbinding; /* server channel binding */ - void *spare_ptr3; + const char *http_method; /* HTTP Digest request method */ void *spare_ptr4; int (*spare_fptr1)(); int (*spare_fptr2)(); diff --git a/lib/common.c b/lib/common.c index d8d2fb7e..e65c17c9 100644 --- a/lib/common.c +++ b/lib/common.c @@ -1,7 +1,7 @@ /* common.c - Functions that are common to server and clinet * Rob Siemborski * Tim Martin - * $Id: common.c,v 1.127 2010/12/01 14:51:53 mel Exp $ + * $Id: common.c,v 1.128 2011/01/14 14:33:21 murch Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -1274,6 +1274,23 @@ int sasl_setprop(sasl_conn_t *conn, int propnum, const void *value) ((sasl_client_conn_t *)conn)->cparams->cbinding = cb; break; } + case SASL_HTTP_METHOD: + if(value && strlen(value)) { + result = _sasl_strdup(value, &str, NULL); + if(result != SASL_OK) MEMERROR(conn); + } else { + str = NULL; + } + + if(conn->type == SASL_CONN_SERVER) { + if(((sasl_server_conn_t *)conn)->sparams->http_method) + sasl_FREE(((sasl_server_conn_t *)conn)->sparams->http_method); + + ((sasl_server_conn_t *)conn)->sparams->http_method = str; + } + + break; + default: sasl_seterror(conn, 0, "Unknown parameter type"); result = SASL_BADPARAM; diff --git a/lib/server.c b/lib/server.c index b8694c91..9da2c9f8 100644 --- a/lib/server.c +++ b/lib/server.c @@ -1,7 +1,7 @@ /* SASL server API implementation * Rob Siemborski * Tim Martin - * $Id: server.c,v 1.165 2010/12/01 15:30:45 mel Exp $ + * $Id: server.c,v 1.166 2011/01/14 14:33:21 murch Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -1274,6 +1274,10 @@ static int mech_permitted(sasl_conn_t *conn, !(plug->features & SASL_FEAT_ALLOWS_PROXY)) { return SASL_NOMECH; } + if ((conn->flags & SASL_NEED_HTTP) && + !(plug->features & SASL_FEAT_SUPPORTS_HTTP)) { + return SASL_NOMECH; + } /* security properties---if there are any flags that differ and are in what the connection are requesting, then fail */ diff --git a/plugins/digestmd5.c b/plugins/digestmd5.c index c49aba5e..66c8ac0e 100644 --- a/plugins/digestmd5.c +++ b/plugins/digestmd5.c @@ -3,7 +3,7 @@ * Rob Siemborski * Tim Martin * Alexey Melnikov - * $Id: digestmd5.c,v 1.199 2010/12/03 18:05:29 murch Exp $ + * $Id: digestmd5.c,v 1.200 2011/01/14 14:33:21 murch Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -122,7 +122,7 @@ extern int gethostname(char *, int); /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: digestmd5.c,v 1.199 2010/12/03 18:05:29 murch Exp $"; +static const char plugin_id[] = "$Id: digestmd5.c,v 1.200 2011/01/14 14:33:21 murch Exp $"; /* Definitions */ #define NONCE_SIZE (32) /* arbitrary */ @@ -218,6 +218,7 @@ typedef struct digest_glob_context { typedef struct context { int state; /* state in the authentication we are in */ enum Context_type i_am; /* are we the client or server? */ + int http_mode; /* use RFC 2617 compatible protocol? */ reauth_cache_t *reauth; @@ -1693,7 +1694,17 @@ static void DigestCalcHA1FromSecret(context_t * text, /* calculate session key */ utils->MD5Init(&Md5Ctx); - utils->MD5Update(&Md5Ctx, HA1, HASHLEN); + if (text->http_mode) { + /* per RFC 2617 Errata ID 1649 */ + HASHHEX HA1Hex; + + CvtHex(HA1, HA1Hex); + utils->MD5Update(&Md5Ctx, HA1Hex, HASHHEXLEN); + } + else { + /* per RFC 2831 */ + utils->MD5Update(&Md5Ctx, HA1, HASHLEN); + } utils->MD5Update(&Md5Ctx, COLON, 1); utils->MD5Update(&Md5Ctx, pszNonce, (unsigned) strlen((char *) pszNonce)); utils->MD5Update(&Md5Ctx, COLON, 1); @@ -1719,6 +1730,7 @@ static char *create_response(context_t * text, unsigned char *cnonce, char *qop, char *digesturi, + const char *method, HASH Secret, char *authorization_id, char **response_value) @@ -1747,7 +1759,7 @@ static char *create_response(context_t * text, (unsigned char *) qop, /* qop-value: "", "auth", * "auth-int" */ (unsigned char *) digesturi, /* requested URL */ - (unsigned char *) "AUTHENTICATE", + (unsigned char *) method, HEntity, /* H(entity body) if qop="auth-int" */ Response /* request-digest or response-digest */ ); @@ -1877,6 +1889,7 @@ static int digestmd5_server_mech_new(void *glob_context, text->state = 1; text->i_am = SERVER; + text->http_mode = (sparams->flags & SASL_NEED_HTTP); text->reauth = ((digest_glob_context_t *) glob_context)->reauth; *conn_context = text; @@ -2113,6 +2126,7 @@ static int digestmd5_server_mech_step2(server_context_t *stext, unsigned int noncecount = 0; char *qop = NULL; char *digesturi = NULL; + const char *method = NULL; char *response = NULL; /* setting the default value (65536) */ @@ -2215,7 +2229,9 @@ static int digestmd5_server_mech_step2(server_context_t *stext, goto FreeAllMem; } _plug_strdup(sparams->utils, value, &qop, NULL); - } else if (strcasecmp(name, "digest-uri") == 0) { + } else if (strcasecmp(name, "digest-uri") == 0 || /* per RFC 2831 */ + (text->http_mode && + strcasecmp(name, "uri") == 0)) { /* per RFC 2617 */ size_t service_len; if (digesturi) { @@ -2227,22 +2243,24 @@ static int digestmd5_server_mech_step2(server_context_t *stext, _plug_strdup(sparams->utils, value, &digesturi, NULL); - /* Verify digest-uri format: - * - * digest-uri-value = serv-type "/" host [ "/" serv-name ] - */ + if (!text->http_mode) { + /* Verify digest-uri format (per RFC 2831): + * + * digest-uri-value = serv-type "/" host [ "/" serv-name ] + */ - /* make sure it's the service that we're expecting */ - service_len = strlen(sparams->service); - if (strncasecmp(digesturi, sparams->service, service_len) || - digesturi[service_len] != '/') { - result = SASL_BADAUTH; - SETERROR(sparams->utils, - "bad digest-uri: doesn't match service"); - goto FreeAllMem; - } - - /* xxx we don't verify the hostname component */ + /* make sure it's the service that we're expecting */ + service_len = strlen(sparams->service); + if (strncasecmp(digesturi, sparams->service, service_len) || + digesturi[service_len] != '/') { + result = SASL_BADAUTH; + SETERROR(sparams->utils, + "bad digest-uri: doesn't match service"); + goto FreeAllMem; + } + + /* xxx we don't verify the hostname component */ + } } else if (strcasecmp(name, "response") == 0) { _plug_strdup(sparams->utils, value, &response, NULL); @@ -2281,6 +2299,14 @@ static int digestmd5_server_mech_step2(server_context_t *stext, goto FreeAllMem; } _plug_strdup(sparams->utils, value, &charset, NULL); + } else if (strcasecmp(name,"algorithm") == 0) { + /* per RFC 2831: algorithm MUST be ignored if received */ + if (text->http_mode && strcasecmp(value, "md5-sess") != 0) { + /* per RFC 2617: algorithm MUST match that sent in challenge */ + SETERROR(sparams->utils, "'algorithm' isn't 'md5-sess'"); + result = SASL_FAIL; + goto FreeAllMem; + } } else { sparams->utils->log(sparams->utils->conn, SASL_LOG_DEBUG, "DIGEST-MD5 unrecognized pair %s/%s: ignoring", @@ -2409,12 +2435,15 @@ static int digestmd5_server_mech_step2(server_context_t *stext, result = SASL_BADAUTH; goto FreeAllMem; } +#if 0 /* XXX Neither RFC 2617 nor RFC 2831 state that the cnonce + needs to remain constant for subsequent authentication to work */ if (text->cnonce && strcmp((char *) cnonce, (char *) text->cnonce) != 0) { SETERROR(sparams->utils, "cnonce changed: authentication aborted"); result = SASL_BADAUTH; goto FreeAllMem; } +#endif result = sparams->utils->prop_request(sparams->propctx, password_request); if(result != SASL_OK) { @@ -2619,7 +2648,16 @@ static int digestmd5_server_mech_step2(server_context_t *stext, result = SASL_FAIL; goto FreeAllMem; } - + + if (text->http_mode) { + /* per RFC 2617 (RFC 2616 Method as set by calling application) */ + method = sparams->http_method; + } + if (!method) { + /* per RFC 2831 */ + method = "AUTHENTICATE"; + } + serverresponse = create_response(text, sparams->utils, text->nonce, @@ -2627,6 +2665,7 @@ static int digestmd5_server_mech_step2(server_context_t *stext, cnonce, qop, digesturi, + method, Secret, authorization_id, &text->response_value); @@ -2648,6 +2687,7 @@ static int digestmd5_server_mech_step2(server_context_t *stext, cnonce, qop, digesturi, + method, SecretBogus, authorization_id, &text->response_value); @@ -2750,12 +2790,37 @@ static int digestmd5_server_mech_step2(server_context_t *stext, if (add_to_challenge(sparams->utils, &text->out_buf, &text->out_buf_len, &resplen, "rspauth", (unsigned char *) text->response_value, - FALSE) != SASL_OK) { + text->http_mode ? TRUE : FALSE) != SASL_OK) { SETERROR(sparams->utils, "internal error: add_to_challenge failed"); result = SASL_FAIL; goto FreeAllMem; } + if (text->http_mode) { + /* per RFC 2617 */ + char ncvalue[10]; + + if (add_to_challenge(sparams->utils, + &text->out_buf, &text->out_buf_len, &resplen, + "cnonce", cnonce, TRUE) != SASL_OK) { + result = SASL_FAIL; + goto FreeAllMem; + } + snprintf(ncvalue, sizeof(ncvalue), "%08x", text->nonce_count); + if (add_to_challenge(sparams->utils, + &text->out_buf, &text->out_buf_len, &resplen, + "nc", (unsigned char *) ncvalue, FALSE) != SASL_OK) { + result = SASL_FAIL; + goto FreeAllMem; + } + if (add_to_challenge(sparams->utils, + &text->out_buf, &text->out_buf_len, &resplen, + "qop", (unsigned char *) qop, FALSE) != SASL_OK) { + result = SASL_FAIL; + goto FreeAllMem; + } + } + /* self check */ if (strlen(text->out_buf) > 2048) { result = SASL_FAIL; @@ -2942,7 +3007,8 @@ static sasl_server_plug_t digestmd5_server_plugins[] = SASL_SEC_NOPLAINTEXT | SASL_SEC_NOANONYMOUS | SASL_SEC_MUTUAL_AUTH, /* security_flags */ - SASL_FEAT_ALLOWS_PROXY, /* features */ + SASL_FEAT_ALLOWS_PROXY + | SASL_FEAT_SUPPORTS_HTTP, /* features */ &server_glob_context, /* glob_context */ &digestmd5_server_mech_new, /* mech_new */ &digestmd5_server_mech_step, /* mech_step */ From 323bc6883e0b40c9ad7c668a3dc18d6d648eabee Mon Sep 17 00:00:00 2001 From: Ken Murchison Date: Fri, 14 Jan 2011 14:35:57 +0000 Subject: [PATCH 057/796] Flag NTLM plugin as HTTP-ready --- ChangeLog | 3 +++ plugins/ntlm.c | 7 ++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index d30b139f..7b43d8d7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +2011-01-14 Ken Murchison + * plugins/ntlm.c: Flag NTLM plugin as HTTP-ready + 2011-01-14 Ken Murchison * include/sasl.h, include/saslplug.h, lib/common.c, lib/server.c, plugins/digest-md5.c: diff --git a/plugins/ntlm.c b/plugins/ntlm.c index 2d6523bc..c7533ca8 100644 --- a/plugins/ntlm.c +++ b/plugins/ntlm.c @@ -1,6 +1,6 @@ /* NTLM SASL plugin * Ken Murchison - * $Id: ntlm.c,v 1.35 2010/11/30 11:41:47 mel Exp $ + * $Id: ntlm.c,v 1.36 2011/01/14 14:35:57 murch Exp $ * * References: * http://www.innovation.ch/java/ntlm.html @@ -100,7 +100,7 @@ /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: ntlm.c,v 1.35 2010/11/30 11:41:47 mel Exp $"; +static const char plugin_id[] = "$Id: ntlm.c,v 1.36 2011/01/14 14:35:57 murch Exp $"; #ifdef WIN32 static ssize_t writev (SOCKET fd, const struct iovec *iov, size_t iovcnt); @@ -1735,7 +1735,8 @@ static sasl_server_plug_t ntlm_server_plugins[] = 0, /* max_ssf */ SASL_SEC_NOPLAINTEXT | SASL_SEC_NOANONYMOUS, /* security_flags */ - SASL_FEAT_WANT_CLIENT_FIRST, /* features */ + SASL_FEAT_WANT_CLIENT_FIRST + | SASL_FEAT_SUPPORTS_HTTP, /* features */ NULL, /* glob_context */ &ntlm_server_mech_new, /* mech_new */ &ntlm_server_mech_step, /* mech_step */ From 6dbd077b8887e1ed5dc8f40b3f9fdc363d49b650 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Tue, 18 Jan 2011 14:42:27 +0000 Subject: [PATCH 058/796] Use the same username for reauthentication cache lookup and update. Thanks to Ken for pointing out the problem. --- plugins/digestmd5.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/digestmd5.c b/plugins/digestmd5.c index 66c8ac0e..cfd1abd8 100644 --- a/plugins/digestmd5.c +++ b/plugins/digestmd5.c @@ -3,7 +3,7 @@ * Rob Siemborski * Tim Martin * Alexey Melnikov - * $Id: digestmd5.c,v 1.200 2011/01/14 14:33:21 murch Exp $ + * $Id: digestmd5.c,v 1.201 2011/01/18 14:42:27 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -122,7 +122,7 @@ extern int gethostname(char *, int); /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: digestmd5.c,v 1.200 2011/01/14 14:33:21 murch Exp $"; +static const char plugin_id[] = "$Id: digestmd5.c,v 1.201 2011/01/18 14:42:27 mel Exp $"; /* Definitions */ #define NONCE_SIZE (32) /* arbitrary */ @@ -2837,8 +2837,8 @@ static int digestmd5_server_mech_step2(server_context_t *stext, if (clientinlen > 0 && text->reauth->timeout && sparams->utils->mutex_lock(text->reauth->mutex) == SASL_OK) { /* LOCK */ - /* Look for an entry for our "internal username" */ - unsigned val = hash(internal_username) % text->reauth->size; + /* Look for an entry for our the username value as received */ + unsigned val = hash(username) % text->reauth->size; switch (result) { case SASL_OK: From dd6ad832b80af6f9128f752656a99edae7db6369 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Tue, 18 Jan 2011 14:49:46 +0000 Subject: [PATCH 059/796] Reauthentication fix to DIGEST-MD5 --- ChangeLog | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ChangeLog b/ChangeLog index 7b43d8d7..d73acfac 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-01-18 Alexey Melnikov + * plugins/digestmd5.c: Use the same username for reauthentication + cache lookup and update. Thanks to Ken for pointing out the + problem. + 2011-01-14 Ken Murchison * plugins/ntlm.c: Flag NTLM plugin as HTTP-ready From 6ba73d83a60319aa0c89a7dc0ab7470d6fc476c8 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Wed, 19 Jan 2011 09:04:29 +0000 Subject: [PATCH 060/796] Minor reformatting changes --- lib/auxprop.c | 9 ++++----- lib/client.c | 6 +++--- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/lib/auxprop.c b/lib/auxprop.c index f91fdd36..eb371b03 100644 --- a/lib/auxprop.c +++ b/lib/auxprop.c @@ -1,6 +1,6 @@ /* auxprop.c - auxilliary property support * Rob Siemborski - * $Id: auxprop.c,v 1.19 2009/01/28 22:49:14 mel Exp $ + * $Id: auxprop.c,v 1.20 2011/01/19 09:04:29 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -1075,10 +1075,9 @@ int sasl_auxprop_store(sasl_conn_t *conn, /* It would be nice if we can show other information like Author, Company, Year, plugin version */ static void -_sasl_print_mechanism ( - sasl_auxprop_plug_t *m, - sasl_info_callback_stage_t stage, - void *rock __attribute__((unused)) +_sasl_print_mechanism (sasl_auxprop_plug_t *m, + sasl_info_callback_stage_t stage, + void *rock __attribute__((unused)) ) { if (stage == SASL_INFO_LIST_START) { diff --git a/lib/client.c b/lib/client.c index 84c0004a..24792bbf 100644 --- a/lib/client.c +++ b/lib/client.c @@ -1,7 +1,7 @@ /* SASL client API implementation * Rob Siemborski * Tim Martin - * $Id: client.c,v 1.80 2010/12/01 15:49:25 murch Exp $ + * $Id: client.c,v 1.81 2011/01/19 09:04:29 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -909,8 +909,8 @@ int sasl_client_step(sasl_conn_t *conn, sasl_client_conn_t *c_conn= (sasl_client_conn_t *) conn; int result; - if(_sasl_client_active==0) return SASL_NOTINIT; - if(!conn) return SASL_BADPARAM; + if (_sasl_client_active == 0) return SASL_NOTINIT; + if (!conn) return SASL_BADPARAM; /* check parameters */ if ((serverin==NULL) && (serverinlen>0)) From 65bf29f78b63088453dac97d765135215d579804 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Wed, 19 Jan 2011 09:05:12 +0000 Subject: [PATCH 061/796] Updated an error message --- lib/server.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/server.c b/lib/server.c index 9da2c9f8..b093764a 100644 --- a/lib/server.c +++ b/lib/server.c @@ -1,7 +1,7 @@ /* SASL server API implementation * Rob Siemborski * Tim Martin - * $Id: server.c,v 1.166 2011/01/14 14:33:21 murch Exp $ + * $Id: server.c,v 1.167 2011/01/19 09:05:12 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -1895,7 +1895,7 @@ static int _sasl_checkpass(sasl_conn_t *conn, if (result == SASL_NOMECH) { /* no mechanism available ?!? */ - _sasl_log(conn, SASL_LOG_ERR, "unknown password verifier %s", mech); + _sasl_log(conn, SASL_LOG_ERR, "unknown password verifier(s) %s", mlist); } if (result != SASL_OK) From 151891f9953825fc65e9c1294590578256603c33 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Wed, 19 Jan 2011 10:19:07 +0000 Subject: [PATCH 062/796] Updated the SCRAM plugin not to use the hardcoded SCRAM-SHA-1 plugin name in logging --- plugins/scram.c | 110 +++++++++++++++++++++++++----------------------- 1 file changed, 57 insertions(+), 53 deletions(-) diff --git a/plugins/scram.c b/plugins/scram.c index 567d628b..63cbddc3 100644 --- a/plugins/scram.c +++ b/plugins/scram.c @@ -1,6 +1,6 @@ /* SCRAM-SHA-1 SASL plugin * Alexey Melnikov - * $Id: scram.c,v 1.18 2010/09/24 19:54:43 mel Exp $ + * $Id: scram.c,v 1.19 2011/01/19 10:19:07 mel Exp $ */ /* * Copyright (c) 2009-2010 Carnegie Mellon University. All rights reserved. @@ -69,7 +69,7 @@ /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: scram.c,v 1.18 2010/09/24 19:54:43 mel Exp $"; +static const char plugin_id[] = "$Id: scram.c,v 1.19 2011/01/19 10:19:07 mel Exp $"; #define NONCE_SIZE (32) /* arbitrary */ #define SALT_SIZE (16) /* arbitrary */ @@ -107,6 +107,10 @@ static const char plugin_id[] = "$Id: scram.c,v 1.18 2010/09/24 19:54:43 mel Exp a new SASL error code for that */ #define SASL_SCRAM_INTERNAL SASL_NOMEM + +#define SCRAM_SASL_MECH "SCRAM-SHA-1" +#define SCRAM_SASL_MECH_LEN 11 + /* Holds the core salt to avoid regenerating salt each auth. */ static unsigned char g_salt_key[SALT_SIZE]; @@ -400,7 +404,7 @@ scram_server_mech_step1(server_context_t *text, int result; if (clientinlen == 0) { - SETERROR(sparams->utils, "SCRAM-SHA-1 input expected"); + SETERROR(sparams->utils, SCRAM_SASL_MECH " input expected"); return SASL_BADPROT; } @@ -408,7 +412,7 @@ scram_server_mech_step1(server_context_t *text, username "," nonce ["," extensions]' */ if (clientinlen < 10) { - SETERROR(sparams->utils, "Invalid SCRAM-SHA-1 input"); + SETERROR(sparams->utils, "Invalid " SCRAM_SASL_MECH " input"); return SASL_BADPROT; } @@ -423,7 +427,7 @@ scram_server_mech_step1(server_context_t *text, inbuf[clientinlen] = 0; if (strlen(inbuf) != clientinlen) { - SETERROR(sparams->utils, "NULs found in SCRAM-SHA-1 input"); + SETERROR(sparams->utils, "NULs found in " SCRAM_SASL_MECH " input"); result = SASL_BADPROT; goto cleanup; } @@ -439,7 +443,7 @@ scram_server_mech_step1(server_context_t *text, switch (p[0]) { case 'p': if (clientin[1] != '=') { - SETERROR(sparams->utils, "The initial 'p' needs to be followed by '=' in SCRAM-SHA-1 input"); + SETERROR(sparams->utils, "The initial 'p' needs to be followed by '=' in " SCRAM_SASL_MECH " input"); result = SASL_BADPROT; goto cleanup; } @@ -456,13 +460,13 @@ scram_server_mech_step1(server_context_t *text, break; default: - SETERROR(sparams->utils, "The initial SCRAM-SHA-1 client response needs to start with 'y', 'n' or 'p'"); + SETERROR(sparams->utils, "The initial " SCRAM_SASL_MECH " client response needs to start with 'y', 'n' or 'p'"); result = SASL_BADPROT; goto cleanup; } if (p[0] != ',') { - SETERROR(sparams->utils, "',' expected in SCRAM-SHA-1 input"); + SETERROR(sparams->utils, "',' expected in " SCRAM_SASL_MECH " input"); result = SASL_BADPROT; goto cleanup; } @@ -475,7 +479,7 @@ scram_server_mech_step1(server_context_t *text, if (p == NULL) { text->authorization_id = NULL; - SETERROR(sparams->utils, "At least nonce is expected in SCRAM-SHA-1 input"); + SETERROR(sparams->utils, "At least nonce is expected in " SCRAM_SASL_MECH " input"); result = SASL_BADPROT; goto cleanup; } @@ -491,12 +495,12 @@ scram_server_mech_step1(server_context_t *text, _plug_strdup(sparams->utils, text->authorization_id, &text->authorization_id, NULL); if (decode_saslname(text->authorization_id) != SASL_OK) { - SETERROR(sparams->utils, "Invalid authorization identity encoding in SCRAM-SHA-1 input"); + SETERROR(sparams->utils, "Invalid authorization identity encoding in " SCRAM_SASL_MECH " input"); result = SASL_BADPROT; goto cleanup; } } else if (p[0] != ',') { - SETERROR(sparams->utils, "',' expected in SCRAM-SHA-1 input"); + SETERROR(sparams->utils, "',' expected in " SCRAM_SASL_MECH " input"); result = SASL_BADPROT; goto cleanup; } else { @@ -509,19 +513,19 @@ scram_server_mech_step1(server_context_t *text, } if (p[1] != '=') { - SETERROR(sparams->utils, "Invalid SCRAM-SHA-1 input"); + SETERROR(sparams->utils, "Invalid " SCRAM_SASL_MECH " input"); result = SASL_BADPROT; goto cleanup; } if (p[0] == 'm') { - SETERROR(sparams->utils, "Unsupported mandatory extension to SCRAM-SHA-1"); + SETERROR(sparams->utils, "Unsupported mandatory extension to " SCRAM_SASL_MECH); result = SASL_BADPROT; goto cleanup; } if (p[0] != 'n') { - SETERROR(sparams->utils, "Username (n=) expected in SCRAM-SHA-1 input"); + SETERROR(sparams->utils, "Username (n=) expected in " SCRAM_SASL_MECH " input"); result = SASL_BADPROT; goto cleanup; } @@ -531,7 +535,7 @@ scram_server_mech_step1(server_context_t *text, /* MUST be followed by a nonce */ if (p == NULL) { - SETERROR(sparams->utils, "Nonce expected after the username in SCRAM-SHA-1 input"); + SETERROR(sparams->utils, "Nonce expected after the username in " SCRAM_SASL_MECH " input"); result = SASL_BADPROT; goto cleanup; } @@ -540,7 +544,7 @@ scram_server_mech_step1(server_context_t *text, p++; if (decode_saslname(authentication_id) != SASL_OK) { - SETERROR(sparams->utils, "Invalid username encoding in SCRAM-SHA-1 input"); + SETERROR(sparams->utils, "Invalid username encoding in " SCRAM_SASL_MECH " input"); result = SASL_BADPROT; goto cleanup; } @@ -548,7 +552,7 @@ scram_server_mech_step1(server_context_t *text, _plug_strdup(sparams->utils, authentication_id, &text->authentication_id, NULL); if (strncmp(p, "r=", 2) != 0) { - SETERROR(sparams->utils, "Nonce expected after the username in SCRAM-SHA-1 input"); + SETERROR(sparams->utils, "Nonce expected after the username in " SCRAM_SASL_MECH " input"); result = SASL_BADPROT; goto cleanup; } @@ -704,16 +708,16 @@ scram_server_mech_step2(server_context_t *text, size_t client_proof_len; size_t server_proof_len; unsigned exact_client_proof_len; - int k; unsigned int hash_len = 0; + int k; if (clientinlen == 0) { - SETERROR(sparams->utils, "SCRAM-SHA-1 input expected"); + SETERROR(sparams->utils, SCRAM_SASL_MECH " input expected"); return SASL_BADPROT; } if (clientinlen < 3 || clientin[1] != '=') { - SETERROR(sparams->utils, "Invalid SCRAM-SHA-1 input"); + SETERROR(sparams->utils, "Invalid " SCRAM_SASL_MECH " input"); return SASL_BADPROT; } @@ -728,7 +732,7 @@ scram_server_mech_step2(server_context_t *text, inbuf[clientinlen] = 0; if (strlen(inbuf) != clientinlen) { - SETERROR(sparams->utils, "NULs found in SCRAM-SHA-1 input"); + SETERROR(sparams->utils, "NULs found in " SCRAM_SASL_MECH " input"); result = SASL_BADPROT; goto cleanup; } @@ -738,7 +742,7 @@ scram_server_mech_step2(server_context_t *text, p = inbuf; if (strncmp(p, "c=", 2) != 0) { - SETERROR(sparams->utils, "Channel binding expected in SCRAM-SHA-1 input"); + SETERROR(sparams->utils, "Channel binding expected in " SCRAM_SASL_MECH " input"); result = SASL_BADPROT; goto cleanup; } @@ -747,7 +751,7 @@ scram_server_mech_step2(server_context_t *text, p = strchr (channel_binding, ','); if (p == NULL) { - SETERROR(sparams->utils, "At least nonce is expected in SCRAM-SHA-1 input"); + SETERROR(sparams->utils, "At least nonce is expected in " SCRAM_SASL_MECH " input"); result = SASL_BADPROT; goto cleanup; } @@ -755,7 +759,7 @@ scram_server_mech_step2(server_context_t *text, p++; if (strncmp(p, "r=", 2) != 0) { - SETERROR(sparams->utils, "Nonce expected in SCRAM-SHA-1 input"); + SETERROR(sparams->utils, "Nonce expected in " SCRAM_SASL_MECH " input"); result = SASL_BADPROT; goto cleanup; } @@ -764,7 +768,7 @@ scram_server_mech_step2(server_context_t *text, p = strchr (nonce, ','); if (p == NULL) { - SETERROR(sparams->utils, "At least proof is expected in SCRAM-SHA-1 input"); + SETERROR(sparams->utils, "At least proof is expected in " SCRAM_SASL_MECH " input"); result = SASL_BADPROT; goto cleanup; } @@ -772,7 +776,7 @@ scram_server_mech_step2(server_context_t *text, p++; if (strcmp(nonce, text->nonce) != 0) { - SETERROR(sparams->utils, "Nonce mismatch SCRAM-SHA-1 input"); + SETERROR(sparams->utils, "Nonce mismatch " SCRAM_SASL_MECH " input"); result = SASL_BADPROT; goto cleanup; } @@ -792,7 +796,7 @@ scram_server_mech_step2(server_context_t *text, } if (client_proof == NULL) { - SETERROR(sparams->utils, "Client proof is expected in SCRAM-SHA-1 input"); + SETERROR(sparams->utils, "Client proof is expected in " SCRAM_SASL_MECH " input"); result = SASL_BADPROT; goto cleanup; } @@ -800,13 +804,13 @@ scram_server_mech_step2(server_context_t *text, /* Check that no extension data exists after the proof */ p = strchr (client_proof, ','); if (p != NULL) { - SETERROR(sparams->utils, "No extension data is allowed after the client proof in SCRAM-SHA-1 input"); + SETERROR(sparams->utils, "No extension data is allowed after the client proof in " SCRAM_SASL_MECH " input"); result = SASL_BADPROT; goto cleanup; } if (strlen(client_proof) != (SCRAM_HASH_SIZE / 3 * 4 + (SCRAM_HASH_SIZE % 3 ? 4 : 0))) { - SETERROR(sparams->utils, "Invalid client proof length in SCRAM-SHA-1 input"); + SETERROR(sparams->utils, "Invalid client proof length in " SCRAM_SASL_MECH " input"); result = SASL_BADPROT; goto cleanup; } @@ -979,13 +983,13 @@ scram_server_mech_step2(server_context_t *text, DecodedClientProof, SCRAM_HASH_SIZE + 1, &exact_client_proof_len) != SASL_OK) { - SETERROR(sparams->utils, "Invalid base64 encoding of the client proof in SCRAM-SHA-1 input"); + SETERROR(sparams->utils, "Invalid base64 encoding of the client proof in " SCRAM_SASL_MECH " input"); result = SASL_BADPROT; goto cleanup; } if (exact_client_proof_len != SCRAM_HASH_SIZE) { - SETERROR(sparams->utils, "Invalid client proof (truncated) in SCRAM-SHA-1 input"); + SETERROR(sparams->utils, "Invalid client proof (truncated) in " SCRAM_SASL_MECH " input"); result = SASL_BADPROT; goto cleanup; } @@ -1090,7 +1094,7 @@ static int scram_server_mech_step(void *conn_context, /* this should be well more than is ever needed */ if (clientinlen > MAX_CLIENTIN_LEN) { - SETERROR(sparams->utils, "SCRAM-SHA-1 input longer than " STRINGIZE((MAX_CLIENTIN_LEN)) " bytes"); + SETERROR(sparams->utils, SCRAM_SASL_MECH " input longer than " STRINGIZE((MAX_CLIENTIN_LEN)) " bytes"); return SASL_BADPROT; } @@ -1124,7 +1128,7 @@ static int scram_server_mech_step(void *conn_context, default: /* should never get here */ sparams->utils->log(NULL, SASL_LOG_ERR, - "Invalid SCRAM-SHA-1 server step %d\n", text->state); + "Invalid " SCRAM_SASL_MECH " server step %d\n", text->state); return SASL_FAIL; } @@ -1151,7 +1155,7 @@ static void scram_server_mech_dispose(void *conn_context, static sasl_server_plug_t scram_server_plugins[] = { { - "SCRAM-SHA-1", /* mech_name */ + SCRAM_SASL_MECH, /* mech_name */ 0, /* max_ssf */ SASL_SEC_NOPLAINTEXT | SASL_SEC_NOACTIVE @@ -1258,7 +1262,7 @@ scram_client_mech_step1(client_context_t *text, /* check if sec layer strong enough */ if (params->props.min_ssf > params->external_ssf) { - SETERROR( params->utils, "SSF requested of SCRAM-SHA-1 plugin"); + SETERROR( params->utils, "SSF requested of " SCRAM_SASL_MECH " plugin"); return SASL_TOOWEAK; } @@ -1496,24 +1500,24 @@ scram_client_mech_step2(client_context_t *text, unsigned int hash_len = 0; if (serverinlen == 0) { - SETERROR(params->utils, "SCRAM-SHA-1 input expected"); + SETERROR(params->utils, SCRAM_SASL_MECH " input expected"); return SASL_BADPROT; } /* [reserved-mext ","] nonce "," salt "," iteration-count ["," extensions] */ if (serverinlen < 3 || serverin[1] != '=') { - SETERROR(params->utils, "Invalid SCRAM-SHA-1 input"); + SETERROR(params->utils, "Invalid " SCRAM_SASL_MECH " input"); return SASL_BADPROT; } if (serverin[0] == 'm') { - SETERROR(params->utils, "Unsupported mandatory extension to SCRAM-SHA-1"); + SETERROR(params->utils, "Unsupported mandatory extension to " SCRAM_SASL_MECH); return SASL_BADPROT; } if (serverin[0] != 'r') { - SETERROR(params->utils, "Nonce (r=) expected in SCRAM-SHA-1 input"); + SETERROR(params->utils, "Nonce (r=) expected in " SCRAM_SASL_MECH " input"); return SASL_BADPROT; } @@ -1527,7 +1531,7 @@ scram_client_mech_step2(client_context_t *text, inbuf[serverinlen] = 0; if (strlen(inbuf) != serverinlen) { - SETERROR(params->utils, "NULs found in SCRAM-SHA-1 input"); + SETERROR(params->utils, "NULs found in " SCRAM_SASL_MECH " input"); result = SASL_BADPROT; goto cleanup; } @@ -1537,7 +1541,7 @@ scram_client_mech_step2(client_context_t *text, /* MUST be followed by a salt */ if (p == NULL) { - SETERROR(params->utils, "Salt expected after the nonce in SCRAM-SHA-1 input"); + SETERROR(params->utils, "Salt expected after the nonce in " SCRAM_SASL_MECH " input"); result = SASL_BADPROT; goto cleanup; } @@ -1546,7 +1550,7 @@ scram_client_mech_step2(client_context_t *text, p++; if (strncmp(p, "s=", 2) != 0) { - SETERROR(params->utils, "Salt expected after the nonce in SCRAM-SHA-1 input"); + SETERROR(params->utils, "Salt expected after the nonce in " SCRAM_SASL_MECH " input"); result = SASL_BADPROT; goto cleanup; } @@ -1558,7 +1562,7 @@ scram_client_mech_step2(client_context_t *text, /* MUST be followed by an iteration-count */ if (p == NULL) { - SETERROR(params->utils, "iteration-count expected after the salt in SCRAM-SHA-1 input"); + SETERROR(params->utils, "iteration-count expected after the salt in " SCRAM_SASL_MECH " input"); result = SASL_BADPROT; goto cleanup; } @@ -1567,7 +1571,7 @@ scram_client_mech_step2(client_context_t *text, p++; if (strncmp(p, "i=", 2) != 0) { - SETERROR(params->utils, "iteration-count expected after the salt in SCRAM-SHA-1 input"); + SETERROR(params->utils, "iteration-count expected after the salt in " SCRAM_SASL_MECH " input"); result = SASL_BADPROT; goto cleanup; } @@ -1585,7 +1589,7 @@ scram_client_mech_step2(client_context_t *text, errno = 0; text->iteration_count = strtoul(counter, &end, 10); if (counter == end || *end != '\0' || errno != 0) { - SETERROR(params->utils, "Invalid iteration-count in SCRAM-SHA-1 input"); + SETERROR(params->utils, "Invalid iteration-count in " SCRAM_SASL_MECH " input"); result = SASL_BADPROT; goto cleanup; } @@ -1651,7 +1655,7 @@ scram_client_mech_step2(client_context_t *text, text->salt, (unsigned int)text->salt_len + 1, &exact_salt_len) != SASL_OK) { - SETERROR(params->utils, "Invalid base64 encoding of the salt in SCRAM-SHA-1 input"); + SETERROR(params->utils, "Invalid base64 encoding of the salt in " SCRAM_SASL_MECH " input"); result = SASL_BADPROT; goto cleanup; } @@ -1861,14 +1865,14 @@ scram_client_mech_step3(client_context_t *text, unsigned int hash_len = 0; if (serverinlen < 3) { - SETERROR(params->utils, "Invalid SCRAM-SHA-1 input expected"); + SETERROR(params->utils, "Invalid " SCRAM_SASL_MECH " input expected"); return SASL_BADPROT; } /* Expecting: 'verifier ["," extensions]' */ if (strncmp(serverin, "v=", 2) != 0) { - SETERROR(params->utils, "ServerSignature expected in SCRAM-SHA-1 input"); + SETERROR(params->utils, "ServerSignature expected in " SCRAM_SASL_MECH " input"); return SASL_BADPROT; } @@ -1884,13 +1888,13 @@ scram_client_mech_step3(client_context_t *text, DecodedServerProof, SCRAM_HASH_SIZE + 1, &exact_server_proof_len) != SASL_OK) { - SETERROR(params->utils, "Invalid base64 encoding of the server proof in SCRAM-SHA-1 input"); + SETERROR(params->utils, "Invalid base64 encoding of the server proof in " SCRAM_SASL_MECH " input"); result = SASL_BADPROT; goto cleanup; } if (exact_server_proof_len != SCRAM_HASH_SIZE) { - SETERROR(params->utils, "Invalid server proof (truncated) in SCRAM-SHA-1 input"); + SETERROR(params->utils, "Invalid server proof (truncated) in " SCRAM_SASL_MECH " input"); result = SASL_BADPROT; goto cleanup; } @@ -1964,7 +1968,7 @@ static int scram_client_mech_step(void *conn_context, /* this should be well more than is ever needed */ if (serverinlen > MAX_SERVERIN_LEN) { - SETERROR(params->utils, "SCRAM-SHA-1 input longer than " STRINGIZE((MAX_SERVERIN_LEN)) " bytes"); + SETERROR(params->utils, SCRAM_SASL_MECH " input longer than " STRINGIZE((MAX_SERVERIN_LEN)) " bytes"); return SASL_BADPROT; } @@ -2004,7 +2008,7 @@ static int scram_client_mech_step(void *conn_context, default: /* should never get here */ params->utils->log(NULL, SASL_LOG_ERR, - "Invalid SCRAM-SHA-1 client step %d\n", text->state); + "Invalid " SCRAM_SASL_MECH " client step %d\n", text->state); return SASL_FAIL; } @@ -2047,7 +2051,7 @@ static void scram_client_mech_dispose(void *conn_context, static sasl_client_plug_t scram_client_plugins[] = { { - "SCRAM-SHA-1", /* mech_name */ + SCRAM_SASL_MECH, /* mech_name */ 0, /* max_ssf */ SASL_SEC_NOPLAINTEXT | SASL_SEC_NOANONYMOUS From d0284efd6678bb7e9b27fd07a05da88b1398b7ca Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Wed, 19 Jan 2011 10:40:11 +0000 Subject: [PATCH 063/796] Added support for storing SCRAM secrets in authPassword attribute --- plugins/scram.c | 703 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 546 insertions(+), 157 deletions(-) diff --git a/plugins/scram.c b/plugins/scram.c index 63cbddc3..1035424a 100644 --- a/plugins/scram.c +++ b/plugins/scram.c @@ -1,6 +1,6 @@ /* SCRAM-SHA-1 SASL plugin * Alexey Melnikov - * $Id: scram.c,v 1.19 2011/01/19 10:19:07 mel Exp $ + * $Id: scram.c,v 1.20 2011/01/19 10:40:11 mel Exp $ */ /* * Copyright (c) 2009-2010 Carnegie Mellon University. All rights reserved. @@ -69,7 +69,7 @@ /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: scram.c,v 1.19 2011/01/19 10:19:07 mel Exp $"; +static const char plugin_id[] = "$Id: scram.c,v 1.20 2011/01/19 10:40:11 mel Exp $"; #define NONCE_SIZE (32) /* arbitrary */ #define SALT_SIZE (16) /* arbitrary */ @@ -85,6 +85,8 @@ static const char plugin_id[] = "$Id: scram.c,v 1.19 2011/01/19 10:19:07 mel Exp #define SCRAM_HASH_SIZE 20 +#define BASE64_LEN(size) (((size) / 3 * 4) + (((size) % 3) ? 4 : 0)) + #define MAX_CLIENTIN_LEN 2048 #define MAX_SERVERIN_LEN 2048 @@ -265,9 +267,9 @@ print_hash (const char * func, const char * hash) /* The result variable need to point to a buffer big enough for the [SHA-1] hash */ static void Hi (const sasl_utils_t * utils, - char * str, + const char * str, size_t str_len, - char * salt, + const char * salt, size_t salt_len, unsigned int iteration_count, char * result) @@ -334,10 +336,98 @@ Hi (const sasl_utils_t * utils, */ static unsigned char * scram_server_user_salt(const sasl_utils_t * utils, - const char * username) + const char * username, + size_t * p_salt_len) { char * result = utils->malloc(SCRAM_HASH_SIZE); - Hi(utils, username, strlen(username), g_salt_key, SALT_SIZE, 20, result); + Hi(utils, username, strlen(username), g_salt_key, SALT_SIZE, 20 /* iterations */, result); + *p_salt_len = SCRAM_HASH_SIZE; + return result; +} + +static int +GenerateScramSecrets (const sasl_utils_t * utils, + const char * password, + size_t password_len, + char * salt, + size_t salt_len, + unsigned int iteration_count, + char * StoredKey, + char * ServerKey, + char ** error_text) +{ + char SaltedPassword[SCRAM_HASH_SIZE]; + char ClientKey[SCRAM_HASH_SIZE]; + sasl_secret_t *sec = NULL; + unsigned int hash_len = 0; + int result; + + *error_text = NULL; + + if (password_len == 0) { + *error_text = "empty secret"; + result = SASL_FAIL; + goto cleanup; + } + + sec = utils->malloc(sizeof(sasl_secret_t) + password_len); + if (sec == NULL) { + result = SASL_NOMEM; + goto cleanup; + } + + sec->len = (unsigned) password_len; + strncpy((char *)sec->data, password, password_len + 1); + + /* SaltedPassword := Hi(password, salt) */ + Hi (utils, + sec->data, + sec->len, + salt, + salt_len, + iteration_count, + SaltedPassword); + + /* ClientKey := HMAC(SaltedPassword, "Client Key") */ + if (HMAC(EVP_sha1(), + (const unsigned char *) SaltedPassword, + SCRAM_HASH_SIZE, + CLIENT_KEY_CONSTANT, + CLIENT_KEY_CONSTANT_LEN, + (unsigned char *)ClientKey, + &hash_len) == NULL) { + *error_text = "HMAC-SHA1 call failed"; + result = SASL_SCRAM_INTERNAL; + goto cleanup; + } + + /* StoredKey := H(ClientKey) */ + if (SHA1(ClientKey, SCRAM_HASH_SIZE, StoredKey) == NULL) { + *error_text = "SHA1 call failed"; + result = SASL_SCRAM_INTERNAL; + goto cleanup; + + } + + /* ServerKey := HMAC(SaltedPassword, "Server Key") */ + if (HMAC(EVP_sha1(), + (const unsigned char *) SaltedPassword, + SCRAM_HASH_SIZE, + SERVER_KEY_CONSTANT, + SERVER_KEY_CONSTANT_LEN, + (unsigned char *)ServerKey, + &hash_len) == NULL) { + *error_text = "HMAC-SHA1 call failed"; + result = SASL_SCRAM_INTERNAL; + goto cleanup; + } + + result = SASL_OK; + +cleanup: + if (sec) { + _plug_free_secret(utils, &sec); + } return result; } @@ -355,7 +445,10 @@ typedef struct server_context { char * nonce; /* in binary form */ char * salt; + size_t salt_len; unsigned int iteration_count; + char StoredKey[SCRAM_HASH_SIZE + 1]; + char ServerKey[SCRAM_HASH_SIZE + 1]; } server_context_t; static int @@ -401,6 +494,12 @@ scram_server_mech_step1(server_context_t *text, size_t gs2_header_length = 0; size_t pure_scram_length; char * inbuf = NULL; + const char *password_request[] = { SASL_AUX_PASSWORD, + "*authPassword", + NULL }; + int canon_flags; + struct propval auxprop_values[3]; + unsigned int hash_len = 0; int result; if (clientinlen == 0) { @@ -587,17 +686,257 @@ scram_server_mech_step1(server_context_t *text, goto cleanup; } - /* NOTE: The following would change, if we start storing salt - and iteration_count in a SCRAM specific attribute */ - text->salt = scram_server_user_salt(sparams->utils, text->authentication_id); - text->iteration_count = DEFAULT_ITERATION_COUNTER; + /* Now we fetch user's password and calculate our secret */ + result = sparams->utils->prop_request(sparams->propctx, password_request); + if (result != SASL_OK) { + goto cleanup; + } + + /* this will trigger the getting of the aux properties */ + canon_flags = SASL_CU_AUTHID; + if (text->authorization_id == NULL || *text->authorization_id == '\0') { + canon_flags |= SASL_CU_AUTHZID; + } + + result = sparams->canon_user(sparams->utils->conn, + text->authentication_id, + 0, + canon_flags, + oparams); + if (result != SASL_OK) { + SETERROR(sparams->utils, "unable to canonify user and get auxprops"); + goto cleanup; + } + + if (text->authorization_id != NULL && *text->authorization_id != '\0') { + result = sparams->canon_user(sparams->utils->conn, + text->authorization_id, + 0, + SASL_CU_AUTHZID, + oparams); + } + if (result != SASL_OK) { + SETERROR(sparams->utils, "unable to canonify authorization ID"); + goto cleanup; + } + + result = sparams->utils->prop_getnames(sparams->propctx, + password_request, + auxprop_values); + if (result < 0 || + ((!auxprop_values[0].name || !auxprop_values[0].values) && + (!auxprop_values[1].name || !auxprop_values[1].values))) { + /* We didn't find this username */ + sparams->utils->seterror(sparams->utils->conn,0, + "no secret in database"); + result = sparams->transition ? SASL_TRANS : SASL_NOUSER; + goto cleanup; + } + + if (auxprop_values[0].name && auxprop_values[0].values) { + char * error_text = NULL; + + text->salt = scram_server_user_salt(sparams->utils, text->authentication_id, &text->salt_len); + + text->iteration_count = DEFAULT_ITERATION_COUNTER; + + + result = GenerateScramSecrets (sparams->utils, + auxprop_values[0].values[0], + strlen(auxprop_values[0].values[0]), + text->salt, + text->salt_len, + text->iteration_count, + text->StoredKey, + text->ServerKey, + &error_text); + if (result != SASL_OK) { + if (error_text != NULL) { + sparams->utils->seterror(sparams->utils->conn, 0, error_text); + } + goto cleanup; + } + + } else if (auxprop_values[1].name && auxprop_values[1].values) { + char s_iteration_count[ITERATION_COUNTER_BUF_LEN+1]; + size_t base64_salt_len; + unsigned int exact_key_len; + const char * scram_hash; + const char * p_field; + char * end; + int i; + + result = SASL_SCRAM_INTERNAL; + + for (i = 0; auxprop_values[1].values[i] != NULL; i++) { + scram_hash = auxprop_values[1].values[i]; + + /* Skip the leading spaces */ + while (*scram_hash == ' ') { + scram_hash++; + } + + if (strncmp(scram_hash, SCRAM_SASL_MECH, SCRAM_SASL_MECH_LEN) != 0) { + continue; + } + scram_hash += SCRAM_SASL_MECH_LEN; + + /* Skip spaces */ + while (*scram_hash == ' ') { + scram_hash++; + } + + if (*scram_hash != '$') { + /* syntax error, ignore the value */ + continue; + } + scram_hash++; + + /* Skip spaces */ + while (*scram_hash == ' ') { + scram_hash++; + } + + p_field = strchr(scram_hash, ':'); + if (p_field == NULL || p_field == scram_hash) { + /* syntax error, ignore the value */ + continue; + } + + if ((p_field - scram_hash) > ITERATION_COUNTER_BUF_LEN) { + /* The iteration counter is too big for us */ + SETERROR(sparams->utils, "Invalid iteration-count in " SCRAM_SASL_MECH " input: the value is too big"); + continue; + } + + memcpy(s_iteration_count, scram_hash, p_field - scram_hash); + s_iteration_count[p_field - scram_hash] = '\0'; + + errno = 0; + text->iteration_count = strtoul(s_iteration_count, &end, 10); + if (s_iteration_count == end || *end != '\0' || errno != 0) { + SETERROR(sparams->utils, "Invalid iteration-count in " SCRAM_SASL_MECH " input: not a number"); + continue; + } + + scram_hash = p_field + 1; + + p_field = scram_hash + strcspn(scram_hash, "$ "); + if (p_field == scram_hash || *p_field == '\0') { + /* syntax error, ignore the value */ + continue; + } + + base64_salt_len = p_field - scram_hash; + text->salt = (char *) sparams->utils->malloc(base64_salt_len); + if (sparams->utils->decode64(scram_hash, + (unsigned int)base64_salt_len, + text->salt, + (unsigned int)base64_salt_len, + &text->salt_len) != SASL_OK) { + SETERROR(sparams->utils, "Invalid base64 encoding of the salt in " SCRAM_SASL_MECH " stored value"); + continue; + } + + scram_hash = p_field; + + /* Skip spaces */ + while (*scram_hash == ' ') { + scram_hash++; + } + + if (*scram_hash != '$') { + /* syntax error, ignore the value */ + sparams->utils->free(text->salt); + text->salt = NULL; + continue; + } + scram_hash++; + + /* Skip spaces */ + while (*scram_hash == ' ') { + scram_hash++; + } + + p_field = strchr(scram_hash, ':'); + if (p_field == NULL || p_field == scram_hash) { + /* syntax error, ignore the value */ + sparams->utils->free(text->salt); + text->salt = NULL; + continue; + } + + if (sparams->utils->decode64(scram_hash, + (unsigned int)(p_field - scram_hash), + text->StoredKey, + SCRAM_HASH_SIZE + 1, + &exact_key_len) != SASL_OK) { + SETERROR(sparams->utils, "Invalid base64 encoding of StoredKey in " SCRAM_SASL_MECH " per-user storage"); + sparams->utils->free(text->salt); + text->salt = NULL; + continue; + } + + if (exact_key_len != SCRAM_HASH_SIZE) { + SETERROR(sparams->utils, "Invalid StoredKey in " SCRAM_SASL_MECH " per-user storage"); + sparams->utils->free(text->salt); + text->salt = NULL; + continue; + } + + scram_hash = p_field + 1; + + p_field = strchr(scram_hash, ' '); + if (p_field == NULL) { + p_field = scram_hash + strlen(scram_hash); + } + + + if (sparams->utils->decode64(scram_hash, + (unsigned int)(p_field - scram_hash), + text->ServerKey, + SCRAM_HASH_SIZE + 1, + &exact_key_len) != SASL_OK) { + SETERROR(sparams->utils, "Invalid base64 encoding of ServerKey in " SCRAM_SASL_MECH " per-user storage"); + sparams->utils->free(text->salt); + text->salt = NULL; + continue; + } + + if (exact_key_len != SCRAM_HASH_SIZE) { + SETERROR(sparams->utils, "Invalid ServerKey in " SCRAM_SASL_MECH " per-user storage"); + sparams->utils->free(text->salt); + text->salt = NULL; + continue; + } + + result = SASL_OK; + break; + } + + if (result != SASL_OK) { + sparams->utils->seterror(sparams->utils->conn, + 0, + "No valid " SCRAM_SASL_MECH " secret found"); + goto cleanup; + } + + } else { + sparams->utils->seterror(sparams->utils->conn, + 0, + "Have neither type of secret"); + return SASL_FAIL; + } + + /* erase the plaintext password */ + sparams->utils->prop_erase(sparams->propctx, password_request[0]); /* base 64 encode it so it has valid chars */ - base64len = (SALT_SIZE / 3 * 4) + ((SALT_SIZE % 3) ? 4 : 0); + base64len = (text->salt_len / 3 * 4) + ((text->salt_len % 3) ? 4 : 0); base64_salt = (char *) sparams->utils->malloc(base64len + 1); if (base64_salt == NULL) { @@ -610,7 +949,7 @@ scram_server_mech_step1(server_context_t *text, * Returns SASL_OK on success, SASL_BUFOVER if result won't fit */ if (sparams->utils->encode64(text->salt, - SALT_SIZE, + (unsigned int)text->salt_len, base64_salt, (unsigned int)base64len + 1, NULL) != SASL_OK) { @@ -688,15 +1027,7 @@ scram_server_mech_step2(server_context_t *text, char *client_proof = NULL; char *inbuf = NULL; char *p; - int canon_flags; - sasl_secret_t *sec = NULL; - size_t len; int result = SASL_FAIL; - const char *password_request[] = { SASL_AUX_PASSWORD, - NULL }; - struct propval auxprop_values[3]; - char StoredKey[SCRAM_HASH_SIZE]; - char ServerKey[SCRAM_HASH_SIZE]; size_t proof_offset; char * full_auth_message; char ReceivedClientKey[SCRAM_HASH_SIZE]; @@ -815,138 +1146,6 @@ scram_server_mech_step2(server_context_t *text, goto cleanup; } - /* Now we fetch user's password and calculate our secret */ - result = sparams->utils->prop_request(sparams->propctx, password_request); - if (result != SASL_OK) { - goto cleanup; - } - - /* this will trigger the getting of the aux properties */ - canon_flags = SASL_CU_AUTHID; - if (text->authorization_id == NULL || *text->authorization_id == '\0') { - canon_flags |= SASL_CU_AUTHZID; - } - - result = sparams->canon_user(sparams->utils->conn, - text->authentication_id, - 0, - canon_flags, - oparams); - if (result != SASL_OK) { - SETERROR(sparams->utils, "unable to canonify user and get auxprops"); - goto cleanup; - } - - if (text->authorization_id != NULL && *text->authorization_id != '\0') { - result = sparams->canon_user(sparams->utils->conn, - text->authorization_id, - 0, - SASL_CU_AUTHZID, - oparams); - } - if (result != SASL_OK) { - SETERROR(sparams->utils, "unable to canonify authorization ID"); - goto cleanup; - } - - result = sparams->utils->prop_getnames(sparams->propctx, - password_request, - auxprop_values); - if (result < 0 || - ((!auxprop_values[0].name || !auxprop_values[0].values) && - (!auxprop_values[1].name || !auxprop_values[1].values))) { - /* We didn't find this username */ - sparams->utils->seterror(sparams->utils->conn,0, - "no secret in database"); - result = sparams->transition ? SASL_TRANS : SASL_NOUSER; - goto cleanup; - } - - if (auxprop_values[0].name && auxprop_values[0].values) { - char SaltedPassword[SCRAM_HASH_SIZE]; - char ClientKey[SCRAM_HASH_SIZE]; - - len = strlen(auxprop_values[0].values[0]); - if (len == 0) { - sparams->utils->seterror(sparams->utils->conn,0, - "empty secret"); - result = SASL_FAIL; - goto cleanup; - } - - sec = sparams->utils->malloc(sizeof(sasl_secret_t) + len); - if (sec == NULL) { - MEMERROR( sparams->utils ); - result = SASL_NOMEM; - goto cleanup; - } - - sec->len = (unsigned) len; - strncpy((char *)sec->data, auxprop_values[0].values[0], len + 1); - - /* SaltedPassword := Hi(password, salt) */ - Hi (sparams->utils, - sec->data, - sec->len, - text->salt, - SALT_SIZE, - text->iteration_count, - SaltedPassword); - - /* ClientKey := HMAC(SaltedPassword, "Client Key") */ - if (HMAC(EVP_sha1(), - (const unsigned char *) SaltedPassword, - SCRAM_HASH_SIZE, - CLIENT_KEY_CONSTANT, - CLIENT_KEY_CONSTANT_LEN, - (unsigned char *)ClientKey, - &hash_len) == NULL) { - sparams->utils->seterror(sparams->utils->conn,0, - "HMAC-SHA1 call failed"); - result = SASL_SCRAM_INTERNAL; - goto cleanup; - } - - /* StoredKey := H(ClientKey) */ - if (SHA1(ClientKey, SCRAM_HASH_SIZE, StoredKey) == NULL) { - sparams->utils->seterror(sparams->utils->conn,0, - "SHA1 call failed"); - result = SASL_SCRAM_INTERNAL; - goto cleanup; - - } - - /* ServerKey := HMAC(SaltedPassword, "Server Key") */ - if (HMAC(EVP_sha1(), - (const unsigned char *) SaltedPassword, - SCRAM_HASH_SIZE, - SERVER_KEY_CONSTANT, - SERVER_KEY_CONSTANT_LEN, - (unsigned char *)ServerKey, - &hash_len) == NULL) { - sparams->utils->seterror(sparams->utils->conn,0, - "HMAC-SHA1 call failed"); - result = SASL_SCRAM_INTERNAL; - goto cleanup; - } - -#ifdef NOT_YET - } else if (auxprop_values[1].name && auxprop_values[1].values) { - /* We have a precomputed secret */ - memcpy(&md5state, auxprop_values[1].values[0], - sizeof(HMAC_SHA1_STATE)); -#endif - } else { - sparams->utils->seterror(sparams->utils->conn, 0, - "Have neither type of secret"); - return SASL_FAIL; - } - - /* erase the plaintext password */ - sparams->utils->prop_erase(sparams->propctx, password_request[0]); - - - /* Construct the full AuthMessage */ full_auth_message = sparams->utils->realloc(text->auth_message, text->auth_message_len + proof_offset + 1); @@ -965,7 +1164,7 @@ scram_server_mech_step2(server_context_t *text, /* ClientSignature := HMAC(StoredKey, AuthMessage) */ if (HMAC(EVP_sha1(), - (const unsigned char *) StoredKey, + (const unsigned char *) text->StoredKey, SCRAM_HASH_SIZE, text->auth_message, (int)text->auth_message_len, @@ -1007,7 +1206,7 @@ scram_server_mech_step2(server_context_t *text, } for (k = 0; k < SCRAM_HASH_SIZE; k++) { - if (CalculatedStoredKey[k] != StoredKey[k]) { + if (CalculatedStoredKey[k] != text->StoredKey[k]) { SETERROR(sparams->utils, "StoredKey mismatch"); result = SASL_BADPROT; goto cleanup; @@ -1016,7 +1215,7 @@ scram_server_mech_step2(server_context_t *text, /* ServerSignature := HMAC(ServerKey, AuthMessage) */ if (HMAC(EVP_sha1(), - (const unsigned char *) ServerKey, + (const unsigned char *) text->ServerKey, SCRAM_HASH_SIZE, text->auth_message, (int)text->auth_message_len, @@ -1070,7 +1269,6 @@ scram_server_mech_step2(server_context_t *text, result = SASL_OK; cleanup: - if (sec) _plug_free_secret(sparams->utils, &sec); return result; } @@ -1135,6 +1333,197 @@ static int scram_server_mech_step(void *conn_context, return SASL_FAIL; /* should never get here */ } +static int scram_setpass(void *glob_context __attribute__((unused)), + sasl_server_params_t *sparams, + const char *userstr, + const char *pass, + unsigned passlen, + const char *oldpass __attribute__((unused)), + unsigned oldpasslen __attribute__((unused)), + unsigned flags) +{ + int r; + char *user = NULL; + char *user_only = NULL; + char *realm = NULL; + sasl_secret_t *sec = NULL; + struct propctx *propctx = NULL; + const char *store_request[] = { "authPassword", + NULL }; + const char *generate_scram_secret; + + /* Do we have a backend that can store properties? */ + if (!sparams->utils->auxprop_store || + sparams->utils->auxprop_store(NULL, NULL, NULL) != SASL_OK) { + SETERROR(sparams->utils, SCRAM_SASL_MECH ": auxprop backend can't store properties"); + return SASL_NOMECH; + } + + sparams->utils->getopt(sparams->utils->getopt_context, + /* This affects all SCRAM plugins, not just SCRAM-SHA-1 */ + "SCRAM", + "scram_secret_generate", + &generate_scram_secret, + NULL); + + /* NOTE: The default (when this option is not set) is NOT to generate authPassword secret */ + if (!(generate_scram_secret && + (generate_scram_secret[0] == '1' || generate_scram_secret[0] == 'y' || + (generate_scram_secret[0] == 'o' && generate_scram_secret[1] == 'n') || + generate_scram_secret[0] == 't'))) { + /* Pretend that everything is Ok, no need to generate noise in the logs */ + return SASL_OK; + } + + r = _plug_parseuser(sparams->utils, + &user_only, + &realm, + sparams->user_realm, + sparams->serverFQDN, + userstr); + if (r) { + SETERROR(sparams->utils, SCRAM_SASL_MECH ": Error parsing user"); + return r; + } + + r = _plug_make_fulluser(sparams->utils, &user, user_only, realm); + if (r) { + goto cleanup; + } + + if ((flags & SASL_SET_DISABLE) || pass == NULL) { + sec = NULL; + } else { + char * error_text = NULL; + char salt[SALT_SIZE + 1]; + char base64_salt[BASE64_LEN(SALT_SIZE) + 1]; + /* size_t salt_len = SALT_SIZE; */ + char StoredKey[SCRAM_HASH_SIZE + 1]; + char ServerKey[SCRAM_HASH_SIZE + 1]; + char base64_StoredKey[BASE64_LEN(SCRAM_HASH_SIZE) + 1]; + char base64_ServerKey[BASE64_LEN(SCRAM_HASH_SIZE) + 1]; + size_t secret_len; + + sparams->utils->rand(sparams->utils->rpool, salt, SALT_SIZE); + + r = GenerateScramSecrets (sparams->utils, + pass, + passlen, + salt, + SALT_SIZE, + DEFAULT_ITERATION_COUNTER, + StoredKey, + ServerKey, + &error_text); + if (r != SASL_OK) { + if (error_text != NULL) { + SETERROR(sparams->utils, error_text); + } + goto cleanup; + } + + /* Returns SASL_OK on success, SASL_BUFOVER if result won't fit */ + if (sparams->utils->encode64(salt, + SALT_SIZE, + base64_salt, + BASE64_LEN(SALT_SIZE) + 1, + NULL) != SASL_OK) { + MEMERROR( sparams->utils ); + r = SASL_NOMEM; + goto cleanup; + } + + base64_salt[BASE64_LEN(SALT_SIZE)] = '\0'; + + + /* Returns SASL_OK on success, SASL_BUFOVER if result won't fit */ + if (sparams->utils->encode64(StoredKey, + SCRAM_HASH_SIZE, + base64_StoredKey, + BASE64_LEN(SCRAM_HASH_SIZE) + 1, + NULL) != SASL_OK) { + MEMERROR( sparams->utils ); + r = SASL_NOMEM; + goto cleanup; + } + + base64_StoredKey[BASE64_LEN(SCRAM_HASH_SIZE)] = '\0'; + + + + /* Returns SASL_OK on success, SASL_BUFOVER if result won't fit */ + if (sparams->utils->encode64(ServerKey, + SCRAM_HASH_SIZE, + base64_ServerKey, + BASE64_LEN(SCRAM_HASH_SIZE) + 1, + NULL) != SASL_OK) { + MEMERROR( sparams->utils ); + r = SASL_NOMEM; + goto cleanup; + } + + base64_ServerKey[BASE64_LEN(SCRAM_HASH_SIZE)] = '\0'; + + secret_len = strlen(SCRAM_SASL_MECH ":$:") + + ITERATION_COUNTER_BUF_LEN + + sizeof(base64_salt) + + sizeof(base64_StoredKey) + + sizeof(base64_ServerKey); + + sec = sparams->utils->malloc(sizeof(sasl_secret_t) + secret_len); + if (sec == NULL) { + MEMERROR( sparams->utils ); + r = SASL_NOMEM; + goto cleanup; + } + + sprintf(sec->data, + "%s$%u:%s$%s:%s", + SCRAM_SASL_MECH, + DEFAULT_ITERATION_COUNTER, + base64_salt, + base64_StoredKey, + base64_ServerKey); + sec->len = (unsigned int) strlen(sec->data); + } + + /* do the store */ + propctx = sparams->utils->prop_new(0); + if (!propctx) { + r = SASL_FAIL; + } + if (!r) { + r = sparams->utils->prop_request(propctx, store_request); + } + if (!r) { + r = sparams->utils->prop_set(propctx, + "authPassword", + (sec ? sec->data : NULL), + (sec ? sec->len : 0)); + } + if (!r) { + r = sparams->utils->auxprop_store(sparams->utils->conn, propctx, user); + } + if (propctx) { + sparams->utils->prop_dispose(&propctx); + } + + if (r) { + SETERROR(sparams->utils, "Error putting " SCRAM_SASL_MECH " secret"); + goto cleanup; + } + + sparams->utils->log(NULL, SASL_LOG_DEBUG, "Setpass for " SCRAM_SASL_MECH " successful\n"); + + cleanup: + if (user) _plug_free_string(sparams->utils, &user); + if (user_only) _plug_free_string(sparams->utils, &user_only); + if (realm) _plug_free_string(sparams->utils, &realm); + if (sec) _plug_free_secret(sparams->utils, &sec); + + return r; +} + static void scram_server_mech_dispose(void *conn_context, const sasl_utils_t *utils) { @@ -1167,7 +1556,7 @@ static sasl_server_plug_t scram_server_plugins[] = &scram_server_mech_step, /* mech_step */ &scram_server_mech_dispose, /* mech_dispose */ NULL, /* mech_free */ - NULL, /* setpass */ + &scram_setpass, /* setpass */ NULL, /* user_query */ NULL, /* idle */ NULL, /* mech avail */ From cb42884b2def5cbc3bbc9f5c5634c9f013d1b3e8 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Wed, 19 Jan 2011 12:01:42 +0000 Subject: [PATCH 064/796] Fixed some Linux warnings in pluginviewer --- utils/pluginviewer.c | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/utils/pluginviewer.c b/utils/pluginviewer.c index 29534eca..c257f795 100644 --- a/utils/pluginviewer.c +++ b/utils/pluginviewer.c @@ -1,7 +1,7 @@ /* pluginviewer.c -- Plugin Viewer for CMU SASL * Alexey Melnikov, Isode Ltd. * - * $Id: pluginviewer.c,v 1.9 2010/02/27 19:24:56 mel Exp $ + * $Id: pluginviewer.c,v 1.10 2011/01/19 12:01:42 mel Exp $ */ /* * Copyright (c) 2004 Carnegie Mellon University. All rights reserved. @@ -135,14 +135,6 @@ static const char *flag_subopts[] = { NULL }; -static const char *ip_subopts[] = { -#define OPT_IP_LOCAL (0) - "local", -#define OPT_IP_REMOTE (1) - "remote", - NULL -}; - /* Whitespace separated list of mechanisms to allow (e.g. 'plain otp'). Used to restrict the mechanisms to a subset of the installed plugins. Default: NULL (i.e. all available) */ @@ -278,13 +270,6 @@ fail(const char *what) exit(EXIT_FAILURE); } -static void -osfail() -{ - perror(progname); - exit(EXIT_FAILURE); -} - /* Produce a space separated list of installed mechanisms */ static void list_installed_server_mechanisms ( @@ -379,7 +364,7 @@ main(int argc, char *argv[]) char *options, *value; const char *available_mechs = NULL; unsigned len; - unsigned count; + int count; sasl_callback_t callbacks[N_CALLBACKS], *callback; char *searchpath = NULL; char *service = "test"; From 13258f43af71fab36850ff6b75bc0f3efcc290e7 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Wed, 19 Jan 2011 12:05:49 +0000 Subject: [PATCH 065/796] Made the default number of SCRAM hash iterations configurable --- plugins/scram.c | 64 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 55 insertions(+), 9 deletions(-) diff --git a/plugins/scram.c b/plugins/scram.c index 1035424a..48924767 100644 --- a/plugins/scram.c +++ b/plugins/scram.c @@ -1,6 +1,6 @@ /* SCRAM-SHA-1 SASL plugin * Alexey Melnikov - * $Id: scram.c,v 1.20 2011/01/19 10:40:11 mel Exp $ + * $Id: scram.c,v 1.21 2011/01/19 12:05:49 mel Exp $ */ /* * Copyright (c) 2009-2010 Carnegie Mellon University. All rights reserved. @@ -69,7 +69,7 @@ /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: scram.c,v 1.20 2011/01/19 10:40:11 mel Exp $"; +static const char plugin_id[] = "$Id: scram.c,v 1.21 2011/01/19 12:05:49 mel Exp $"; #define NONCE_SIZE (32) /* arbitrary */ #define SALT_SIZE (16) /* arbitrary */ @@ -737,11 +737,32 @@ scram_server_mech_step1(server_context_t *text, if (auxprop_values[0].name && auxprop_values[0].values) { char * error_text = NULL; + char * s_iteration_count; + char * end; text->salt = scram_server_user_salt(sparams->utils, text->authentication_id, &text->salt_len); - text->iteration_count = DEFAULT_ITERATION_COUNTER; + sparams->utils->getopt(sparams->utils->getopt_context, + /* Different SCRAM hashes can have different strengh */ + SCRAM_SASL_MECH, + "scram_iteration_counter", + &s_iteration_count, + NULL); + if (s_iteration_count != NULL) { + errno = 0; + text->iteration_count = strtoul(s_iteration_count, &end, 10); + if (s_iteration_count == end || *end != '\0' || errno != 0) { + sparams->utils->log(NULL, + SASL_LOG_DEBUG, + "Invalid iteration-count in scram_iteration_count SASL option: not a number. Using the default instead."); + s_iteration_count = NULL; + } + } + + if (s_iteration_count == NULL) { + text->iteration_count = DEFAULT_ITERATION_COUNTER; + } result = GenerateScramSecrets (sparams->utils, auxprop_values[0].values[0], @@ -1403,6 +1424,31 @@ static int scram_setpass(void *glob_context __attribute__((unused)), char base64_StoredKey[BASE64_LEN(SCRAM_HASH_SIZE) + 1]; char base64_ServerKey[BASE64_LEN(SCRAM_HASH_SIZE) + 1]; size_t secret_len; + unsigned int iteration_count = DEFAULT_ITERATION_COUNTER; + char * s_iteration_count; + char * end; + + sparams->utils->getopt(sparams->utils->getopt_context, + /* Different SCRAM hashes can have different strengh */ + SCRAM_SASL_MECH, + "scram_iteration_counter", + &s_iteration_count, + NULL); + + if (s_iteration_count != NULL) { + errno = 0; + iteration_count = strtoul(s_iteration_count, &end, 10); + if (s_iteration_count == end || *end != '\0' || errno != 0) { + sparams->utils->log(NULL, + SASL_LOG_DEBUG, + "Invalid iteration-count in scram_iteration_count SASL option: not a number. Using the default instead."); + s_iteration_count = NULL; + } + } + + if (s_iteration_count == NULL) { + iteration_count = DEFAULT_ITERATION_COUNTER; + } sparams->utils->rand(sparams->utils->rpool, salt, SALT_SIZE); @@ -1411,7 +1457,7 @@ static int scram_setpass(void *glob_context __attribute__((unused)), passlen, salt, SALT_SIZE, - DEFAULT_ITERATION_COUNTER, + iteration_count, StoredKey, ServerKey, &error_text); @@ -1480,7 +1526,7 @@ static int scram_setpass(void *glob_context __attribute__((unused)), sprintf(sec->data, "%s$%u:%s$%s:%s", SCRAM_SASL_MECH, - DEFAULT_ITERATION_COUNTER, + iteration_count, base64_salt, base64_StoredKey, base64_ServerKey); @@ -1571,15 +1617,15 @@ int scram_server_plug_init(const sasl_utils_t *utils, int *plugcount) { if (maxversion < SASL_SERVER_PLUG_VERSION) { - SETERROR( utils, "SCRAM version mismatch"); + SETERROR( utils, SCRAM_SASL_MECH " version mismatch"); return SASL_BADVERS; } *out_version = SASL_SERVER_PLUG_VERSION; *pluglist = scram_server_plugins; - *plugcount = 1; + *plugcount = 1; utils->rand(utils->rpool, (char *)g_salt_key, SALT_SIZE); - + return SASL_OK; } @@ -2466,7 +2512,7 @@ int scram_client_plug_init(const sasl_utils_t *utils, int *plugcount) { if (maxversion < SASL_CLIENT_PLUG_VERSION) { - SETERROR( utils, "SCRAM version mismatch"); + SETERROR( utils, SCRAM_SASL_MECH " version mismatch"); return SASL_BADVERS; } From 3b5d1e5a5ddcc0b59855b94a4631a6e0c9fdda77 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Wed, 19 Jan 2011 12:15:42 +0000 Subject: [PATCH 066/796] Fixed some Windows warnings in SASL security layer handling --- lib/common.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/common.c b/lib/common.c index e65c17c9..b9727448 100644 --- a/lib/common.c +++ b/lib/common.c @@ -1,7 +1,7 @@ /* common.c - Functions that are common to server and clinet * Rob Siemborski * Tim Martin - * $Id: common.c,v 1.128 2011/01/14 14:33:21 murch Exp $ + * $Id: common.c,v 1.129 2011/01/19 12:15:42 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -386,7 +386,7 @@ _sasl_encodev (sasl_conn_t *conn, conn->multipacket_encoded_data.curlen += *outputlen; *output = conn->multipacket_encoded_data.data; - *outputlen = conn->multipacket_encoded_data.curlen; + *outputlen = (unsigned)conn->multipacket_encoded_data.curlen; } (*p_num_packets)++; @@ -410,7 +410,7 @@ int sasl_encodev(sasl_conn_t *conn, struct iovec last_invec; unsigned cur_numiov; char * next_buf = NULL; - unsigned remainder_len; + size_t remainder_len; unsigned index_offset; unsigned allocated = 0; /* Number of generated SASL packets */ @@ -482,7 +482,7 @@ int sasl_encodev(sasl_conn_t *conn, if (next_buf != NULL) { cur_invec[0].iov_base = next_buf; - cur_invec[0].iov_len = remainder_len; + cur_invec[0].iov_len = (long)remainder_len; cur_numiov++; index_offset = 1; } else { @@ -566,7 +566,7 @@ int sasl_encodev(sasl_conn_t *conn, /* Force encoding of any partial buffer. Might not be optimal on the wire. */ if (next_buf != NULL) { last_invec.iov_base = next_buf; - last_invec.iov_len = remainder_len; + last_invec.iov_len = (long)remainder_len; result = _sasl_encodev (conn, &last_invec, From 847a3dec6061d7a460ed85a2658e3f8e9058e5e7 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Wed, 19 Jan 2011 12:27:44 +0000 Subject: [PATCH 067/796] Server side SASL context should list *-PLUS SASL mechanisms before the corresponding non-PLUS mechanisms for naive SASL clients. --- lib/server.c | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/lib/server.c b/lib/server.c index b093764a..71f8aa0a 100644 --- a/lib/server.c +++ b/lib/server.c @@ -1,7 +1,7 @@ /* SASL server API implementation * Rob Siemborski * Tim Martin - * $Id: server.c,v 1.167 2011/01/19 09:05:12 mel Exp $ + * $Id: server.c,v 1.168 2011/01/19 12:27:44 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -1744,38 +1744,44 @@ int _sasl_server_listmech(sasl_conn_t *conn, for (lup = 0; lup < s_conn->mech_length; lup++) { /* currently, we don't use the "user" parameter for anything */ if (mech_permitted(conn, listptr) == SASL_OK) { + /* * If the server would never succeed in the authentication of - * he non-PLUS-variant due to policy reasons, it MUST advertise + * the non-PLUS-variant due to policy reasons, it MUST advertise * only the PLUS-variant. */ - if (!SASL_CB_PRESENT(s_conn->sparams) || - !SASL_CB_CRITICAL(s_conn->sparams)) { - if (pcount != NULL) - (*pcount)++; - if (flag) + if ((listptr->m.plug->features & SASL_FEAT_CHANNEL_BINDING) && + SASL_CB_PRESENT(s_conn->sparams)) { + if (pcount != NULL) { + (*pcount)++; + } + if (flag) { strcat(conn->mechlist_buf, mysep); - else + } else { flag = 1; + } strcat(conn->mechlist_buf, listptr->m.plug->mech_name); - } + strcat(conn->mechlist_buf, "-PLUS"); + } + /* * If the server cannot support channel binding, it SHOULD * advertise only the non-PLUS-variant. Here, supporting channel * binding means the underlying SASL mechanism supports it and * the application has set some channel binding data. */ - if ((listptr->m.plug->features & SASL_FEAT_CHANNEL_BINDING) && - SASL_CB_PRESENT(s_conn->sparams)) { - if (pcount != NULL) - (*pcount)++; - if (flag) + if (!SASL_CB_PRESENT(s_conn->sparams) || + !SASL_CB_CRITICAL(s_conn->sparams)) { + if (pcount != NULL) { + (*pcount)++; + } + if (flag) { strcat(conn->mechlist_buf, mysep); - else + } else { flag = 1; + } strcat(conn->mechlist_buf, listptr->m.plug->mech_name); - strcat(conn->mechlist_buf, "-PLUS"); - } + } } listptr = listptr->next; From 3aa317dbacd05d67a4ed524409cadf168d06671f Mon Sep 17 00:00:00 2001 From: Ken Murchison Date: Wed, 19 Jan 2011 21:28:49 +0000 Subject: [PATCH 068/796] Changed server-side of HTTP Digest so that the application must pass an HTTP Request structure (Method/URI/Entity-Body) rather than just the HTTP Method --- ChangeLog | 7 +++++ include/sasl.h | 11 ++++++-- include/saslplug.h | 2 +- lib/common.c | 26 ++++++++---------- lib/server.c | 7 ++++- plugins/digestmd5.c | 67 ++++++++++++++++++++++++++++++--------------- 6 files changed, 80 insertions(+), 40 deletions(-) diff --git a/ChangeLog b/ChangeLog index d73acfac..cf87cdae 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-01-19 Ken Murchison + * include/sasl.h, include/saslplug.h, + lib/common.c, lib/server.c, plugins/digest-md5.c: + Changed server-side of HTTP Digest so that the application + must pass an HTTP Request structure (Method/URI/Entity-Body) + rather than just the HTTP Method + 2011-01-18 Alexey Melnikov * plugins/digestmd5.c: Use the same username for reauthentication cache lookup and update. Thanks to Ken for pointing out the diff --git a/include/sasl.h b/include/sasl.h index b7ea9014..cf5cc241 100755 --- a/include/sasl.h +++ b/include/sasl.h @@ -836,8 +836,15 @@ typedef struct sasl_channel_binding { #define SASL_CHANNEL_BINDING 21 -/* HTTP request method (RFC 2616) - ONLY used for HTTP Digest auth (RFC 2617) */ -#define SASL_HTTP_METHOD 22 +/* HTTP Request (RFC 2616) - ONLY used for HTTP Digest Auth (RFC 2617) */ +typedef struct sasl_http_request { + const char *method; + const char *uri; + const unsigned char *entity; + unsigned long elen; +} sasl_http_request_t; + +#define SASL_HTTP_REQUEST 22 /* set property in SASL connection state * returns: diff --git a/include/saslplug.h b/include/saslplug.h index 7151e553..4d0301be 100755 --- a/include/saslplug.h +++ b/include/saslplug.h @@ -580,7 +580,7 @@ typedef struct sasl_server_params { /* for additions which don't require a version upgrade; set to 0 */ const void *gss_creds; /* GSS credential handle */ const sasl_channel_binding_t *cbinding; /* server channel binding */ - const char *http_method; /* HTTP Digest request method */ + const sasl_http_request_t *http_request;/* HTTP Digest request method */ void *spare_ptr4; int (*spare_fptr1)(); int (*spare_fptr2)(); diff --git a/lib/common.c b/lib/common.c index b9727448..f9a44d6d 100644 --- a/lib/common.c +++ b/lib/common.c @@ -1,7 +1,7 @@ /* common.c - Functions that are common to server and clinet * Rob Siemborski * Tim Martin - * $Id: common.c,v 1.129 2011/01/19 12:15:42 mel Exp $ + * $Id: common.c,v 1.130 2011/01/19 21:28:49 murch Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -1047,6 +1047,12 @@ int sasl_getprop(sasl_conn_t *conn, int propnum, const void **pvalue) *(void **)pvalue = ((sasl_server_conn_t *)conn)->sparams->gss_creds; break; + case SASL_HTTP_REQUEST: { + if (conn->type == SASL_CONN_SERVER) + *(const sasl_http_request_t **)pvalue = + ((sasl_server_conn_t *)conn)->sparams->http_request; + break; + } default: result = SASL_BADPARAM; } @@ -1274,22 +1280,14 @@ int sasl_setprop(sasl_conn_t *conn, int propnum, const void *value) ((sasl_client_conn_t *)conn)->cparams->cbinding = cb; break; } - case SASL_HTTP_METHOD: - if(value && strlen(value)) { - result = _sasl_strdup(value, &str, NULL); - if(result != SASL_OK) MEMERROR(conn); - } else { - str = NULL; - } - - if(conn->type == SASL_CONN_SERVER) { - if(((sasl_server_conn_t *)conn)->sparams->http_method) - sasl_FREE(((sasl_server_conn_t *)conn)->sparams->http_method); - ((sasl_server_conn_t *)conn)->sparams->http_method = str; - } + case SASL_HTTP_REQUEST: { + const sasl_http_request_t *req = (const sasl_http_request_t *)value; + if (conn->type == SASL_CONN_SERVER) + ((sasl_server_conn_t *)conn)->sparams->http_request = req; break; + } default: sasl_seterror(conn, 0, "Unknown parameter type"); diff --git a/lib/server.c b/lib/server.c index 71f8aa0a..a16a560d 100644 --- a/lib/server.c +++ b/lib/server.c @@ -1,7 +1,7 @@ /* SASL server API implementation * Rob Siemborski * Tim Martin - * $Id: server.c,v 1.168 2011/01/19 12:27:44 mel Exp $ + * $Id: server.c,v 1.169 2011/01/19 21:28:49 murch Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -2279,6 +2279,11 @@ _sasl_print_mechanism ( printf ("%cCHANNEL_BINDING", delimiter); delimiter = '|'; } + + if (m->plug->features & SASL_FEAT_SUPPORTS_HTTP) { + printf ("%cSUPPORTS_HTTP", delimiter); + delimiter = '|'; + } } if (m->f) { diff --git a/plugins/digestmd5.c b/plugins/digestmd5.c index cfd1abd8..c010f978 100644 --- a/plugins/digestmd5.c +++ b/plugins/digestmd5.c @@ -3,7 +3,7 @@ * Rob Siemborski * Tim Martin * Alexey Melnikov - * $Id: digestmd5.c,v 1.201 2011/01/18 14:42:27 mel Exp $ + * $Id: digestmd5.c,v 1.202 2011/01/19 21:28:49 murch Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -122,7 +122,7 @@ extern int gethostname(char *, int); /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: digestmd5.c,v 1.201 2011/01/18 14:42:27 mel Exp $"; +static const char plugin_id[] = "$Id: digestmd5.c,v 1.202 2011/01/19 21:28:49 murch Exp $"; /* Definitions */ #define NONCE_SIZE (32) /* arbitrary */ @@ -1730,18 +1730,19 @@ static char *create_response(context_t * text, unsigned char *cnonce, char *qop, char *digesturi, - const char *method, + const sasl_http_request_t *request, HASH Secret, char *authorization_id, char **response_value) { HASHHEX SessionKey; - HASHHEX HEntity = "00000000000000000000000000000000"; HASHHEX Response; char *result; + /* RFC 2831 defaults */ + const char *method = "AUTHENTICATE"; + HASHHEX HEntity = "00000000000000000000000000000000"; - if (qop == NULL) - qop = "auth"; + if (qop == NULL) qop = "auth"; DigestCalcHA1FromSecret(text, utils, @@ -1750,7 +1751,22 @@ static char *create_response(context_t * text, nonce, cnonce, SessionKey); - + + if (request) { + /* per RFC 2617 */ + MD5_CTX Md5Ctx; + HASH HE; + + method = request->method; + utils->MD5Init(&Md5Ctx); + utils->MD5Update(&Md5Ctx, + request->entity ? request->entity : (u_char *) "", + request->elen); + utils->MD5Final(HE, &Md5Ctx); + CvtHex(HE, HEntity); + } + + /* Calculate response for comparison with client's response */ DigestCalcResponse(utils, SessionKey,/* HEX(H(A1)) */ nonce, /* nonce from server */ @@ -1768,7 +1784,7 @@ static char *create_response(context_t * text, memcpy(result, Response, HASHHEXLEN); result[HASHHEXLEN] = 0; - /* response_value (used for reauth i think) */ + /* Calculate response value for mutal auth with the client (NO Method) */ if (response_value != NULL) { char * new_response_value; @@ -2126,7 +2142,7 @@ static int digestmd5_server_mech_step2(server_context_t *stext, unsigned int noncecount = 0; char *qop = NULL; char *digesturi = NULL; - const char *method = NULL; + const sasl_http_request_t *request = NULL; char *response = NULL; /* setting the default value (65536) */ @@ -2166,6 +2182,11 @@ static int digestmd5_server_mech_step2(server_context_t *stext, goto FreeAllMem; } + if (text->http_mode) { + /* per RFC 2617 (RFC 2616 request as set by calling application) */ + request = sparams->http_request; + } + in = sparams->utils->malloc(clientinlen + 1); memcpy(in, clientin, clientinlen); @@ -2243,7 +2264,16 @@ static int digestmd5_server_mech_step2(server_context_t *stext, _plug_strdup(sparams->utils, value, &digesturi, NULL); - if (!text->http_mode) { + if (text->http_mode && request && request->uri) { + /* Verify digest-uri matches HTTP request (per RFC 2617) */ + if (strcmp(digesturi, request->uri)) { + result = SASL_BADAUTH; + SETERROR(sparams->utils, + "bad digest-uri: doesn't match HTTP request"); + goto FreeAllMem; + } + } + else { /* Verify digest-uri format (per RFC 2831): * * digest-uri-value = serv-type "/" host [ "/" serv-name ] @@ -2387,6 +2417,8 @@ static int digestmd5_server_mech_step2(server_context_t *stext, if (!text->nonce) { /* we don't have any reauth info, so bail */ + sparams->utils->log(sparams->utils->conn, SASL_LOG_DEBUG, + "No reauth info for '%s' found", username); result = SASL_FAIL; goto FreeAllMem; } @@ -2649,15 +2681,6 @@ static int digestmd5_server_mech_step2(server_context_t *stext, goto FreeAllMem; } - if (text->http_mode) { - /* per RFC 2617 (RFC 2616 Method as set by calling application) */ - method = sparams->http_method; - } - if (!method) { - /* per RFC 2831 */ - method = "AUTHENTICATE"; - } - serverresponse = create_response(text, sparams->utils, text->nonce, @@ -2665,7 +2688,7 @@ static int digestmd5_server_mech_step2(server_context_t *stext, cnonce, qop, digesturi, - method, + request, Secret, authorization_id, &text->response_value); @@ -2687,7 +2710,7 @@ static int digestmd5_server_mech_step2(server_context_t *stext, cnonce, qop, digesturi, - method, + request, SecretBogus, authorization_id, &text->response_value); @@ -2795,7 +2818,7 @@ static int digestmd5_server_mech_step2(server_context_t *stext, result = SASL_FAIL; goto FreeAllMem; } - + if (text->http_mode) { /* per RFC 2617 */ char ncvalue[10]; From 016dc300d6eaa2a29817ac2cc21b0f31fbdae0c9 Mon Sep 17 00:00:00 2001 From: Ken Murchison Date: Wed, 19 Jan 2011 23:06:52 +0000 Subject: [PATCH 069/796] more server-side HTTP Digest changes --- plugins/digestmd5.c | 47 ++++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/plugins/digestmd5.c b/plugins/digestmd5.c index c010f978..a15bfe5d 100644 --- a/plugins/digestmd5.c +++ b/plugins/digestmd5.c @@ -3,7 +3,7 @@ * Rob Siemborski * Tim Martin * Alexey Melnikov - * $Id: digestmd5.c,v 1.202 2011/01/19 21:28:49 murch Exp $ + * $Id: digestmd5.c,v 1.203 2011/01/19 23:06:52 murch Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -122,7 +122,7 @@ extern int gethostname(char *, int); /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: digestmd5.c,v 1.202 2011/01/19 21:28:49 murch Exp $"; +static const char plugin_id[] = "$Id: digestmd5.c,v 1.203 2011/01/19 23:06:52 murch Exp $"; /* Definitions */ #define NONCE_SIZE (32) /* arbitrary */ @@ -1729,18 +1729,16 @@ static char *create_response(context_t * text, unsigned int ncvalue, unsigned char *cnonce, char *qop, - char *digesturi, const sasl_http_request_t *request, HASH Secret, char *authorization_id, char **response_value) { HASHHEX SessionKey; + HASH EntityHash; + HASHHEX HEntity; HASHHEX Response; char *result; - /* RFC 2831 defaults */ - const char *method = "AUTHENTICATE"; - HASHHEX HEntity = "00000000000000000000000000000000"; if (qop == NULL) qop = "auth"; @@ -1752,19 +1750,19 @@ static char *create_response(context_t * text, cnonce, SessionKey); - if (request) { + if (text->http_mode) { /* per RFC 2617 */ MD5_CTX Md5Ctx; - HASH HE; - method = request->method; utils->MD5Init(&Md5Ctx); - utils->MD5Update(&Md5Ctx, - request->entity ? request->entity : (u_char *) "", - request->elen); - utils->MD5Final(HE, &Md5Ctx); - CvtHex(HE, HEntity); + utils->MD5Update(&Md5Ctx, request->entity, request->elen); + utils->MD5Final(EntityHash, &Md5Ctx); + } + else { + /* per RFC 2831 */ + memset(EntityHash, 0, HASHLEN); } + CvtHex(EntityHash, HEntity); /* Calculate response for comparison with client's response */ DigestCalcResponse(utils, @@ -1774,8 +1772,8 @@ static char *create_response(context_t * text, cnonce, /* client nonce */ (unsigned char *) qop, /* qop-value: "", "auth", * "auth-int" */ - (unsigned char *) digesturi, /* requested URL */ - (unsigned char *) method, + (unsigned char *) request->uri, /* requested URL */ + (unsigned char *) request->method, HEntity, /* H(entity body) if qop="auth-int" */ Response /* request-digest or response-digest */ ); @@ -1795,7 +1793,7 @@ static char *create_response(context_t * text, cnonce, /* client nonce */ (unsigned char *) qop, /* qop-value: "", "auth", * "auth-int" */ - (unsigned char *) digesturi, /* requested URL */ + (unsigned char *) request->uri, /* requested URL */ NULL, HEntity, /* H(entity body) if qop="auth-int" */ Response /* request-digest or response-digest */ @@ -2142,7 +2140,8 @@ static int digestmd5_server_mech_step2(server_context_t *stext, unsigned int noncecount = 0; char *qop = NULL; char *digesturi = NULL; - const sasl_http_request_t *request = NULL; + sasl_http_request_t rfc2831_request; + const sasl_http_request_t *request; char *response = NULL; /* setting the default value (65536) */ @@ -2186,6 +2185,14 @@ static int digestmd5_server_mech_step2(server_context_t *stext, /* per RFC 2617 (RFC 2616 request as set by calling application) */ request = sparams->http_request; } + else { + /* per RFC 2831 */ + rfc2831_request.method = "AUTHENTICATE"; + rfc2831_request.uri = NULL; /* to be filled in below from response */ + rfc2831_request.entity = NULL; + rfc2831_request.elen = 0; + request = &rfc2831_request; + } in = sparams->utils->malloc(clientinlen + 1); @@ -2290,6 +2297,8 @@ static int digestmd5_server_mech_step2(server_context_t *stext, } /* xxx we don't verify the hostname component */ + + rfc2831_request.uri = digesturi; } } else if (strcasecmp(name, "response") == 0) { @@ -2687,7 +2696,6 @@ static int digestmd5_server_mech_step2(server_context_t *stext, text->nonce_count, cnonce, qop, - digesturi, request, Secret, authorization_id, @@ -2709,7 +2717,6 @@ static int digestmd5_server_mech_step2(server_context_t *stext, text->nonce_count, cnonce, qop, - digesturi, request, SecretBogus, authorization_id, From eafe894dc19ecdbe559a5a710ee173c5cd1985ad Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Fri, 21 Jan 2011 14:58:07 +0000 Subject: [PATCH 070/796] Better default ordering of SASL mechanisms --- lib/client.c | 31 +++++++++++++++++-------------- lib/server.c | 29 +++++++++++++++++------------ 2 files changed, 34 insertions(+), 26 deletions(-) diff --git a/lib/client.c b/lib/client.c index 24792bbf..4e9a909f 100644 --- a/lib/client.c +++ b/lib/client.c @@ -1,7 +1,7 @@ /* SASL client API implementation * Rob Siemborski * Tim Martin - * $Id: client.c,v 1.81 2011/01/19 09:04:29 mel Exp $ + * $Id: client.c,v 1.82 2011/01/21 14:58:07 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -145,29 +145,32 @@ static int mech_compare(const sasl_client_plug_t *a, const sasl_client_plug_t *b) { unsigned sec_diff; - - if (a->max_ssf > b->max_ssf) return 1; - if (a->max_ssf < b->max_ssf) return -1; + unsigned features_diff; /* XXX the following is fairly arbitrary, but its independent of the order in which the plugins are loaded */ sec_diff = a->security_flags ^ b->security_flags; - if (sec_diff & a->security_flags & SASL_SEC_FORWARD_SECRECY) return 1; - if (sec_diff & b->security_flags & SASL_SEC_FORWARD_SECRECY) return -1; - if (sec_diff & a->security_flags & SASL_SEC_NOACTIVE) return 1; - if (sec_diff & b->security_flags & SASL_SEC_NOACTIVE) return -1; - if (sec_diff & a->security_flags & SASL_SEC_NODICTIONARY) return 1; - if (sec_diff & b->security_flags & SASL_SEC_NODICTIONARY) return -1; - if (sec_diff & a->security_flags & SASL_SEC_MUTUAL_AUTH) return 1; - if (sec_diff & b->security_flags & SASL_SEC_MUTUAL_AUTH) return -1; if (sec_diff & a->security_flags & SASL_SEC_NOANONYMOUS) return 1; if (sec_diff & b->security_flags & SASL_SEC_NOANONYMOUS) return -1; if (sec_diff & a->security_flags & SASL_SEC_NOPLAINTEXT) return 1; if (sec_diff & b->security_flags & SASL_SEC_NOPLAINTEXT) return -1; - if (sec_diff & a->security_flags & SASL_SEC_PASS_CREDENTIALS) return 1; - if (sec_diff & b->security_flags & SASL_SEC_PASS_CREDENTIALS) return -1; + if (sec_diff & a->security_flags & SASL_SEC_MUTUAL_AUTH) return 1; + if (sec_diff & b->security_flags & SASL_SEC_MUTUAL_AUTH) return -1; + if (sec_diff & a->security_flags & SASL_SEC_NOACTIVE) return 1; + if (sec_diff & b->security_flags & SASL_SEC_NOACTIVE) return -1; + if (sec_diff & a->security_flags & SASL_SEC_NODICTIONARY) return 1; + if (sec_diff & b->security_flags & SASL_SEC_NODICTIONARY) return -1; + if (sec_diff & a->security_flags & SASL_SEC_FORWARD_SECRECY) return 1; + if (sec_diff & b->security_flags & SASL_SEC_FORWARD_SECRECY) return -1; + + features_diff = a->features ^ b->features; + if (features_diff & a->features & SASL_FEAT_CHANNEL_BINDING) return 1; + if (features_diff & b->features & SASL_FEAT_CHANNEL_BINDING) return -1; + if (a->max_ssf > b->max_ssf) return 1; + if (a->max_ssf < b->max_ssf) return -1; + return 0; } diff --git a/lib/server.c b/lib/server.c index a16a560d..f6a545d9 100644 --- a/lib/server.c +++ b/lib/server.c @@ -1,7 +1,7 @@ /* SASL server API implementation * Rob Siemborski * Tim Martin - * $Id: server.c,v 1.169 2011/01/19 21:28:49 murch Exp $ + * $Id: server.c,v 1.170 2011/01/21 14:58:07 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -385,26 +385,31 @@ static int mech_compare(const sasl_server_plug_t *a, const sasl_server_plug_t *b) { unsigned sec_diff; - - if (a->max_ssf > b->max_ssf) return 1; - if (a->max_ssf < b->max_ssf) return -1; + unsigned features_diff; /* XXX the following is fairly arbitrary, but its independent of the order in which the plugins are loaded */ sec_diff = a->security_flags ^ b->security_flags; - if (sec_diff & a->security_flags & SASL_SEC_FORWARD_SECRECY) return 1; - if (sec_diff & b->security_flags & SASL_SEC_FORWARD_SECRECY) return -1; - if (sec_diff & a->security_flags & SASL_SEC_NOACTIVE) return 1; - if (sec_diff & b->security_flags & SASL_SEC_NOACTIVE) return -1; - if (sec_diff & a->security_flags & SASL_SEC_NODICTIONARY) return 1; - if (sec_diff & b->security_flags & SASL_SEC_NODICTIONARY) return -1; - if (sec_diff & a->security_flags & SASL_SEC_MUTUAL_AUTH) return 1; - if (sec_diff & b->security_flags & SASL_SEC_MUTUAL_AUTH) return -1; if (sec_diff & a->security_flags & SASL_SEC_NOANONYMOUS) return 1; if (sec_diff & b->security_flags & SASL_SEC_NOANONYMOUS) return -1; if (sec_diff & a->security_flags & SASL_SEC_NOPLAINTEXT) return 1; if (sec_diff & b->security_flags & SASL_SEC_NOPLAINTEXT) return -1; + if (sec_diff & a->security_flags & SASL_SEC_MUTUAL_AUTH) return 1; + if (sec_diff & b->security_flags & SASL_SEC_MUTUAL_AUTH) return -1; + if (sec_diff & a->security_flags & SASL_SEC_NOACTIVE) return 1; + if (sec_diff & b->security_flags & SASL_SEC_NOACTIVE) return -1; + if (sec_diff & a->security_flags & SASL_SEC_NODICTIONARY) return 1; + if (sec_diff & b->security_flags & SASL_SEC_NODICTIONARY) return -1; + if (sec_diff & a->security_flags & SASL_SEC_FORWARD_SECRECY) return 1; + if (sec_diff & b->security_flags & SASL_SEC_FORWARD_SECRECY) return -1; + + features_diff = a->features ^ b->features; + if (features_diff & a->features & SASL_FEAT_CHANNEL_BINDING) return 1; + if (features_diff & b->features & SASL_FEAT_CHANNEL_BINDING) return -1; + + if (a->max_ssf > b->max_ssf) return 1; + if (a->max_ssf < b->max_ssf) return -1; return 0; } From 80d79113041b216e5b8a6687d9d3bc26f2f1553b Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Fri, 21 Jan 2011 15:02:41 +0000 Subject: [PATCH 071/796] Fixed handling of channel bindings on the client side (see ChangeLog for details) --- include/saslplug.h | 4 +-- lib/client.c | 63 ++++++++++++++++++++++++++++------------------ 2 files changed, 41 insertions(+), 26 deletions(-) diff --git a/include/saslplug.h b/include/saslplug.h index 4d0301be..4280707d 100755 --- a/include/saslplug.h +++ b/include/saslplug.h @@ -225,8 +225,8 @@ typedef enum { typedef enum { SASL_CB_DISP_NONE = 0, /* client did not support CB */ - SASL_CB_DISP_USED, /* client supports and used CB */ - SASL_CB_DISP_WANT /* client supports CB, thinks server does not */ + SASL_CB_DISP_WANT, /* client supports CB, thinks server does not */ + SASL_CB_DISP_USED /* client supports and used CB */ } sasl_cbinding_disp_t; /* TRUE if channel binding is non-NULL */ diff --git a/lib/client.c b/lib/client.c index 4e9a909f..542ef4b4 100644 --- a/lib/client.c +++ b/lib/client.c @@ -1,7 +1,7 @@ /* SASL client API implementation * Rob Siemborski * Tim Martin - * $Id: client.c,v 1.82 2011/01/21 14:58:07 mel Exp $ + * $Id: client.c,v 1.83 2011/01/21 15:02:41 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -644,10 +644,11 @@ _sasl_cbinding_disp(sasl_client_params_t *cparams, if (SASL_CB_PRESENT(cparams)) { if (mech_nego) { - if (!server_can_cb && SASL_CB_CRITICAL(cparams)) + if (!server_can_cb && SASL_CB_CRITICAL(cparams)) { return SASL_NOMECH; - else + } else { *cbindingdisp = SASL_CB_DISP_WANT; + } } else if (SASL_CB_CRITICAL(cparams)) { *cbindingdisp = SASL_CB_DISP_USED; } @@ -690,11 +691,13 @@ int sasl_client_start(sasl_conn_t *conn, { sasl_client_conn_t *c_conn = (sasl_client_conn_t *) conn; char *ordered_mechs = NULL, *name; - cmechanism_t *m=NULL,*bestm=NULL; + cmechanism_t *m = NULL, *bestm = NULL; size_t i, list_len; sasl_ssf_t bestssf = 0, minssf = 0; int result, server_can_cb = 0; sasl_cbinding_disp_t cbindingdisp; + sasl_cbinding_disp_t cur_cbindingdisp; + sasl_cbinding_disp_t best_cbindingdisp = SASL_CB_DISP_NONE; if (_sasl_client_active == 0) return SASL_NOTINIT; @@ -735,18 +738,22 @@ int sasl_client_start(sasl_conn_t *conn, * are doing mechanism negotiation and whether server supports * channel bindings. */ - result = _sasl_cbinding_disp(c_conn->cparams, (list_len > 1), - server_can_cb, &cbindingdisp); + result = _sasl_cbinding_disp(c_conn->cparams, + (list_len > 1), + server_can_cb, + &cbindingdisp); if (result != 0) goto done; for (i = 0, name = ordered_mechs; i < list_len; i++) { + /* for each mechanism in client's list */ for (m = c_conn->mech_list; m != NULL; m = m->next) { int myflags, plus; - if (!_sasl_is_equal_mech(name, m->m.plug->mech_name, &plus)) + if (!_sasl_is_equal_mech(name, m->m.plug->mech_name, &plus)) { continue; + } /* Do we have the prompts for it? */ if (!have_prompts(conn, m->m.plug)) @@ -770,7 +777,7 @@ int sasl_client_start(sasl_conn_t *conn, } /* Can we meet it's features? */ - if (cbindingdisp != SASL_CB_DISP_NONE && + if (cbindingdisp == SASL_CB_DISP_USED && !(m->m.plug->features & SASL_FEAT_CHANNEL_BINDING)) { break; } @@ -786,20 +793,6 @@ int sasl_client_start(sasl_conn_t *conn, break; } -#ifdef PREFER_MECH - if (strcasecmp(m->m.plug->mech_name, PREFER_MECH) && - bestm && m->m.plug->max_ssf <= bestssf) { - /* this mechanism isn't our favorite, and it's no better - than what we already have! */ - break; - } -#else - if (bestm && m->m.plug->max_ssf <= bestssf) { - /* this mechanism is no better than what we already have! */ - break; - } -#endif - /* compare security flags, only take new mechanism if it has * all the security flags of the previous one. * @@ -825,12 +818,34 @@ int sasl_client_start(sasl_conn_t *conn, } if (SASL_CB_PRESENT(c_conn->cparams) && plus) { - cbindingdisp = SASL_CB_DISP_USED; + cur_cbindingdisp = SASL_CB_DISP_USED; + } else { + cur_cbindingdisp = cbindingdisp; } + if (bestm && (best_cbindingdisp > cur_cbindingdisp)) { + break; + } + +#ifdef PREFER_MECH + if (strcasecmp(m->m.plug->mech_name, PREFER_MECH) && + bestm && m->m.plug->max_ssf <= bestssf) { + /* this mechanism isn't our favorite, and it's no better + than what we already have! */ + break; + } +#else + if (bestm && m->m.plug->max_ssf <= bestssf) { + /* this mechanism is no better than what we already have! */ + break; + } +#endif + if (mech) { *mech = m->m.plug->mech_name; } + + best_cbindingdisp = cur_cbindingdisp; bestssf = m->m.plug->max_ssf; bestm = m; break; @@ -858,7 +873,7 @@ int sasl_client_start(sasl_conn_t *conn, c_conn->cparams->external_ssf = conn->external.ssf; c_conn->cparams->props = conn->props; - c_conn->cparams->cbindingdisp = cbindingdisp; + c_conn->cparams->cbindingdisp = best_cbindingdisp; c_conn->mech = bestm; /* init that plugin */ From 09109ebc725c082322a78c3b505c3b5e979ca12e Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Fri, 21 Jan 2011 15:19:36 +0000 Subject: [PATCH 072/796] Fixed libsasl to accept *-PLUS SASL mechanism names in client_mech_list/mech_list options. --- lib/client.c | 13 ++++++++----- lib/common.c | 12 ++++++------ lib/saslint.h | 3 ++- lib/server.c | 12 ++++++++---- 4 files changed, 24 insertions(+), 16 deletions(-) diff --git a/lib/client.c b/lib/client.c index 542ef4b4..a12e181e 100644 --- a/lib/client.c +++ b/lib/client.c @@ -1,7 +1,7 @@ /* SASL client API implementation * Rob Siemborski * Tim Martin - * $Id: client.c,v 1.83 2011/01/21 15:02:41 mel Exp $ + * $Id: client.c,v 1.84 2011/01/21 15:19:36 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -396,6 +396,7 @@ int sasl_client_new(const char *service, sasl_getopt_t *getopt; void *context; const char *mlist = NULL; + int plus = 0; if (_sasl_client_active == 0) return SASL_NOTINIT; @@ -455,10 +456,10 @@ int sasl_client_new(const char *service, for (mptr = cmechlist->mech_list; mptr; mptr = mptr->next) { const sasl_client_plug_t *plug = mptr->m.plug; - if (((size_t) (cp - mlist) == strlen(plug->mech_name)) && - !strncasecmp(mlist, plug->mech_name, strlen(plug->mech_name))) + if (_sasl_is_equal_mech(mlist, plug->mech_name, (size_t) (cp - mlist), &plus)) { /* found a match */ break; + } } if (mptr) { new = sasl_ALLOC(sizeof(cmechanism_t)); @@ -692,7 +693,7 @@ int sasl_client_start(sasl_conn_t *conn, sasl_client_conn_t *c_conn = (sasl_client_conn_t *) conn; char *ordered_mechs = NULL, *name; cmechanism_t *m = NULL, *bestm = NULL; - size_t i, list_len; + size_t i, list_len, name_len; sasl_ssf_t bestssf = 0, minssf = 0; int result, server_can_cb = 0; sasl_cbinding_disp_t cbindingdisp; @@ -747,11 +748,13 @@ int sasl_client_start(sasl_conn_t *conn, for (i = 0, name = ordered_mechs; i < list_len; i++) { + name_len = strlen(name); + /* for each mechanism in client's list */ for (m = c_conn->mech_list; m != NULL; m = m->next) { int myflags, plus; - if (!_sasl_is_equal_mech(name, m->m.plug->mech_name, &plus)) { + if (!_sasl_is_equal_mech(name, m->m.plug->mech_name, name_len, &plus)) { continue; } diff --git a/lib/common.c b/lib/common.c index f9a44d6d..608128ee 100644 --- a/lib/common.c +++ b/lib/common.c @@ -1,7 +1,7 @@ /* common.c - Functions that are common to server and clinet * Rob Siemborski * Tim Martin - * $Id: common.c,v 1.130 2011/01/19 21:28:49 murch Exp $ + * $Id: common.c,v 1.131 2011/01/21 15:19:36 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -2405,17 +2405,17 @@ int sasl_listmech(sasl_conn_t *conn, int _sasl_is_equal_mech(const char *req_mech, const char *plug_mech, + size_t req_mech_len, int *plus) { - size_t len = strlen(req_mech); size_t n; - if (len > 5 && - strcasecmp(&req_mech[len - 5], "-PLUS") == 0) { - n = len - 5; + if (req_mech_len > 5 && + strcasecmp(&req_mech[req_mech_len - 5], "-PLUS") == 0) { + n = req_mech_len - 5; *plus = 1; } else { - n = len; + n = req_mech_len; *plus = 0; } diff --git a/lib/saslint.h b/lib/saslint.h index 869b4204..8c7bca00 100644 --- a/lib/saslint.h +++ b/lib/saslint.h @@ -1,7 +1,7 @@ /* saslint.h - internal SASL library definitions * Rob Siemborski * Tim Martin - * $Id: saslint.h,v 1.71 2010/12/01 15:08:00 mel Exp $ + * $Id: saslint.h,v 1.72 2011/01/21 15:19:36 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -319,6 +319,7 @@ void sasl_common_done(void); extern int _sasl_is_equal_mech(const char *req_mech, const char *plug_mech, + size_t req_mech_len, int *plus); /* diff --git a/lib/server.c b/lib/server.c index f6a545d9..cca2c2b6 100644 --- a/lib/server.c +++ b/lib/server.c @@ -1,7 +1,7 @@ /* SASL server API implementation * Rob Siemborski * Tim Martin - * $Id: server.c,v 1.170 2011/01/21 14:58:07 mel Exp $ + * $Id: server.c,v 1.171 2011/01/21 15:19:36 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -1017,6 +1017,7 @@ int sasl_server_new(const char *service, void *context; const char *log_level, *auto_trans; const char *mlist = NULL; + int plus = 0; if (_sasl_server_active==0) return SASL_NOTINIT; if (! pconn) return SASL_FAIL; @@ -1125,10 +1126,10 @@ int sasl_server_new(const char *service, for (mptr = mechlist->mech_list; mptr; mptr = mptr->next) { const sasl_server_plug_t *plug = mptr->m.plug; - if (((size_t) (cp - mlist) == strlen(plug->mech_name)) && - !strncasecmp(mlist, plug->mech_name, strlen(plug->mech_name))) + if (_sasl_is_equal_mech(mlist, plug->mech_name, (size_t) (cp - mlist), &plus)) { /* found a match */ break; + } } if (mptr) { mechanism_t *new = sasl_ALLOC(sizeof(mechanism_t)); @@ -1369,6 +1370,7 @@ int sasl_server_start(sasl_conn_t *conn, int result; context_list_t *cur, **prev; mechanism_t *m; + size_t mech_len; int plus = 0; if (_sasl_server_active==0) return SASL_NOTINIT; @@ -1385,10 +1387,12 @@ int sasl_server_start(sasl_conn_t *conn, /* make sure mech is valid mechanism if not return appropriate error */ m = s_conn->mech_list; + mech_len = strlen(mech); while (m != NULL) { - if (_sasl_is_equal_mech(mech, m->m.plug->mech_name, &plus)) + if (_sasl_is_equal_mech(mech, m->m.plug->mech_name, mech_len, &plus)) { break; + } m = m->next; } From 4883553b0e25edfa9f72fe254c158f782a898aec Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Fri, 21 Jan 2011 15:24:30 +0000 Subject: [PATCH 073/796] Updated as per my recent SCRAM and channel binding related changes --- ChangeLog | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/ChangeLog b/ChangeLog index cf87cdae..80989188 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,29 @@ +2011-01-21 Alexey Melnikov + * lib/client.c, lib/server.c, lib/common.c, lib/saslint.h: Fixed libsasl + to accept *-PLUS SASL mechanism names in client_mech_list/mech_list options. + As *-PLUS mechanism names were synthesized and didn't correspond to real + plugin names, setting client_mech_list to "SCRAM-SHA-1-PLUS" (for example) + was resulting in authentication failure due to inability to find a matching + SASL plugin. + +2011-01-21 Alexey Melnikov + * include/saslplug.h, lib/client.c: Fixed handling of channel bindings + on the client side. The client side was failing to select a suitable + SASL mechanism when the application specified channel bindings, but + didn't make them mandatory to use. In such a configuration, if a + non channel binding capable mechanism was selected through + "client_mech_list" SASL option, sasl_client_start would fail. + For example if the server supports both SCRAM-SHA-1[-PLUS] and + PLAIN and "client_mech_list" was set to "PLAIN", authentication + would never work. + +2011-01-21 Alexey Melnikov + * lib/client.c, lib/server.c: Better default ordering of SASL mechanisms. + Ordering by plugins max_ssf produces wrong result in case an application + using SASL doesn't care about SASL security layers. Before this change + DIGEST-MD5 was always preferred over SCRAM-SHA-1[-PLUS]. In particular + this change takes support for channel bindings into considerations. + 2011-01-19 Ken Murchison * include/sasl.h, include/saslplug.h, lib/common.c, lib/server.c, plugins/digest-md5.c: @@ -5,6 +31,34 @@ must pass an HTTP Request structure (Method/URI/Entity-Body) rather than just the HTTP Method +2011-01-19 Alexey Melnikov + * lib/server.c: Server side SASL context should list *-PLUS SASL + mechanisms before the corresponding non-PLUS mechanisms for naive + SASL clients. + +2011-01-19 Alexey Melnikov + * lib/common.c: Fixed some Windows warnings in SASL security layer + handling. + +2011-01-19 Alexey Melnikov + * plugins/scram.c: Made the default number of SCRAM hash iterations + configurable using a new SASL option called "scram_iteration_counter". + Also fixed a couple of error messages. + +2011-01-19 Alexey Melnikov + * utils/pluginviewer.c: Fixed some Linux warnings in pluginviewer. + +2011-01-19 Alexey Melnikov + * plugins/scram.c: Added support for storing SCRAM secrets in + authPassword attribute. Also added the "scram_secret_generate" option + for controlling if authPassword SCRAM secret should be generated + or not. By default (when not specified) the authPassword SCRAM secret + is NOT generated. + +2011-01-19 Alexey Melnikov + * plugins/scram.c: Updated the SCRAM plugin not to use the hardcoded + SCRAM-SHA-1 plugin name in logging. + 2011-01-18 Alexey Melnikov * plugins/digestmd5.c: Use the same username for reauthentication cache lookup and update. Thanks to Ken for pointing out the From b55f639c7c07677ef745f2e36b1f72d5ff9142b6 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Fri, 21 Jan 2011 15:37:44 +0000 Subject: [PATCH 074/796] Added support for channel bindings to SCRAM-SHA-1. --- ChangeLog | 3 + plugins/scram.c | 233 +++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 212 insertions(+), 24 deletions(-) diff --git a/ChangeLog b/ChangeLog index 80989188..67d1076b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +2011-01-21 Alexey Melnikov + * plugins/scram.c: Added support for channel bindings to SCRAM-SHA-1. + 2011-01-21 Alexey Melnikov * lib/client.c, lib/server.c, lib/common.c, lib/saslint.h: Fixed libsasl to accept *-PLUS SASL mechanism names in client_mech_list/mech_list options. diff --git a/plugins/scram.c b/plugins/scram.c index 48924767..5433ed26 100644 --- a/plugins/scram.c +++ b/plugins/scram.c @@ -1,6 +1,6 @@ /* SCRAM-SHA-1 SASL plugin * Alexey Melnikov - * $Id: scram.c,v 1.21 2011/01/19 12:05:49 mel Exp $ + * $Id: scram.c,v 1.22 2011/01/21 15:37:44 mel Exp $ */ /* * Copyright (c) 2009-2010 Carnegie Mellon University. All rights reserved. @@ -69,7 +69,7 @@ /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: scram.c,v 1.21 2011/01/19 12:05:49 mel Exp $"; +static const char plugin_id[] = "$Id: scram.c,v 1.22 2011/01/21 15:37:44 mel Exp $"; #define NONCE_SIZE (32) /* arbitrary */ #define SALT_SIZE (16) /* arbitrary */ @@ -99,6 +99,11 @@ static const char plugin_id[] = "$Id: scram.c,v 1.21 2011/01/19 12:05:49 mel Exp #define CLIENT_KEY_CONSTANT_LEN sizeof(CLIENT_KEY_CONSTANT)-1 #define SERVER_KEY_CONSTANT_LEN sizeof(SERVER_KEY_CONSTANT)-1 +#define SCRAM_CB_FLAG_MASK 0x0F +#define SCRAM_CB_FLAG_N 0x00 +#define SCRAM_CB_FLAG_P 0x01 +#define SCRAM_CB_FLAG_Y 0x02 + #ifdef SCRAM_DEBUG #define PRINT_HASH(func,hash) print_hash(func,hash) #else @@ -449,6 +454,11 @@ typedef struct server_context { unsigned int iteration_count; char StoredKey[SCRAM_HASH_SIZE + 1]; char ServerKey[SCRAM_HASH_SIZE + 1]; + + int cb_flags; + char *cbindingname; + char *gs2_header; + size_t gs2_header_length; } server_context_t; static int @@ -491,7 +501,6 @@ scram_server_mech_step1(server_context_t *text, char * base64_salt = NULL; size_t base64len; size_t estimated_challenge_len; - size_t gs2_header_length = 0; size_t pure_scram_length; char * inbuf = NULL; const char *password_request[] = { SASL_AUX_PASSWORD, @@ -541,19 +550,38 @@ scram_server_mech_step1(server_context_t *text, ;; The selected channel binding follows "p=". */ switch (p[0]) { case 'p': - if (clientin[1] != '=') { + if (p[1] != '=') { SETERROR(sparams->utils, "The initial 'p' needs to be followed by '=' in " SCRAM_SASL_MECH " input"); result = SASL_BADPROT; goto cleanup; } + p++; + + text->cbindingname = p + 1; + p = strchr (p, ','); + if (p == NULL) { + text->cbindingname = NULL; + + SETERROR(sparams->utils, "Channel binding name must be terminated by a comma in " SCRAM_SASL_MECH " input"); + result = SASL_BADPROT; + goto cleanup; + } + + *p = '\0'; + _plug_strdup(sparams->utils, text->cbindingname, &text->cbindingname, NULL); + *p = ','; + + text->cb_flags = SCRAM_CB_FLAG_P; break; case 'n': + text->cb_flags = SCRAM_CB_FLAG_N; /* We always have at least 10 bytes, so this is safe */ p++; break; case 'y': + text->cb_flags = SCRAM_CB_FLAG_Y; /* We always have at least 10 bytes, so this is safe */ p++; break; @@ -586,7 +614,7 @@ scram_server_mech_step1(server_context_t *text, /* End of the GS2 header */ p[0] = '\0'; /* The GS2 header length DOES include the terminating comma */ - gs2_header_length = p - inbuf + 1; + text->gs2_header_length = p - inbuf + 1; p++; @@ -606,11 +634,25 @@ scram_server_mech_step1(server_context_t *text, /* End of the GS2 header */ p[0] = '\0'; /* The GS2 header length DOES include the terminating comma */ - gs2_header_length = p - inbuf + 1; + text->gs2_header_length = p - inbuf + 1; p++; } + text->gs2_header = sparams->utils->malloc (text->gs2_header_length + 1); + if (text->gs2_header == NULL) { + MEMERROR( sparams->utils ); + result = SASL_NOMEM; + goto cleanup; + } + + memcpy(text->gs2_header, inbuf, text->gs2_header_length - 1); + /* Remember the comma */ + text->gs2_header[text->gs2_header_length - 1] = ','; + text->gs2_header[text->gs2_header_length] = 0; + + + if (p[1] != '=') { SETERROR(sparams->utils, "Invalid " SCRAM_SASL_MECH " input"); result = SASL_BADPROT; @@ -1002,7 +1044,7 @@ scram_server_mech_step1(server_context_t *text, /* Save the (client response, ",", server challenge, ","). Note, we skip the GS2 prefix here */ - pure_scram_length = clientinlen - gs2_header_length; + pure_scram_length = clientinlen - text->gs2_header_length; text->auth_message_len = pure_scram_length + 1 + estimated_challenge_len + 1; text->auth_message = sparams->utils->malloc (text->auth_message_len + 1); if (text->auth_message == NULL) { @@ -1011,7 +1053,7 @@ scram_server_mech_step1(server_context_t *text, goto cleanup; } - memcpy(text->auth_message, clientin + gs2_header_length, pure_scram_length); + memcpy(text->auth_message, clientin + text->gs2_header_length, pure_scram_length); text->auth_message[pure_scram_length] = ','; strcpy (text->auth_message + pure_scram_length + 1, text->out_buf); strcat (text->auth_message + pure_scram_length + 1, ","); @@ -1045,6 +1087,9 @@ scram_server_mech_step2(server_context_t *text, sasl_out_params_t *oparams) { char *channel_binding = NULL; + size_t channel_binding_len = 0; + char *binary_channel_binding = NULL; + size_t binary_channel_binding_len = 0; char *client_proof = NULL; char *inbuf = NULL; char *p; @@ -1110,6 +1155,74 @@ scram_server_mech_step2(server_context_t *text, *p = '\0'; p++; + channel_binding_len = strlen(channel_binding); + + /* We can calculate the exact length, but the decoded (binary) data + is always shorter than its base64 version. */ + binary_channel_binding = (char *) sparams->utils->malloc(channel_binding_len + 1); + + if (sparams->utils->decode64(channel_binding, + (unsigned int)channel_binding_len, + binary_channel_binding, + (unsigned int)channel_binding_len, + &binary_channel_binding_len) != SASL_OK) { + SETERROR(sparams->utils, "Invalid base64 encoding of the channel bindings in " SCRAM_SASL_MECH); + result = SASL_BADPROT; + goto cleanup; + } + + if (binary_channel_binding_len < text->gs2_header_length || + strncmp(binary_channel_binding, text->gs2_header, text->gs2_header_length) != 0) { + sparams->utils->seterror (sparams->utils->conn, + 0, + "Channel bindings prefix doesn't match the one received in the GS2 header of " + SCRAM_SASL_MECH ". Expected \"%s\"", + text->gs2_header); + result = SASL_BADPROT; + goto cleanup; + } + + switch (text->cb_flags & SCRAM_CB_FLAG_MASK) { + case SCRAM_CB_FLAG_P: + binary_channel_binding_len -= text->gs2_header_length; + if (binary_channel_binding_len == 0) { + SETERROR(sparams->utils, "Channel bindings data expected in " SCRAM_SASL_MECH); + result = SASL_BADPROT; + goto cleanup; + } + + if (strcmp(sparams->cbinding->name, text->cbindingname) != 0) { + sparams->utils->seterror (sparams->utils->conn, + 0, + "Unsupported channel bindings type received in " SCRAM_SASL_MECH + ". Expected: %s, received: %s", + sparams->cbinding->name, + text->cbindingname); + result = SASL_BADPROT; + goto cleanup; + } + + if (binary_channel_binding_len != sparams->cbinding->len) { + sparams->utils->seterror (sparams->utils->conn, + 0, + "Unsupported channel bindings length received in " SCRAM_SASL_MECH + ". Expected lenght: %d, received: %d", + sparams->cbinding->len, + binary_channel_binding_len); + result = SASL_BADPROT; + goto cleanup; + } + + if (memcmp(binary_channel_binding + text->gs2_header_length, + sparams->cbinding->data, + binary_channel_binding_len) != 0) { + SETERROR(sparams->utils, "Channel bindings mismatch in " SCRAM_SASL_MECH); + result = SASL_BADPROT; + goto cleanup; + } + break; + } + if (strncmp(p, "r=", 2) != 0) { SETERROR(sparams->utils, "Nonce expected in " SCRAM_SASL_MECH " input"); result = SASL_BADPROT; @@ -1278,6 +1391,20 @@ scram_server_mech_step2(server_context_t *text, /* set oparams */ + + switch (text->cb_flags & SCRAM_CB_FLAG_MASK) { + case SCRAM_CB_FLAG_N: + oparams->cbindingdisp = SASL_CB_DISP_NONE; + break; + case SCRAM_CB_FLAG_P: + oparams->cbindingdisp = SASL_CB_DISP_USED; + oparams->cbindingname = text->cbindingname; + break; + case SCRAM_CB_FLAG_Y: + oparams->cbindingdisp = SASL_CB_DISP_WANT; + break; + } + oparams->doneflag = 1; oparams->mech_ssf = 0; oparams->maxoutbuf = 0; @@ -1290,6 +1417,9 @@ scram_server_mech_step2(server_context_t *text, result = SASL_OK; cleanup: + if (binary_channel_binding != NULL) { + sparams->utils->free(binary_channel_binding); + } return result; } @@ -1583,7 +1713,15 @@ static void scram_server_mech_dispose(void *conn_context, if (text->auth_message) _plug_free_string(utils,&(text->auth_message)); if (text->nonce) _plug_free_string(utils,&(text->nonce)); if (text->salt) utils->free(text->salt); - + if (text->cbindingname != NULL) { + utils->free(text->cbindingname); + text->cbindingname = NULL; + } + if (text->gs2_header != NULL) { + utils->free(text->gs2_header); + text->gs2_header = NULL; + } + utils->free(text); } @@ -1596,7 +1734,8 @@ static sasl_server_plug_t scram_server_plugins[] = | SASL_SEC_NOACTIVE | SASL_SEC_NOANONYMOUS | SASL_SEC_MUTUAL_AUTH, /* security_flags */ - SASL_FEAT_ALLOWS_PROXY, /* features */ + SASL_FEAT_ALLOWS_PROXY + | SASL_FEAT_CHANNEL_BINDING, /* features */ NULL, /* glob_context */ &scram_server_mech_new, /* mech_new */ &scram_server_mech_step, /* mech_step */ @@ -1649,6 +1788,8 @@ typedef struct client_context { size_t salt_len; unsigned int iteration_count; char SaltedPassword[SCRAM_HASH_SIZE]; + + int cb_flags; } client_context_t; static int scram_client_mech_new(void *glob_context __attribute__((unused)), @@ -1800,6 +1941,26 @@ scram_client_mech_step1(client_context_t *text, } } + switch (params->cbindingdisp) { + case SASL_CB_DISP_NONE: + text->cb_flags = SCRAM_CB_FLAG_N; + channel_binding_state = 'n'; + break; + case SASL_CB_DISP_USED: + if (!SASL_CB_PRESENT(params)) { + result = SASL_BADPARAM; + goto cleanup; + } + channel_binding_name = params->cbinding->name; + text->cb_flags = SCRAM_CB_FLAG_P; + channel_binding_state = 'p'; + break; + case SASL_CB_DISP_WANT: + text->cb_flags = SCRAM_CB_FLAG_Y; + channel_binding_state = 'y'; + break; + } + text->nonce = params->utils->malloc (NONCE_SIZE + 1); if (text->nonce == NULL) { @@ -1864,12 +2025,10 @@ scram_client_mech_step1(client_context_t *text, text->gs2_header_length = strlen(text->out_buf); _plug_strdup(params->utils, text->out_buf, &text->gs2_header, NULL); - snprintf(text->out_buf + text->gs2_header_length, - maxsize + 1, - "n=%s,r=%s", - encoded_authcid, - text->nonce); - + sprintf(text->out_buf + text->gs2_header_length, + "n=%s,r=%s", + encoded_authcid, + text->nonce); /* Save the copy of the client-first-message */ @@ -1921,9 +2080,11 @@ scram_client_mech_step2(client_context_t *text, size_t length_no_proof; char * full_auth_message; size_t cb_bin_length; + size_t channel_binding_data_len = 0; size_t cb_encoded_length; char * channel_binding_data = NULL; char * cb_encoded = NULL; + char * cb_bin = NULL; int result; char ClientKey[SCRAM_HASH_SIZE]; char StoredKey[SCRAM_HASH_SIZE]; @@ -2100,12 +2261,32 @@ scram_client_mech_step2(client_context_t *text, /* Now we generate client response */ if (text->gs2_header[0] == 'p') { + + if (params->cbinding == NULL) { + result = SASL_FAIL; + goto cleanup; + } + + channel_binding_data = params->cbinding->data; + channel_binding_data_len = params->cbinding->len; } cb_bin_length = text->gs2_header_length + - ((channel_binding_data != NULL) ? strlen(channel_binding_data) : 0); + ((channel_binding_data != NULL) ? channel_binding_data_len : 0); cb_encoded_length = (cb_bin_length / 3 * 4) + ((cb_bin_length % 3) ? 4 : 0); + if (channel_binding_data != NULL) { + cb_bin = (char *) params->utils->malloc(cb_bin_length + 1); + if (cb_bin == NULL) { + MEMERROR( params->utils ); + result = SASL_NOMEM; + goto cleanup; + } + + memcpy(cb_bin, text->gs2_header, text->gs2_header_length); + memcpy(cb_bin + text->gs2_header_length, channel_binding_data, channel_binding_data_len); + } + cb_encoded = (char *) params->utils->malloc(cb_encoded_length + 1); if (cb_encoded == NULL) { MEMERROR( params->utils ); @@ -2116,12 +2297,11 @@ scram_client_mech_step2(client_context_t *text, /* * Returns SASL_OK on success, SASL_BUFOVER if result won't fit */ - if (params->utils->encode64( - text->gs2_header, - (unsigned int)cb_bin_length, - cb_encoded, - (unsigned int)cb_encoded_length + 1, - NULL) != SASL_OK) { + if (params->utils->encode64((cb_bin != NULL) ? cb_bin : text->gs2_header, + (unsigned int)cb_bin_length, + cb_encoded, + (unsigned int)cb_encoded_length + 1, + NULL) != SASL_OK) { MEMERROR( params->utils ); result = SASL_NOMEM; goto cleanup; @@ -2275,6 +2455,10 @@ scram_client_mech_step2(client_context_t *text, params->utils->free(cb_encoded); } + if (cb_bin != NULL) { + params->utils->free(cb_bin); + } + return result; } @@ -2492,7 +2676,8 @@ static sasl_client_plug_t scram_client_plugins[] = | SASL_SEC_NOANONYMOUS | SASL_SEC_NOACTIVE | SASL_SEC_MUTUAL_AUTH, /* security_flags */ - SASL_FEAT_ALLOWS_PROXY, /* features */ + SASL_FEAT_ALLOWS_PROXY + | SASL_FEAT_CHANNEL_BINDING, /* features */ NULL, /* required_prompts */ NULL, /* glob_context */ &scram_client_mech_new, /* mech_new */ From acc2e0ce35f3be05d824f4824849cb9d4bb3698e Mon Sep 17 00:00:00 2001 From: Ken Murchison Date: Tue, 25 Jan 2011 20:36:42 +0000 Subject: [PATCH 075/796] Allow DIGEST-MD5 plugin to be used for client-side HTTP Digest (RFC 2617) --- ChangeLog | 6 ++ include/saslplug.h | 2 +- lib/client.c | 12 ++- lib/common.c | 7 +- plugins/digestmd5.c | 210 ++++++++++++++++++++++++++++++++++---------- 5 files changed, 190 insertions(+), 47 deletions(-) diff --git a/ChangeLog b/ChangeLog index 67d1076b..b00a5f5a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-01-25 Ken Murchison + * include/sasl.h, include/saslplug.h, lib/client.c, lib/common.c, + plugins/digest-md5.c sample/http_digest_client.c: + Allow DIGEST-MD5 plugin to be used for client-side + HTTP Digest (RFC 2617) + 2011-01-21 Alexey Melnikov * plugins/scram.c: Added support for channel bindings to SCRAM-SHA-1. diff --git a/include/saslplug.h b/include/saslplug.h index 4280707d..00e26719 100755 --- a/include/saslplug.h +++ b/include/saslplug.h @@ -270,7 +270,7 @@ typedef struct sasl_client_params { /* for additions which don't require a version upgrade; set to 0 */ const void *gss_creds; /* GSS credential handle */ const sasl_channel_binding_t *cbinding; /* client channel binding */ - void *spare_ptr3; + const sasl_http_request_t *http_request;/* HTTP Digest request method */ void *spare_ptr4; /* Canonicalize a user name from on-wire to internal format diff --git a/lib/client.c b/lib/client.c index a12e181e..9ec49e87 100644 --- a/lib/client.c +++ b/lib/client.c @@ -1,7 +1,7 @@ /* SASL client API implementation * Rob Siemborski * Tim Martin - * $Id: client.c,v 1.84 2011/01/21 15:19:36 mel Exp $ + * $Id: client.c,v 1.85 2011/01/25 20:36:42 murch Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -796,6 +796,11 @@ int sasl_client_start(sasl_conn_t *conn, break; } + if ((conn->flags & SASL_NEED_HTTP) && + !(m->m.plug->features & SASL_FEAT_SUPPORTS_HTTP)) { + break; + } + /* compare security flags, only take new mechanism if it has * all the security flags of the previous one. * @@ -1255,6 +1260,11 @@ _sasl_print_mechanism ( printf ("%cCHANNEL_BINDING", delimiter); delimiter = '|'; } + + if (m->plug->features & SASL_FEAT_SUPPORTS_HTTP) { + printf ("%cSUPPORTS_HTTP", delimiter); + delimiter = '|'; + } } /* Delay loading is not supported for the client side plugins: diff --git a/lib/common.c b/lib/common.c index 608128ee..6d8bdb93 100644 --- a/lib/common.c +++ b/lib/common.c @@ -1,7 +1,7 @@ /* common.c - Functions that are common to server and clinet * Rob Siemborski * Tim Martin - * $Id: common.c,v 1.131 2011/01/21 15:19:36 mel Exp $ + * $Id: common.c,v 1.132 2011/01/25 20:36:42 murch Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -1051,6 +1051,9 @@ int sasl_getprop(sasl_conn_t *conn, int propnum, const void **pvalue) if (conn->type == SASL_CONN_SERVER) *(const sasl_http_request_t **)pvalue = ((sasl_server_conn_t *)conn)->sparams->http_request; + else + *(const sasl_http_request_t **)pvalue = + ((sasl_client_conn_t *)conn)->cparams->http_request; break; } default: @@ -1286,6 +1289,8 @@ int sasl_setprop(sasl_conn_t *conn, int propnum, const void *value) if (conn->type == SASL_CONN_SERVER) ((sasl_server_conn_t *)conn)->sparams->http_request = req; + else + ((sasl_client_conn_t *)conn)->cparams->http_request = req; break; } diff --git a/plugins/digestmd5.c b/plugins/digestmd5.c index a15bfe5d..64c6fae1 100644 --- a/plugins/digestmd5.c +++ b/plugins/digestmd5.c @@ -3,7 +3,7 @@ * Rob Siemborski * Tim Martin * Alexey Melnikov - * $Id: digestmd5.c,v 1.203 2011/01/19 23:06:52 murch Exp $ + * $Id: digestmd5.c,v 1.204 2011/01/25 20:36:42 murch Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -122,7 +122,7 @@ extern int gethostname(char *, int); /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: digestmd5.c,v 1.203 2011/01/19 23:06:52 murch Exp $"; +static const char plugin_id[] = "$Id: digestmd5.c,v 1.204 2011/01/25 20:36:42 murch Exp $"; /* Definitions */ #define NONCE_SIZE (32) /* arbitrary */ @@ -195,6 +195,10 @@ typedef struct reauth_entry { int protection; struct digest_cipher *cipher; unsigned long server_maxbuf; + + /* for HTTP mode (RFC 2617) only */ + char *algorithm; + unsigned char *opaque; } c; /* client stuff */ } u; } reauth_entry_t; @@ -240,7 +244,7 @@ typedef struct context { HASH Ki_send; HASH Ki_receive; - HASH HA1; /* Kcc or Kcs */ + HASH HA1; /* Kcc or Kcs */ /* copy of utils from the params structures */ const sasl_utils_t *utils; @@ -2182,7 +2186,7 @@ static int digestmd5_server_mech_step2(server_context_t *stext, } if (text->http_mode) { - /* per RFC 2617 (RFC 2616 request as set by calling application) */ + /* per RFC 2617 (HTTP Request as set by calling application) */ request = sparams->http_request; } else { @@ -2959,7 +2963,8 @@ static int digestmd5_server_mech_step(void *conn_context, case 1: /* setup SSF limits */ - if (!sparams->props.maxbufsize) { + if (!text->http_mode && /* HTTP Digest doesn't need buffer */ + !sparams->props.maxbufsize) { stext->limitssf = 0; stext->requiressf = 0; } else { @@ -3124,6 +3129,10 @@ typedef struct client_context { int protection; struct digest_cipher *cipher; unsigned long server_maxbuf; + + /* for HTTP mode (RFC 2617) only */ + char *algorithm; + unsigned char *opaque; } client_context_t; static digest_glob_context_t client_glob_context; @@ -3131,6 +3140,7 @@ static digest_glob_context_t client_glob_context; /* calculate H(A1) as per spec */ static void DigestCalcHA1(context_t * text, const sasl_utils_t * utils, + char *pszAlg, unsigned char *pszUserName, unsigned char *pszRealm, sasl_secret_t * pszPassword, @@ -3150,19 +3160,32 @@ static void DigestCalcHA1(context_t * text, FALSE, HA1); - /* calculate the session key */ - utils->MD5Init(&Md5Ctx); - utils->MD5Update(&Md5Ctx, HA1, HASHLEN); - utils->MD5Update(&Md5Ctx, COLON, 1); - utils->MD5Update(&Md5Ctx, pszNonce, (unsigned) strlen((char *) pszNonce)); - utils->MD5Update(&Md5Ctx, COLON, 1); - utils->MD5Update(&Md5Ctx, pszCNonce, (unsigned) strlen((char *) pszCNonce)); - if (pszAuthorization_id != NULL) { + if (!text->http_mode || /* per RFC 2831 */ + (pszAlg && strcasecmp(pszAlg, "md5-sess") == 0)) { /* per RFC 2617 */ + /* calculate the session key */ + utils->MD5Init(&Md5Ctx); + if (text->http_mode) { + /* per RFC 2617 Errata ID 1649 */ + HASHHEX HA1Hex; + + CvtHex(HA1, HA1Hex); + utils->MD5Update(&Md5Ctx, HA1Hex, HASHHEXLEN); + } + else { + /* per RFC 2831 */ + utils->MD5Update(&Md5Ctx, HA1, HASHLEN); + } + utils->MD5Update(&Md5Ctx, COLON, 1); + utils->MD5Update(&Md5Ctx, pszNonce, (unsigned) strlen((char *) pszNonce)); utils->MD5Update(&Md5Ctx, COLON, 1); - utils->MD5Update(&Md5Ctx, pszAuthorization_id, - (unsigned) strlen((char *) pszAuthorization_id)); + utils->MD5Update(&Md5Ctx, pszCNonce, (unsigned) strlen((char *) pszCNonce)); + if (pszAuthorization_id != NULL) { + utils->MD5Update(&Md5Ctx, COLON, 1); + utils->MD5Update(&Md5Ctx, pszAuthorization_id, + (unsigned) strlen((char *) pszAuthorization_id)); + } + utils->MD5Final(HA1, &Md5Ctx); } - utils->MD5Final(HA1, &Md5Ctx); CvtHex(HA1, SessionKey); @@ -3175,24 +3198,26 @@ static void DigestCalcHA1(context_t * text, static char *calculate_response(context_t * text, const sasl_utils_t * utils, + char *algorithm, unsigned char *username, unsigned char *realm, unsigned char *nonce, unsigned int ncvalue, unsigned char *cnonce, char *qop, - unsigned char *digesturi, + const sasl_http_request_t *request, sasl_secret_t * passwd, unsigned char *authorization_id, char **response_value) { HASHHEX SessionKey; - HASHHEX HEntity = "00000000000000000000000000000000"; + HASH EntityHash; + HASHHEX HEntity; HASHHEX Response; char *result; /* Verifing that all parameters was defined */ - if(!username || !cnonce || !nonce || !ncvalue || !digesturi || !passwd) { + if(!username || !cnonce || !nonce || !ncvalue || !request || !passwd) { PARAMERROR( utils ); return NULL; } @@ -3209,6 +3234,7 @@ static char *calculate_response(context_t * text, DigestCalcHA1(text, utils, + algorithm, username, realm, passwd, @@ -3217,6 +3243,20 @@ static char *calculate_response(context_t * text, cnonce, SessionKey); + if (text->http_mode) { + /* per RFC 2617 */ + MD5_CTX Md5Ctx; + + utils->MD5Init(&Md5Ctx); + utils->MD5Update(&Md5Ctx, request->entity, request->elen); + utils->MD5Final(EntityHash, &Md5Ctx); + } + else { + /* per RFC 2831 */ + memset(EntityHash, 0, HASHLEN); + } + CvtHex(EntityHash, HEntity); + DigestCalcResponse(utils, SessionKey,/* HEX(H(A1)) */ nonce, /* nonce from server */ @@ -3224,8 +3264,8 @@ static char *calculate_response(context_t * text, cnonce, /* client nonce */ (unsigned char *) qop, /* qop-value: "", "auth", * "auth-int" */ - digesturi, /* requested URL */ - (unsigned char *) "AUTHENTICATE", + (unsigned char *) request->uri, /* requested URL */ + (unsigned char *) request->method, HEntity, /* H(entity body) if qop="auth-int" */ Response /* request-digest or response-digest */ ); @@ -3244,7 +3284,7 @@ static char *calculate_response(context_t * text, cnonce, /* client nonce */ (unsigned char *) qop, /* qop-value: "", "auth", * "auth-int" */ - (unsigned char *) digesturi, /* requested URL */ + (unsigned char *) request->uri, /* requested URL */ NULL, HEntity, /* H(entity body) if qop="auth-int" */ Response /* request-digest or response-digest */ @@ -3273,7 +3313,7 @@ static int make_client_response(context_t *text, client_context_t *ctext = (client_context_t *) text; char *qop = NULL; unsigned nbits = 0; - unsigned char *digesturi = NULL; + char *digesturi = NULL; bool IsUTF8 = FALSE; char ncvalue[10]; char maxbufstr[64]; @@ -3281,6 +3321,8 @@ static int make_client_response(context_t *text, unsigned resplen = 0; int result = SASL_OK; cipher_free_t *old_cipher_free = NULL; + sasl_http_request_t rfc2831_request; + const sasl_http_request_t *request; params->utils->log(params->utils->conn, SASL_LOG_DEBUG, "DIGEST-MD5 make_client_response()"); @@ -3320,33 +3362,47 @@ static int make_client_response(context_t *text, oparams->mech_ssf = 0; } - digesturi = params->utils->malloc(strlen(params->service) + 1 + - strlen(params->serverFQDN) + 1 + - 1); - if (digesturi == NULL) { - result = SASL_NOMEM; - goto FreeAllocatedMem; - }; - - /* allocated exactly this. safe */ - strcpy((char *) digesturi, params->service); - strcat((char *) digesturi, "/"); - strcat((char *) digesturi, params->serverFQDN); - /* - * strcat (digesturi, "/"); strcat (digesturi, params->serverFQDN); - */ + if (text->http_mode) { + /* per RFC 2617 (HTTP Request as set by calling application) */ + request = params->http_request; + } + else { + /* per RFC 2831 */ + digesturi = params->utils->malloc(strlen(params->service) + 1 + + strlen(params->serverFQDN) + 1 + + 1); + if (digesturi == NULL) { + result = SASL_NOMEM; + goto FreeAllocatedMem; + } + + /* allocated exactly this. safe */ + strcpy(digesturi, params->service); + strcat(digesturi, "/"); + strcat(digesturi, params->serverFQDN); + /* + * strcat (digesturi, "/"); strcat (digesturi, params->serverFQDN); + */ + + rfc2831_request.method = "AUTHENTICATE"; + rfc2831_request.uri = digesturi; + rfc2831_request.entity = NULL; + rfc2831_request.elen = 0; + request = &rfc2831_request; + } /* response */ response = calculate_response(text, params->utils, + ctext->algorithm, (unsigned char *) oparams->authid, (unsigned char *) text->realm, text->nonce, text->nonce_count, text->cnonce, qop, - digesturi, + request, ctext->password, strcmp(oparams->user, oparams->authid) ? (unsigned char *) oparams->user : NULL, @@ -3438,10 +3494,31 @@ static int make_client_response(context_t *text, } if (add_to_challenge(params->utils, &text->out_buf, &text->out_buf_len, &resplen, - "digest-uri", digesturi, TRUE) != SASL_OK) { + text->http_mode ? "uri" /* per RFC 2617 */ + : "digest-uri", /* per RFC 2831 */ + (unsigned char *) request->uri, + TRUE) != SASL_OK) { result = SASL_FAIL; goto FreeAllocatedMem; } + if (text->http_mode) { + /* per RFC 2617: algorithm & opaque MUST be sent back to server */ + if (add_to_challenge(params->utils, + &text->out_buf, &text->out_buf_len, &resplen, + "algorithm", (unsigned char *) ctext->algorithm, + FALSE) != SASL_OK) { + result = SASL_FAIL; + goto FreeAllocatedMem; + } + if (ctext->opaque) { + if (add_to_challenge(params->utils, + &text->out_buf, &text->out_buf_len, &resplen, + "opaque", ctext->opaque, TRUE) != SASL_OK) { + result = SASL_FAIL; + goto FreeAllocatedMem; + } + } + } if (add_to_challenge(params->utils, &text->out_buf, &text->out_buf_len, &resplen, "response", (unsigned char *) response, @@ -3520,6 +3597,7 @@ static int parse_server_challenge(client_context_t *ctext, int maxbuf_count = 0; bool IsUTF8 = FALSE; int algorithm_count = 0; + int opaque_count = 0; params->utils->log(params->utils->conn, SASL_LOG_DEBUG, "DIGEST-MD5 parse_server_challenge()"); @@ -3738,14 +3816,22 @@ static int parse_server_challenge(client_context_t *ctext, IsUTF8 = TRUE; } } else if (strcasecmp(name,"algorithm")==0) { - if (strcasecmp(value, "md5-sess") != 0) + if (text->http_mode && strcasecmp(value, "md5") == 0) { + /* per RFC 2617: need to support both "md5" and "md5-sess" */ + } + else if (strcasecmp(value, "md5-sess") != 0) { params->utils->seterror(params->utils->conn, 0, "'algorithm' isn't 'md5-sess'"); result = SASL_FAIL; goto FreeAllocatedMem; } - + + if (text->http_mode) { + /* per RFC 2617: algorithm MUST be saved */ + _plug_strdup(params->utils, value, (char **) &ctext->algorithm, + NULL); + } algorithm_count++; if (algorithm_count > 1) { @@ -3754,6 +3840,21 @@ static int parse_server_challenge(client_context_t *ctext, result = SASL_FAIL; goto FreeAllocatedMem; } + } else if (strcasecmp(name,"opaque")==0) { + /* per RFC 2831: opaque MUST be ignored if received */ + if (text->http_mode) { + /* per RFC 2617: opaque MUST be saved */ + _plug_strdup(params->utils, value, (char **) &ctext->opaque, + NULL); + opaque_count++; + if (opaque_count > 1) + { + params->utils->seterror(params->utils->conn, 0, + "Must see 'opaque' only once"); + result = SASL_FAIL; + goto FreeAllocatedMem; + } + } } else { params->utils->log(params->utils->conn, SASL_LOG_DEBUG, "DIGEST-MD5 unrecognized pair %s/%s: ignoring", @@ -3793,7 +3894,8 @@ static int parse_server_challenge(client_context_t *ctext, external = params->external_ssf; /* what do we _need_? how much is too much? */ - if (params->props.maxbufsize == 0) { + if (!text->http_mode && /* HTTP Digest doesn't need buffer */ + params->props.maxbufsize == 0) { musthave = 0; limit = 0; } else { @@ -4055,6 +4157,7 @@ static int digestmd5_client_mech_new(void *glob_context, text->state = 1; text->i_am = CLIENT; + text->http_mode = (params->flags & SASL_NEED_HTTP); text->reauth = ((digest_glob_context_t *) glob_context)->reauth; *conn_context = text; @@ -4099,6 +4202,17 @@ digestmd5_client_mech_step1(client_context_t *ctext, text->nonce_count = ++text->reauth->e[val].nonce_count; _plug_strdup(params->utils, (char *) text->reauth->e[val].cnonce, (char **) &text->cnonce, NULL); + if (text->http_mode) { + /* per RFC 2617: algorithm & opaque MUST be sent back to server */ + _plug_strdup(params->utils, + (char *) text->reauth->e[val].u.c.algorithm, + (char **) &ctext->algorithm, NULL); + if (text->reauth->e[val].u.c.opaque) { + _plug_strdup(params->utils, + (char *) text->reauth->e[val].u.c.opaque, + (char **) &ctext->opaque, NULL); + } + } ctext->protection = text->reauth->e[val].u.c.protection; ctext->cipher = text->reauth->e[val].u.c.cipher; ctext->server_maxbuf = text->reauth->e[val].u.c.server_maxbuf; @@ -4274,6 +4388,13 @@ digestmd5_client_mech_step3(client_context_t *ctext, text->reauth->e[val].cnonce = text->cnonce; text->cnonce = NULL; _plug_strdup(params->utils, params->serverFQDN, &text->reauth->e[val].u.c.serverFQDN, NULL); + if (text->http_mode) { + /* per RFC 2617: algorithm & opaque MUST be saved */ + text->reauth->e[val].u.c.algorithm = ctext->algorithm; + ctext->algorithm = NULL; + text->reauth->e[val].u.c.opaque = ctext->opaque; + ctext->opaque = NULL; + } text->reauth->e[val].u.c.protection = ctext->protection; text->reauth->e[val].u.c.cipher = ctext->cipher; text->reauth->e[val].u.c.server_maxbuf = ctext->server_maxbuf; @@ -4418,7 +4539,8 @@ static sasl_client_plug_t digestmd5_client_plugins[] = | SASL_SEC_NOANONYMOUS | SASL_SEC_MUTUAL_AUTH, /* security_flags */ SASL_FEAT_NEEDSERVERFQDN - | SASL_FEAT_ALLOWS_PROXY, /* features */ + | SASL_FEAT_ALLOWS_PROXY + | SASL_FEAT_SUPPORTS_HTTP, /* features */ NULL, /* required_prompts */ &client_glob_context, /* glob_context */ &digestmd5_client_mech_new, /* mech_new */ From 33c884d3485b2764289242a1fb83aeb8d4efb882 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Fri, 25 Mar 2011 11:54:49 +0000 Subject: [PATCH 076/796] Added GS2 plugin from Luke Howard --- README.GS2 | 3 + plugins/Makefile.am | 10 +- plugins/gs2_token.c | 216 ++++++++++++++++++++++++++++++++++++++++++++ plugins/gs2_token.h | 46 ++++++++++ plugins/makeinit.sh | 2 +- 5 files changed, 273 insertions(+), 4 deletions(-) create mode 100644 README.GS2 create mode 100644 plugins/gs2_token.c create mode 100644 plugins/gs2_token.h diff --git a/README.GS2 b/README.GS2 new file mode 100644 index 00000000..973cee88 --- /dev/null +++ b/README.GS2 @@ -0,0 +1,3 @@ +To build the GS2 SASL mechanism, you need MIT Kerberos 1.9. + +Please e-mail lukeh@padl.com with any bug reports. diff --git a/plugins/Makefile.am b/plugins/Makefile.am index 2cbb39e4..ca342f6c 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -1,7 +1,7 @@ # Makefile.am for the SASL plugins # Rob Siemborski # Rob Earhart -# $Id: Makefile.am,v 1.80 2009/05/07 13:49:31 murch Exp $ +# $Id: Makefile.am,v 1.81 2011/03/25 11:54:49 mel Exp $ # ################################################################ # Copyright (c) 2000 Carnegie Mellon University. All rights reserved. @@ -65,7 +65,7 @@ common_sources = plugin_common.c plugin_common.h sasldir = $(prefix)/lib/sasl2 sasl_LTLIBRARIES = @SASL_MECHS@ EXTRA_LTLIBRARIES = libplain.la libanonymous.la libkerberos4.la libcrammd5.la \ - libgssapiv2.la libdigestmd5.la liblogin.la libsrp.la libotp.la \ + libgs2.la libgssapiv2.la libdigestmd5.la liblogin.la libsrp.la libotp.la \ libntlm.la libpassdss.la libsasldb.la libsql.la libldapdb.la libplain_la_SOURCES = plain.c plain_init.c $(common_sources) @@ -80,6 +80,10 @@ libkerberos4_la_SOURCES = kerberos4.c kerberos4_init.c $(common_sources) libkerberos4_la_DEPENDENCIES = $(COMPAT_OBJS) libkerberos4_la_LIBADD = $(SASL_KRB_LIB) $(LIB_SOCKET) $(COMPAT_OBJS) +libgs2_la_SOURCES = gs2.c gs2_init.c gs2_token.c $(common_sources) +libgs2_la_DEPENDENCIES = $(COMPAT_OBJS) +libgs2_la_LIBADD = $(GSSAPIBASE_LIBS) $(GSSAPI_LIBS) $(LIB_SOCKET) $(COMPAT_OBJS) + libgssapiv2_la_SOURCES = gssapi.c gssapiv2_init.c $(common_sources) libgssapiv2_la_DEPENDENCIES = $(COMPAT_OBJS) libgssapiv2_la_LIBADD = $(GSSAPIBASE_LIBS) $(GSSAPI_LIBS) $(LIB_SOCKET) $(COMPAT_OBJS) @@ -129,7 +133,7 @@ libsql_la_LIBADD = $(COMPAT_OBJS) # Instructions for making the _init files -init_src=anonymous_init.c crammd5_init.c digestmd5_init.c gssapiv2_init.c \ +init_src=anonymous_init.c crammd5_init.c digestmd5_init.c gs2_init.c gssapiv2_init.c \ kerberos4_init.c login_init.c plain_init.c srp_init.c otp_init.c ntlm_init.c \ passdss_init.c sasldb_init.c sql_init.c ldapdb_init.c diff --git a/plugins/gs2_token.c b/plugins/gs2_token.c new file mode 100644 index 00000000..c8c33aa4 --- /dev/null +++ b/plugins/gs2_token.c @@ -0,0 +1,216 @@ +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include "gs2_token.h" + +/* + * $Id: gs2_token.c,v 1.1 2011/03/25 11:54:49 mel Exp $ + */ + +/* XXXX this code currently makes the assumption that a mech oid will + never be longer than 127 bytes. This assumption is not inherent in + the interfaces, so the code can be fixed if the OSI namespace + balloons unexpectedly. */ + +/* + * Each token looks like this: + * 0x60 tag for APPLICATION 0, SEQUENCE + * (constructed, definite-length) + * possible multiple bytes, need to parse/generate + * 0x06 tag for OBJECT IDENTIFIER + * compile-time constant string (assume 1 byte) + * compile-time constant string + * the ANY containing the application token + * bytes 0,1 are the token type + * bytes 2,n are the token data + * + * Note that the token type field is a feature of RFC 1964 mechanisms and + * is not used by other GSSAPI mechanisms. As such, a token type of -1 + * is interpreted to mean that no token type should be expected or + * generated. + * + * For the purposes of this abstraction, the token "header" consists of + * the sequence tag and length octets, the mech OID DER encoding, and the + * first two inner bytes, which indicate the token type. The token + * "body" consists of everything else. + */ + +static size_t +der_length_size(size_t length) +{ + if (length < (1<<7)) + return 1; + else if (length < (1<<8)) + return 2; +#if INT_MAX == 0x7fff + else + return 3; +#else + else if (length < (1<<16)) + return 3; + else if (length < (1<<24)) + return 4; + else + return 5; +#endif +} + +static void +der_write_length(unsigned char **buf, size_t length) +{ + if (length < (1<<7)) { + *(*buf)++ = (unsigned char)length; + } else { + *(*buf)++ = (unsigned char)(der_length_size(length)+127); +#if INT_MAX > 0x7fff + if (length >= (1<<24)) + *(*buf)++ = (unsigned char)(length>>24); + if (length >= (1<<16)) + *(*buf)++ = (unsigned char)((length>>16)&0xff); +#endif + if (length >= (1<<8)) + *(*buf)++ = (unsigned char)((length>>8)&0xff); + *(*buf)++ = (unsigned char)(length&0xff); + } +} + +/* returns decoded length, or < 0 on failure. Advances buf and + decrements bufsize */ + +static int +der_read_length(unsigned char **buf, ssize_t *bufsize) +{ + unsigned char sf; + int ret; + + if (*bufsize < 1) + return -1; + + sf = *(*buf)++; + (*bufsize)--; + if (sf & 0x80) { + if ((sf &= 0x7f) > ((*bufsize)-1)) + return -1; + if (sf > sizeof(int)) + return -1; + ret = 0; + for (; sf; sf--) { + ret = (ret<<8) + (*(*buf)++); + (*bufsize)--; + } + } else { + ret = sf; + } + + return ret; +} + +/* returns the length of a token, given the mech oid and the body size */ + +size_t +gs2_token_size(const gss_OID_desc *mech, size_t body_size) +{ + /* set body_size to sequence contents size */ + body_size += 2 + (size_t) mech->length; /* NEED overflow check */ + return 1 + der_length_size(body_size) + body_size; +} + +/* fills in a buffer with the token header. The buffer is assumed to + be the right size. buf is advanced past the token header */ + +void +gs2_make_token_header( + const gss_OID_desc *mech, + size_t body_size, + unsigned char **buf) +{ + *(*buf)++ = 0x60; + der_write_length(buf, 2 + mech->length + body_size); + *(*buf)++ = 0x06; + *(*buf)++ = (unsigned char)mech->length; + memcpy(*buf, mech->elements, mech->length); + *buf += mech->length; +} + +/* + * Given a buffer containing a token, reads and verifies the token, + * leaving buf advanced past the token header, and setting body_size + * to the number of remaining bytes. Returns 0 on success, + * G_BAD_TOK_HEADER for a variety of errors, and G_WRONG_MECH if the + * mechanism in the token does not match the mech argument. buf and + * *body_size are left unmodified on error. + */ + +OM_uint32 +gs2_verify_token_header(OM_uint32 *minor, + gss_const_OID mech, + size_t *body_size, + unsigned char **buf_in, + size_t toksize_in) +{ + unsigned char *buf = *buf_in; + ssize_t seqsize; + gss_OID_desc toid; + ssize_t toksize = (ssize_t)toksize_in; + + *minor = 0; + + if ((toksize -= 1) < 0) + return GSS_S_DEFECTIVE_TOKEN; + + if (*buf++ != 0x60) + return GSS_S_DEFECTIVE_TOKEN; + + seqsize = der_read_length(&buf, &toksize); + if (seqsize < 0) + return GSS_S_DEFECTIVE_TOKEN; + + if (seqsize != toksize) + return GSS_S_DEFECTIVE_TOKEN; + + if ((toksize -= 1) < 0) + return GSS_S_DEFECTIVE_TOKEN; + + if (*buf++ != 0x06) + return GSS_S_DEFECTIVE_TOKEN; + + if ((toksize -= 1) < 0) + return GSS_S_DEFECTIVE_TOKEN; + + toid.length = *buf++; + + if ((toksize -= toid.length) < 0) + return GSS_S_DEFECTIVE_TOKEN; + + toid.elements = buf; + buf += toid.length; + + if (!g_OID_equal(&toid, mech)) + return GSS_S_BAD_MECH; + + *buf_in = buf; + *body_size = toksize; + + return GSS_S_COMPLETE; +} diff --git a/plugins/gs2_token.h b/plugins/gs2_token.h new file mode 100644 index 00000000..a83e2642 --- /dev/null +++ b/plugins/gs2_token.h @@ -0,0 +1,46 @@ +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _GS2_TOKEN_H_ +#define _GS2_TOKEN_H_ 1 + +#define g_OID_equal(o1, o2) \ + (((o1)->length == (o2)->length) && \ + (memcmp((o1)->elements, (o2)->elements, (o1)->length) == 0)) + +extern OM_uint32 +gs2_verify_token_header(OM_uint32 *minor, + gss_const_OID mech, + size_t *body_size, + unsigned char **buf_in, + size_t toksize_in); + +extern void +gs2_make_token_header( + const gss_OID_desc *mech, + size_t body_size, + unsigned char **buf); + +extern size_t +gs2_token_size(const gss_OID_desc *mech, size_t body_size); + +#endif /* _GS2_TOKEN_H_ */ diff --git a/plugins/makeinit.sh b/plugins/makeinit.sh index 51337f52..7950dff0 100644 --- a/plugins/makeinit.sh +++ b/plugins/makeinit.sh @@ -1,5 +1,5 @@ # mechanism plugins -for mech in anonymous crammd5 digestmd5 gssapiv2 kerberos4 login ntlm otp passdss plain srp; do +for mech in anonymous crammd5 digestmd5 gssapiv2 kerberos4 login ntlm otp passdss plain srp gs2; do echo " #include From 8a570675cbb9cb3b601ea51fa2150c06b470d9e9 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Fri, 25 Mar 2011 12:03:01 +0000 Subject: [PATCH 077/796] Committed Luke Howard's GS2 plugin --- ChangeLog | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index b00a5f5a..abd46447 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-03-25 Alexey Melnikov + * plugins/Makefile.am, plugins/makeinit.sh, plugins/gs2_token.h, + plugins/gs2_token.c, README.GS2, cmulocal/sasl2.m4: GS2 plugin + from Luke Howard + 2011-01-25 Ken Murchison * include/sasl.h, include/saslplug.h, lib/client.c, lib/common.c, plugins/digest-md5.c sample/http_digest_client.c: @@ -9,11 +14,11 @@ 2011-01-21 Alexey Melnikov * lib/client.c, lib/server.c, lib/common.c, lib/saslint.h: Fixed libsasl - to accept *-PLUS SASL mechanism names in client_mech_list/mech_list options. - As *-PLUS mechanism names were synthesized and didn't correspond to real - plugin names, setting client_mech_list to "SCRAM-SHA-1-PLUS" (for example) - was resulting in authentication failure due to inability to find a matching - SASL plugin. + to accept *-PLUS SASL mechanism names in client_mech_list/mech_list + options. As *-PLUS mechanism names were synthesized and didn't + correspond to real plugin names, setting client_mech_list to + "SCRAM-SHA-1-PLUS" (for example) was resulting in authentication + failure due to inability to find a matching SASL plugin. 2011-01-21 Alexey Melnikov * include/saslplug.h, lib/client.c: Fixed handling of channel bindings From 68a1005ba66a436699980313fefc154e03177f02 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Tue, 5 Apr 2011 14:50:07 +0000 Subject: [PATCH 078/796] Enable SCRAM plugin build on Windows and Unix --- ChangeLog | 5 +++++ configure.in | 29 ++++++++++++++++++++++++++++- lib/staticopen.h | 6 +++++- plugins/Makefile.am | 10 +++++++--- plugins/NTMakefile | 16 +++++++++++++--- plugins/makeinit.sh | 2 +- win32/include/config.h | 1 + 7 files changed, 60 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index abd46447..f8f086f7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-04-05 Alexey Melnikov + * configure.in, plugins/Makefile.am, plugins/NTMakefile, + plugins/makeinit.sh, lib/staticopen.h, win32/include/config.h: + Enabled SCRAM plugin build + 2011-03-25 Alexey Melnikov * plugins/Makefile.am, plugins/makeinit.sh, plugins/gs2_token.h, plugins/gs2_token.c, README.GS2, cmulocal/sasl2.m4: GS2 plugin diff --git a/configure.in b/configure.in index 47138d96..55caf13b 100644 --- a/configure.in +++ b/configure.in @@ -1,7 +1,7 @@ dnl configure.in for the SASL library dnl Rob Siemborski dnl Rob Earhart -dnl $Id: configure.in,v 1.218 2009/05/20 12:24:48 murch Exp $ +dnl $Id: configure.in,v 1.219 2011/04/05 14:50:07 mel Exp $ dnl dnl Copyright (c) 2001 Carnegie Mellon University. All rights reserved. dnl @@ -426,6 +426,33 @@ else AC_MSG_RESULT(disabled) fi +dnl SCRAM +AC_ARG_ENABLE(scram, [ --enable-scram enable SCRAM authentication [[yes]] ], + scram=$enableval, + scram=yes) + +if test "$with_openssl" = no; then + AC_WARN([OpenSSL not found -- SCRAM will be disabled]) + scram=no +fi + +AC_MSG_CHECKING(SCRAM) +if test "$scram" != no; then + AC_MSG_RESULT(enabled) + SCRAM_LIBS="-lisode_crypto $LIB_RSAREF" + + SASL_MECHS="$SASL_MECHS libscram.la" + if test "$enable_static" = yes; then + SASL_STATIC_SRCS="$SASL_STATIC_SRCS \$(top_srcdir)/plugins/scram.c" + SASL_STATIC_OBJS="$SASL_STATIC_OBJS scram.o" + AC_DEFINE(STATIC_SCRAM, [], [Link SCRAM Staticly]) + fi + + AC_SUBST(SCRAM_LIBS) +else + AC_MSG_RESULT(disabled) +fi + dnl OTP AC_ARG_ENABLE(otp, [ --enable-otp enable OTP authentication [[yes]] ], otp=$enableval, diff --git a/lib/staticopen.h b/lib/staticopen.h index dbf3b33e..4e503195 100644 --- a/lib/staticopen.h +++ b/lib/staticopen.h @@ -1,7 +1,7 @@ /* staticopen.h * Rob Siemborski * Howard Chu - * $Id: staticopen.h,v 1.8 2005/02/16 20:52:09 shadow Exp $ + * $Id: staticopen.h,v 1.9 2011/04/05 14:50:07 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -88,6 +88,10 @@ extern SPECIFIC_CLIENT_PLUG_INIT_PROTO( crammd5 ); extern SPECIFIC_SERVER_PLUG_INIT_PROTO( digestmd5 ); extern SPECIFIC_CLIENT_PLUG_INIT_PROTO( digestmd5 ); #endif +#ifdef STATIC_SCRAM +extern SPECIFIC_SERVER_PLUG_INIT_PROTO( scram ); +extern SPECIFIC_CLIENT_PLUG_INIT_PROTO( scram ); +#endif #ifdef STATIC_GSSAPIV2 extern SPECIFIC_SERVER_PLUG_INIT_PROTO( gssapiv2 ); extern SPECIFIC_CLIENT_PLUG_INIT_PROTO( gssapiv2 ); diff --git a/plugins/Makefile.am b/plugins/Makefile.am index ca342f6c..df228f4c 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -1,7 +1,7 @@ # Makefile.am for the SASL plugins # Rob Siemborski # Rob Earhart -# $Id: Makefile.am,v 1.81 2011/03/25 11:54:49 mel Exp $ +# $Id: Makefile.am,v 1.82 2011/04/05 14:50:07 mel Exp $ # ################################################################ # Copyright (c) 2000 Carnegie Mellon University. All rights reserved. @@ -66,7 +66,7 @@ sasldir = $(prefix)/lib/sasl2 sasl_LTLIBRARIES = @SASL_MECHS@ EXTRA_LTLIBRARIES = libplain.la libanonymous.la libkerberos4.la libcrammd5.la \ libgs2.la libgssapiv2.la libdigestmd5.la liblogin.la libsrp.la libotp.la \ - libntlm.la libpassdss.la libsasldb.la libsql.la libldapdb.la + libscram.la libntlm.la libpassdss.la libsasldb.la libsql.la libldapdb.la libplain_la_SOURCES = plain.c plain_init.c $(common_sources) libplain_la_DEPENDENCIES = $(COMPAT_OBJS) @@ -96,6 +96,10 @@ libdigestmd5_la_SOURCES = digestmd5.c digestmd5_init.c $(common_sources) libdigestmd5_la_DEPENDENCIES = $(COMPAT_OBJS) libdigestmd5_la_LIBADD = $(LIB_DES) $(LIB_SOCKET) $(COMPAT_OBJS) +libscram_la_SOURCES = scram.c scram_init.c $(common_sources) +libscram_la_DEPENDENCIES = $(COMPAT_OBJS) +libscram_la_LIBADD = $(SCRAM_LIBS) $(COMPAT_OBJS) + liblogin_la_SOURCES = login.c login_init.c $(common_sources) liblogin_la_DEPENDENCIES = $(COMPAT_OBJS) liblogin_la_LIBADD = $(PLAIN_LIBS) $(COMPAT_OBJS) @@ -133,7 +137,7 @@ libsql_la_LIBADD = $(COMPAT_OBJS) # Instructions for making the _init files -init_src=anonymous_init.c crammd5_init.c digestmd5_init.c gs2_init.c gssapiv2_init.c \ +init_src=anonymous_init.c crammd5_init.c digestmd5_init.c scram_init.c gs2_init.c gssapiv2_init.c \ kerberos4_init.c login_init.c plain_init.c srp_init.c otp_init.c ntlm_init.c \ passdss_init.c sasldb_init.c sql_init.c ldapdb_init.c diff --git a/plugins/NTMakefile b/plugins/NTMakefile index a0a57a6b..ffd0ef50 100755 --- a/plugins/NTMakefile +++ b/plugins/NTMakefile @@ -45,10 +45,11 @@ PLUGINS=saslANONYMOUS.dll \ saslCRAMMD5.dll \ saslDIGESTMD5.dll \ saslLOGIN.dll \ + saslSCRAM.dll \ $(PLUGINS_EXT) \ saslSASLDB.dll -generated_rc=saslANONYMOUS.rc saslPLAIN.rc saslCRAMMD5.rc saslDIGESTMD5.rc saslLOGIN.rc saslNTLM.rc saslGSSAPI.rc saslSRP.rc saslOTP.rc saslSASLDB.rc saslSQLITE.rc saslLDAPDB.rc +generated_rc=saslANONYMOUS.rc saslPLAIN.rc saslCRAMMD5.rc saslDIGESTMD5.rc saslLOGIN.rc saslNTLM.rc saslSCRAM.rc saslGSSAPI.rc saslSRP.rc saslOTP.rc saslSASLDB.rc saslSQLITE.rc saslLDAPDB.rc # WS2tcpip.h included in Visual Studio 7 provides getaddrinfo, ... # emulation on Windows, so there is no need to build getaddrinfo.c @@ -81,6 +82,10 @@ saslLOGIN_sources = login.c login_init.c $(common_sources) saslLOGIN_objs = login.obj login_init.obj $(common_objs) saslLOGIN_out = saslLOGIN.dll saslLOGIN.exp saslLOGIN.lib +saslSCRAM_sources = scram.c scram_init.c $(common_sources) +saslSCRAM_objs = scram.obj scram_init.obj $(common_objs) +saslSCRAM_out = saslSCRAM.dll saslSCRAM.exp saslSCRAM.lib + saslNTLM_sources = ntlm.c ntlm_init.c $(common_sources) saslNTLM_objs = ntlm.obj ntlm_init.obj $(common_objs) saslNTLM_out = saslNTLM.dll saslNTLM.exp saslNTLM.lib @@ -130,8 +135,8 @@ saslSASLDB_sources = sasldb.c sasldb_init.c $(libsasldb_sources) $(common_source saslSASLDB_objs = sasldb.obj sasldb_init.obj $(libsasldb_objs) $(common_objs) saslSASLDB_out = saslSASLDB.dll saslSASLDB.exp saslSASLDB.lib -all_objs = $(saslANONYMOUS_objs) $(saslPLAIN_objs) $(saslCRAMMD5_objs) $(saslDIGESTMD5_objs) $(saslLOGIN_objs) $(saslNTLM_objs) $(saslGSSAPI_objs) $(saslSRP_objs) $(saslOTP_objs) $(saslSASLDB_objs) $(saslSQL_objs) $(saslLDAPDB_objs) -all_out = $(saslANONYMOUS_out) $(saslPLAIN_out) $(saslCRAMMD5_out) $(saslDIGESTMD5_out) $(saslLOGIN_out) $(saslNTLM_out) $(saslGSSAPI_out) $(saslSRP_out) $(saslOTP_out) $(saslSASLDB_out) $(saslSQL_out) $(saslLDAPDB_out) +all_objs = $(saslANONYMOUS_objs) $(saslPLAIN_objs) $(saslCRAMMD5_objs) $(saslDIGESTMD5_objs) $(saslLOGIN_objs) $(saslSCRAM_objs) $(saslNTLM_objs) $(saslGSSAPI_objs) $(saslSRP_objs) $(saslOTP_objs) $(saslSASLDB_objs) $(saslSQL_objs) $(saslLDAPDB_objs) +all_out = $(saslANONYMOUS_out) $(saslPLAIN_out) $(saslCRAMMD5_out) $(saslDIGESTMD5_out) $(saslLOGIN_out) $(saslSCRAM_out) $(saslNTLM_out) $(saslGSSAPI_out) $(saslSRP_out) $(saslOTP_out) $(saslSASLDB_out) $(saslSQL_out) $(saslLDAPDB_out) # LIBSASL_EXPORTS is required to export additional DB routines from sasldb DB_FLAGS = /I $(DB_INCLUDE) /I "..\sasldb" /D "LIBSASL_EXPORTS" /D "KEEP_DB_OPEN" @@ -206,6 +211,11 @@ saslLOGIN.dll: $(saslLOGIN_objs) saslLOGIN.res << IF EXIST $@.manifest mt -manifest $@.manifest -outputresource:$@;2 +saslSCRAM.dll: $(saslSCRAM_objs) saslSCRAM.res + $(LINK32DLL) @<< $(OPENSSL_LIBS) $(LINK32DLL_FLAGS) /out:"saslSCRAM.dll" /implib:"saslSCRAM.lib" $(saslSCRAM_objs) saslSCRAM.res +<< + IF EXIST $@.manifest mt -manifest $@.manifest -outputresource:$@;2 + saslNTLM.dll: $(saslNTLM_objs) saslNTLM.res $(LINK32DLL) @<< $(OPENSSL_LIBS) $(LINK32DLL_FLAGS) /out:"saslNTLM.dll" /implib:"saslNTLM.lib" $(saslNTLM_objs) saslNTLM.res << diff --git a/plugins/makeinit.sh b/plugins/makeinit.sh index 7950dff0..3d889641 100644 --- a/plugins/makeinit.sh +++ b/plugins/makeinit.sh @@ -1,5 +1,5 @@ # mechanism plugins -for mech in anonymous crammd5 digestmd5 gssapiv2 kerberos4 login ntlm otp passdss plain srp gs2; do +for mech in anonymous crammd5 digestmd5 scram gssapiv2 kerberos4 login ntlm otp passdss plain srp gs2; do echo " #include diff --git a/win32/include/config.h b/win32/include/config.h index 3d74e2af..aa4a5297 100644 --- a/win32/include/config.h +++ b/win32/include/config.h @@ -95,6 +95,7 @@ typedef int intptr_t; #define STATIC_ANONYMOUS 1 #define STATIC_CRAMMD5 1 #define STATIC_DIGESTMD5 1 +#define STATIC_SCRAM 1 #define STATIC_GSSAPIV2 1 /* #undef STATIC_KERBEROS4 */ #define STATIC_LOGIN 1 From 890000b72aacf0fcdfe3debc37e449e12ace385a Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Thu, 7 Apr 2011 08:44:29 +0000 Subject: [PATCH 079/796] Added GS2 plugin from Luke Howard --- plugins/gs2.c | 1834 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1834 insertions(+) create mode 100644 plugins/gs2.c diff --git a/plugins/gs2.c b/plugins/gs2.c new file mode 100644 index 00000000..5afe7bbb --- /dev/null +++ b/plugins/gs2.c @@ -0,0 +1,1834 @@ +/* + * Copyright (c) 2010, JANET(UK) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of JANET(UK) nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* + * Copyright (c) 1998-2003 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any other legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#ifdef HAVE_GSSAPI_GSSAPI_EXT_H +#include +#endif +#include +#include +#include +#include +#include + +#include "plugin_common.h" + +#ifdef HAVE_UNISTD_H +#include +#endif + +#include +#include +#include "gs2_token.h" + +#define GS2_CB_FLAG_MASK 0x0F +#define GS2_CB_FLAG_N 0x00 +#define GS2_CB_FLAG_P 0x01 +#define GS2_CB_FLAG_Y 0x02 +#define GS2_NONSTD_FLAG 0x10 + +typedef struct context { + gss_ctx_id_t gss_ctx; + gss_name_t client_name; + gss_name_t server_name; + gss_cred_id_t server_creds; + gss_cred_id_t client_creds; + char *out_buf; + unsigned out_buf_len; + const sasl_utils_t *utils; + char *authid; + char *authzid; + union { + sasl_client_plug_t *client; + sasl_server_plug_t *server; + } plug; + gss_OID mechanism; + int gs2_flags; + char *cbindingname; + struct gss_channel_bindings_struct gss_cbindings; + sasl_secret_t *password; + unsigned int free_password; + OM_uint32 lifetime; +} context_t; + +static gss_OID_set gs2_mechs = GSS_C_NO_OID_SET; + +static int gs2_get_init_creds(context_t *context, + sasl_client_params_t *params, + sasl_interact_t **prompt_need, + sasl_out_params_t *oparams); + +static int gs2_verify_initial_message(context_t *text, + sasl_server_params_t *sparams, + const char *in, + unsigned inlen, + gss_buffer_t token); + +static int gs2_make_header(context_t *text, + sasl_client_params_t *cparams, + const char *authzid, + char **out, + unsigned *outlen); + +static int gs2_make_message(context_t *text, + sasl_client_params_t *cparams, + int initialContextToken, + gss_buffer_t token, + char **out, + unsigned *outlen); + +static int gs2_get_mech_attrs(const sasl_utils_t *utils, + const gss_OID mech, + unsigned int *security_flags, + unsigned int *features, + const unsigned long **prompts); + +static int gs2_indicate_mechs(const sasl_utils_t *utils); + +static int gs2_map_sasl_name(const sasl_utils_t *utils, + const char *mech, + gss_OID *oid); + +static int gs2_duplicate_buffer(const sasl_utils_t *utils, + const gss_buffer_t src, + gss_buffer_t dst); + +static int gs2_unescape_authzid(const sasl_utils_t *utils, + char **in, + unsigned *inlen, + char **authzid); + +static int gs2_escape_authzid(const sasl_utils_t *utils, + const char *in, + unsigned inlen, + char **authzid); + +/* sasl_gs_log: only logs status string returned from gss_display_status() */ +#define sasl_gs2_log(x,y,z) sasl_gs2_seterror_(x,y,z,1) +#define sasl_gs2_seterror(x,y,z) sasl_gs2_seterror_(x,y,z,0) + +static int +sasl_gs2_seterror_(const sasl_utils_t *utils, OM_uint32 maj, OM_uint32 min, + int logonly); + +static context_t * +sasl_gs2_new_context(const sasl_utils_t *utils) +{ + context_t *ret; + + ret = utils->malloc(sizeof(context_t)); + if (ret == NULL) + return NULL; + + memset(ret, 0, sizeof(context_t)); + ret->utils = utils; + + return ret; +} + +static int +sasl_gs2_free_context_contents(context_t *text) +{ + OM_uint32 min_stat; + + if (text == NULL) + return SASL_OK; + + if (text->gss_ctx != GSS_C_NO_CONTEXT) { + gss_delete_sec_context(&min_stat,&text->gss_ctx, + GSS_C_NO_BUFFER); + text->gss_ctx = GSS_C_NO_CONTEXT; + } + + if (text->client_name != GSS_C_NO_NAME) { + gss_release_name(&min_stat,&text->client_name); + text->client_name = GSS_C_NO_NAME; + } + + if (text->server_name != GSS_C_NO_NAME) { + gss_release_name(&min_stat,&text->server_name); + text->server_name = GSS_C_NO_NAME; + } + + if (text->server_creds != GSS_C_NO_CREDENTIAL) { + gss_release_cred(&min_stat, &text->server_creds); + text->server_creds = GSS_C_NO_CREDENTIAL; + } + + if (text->client_creds != GSS_C_NO_CREDENTIAL) { + gss_release_cred(&min_stat, &text->client_creds); + text->client_creds = GSS_C_NO_CREDENTIAL; + } + + if (text->authid != NULL) { + text->utils->free(text->authid); + text->authid = NULL; + } + + if (text->authzid != NULL) { + text->utils->free(text->authzid); + text->authzid = NULL; + } + + gss_release_buffer(&min_stat, &text->gss_cbindings.application_data); + + if (text->out_buf != NULL) { + text->utils->free(text->out_buf); + text->out_buf = NULL; + } + + text->out_buf_len = 0; + + if (text->cbindingname != NULL) { + text->utils->free(text->cbindingname); + text->cbindingname = NULL; + } + + if (text->free_password) + _plug_free_secret(text->utils, &text->password); + + memset(text, 0, sizeof(*text)); + + return SASL_OK; +} + +static void +gs2_common_mech_dispose(void *conn_context, const sasl_utils_t *utils) +{ + sasl_gs2_free_context_contents((context_t *)(conn_context)); + utils->free(conn_context); +} + +static void +gs2_common_mech_free(void *global_context __attribute__((unused)), + const sasl_utils_t *utils) +{ + OM_uint32 minor; + + if (gs2_mechs != GSS_C_NO_OID_SET) { + gss_release_oid_set(&minor, &gs2_mechs); + gs2_mechs = GSS_C_NO_OID_SET; + } +} + +/***************************** Server Section *****************************/ + +static int +gs2_server_mech_new(void *glob_context, + sasl_server_params_t *params, + const char *challenge __attribute__((unused)), + unsigned challen __attribute__((unused)), + void **conn_context) +{ + context_t *text; + int ret; + + text = sasl_gs2_new_context(params->utils); + if (text == NULL) { + MEMERROR(params->utils); + return SASL_NOMEM; + } + + text->gss_ctx = GSS_C_NO_CONTEXT; + text->client_name = GSS_C_NO_NAME; + text->server_name = GSS_C_NO_NAME; + text->server_creds = GSS_C_NO_CREDENTIAL; + text->client_creds = GSS_C_NO_CREDENTIAL; + text->plug.server = glob_context; + + ret = gs2_map_sasl_name(params->utils, text->plug.server->mech_name, + &text->mechanism); + if (ret != SASL_OK) { + gs2_common_mech_dispose(text, params->utils); + return ret; + } + + *conn_context = text; + + return SASL_OK; +} + +static int +gs2_server_mech_step(void *conn_context, + sasl_server_params_t *params, + const char *clientin, + unsigned clientinlen, + const char **serverout, + unsigned *serveroutlen, + sasl_out_params_t *oparams) +{ + context_t *text = (context_t *)conn_context; + gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; + OM_uint32 maj_stat = GSS_S_FAILURE, min_stat = 0; + gss_buffer_desc name_buf = GSS_C_EMPTY_BUFFER; + gss_buffer_desc short_name_buf = GSS_C_EMPTY_BUFFER; + gss_name_t without = GSS_C_NO_NAME; + gss_OID_set_desc mechs; + OM_uint32 out_flags = 0; + int ret = 0, equal = 0; + int initialContextToken = (text->gss_ctx == GSS_C_NO_CONTEXT); + char *p; + + if (serverout == NULL) { + PARAMERROR(text->utils); + return SASL_BADPARAM; + } + + *serverout = NULL; + *serveroutlen = 0; + + if (initialContextToken) { + name_buf.length = strlen(params->service) + 1 + strlen(params->serverFQDN); + name_buf.value = params->utils->malloc(name_buf.length + 1); + if (name_buf.value == NULL) { + MEMERROR(text->utils); + ret = SASL_NOMEM; + goto cleanup; + } + snprintf(name_buf.value, name_buf.length + 1, + "%s@%s", params->service, params->serverFQDN); + maj_stat = gss_import_name(&min_stat, + &name_buf, + GSS_C_NT_HOSTBASED_SERVICE, + &text->server_name); + params->utils->free(name_buf.value); + name_buf.value = NULL; + + if (GSS_ERROR(maj_stat)) + goto cleanup; + + assert(text->server_creds == GSS_C_NO_CREDENTIAL); + + mechs.count = 1; + mechs.elements = (gss_OID)text->mechanism; + + if (params->gss_creds == GSS_C_NO_CREDENTIAL) { + maj_stat = gss_acquire_cred(&min_stat, + text->server_name, + GSS_C_INDEFINITE, + &mechs, + GSS_C_ACCEPT, + &text->server_creds, + NULL, + &text->lifetime); + if (GSS_ERROR(maj_stat)) + goto cleanup; + } + + ret = gs2_verify_initial_message(text, + params, + clientin, + clientinlen, + &input_token); + if (ret != SASL_OK) + goto cleanup; + } else { + input_token.value = (void *)clientin; + input_token.length = clientinlen; + } + + maj_stat = gss_accept_sec_context(&min_stat, + &text->gss_ctx, + (params->gss_creds != GSS_C_NO_CREDENTIAL) + ? (gss_cred_id_t)params->gss_creds + : text->server_creds, + &input_token, + &text->gss_cbindings, + &text->client_name, + NULL, + &output_token, + &out_flags, + &text->lifetime, + &text->client_creds); + if (GSS_ERROR(maj_stat)) { + sasl_gs2_log(text->utils, maj_stat, min_stat); + text->utils->seterror(text->utils->conn, SASL_NOLOG, + "GS2 Failure: gss_accept_sec_context"); + ret = (maj_stat == GSS_S_BAD_BINDINGS) ? SASL_BADBINDING : SASL_BADAUTH; + goto cleanup; + } + + *serveroutlen = output_token.length; + if (output_token.value != NULL) { + ret = _plug_buf_alloc(text->utils, &text->out_buf, + &text->out_buf_len, *serveroutlen); + if (ret != SASL_OK) + goto cleanup; + memcpy(text->out_buf, output_token.value, *serveroutlen); + *serverout = text->out_buf; + } else { + /* No output token, send an empty string */ + *serverout = ""; + serveroutlen = 0; + } + + if (maj_stat == GSS_S_CONTINUE_NEEDED) { + ret = SASL_CONTINUE; + goto cleanup; + } + + assert(maj_stat == GSS_S_COMPLETE); + + if ((out_flags & GSS_C_SEQUENCE_FLAG) == 0) { + ret = SASL_BADAUTH; + goto cleanup; + } + + maj_stat = gss_display_name(&min_stat, text->client_name, + &name_buf, NULL); + if (GSS_ERROR(maj_stat)) + goto cleanup; + + ret = gs2_duplicate_buffer(params->utils, &name_buf, &short_name_buf); + if (ret != 0) + goto cleanup; + + p = (char *)memchr(name_buf.value, '@', name_buf.length); + if (p != NULL) { + short_name_buf.length = (p - (char *)name_buf.value); + + maj_stat = gss_import_name(&min_stat, + &short_name_buf, + GSS_C_NT_USER_NAME, + &without); + if (GSS_ERROR(maj_stat)) { + ret = SASL_FAIL; + goto cleanup; + } + + maj_stat = gss_compare_name(&min_stat, text->client_name, + without, &equal); + if (GSS_ERROR(maj_stat)) { + ret = SASL_FAIL; + goto cleanup; + } + + if (equal) + ((char *)short_name_buf.value)[short_name_buf.length] = '\0'; + } + + text->authid = (char *)short_name_buf.value; + short_name_buf.value = NULL; + short_name_buf.length = 0; + + if (text->authzid != NULL) { + ret = params->canon_user(params->utils->conn, + text->authzid, 0, + SASL_CU_AUTHZID, oparams); + if (ret != SASL_OK) + goto cleanup; + } + + ret = params->canon_user(params->utils->conn, + text->authid, 0, + text->authzid == NULL + ? (SASL_CU_AUTHZID | SASL_CU_AUTHID) + : SASL_CU_AUTHID, + oparams); + if (ret != SASL_OK) + goto cleanup; + + switch (text->gs2_flags & GS2_CB_FLAG_MASK) { + case GS2_CB_FLAG_N: + oparams->cbindingdisp = SASL_CB_DISP_NONE; + break; + case GS2_CB_FLAG_P: + oparams->cbindingdisp = SASL_CB_DISP_USED; + oparams->cbindingname = text->cbindingname; + break; + case GS2_CB_FLAG_Y: + oparams->cbindingdisp = SASL_CB_DISP_WANT; + break; + } + + if (text->client_creds != GSS_C_NO_CREDENTIAL) + oparams->client_creds = &text->client_creds; + else + oparams->client_creds = NULL; + + oparams->gss_peer_name = text->client_name; + oparams->gss_local_name = text->server_name; + oparams->maxoutbuf = 0xFFFFFF; + oparams->encode = NULL; + oparams->decode = NULL; + oparams->mech_ssf = 0; + oparams->doneflag = 1; + + ret = SASL_OK; + +cleanup: + if (initialContextToken) + gss_release_buffer(&min_stat, &input_token); + gss_release_buffer(&min_stat, &name_buf); + gss_release_buffer(&min_stat, &short_name_buf); + gss_release_buffer(&min_stat, &output_token); + gss_release_name(&min_stat, &without); + + if (ret == SASL_OK && maj_stat != GSS_S_COMPLETE) { + sasl_gs2_seterror(text->utils, maj_stat, min_stat); + ret = SASL_FAIL; + } + if (ret != SASL_OK && ret != SASL_CONTINUE) + sasl_gs2_free_context_contents(text); + + return ret; +} + +static int +gs2_common_plug_init(const sasl_utils_t *utils, + size_t plugsize, + int (*plug_alloc)(const sasl_utils_t *, + void *, + const gss_buffer_t, + const gss_OID), + void **pluglist, + int *plugcount) +{ + OM_uint32 major, minor; + size_t i, count = 0; + void *plugs = NULL; + + *pluglist = NULL; + *plugcount = 0; + + if (gs2_indicate_mechs(utils) != SASL_OK) { + return SASL_NOMECH; + } + + plugs = utils->malloc(gs2_mechs->count * plugsize); + if (plugs == NULL) { + MEMERROR(utils); + return SASL_NOMEM; + } + memset(plugs, 0, gs2_mechs->count * plugsize); + + for (i = 0; i < gs2_mechs->count; i++) { + gss_buffer_desc sasl_mech_name = GSS_C_EMPTY_BUFFER; + + major = gss_inquire_saslname_for_mech(&minor, + &gs2_mechs->elements[i], + &sasl_mech_name, + GSS_C_NO_BUFFER, + GSS_C_NO_BUFFER); + if (GSS_ERROR(major)) + continue; + +#define PLUG_AT(index) (void *)((unsigned char *)plugs + (count * plugsize)) + + if (plug_alloc(utils, PLUG_AT(count), &sasl_mech_name, + &gs2_mechs->elements[i]) == SASL_OK) + count++; + + gss_release_buffer(&minor, &sasl_mech_name); + } + + if (count == 0) { + utils->free(plugs); + return SASL_NOMECH; + } + + *pluglist = plugs; + *plugcount = count; + + return SASL_OK; +} + +static int +gs2_server_plug_alloc(const sasl_utils_t *utils, + void *plug, + gss_buffer_t sasl_name, + gss_OID mech) +{ + int ret; + sasl_server_plug_t *splug = (sasl_server_plug_t *)plug; + gss_buffer_desc buf; + + memset(splug, 0, sizeof(*splug)); + + ret = gs2_get_mech_attrs(utils, mech, + &splug->security_flags, + &splug->features, + NULL); + if (ret != SASL_OK) + return ret; + + ret = gs2_duplicate_buffer(utils, sasl_name, &buf); + if (ret != SASL_OK) + return ret; + + splug->mech_name = (char *)buf.value; + splug->glob_context = plug; + splug->mech_new = gs2_server_mech_new; + splug->mech_step = gs2_server_mech_step; + splug->mech_dispose = gs2_common_mech_dispose; + splug->mech_free = gs2_common_mech_free; + + return SASL_OK; +} + +static sasl_server_plug_t *gs2_server_plugins; +static int gs2_server_plugcount; + +int +gs2_server_plug_init(const sasl_utils_t *utils, + int maxversion, + int *outversion, + sasl_server_plug_t **pluglist, + int *plugcount) +{ + int ret; + + *pluglist = NULL; + *plugcount = 0; + + if (maxversion < SASL_SERVER_PLUG_VERSION) + return SASL_BADVERS; + + *outversion = SASL_SERVER_PLUG_VERSION; + + if (gs2_server_plugins == NULL) { + ret = gs2_common_plug_init(utils, + sizeof(sasl_server_plug_t), + gs2_server_plug_alloc, + (void **)&gs2_server_plugins, + &gs2_server_plugcount); + if (ret != SASL_OK) + return ret; + } + + *pluglist = gs2_server_plugins; + *plugcount = gs2_server_plugcount; + + return SASL_OK; +} + +/***************************** Client Section *****************************/ + +static int gs2_client_mech_step(void *conn_context, + sasl_client_params_t *params, + const char *serverin, + unsigned serverinlen, + sasl_interact_t **prompt_need, + const char **clientout, + unsigned *clientoutlen, + sasl_out_params_t *oparams) +{ + context_t *text = (context_t *)conn_context; + gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc name_buf = GSS_C_EMPTY_BUFFER; + OM_uint32 maj_stat = GSS_S_FAILURE, min_stat = 0; + OM_uint32 req_flags, ret_flags; + int ret = SASL_FAIL; + int initialContextToken; + + *clientout = NULL; + *clientoutlen = 0; + + if (text->gss_ctx == GSS_C_NO_CONTEXT) { + ret = gs2_get_init_creds(text, params, prompt_need, oparams); + if (ret != SASL_OK) + goto cleanup; + + initialContextToken = 1; + } else + initialContextToken = 0; + + if (text->server_name == GSS_C_NO_NAME) { /* only once */ + name_buf.length = strlen(params->service) + 1 + strlen(params->serverFQDN); + name_buf.value = params->utils->malloc(name_buf.length + 1); + if (name_buf.value == NULL) { + ret = SASL_NOMEM; + goto cleanup; + } + if (params->serverFQDN == NULL || + strlen(params->serverFQDN) == 0) { + SETERROR(text->utils, "GS2 Failure: no serverFQDN"); + ret = SASL_FAIL; + goto cleanup; + } + + snprintf(name_buf.value, name_buf.length + 1, + "%s@%s", params->service, params->serverFQDN); + + maj_stat = gss_import_name(&min_stat, + &name_buf, + GSS_C_NT_HOSTBASED_SERVICE, + &text->server_name); + params->utils->free(name_buf.value); + name_buf.value = NULL; + + if (GSS_ERROR(maj_stat)) + goto cleanup; + } + + /* From GSSAPI plugin: apparently this is for some IMAP bug workaround */ + if (serverinlen == 0 && text->gss_ctx != GSS_C_NO_CONTEXT) { + gss_delete_sec_context(&min_stat, &text->gss_ctx, GSS_C_NO_BUFFER); + text->gss_ctx = GSS_C_NO_CONTEXT; + } + + input_token.value = (void *)serverin; + input_token.length = serverinlen; + + if (initialContextToken) { + if ((text->plug.client->features & SASL_FEAT_GSS_FRAMING) == 0) + text->gs2_flags |= GS2_NONSTD_FLAG; + + switch (params->cbindingdisp) { + case SASL_CB_DISP_NONE: + text->gs2_flags |= GS2_CB_FLAG_N; + break; + case SASL_CB_DISP_USED: + text->gs2_flags |= GS2_CB_FLAG_P; + break; + case SASL_CB_DISP_WANT: + text->gs2_flags |= GS2_CB_FLAG_Y; + break; + } + + ret = gs2_make_header(text, params, + strcmp(oparams->user, oparams->authid) ? + (char *) oparams->user : NULL, + &text->out_buf, &text->out_buf_len); + if (ret != 0) + goto cleanup; + } + + req_flags = GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG; + + maj_stat = gss_init_sec_context(&min_stat, + (params->gss_creds != GSS_C_NO_CREDENTIAL) + ? (gss_cred_id_t)params->gss_creds + : text->client_creds, + &text->gss_ctx, + text->server_name, + (gss_OID)text->mechanism, + req_flags, + GSS_C_INDEFINITE, + &text->gss_cbindings, + serverinlen ? &input_token : GSS_C_NO_BUFFER, + NULL, + &output_token, + &ret_flags, + &text->lifetime); + if (GSS_ERROR(maj_stat)) + goto cleanup; + + ret = gs2_make_message(text, params, initialContextToken, &output_token, + &text->out_buf, &text->out_buf_len); + if (ret != 0) + goto cleanup; + + *clientout = text->out_buf; + *clientoutlen = text->out_buf_len; + + if (maj_stat == GSS_S_CONTINUE_NEEDED) { + ret = SASL_CONTINUE; + goto cleanup; + } + + if (text->client_name != GSS_C_NO_NAME) + gss_release_name(&min_stat, &text->client_name); + + maj_stat = gss_inquire_context(&min_stat, + text->gss_ctx, + &text->client_name, + NULL, + &text->lifetime, + NULL, + &ret_flags, /* flags */ + NULL, + NULL); + if (GSS_ERROR(maj_stat)) + goto cleanup; + + if ((ret_flags & req_flags) != req_flags) { + maj_stat = SASL_BADAUTH; + goto cleanup; + } + + maj_stat = gss_display_name(&min_stat, + text->client_name, + &name_buf, + NULL); + if (GSS_ERROR(maj_stat)) + goto cleanup; + + oparams->gss_peer_name = text->server_name; + oparams->gss_local_name = text->client_name; + oparams->encode = NULL; + oparams->decode = NULL; + oparams->mech_ssf = 0; + oparams->maxoutbuf = 0xFFFFFF; + oparams->doneflag = 1; + +cleanup: + gss_release_buffer(&min_stat, &output_token); + gss_release_buffer(&min_stat, &name_buf); + + if (ret == SASL_OK && maj_stat != GSS_S_COMPLETE) { + sasl_gs2_seterror(text->utils, maj_stat, min_stat); + ret = SASL_FAIL; + } + if (ret != SASL_OK && ret != SASL_CONTINUE) + sasl_gs2_free_context_contents(text); + + return ret; +} + +static int gs2_client_mech_new(void *glob_context, + sasl_client_params_t *params, + void **conn_context) +{ + context_t *text; + int ret; + + text = sasl_gs2_new_context(params->utils); + if (text == NULL) { + MEMERROR(params->utils); + return SASL_NOMEM; + } + + text->gss_ctx = GSS_C_NO_CONTEXT; + text->client_name = GSS_C_NO_NAME; + text->server_creds = GSS_C_NO_CREDENTIAL; + text->client_creds = GSS_C_NO_CREDENTIAL; + text->plug.client = glob_context; + + ret = gs2_map_sasl_name(params->utils, text->plug.client->mech_name, + &text->mechanism); + if (ret != SASL_OK) { + gs2_common_mech_dispose(text, params->utils); + return ret; + } + + *conn_context = text; + + return SASL_OK; +} + +static int +gs2_client_plug_alloc(const sasl_utils_t *utils, + void *plug, + gss_buffer_t sasl_name, + gss_OID mech) +{ + int ret; + sasl_client_plug_t *cplug = (sasl_client_plug_t *)plug; + gss_buffer_desc buf; + + memset(cplug, 0, sizeof(*cplug)); + + ret = gs2_get_mech_attrs(utils, mech, + &cplug->security_flags, + &cplug->features, + &cplug->required_prompts); + if (ret != SASL_OK) + return ret; + + ret = gs2_duplicate_buffer(utils, sasl_name, &buf); + if (ret != SASL_OK) + return ret; + + cplug->mech_name = (char *)buf.value; + cplug->features |= SASL_FEAT_NEEDSERVERFQDN; + cplug->glob_context = plug; + cplug->mech_new = gs2_client_mech_new; + cplug->mech_step = gs2_client_mech_step; + cplug->mech_dispose = gs2_common_mech_dispose; + cplug->mech_free = gs2_common_mech_free; + + return SASL_OK; +} + +static sasl_client_plug_t *gs2_client_plugins; +static int gs2_client_plugcount; + +int +gs2_client_plug_init(const sasl_utils_t *utils, + int maxversion, + int *outversion, + sasl_client_plug_t **pluglist, + int *plugcount) +{ + int ret; + + *pluglist = NULL; + *plugcount = 0; + + if (maxversion < SASL_CLIENT_PLUG_VERSION) + return SASL_BADVERS; + + *outversion = SASL_CLIENT_PLUG_VERSION; + + if (gs2_client_plugins == NULL) { + ret = gs2_common_plug_init(utils, + sizeof(sasl_client_plug_t), + gs2_client_plug_alloc, + (void **)&gs2_client_plugins, + &gs2_client_plugcount); + if (ret != SASL_OK) + return ret; + } + + *pluglist = gs2_client_plugins; + *plugcount = gs2_client_plugcount; + + return SASL_OK; +} + +/* + * Copy header and application channel bindings to GSS channel bindings + * structure in context. + */ +static int +gs2_save_cbindings(context_t *text, + gss_buffer_t header, + const sasl_channel_binding_t *cbinding) +{ + gss_buffer_t gss_cbindings = &text->gss_cbindings.application_data; + size_t len; + unsigned char *p; + + assert(gss_cbindings->value == NULL); + + /* + * The application-data field MUST be set to the gs2-header, excluding + * the initial [gs2-nonstd-flag ","] part, concatenated with, when a + * gs2-cb-flag of "p" is used, the application's channel binding data. + */ + len = header->length; + if (text->gs2_flags & GS2_NONSTD_FLAG) { + assert(len > 2); + len -= 2; + } + if ((text->gs2_flags & GS2_CB_FLAG_MASK) == GS2_CB_FLAG_P && + cbinding != NULL) { + len += cbinding->len; + } + + gss_cbindings->length = len; + gss_cbindings->value = text->utils->malloc(len); + if (gss_cbindings->value == NULL) + return SASL_NOMEM; + + p = (unsigned char *)gss_cbindings->value; + if (text->gs2_flags & GS2_NONSTD_FLAG) { + memcpy(p, (unsigned char *)header->value + 2, header->length - 2); + p += header->length - 2; + } else { + memcpy(p, header->value, header->length); + p += header->length; + } + + if ((text->gs2_flags & GS2_CB_FLAG_MASK) == GS2_CB_FLAG_P && + cbinding != NULL) { + memcpy(p, cbinding->data, cbinding->len); + } + + return SASL_OK; +} + +#define CHECK_REMAIN(n) do { if (remain < (n)) return SASL_BADPROT; } while (0) + +/* + * Verify gs2-header, save authzid and channel bindings to context. + */ +static int +gs2_verify_initial_message(context_t *text, + sasl_server_params_t *sparams, + const char *in, + unsigned inlen, + gss_buffer_t token) +{ + char *p = (char *)in; + unsigned remain = inlen; + int ret; + gss_buffer_desc buf = GSS_C_EMPTY_BUFFER; + + assert(text->cbindingname == NULL); + assert(text->authzid == NULL); + + token->length = 0; + token->value = NULL; + + /* minimum header includes CB flag and non-zero GSS token */ + CHECK_REMAIN(4); /* [pny],,. */ + + /* non-standard GSS framing flag */ + if (remain > 1 && memcmp(p, "F,", 2) == 0) { + text->gs2_flags |= GS2_NONSTD_FLAG; + remain -= 2; + p += 2; + } + + /* SASL channel bindings */ + CHECK_REMAIN(1); /* [pny] */ + remain--; + switch (*p++) { + case 'p': + CHECK_REMAIN(1); /* = */ + remain--; + if (*p++ != '=') + return SASL_BADPROT; + + ret = gs2_unescape_authzid(text->utils, &p, &remain, &text->cbindingname); + if (ret != SASL_OK) + return ret; + + text->gs2_flags |= GS2_CB_FLAG_P; + break; + case 'n': + text->gs2_flags |= GS2_CB_FLAG_N; + break; + case 'y': + text->gs2_flags |= GS2_CB_FLAG_Y; + break; + } + + CHECK_REMAIN(1); /* , */ + remain--; + if (*p++ != ',') + return SASL_BADPROT; + + /* authorization identity */ + if (remain > 1 && memcmp(p, "a=", 2) == 0) { + CHECK_REMAIN(2); + remain -= 2; + p += 2; + + ret = gs2_unescape_authzid(text->utils, &p, &remain, &text->authzid); + if (ret != SASL_OK) + return ret; + } + + /* end of header */ + CHECK_REMAIN(1); /* , */ + remain--; + if (*p++ != ',') + return SASL_BADPROT; + + buf.length = inlen - remain; + buf.value = (void *)in; + + /* stash channel bindings to pass into gss_accept_sec_context() */ + ret = gs2_save_cbindings(text, &buf, sparams->cbinding); + if (ret != SASL_OK) + return ret; + + buf.length = remain; + buf.value = p; + + if (text->gs2_flags & GS2_NONSTD_FLAG) { + token->value = text->utils->malloc(buf.length); + if (token->value == NULL) + return SASL_NOMEM; + + token->length = buf.length; + memcpy(token->value, buf.value, buf.length); + } else { + unsigned int token_size; + + /* create a properly formed GSS token */ + token_size = gs2_token_size(text->mechanism, buf.length); + token->value = text->utils->malloc(token_size); + if (token->value == NULL) + return SASL_NOMEM; + + token->length = token_size; + + p = (char *)token->value; + gs2_make_token_header(text->mechanism, buf.length, + (unsigned char **)&p); + memcpy(p, buf.value, buf.length); + } + + return SASL_OK; +} + +/* + * Create gs2-header, save channel bindings to context. + */ +static int +gs2_make_header(context_t *text, + sasl_client_params_t *cparams, + const char *authzid, + char **out, + unsigned *outlen) +{ + size_t required = 0; + size_t wire_authzid_len = 0, cbnamelen = 0; + char *wire_authzid = NULL; + char *p; + int ret; + gss_buffer_desc buf; + + *out = NULL; + *outlen = 0; + + /* non-standard GSS framing flag */ + if (text->gs2_flags & GS2_NONSTD_FLAG) + required += 2; /* F, */ + + /* SASL channel bindings */ + switch (text->gs2_flags & GS2_CB_FLAG_MASK) { + case GS2_CB_FLAG_P: + if (!SASL_CB_PRESENT(cparams)) + return SASL_BADPARAM; + cbnamelen = strlen(cparams->cbinding->name); + required += 1 /*=*/ + cbnamelen; + /* fallthrough */ + case GS2_CB_FLAG_N: + case GS2_CB_FLAG_Y: + required += 2; /* [pny], */ + break; + default: + return SASL_BADPARAM; + } + + /* authorization identity */ + if (authzid != NULL) { + ret = gs2_escape_authzid(text->utils, authzid, + strlen(authzid), &wire_authzid); + if (ret != SASL_OK) + return ret; + + wire_authzid_len = strlen(wire_authzid); + required += 2 /* a= */ + wire_authzid_len; + } + + required += 1; /* trailing comma */ + + ret = _plug_buf_alloc(text->utils, out, outlen, required); + if (ret != SASL_OK) { + text->utils->free(wire_authzid); + return ret; + } + + *out = text->out_buf; + *outlen = required; + + p = (char *)text->out_buf; + if (text->gs2_flags & GS2_NONSTD_FLAG) { + *p++ = 'F'; + *p++ = ','; + } + switch (text->gs2_flags & GS2_CB_FLAG_MASK) { + case GS2_CB_FLAG_P: + memcpy(p, "p=", 2); + memcpy(p + 2, cparams->cbinding->name, cbnamelen); + p += 2 + cbnamelen; + break; + case GS2_CB_FLAG_N: + *p++ = 'n'; + break; + case GS2_CB_FLAG_Y: + *p++ = 'y'; + break; + } + *p++ = ','; + if (wire_authzid != NULL) { + memcpy(p, "a=", 2); + memcpy(p + 2, wire_authzid, wire_authzid_len); + text->utils->free(wire_authzid); + p += 2 + wire_authzid_len; + } + *p++ = ','; + + assert(p == (char *)text->out_buf + required); + + buf.length = required; + buf.value = *out; + + ret = gs2_save_cbindings(text, &buf, cparams->cbinding); + if (ret != SASL_OK) + return ret; + + return SASL_OK; +} + +/* + * Convert a GSS token to a GS2 one + */ +static int +gs2_make_message(context_t *text, + sasl_client_params_t *cparams __attribute__((unused)), + int initialContextToken, + gss_buffer_t token, + char **out, + unsigned *outlen) +{ + OM_uint32 major, minor; + unsigned char *mech_token_data; + size_t mech_token_size; + char *p; + unsigned header_len = 0; + int ret; + + mech_token_size = token->length; + mech_token_data = (unsigned char *)token->value; + + if (initialContextToken) { + header_len = *outlen; + + major = gs2_verify_token_header(&minor, text->mechanism, + &mech_token_size, &mech_token_data, + token->length); + if ((major == GSS_S_DEFECTIVE_TOKEN && + (text->plug.client->features & SASL_FEAT_GSS_FRAMING)) || + GSS_ERROR(major)) + return SASL_FAIL; + } + + ret = _plug_buf_alloc(text->utils, out, outlen, + header_len + mech_token_size); + if (ret != 0) + return ret; + + p = *out + header_len; + memcpy(p, mech_token_data, mech_token_size); + + *outlen = header_len + mech_token_size; + + return SASL_OK; +} + +static const unsigned long gs2_required_prompts[] = { + SASL_CB_LIST_END +}; + +/* + * Map GSS mechanism attributes to SASL ones + */ +static int +gs2_get_mech_attrs(const sasl_utils_t *utils, + const gss_OID mech, + unsigned int *security_flags, + unsigned int *features, + const unsigned long **prompts) +{ + OM_uint32 major, minor; + int present; + gss_OID_set attrs = GSS_C_NO_OID_SET; + + major = gss_inquire_attrs_for_mech(&minor, mech, &attrs, NULL); + if (GSS_ERROR(major)) { + utils->seterror(utils->conn, SASL_NOLOG, + "GS2 Failure: gss_inquire_attrs_for_mech"); + return SASL_FAIL; + } + + *security_flags = SASL_SEC_NOPLAINTEXT | SASL_SEC_NOACTIVE; + *features = SASL_FEAT_WANT_CLIENT_FIRST | SASL_FEAT_CHANNEL_BINDING; + if (prompts != NULL) + *prompts = gs2_required_prompts; + +#define MA_PRESENT(a) (gss_test_oid_set_member(&minor, (gss_OID)(a), \ + attrs, &present) == GSS_S_COMPLETE && \ + present) + + if (MA_PRESENT(GSS_C_MA_PFS)) + *security_flags |= SASL_SEC_FORWARD_SECRECY; + if (!MA_PRESENT(GSS_C_MA_AUTH_INIT_ANON)) + *security_flags |= SASL_SEC_NOANONYMOUS; + if (MA_PRESENT(GSS_C_MA_DELEG_CRED)) + *security_flags |= SASL_SEC_PASS_CREDENTIALS; + if (MA_PRESENT(GSS_C_MA_AUTH_TARG)) + *security_flags |= SASL_SEC_MUTUAL_AUTH; + if (MA_PRESENT(GSS_C_MA_AUTH_INIT_INIT) && prompts != NULL) + *prompts = NULL; + if (MA_PRESENT(GSS_C_MA_ITOK_FRAMED)) + *features |= SASL_FEAT_GSS_FRAMING; + + gss_release_oid_set(&minor, &attrs); + + return SASL_OK; +} + +/* + * Enumerate GSS mechanisms that can be used for GS2 + */ +static int gs2_indicate_mechs(const sasl_utils_t *utils) +{ + OM_uint32 major, minor; + gss_OID_desc desired_oids[3]; + gss_OID_set_desc desired_attrs; + gss_OID_desc except_oids[3]; + gss_OID_set_desc except_attrs; + + if (gs2_mechs != GSS_C_NO_OID_SET) + return SASL_OK; + + desired_oids[0] = *GSS_C_MA_AUTH_INIT; + desired_oids[1] = *GSS_C_MA_AUTH_TARG; + desired_oids[2] = *GSS_C_MA_CBINDINGS; + desired_attrs.count = sizeof(desired_oids)/sizeof(desired_oids[0]); + desired_attrs.elements = desired_oids; + + except_oids[0] = *GSS_C_MA_MECH_NEGO; + except_oids[1] = *GSS_C_MA_NOT_MECH; + except_oids[2] = *GSS_C_MA_DEPRECATED; + + except_attrs.count = sizeof(except_oids)/sizeof(except_oids[0]); + except_attrs.elements = except_oids; + + major = gss_indicate_mechs_by_attrs(&minor, + &desired_attrs, + &except_attrs, + GSS_C_NO_OID_SET, + &gs2_mechs); + if (GSS_ERROR(major)) { + utils->seterror(utils->conn, SASL_NOLOG, + "GS2 Failure: gss_indicate_mechs_by_attrs"); + return SASL_FAIL; + } + + return (gs2_mechs->count > 0) ? SASL_OK : SASL_NOMECH; +} + +/* + * Map SASL mechanism name to OID + */ +static int +gs2_map_sasl_name(const sasl_utils_t *utils, + const char *mech, + gss_OID *oid) +{ + OM_uint32 major, minor; + gss_buffer_desc buf; + + buf.length = strlen(mech); + buf.value = (void *)mech; + + major = gss_inquire_mech_for_saslname(&minor, &buf, oid); + if (GSS_ERROR(major)) { + utils->seterror(utils->conn, SASL_NOLOG, + "GS2 Failure: gss_inquire_mech_for_saslname"); + return SASL_FAIL; + } + + return SASL_OK; +} + +static int +gs2_duplicate_buffer(const sasl_utils_t *utils, + const gss_buffer_t src, + gss_buffer_t dst) +{ + dst->value = utils->malloc(src->length + 1); + if (dst->value == NULL) + return SASL_NOMEM; + + memcpy(dst->value, src->value, src->length); + ((char *)dst->value)[src->length] = '\0'; + dst->length = src->length; + + return SASL_OK; +} + +static int +gs2_unescape_authzid(const sasl_utils_t *utils, + char **endp, + unsigned *remain, + char **authzid) +{ + char *in = *endp; + size_t i, len, inlen = *remain; + char *p; + + *endp = NULL; + + for (i = 0, len = 0; i < inlen; i++) { + if (in[i] == ',') { + *endp = &in[i]; + *remain -= i; + break; + } else if (in[i] == '=') { + if (inlen <= i + 2) + return SASL_BADPROT; + i += 2; + } + len++; + } + + if (len == 0 || *endp == NULL) + return SASL_BADPROT; + + p = *authzid = utils->malloc(len + 1); + if (*authzid == NULL) + return SASL_NOMEM; + + for (i = 0; i < inlen; i++) { + if (in[i] == ',') + break; + else if (in[i] == '=') { + if (memcmp(&in[i + 1], "2C", 2) == 0) + *p++ = ','; + else if (memcmp(&in[i + 1], "3D", 2) == 0) + *p++ = '='; + else { + utils->free(*authzid); + *authzid = NULL; + return SASL_BADPROT; + } + i += 2; + } else + *p++ = in[i]; + } + + *p = '\0'; + + return SASL_OK; +} + +static int +gs2_escape_authzid(const sasl_utils_t *utils, + const char *in, + unsigned inlen, + char **authzid) +{ + size_t i; + char *p; + + p = *authzid = utils->malloc((inlen * 3) + 1); + if (*authzid == NULL) + return SASL_NOMEM; + + for (i = 0; i < inlen; i++) { + if (in[i] == ',') { + memcpy(p, "=2C", 3); + p += 3; + } else if (in[i] == '=') { + memcpy(p, "=3D", 3); + p += 3; + } else { + *p++ = in[i]; + } + } + + *p = '\0'; + + return SASL_OK; +} + +#define GOT_CREDS(text, params) ((text)->client_creds != NULL || (params)->gss_creds != NULL) +#define CRED_ERROR(status) ((status) == GSS_S_CRED_UNAVAIL || (status) == GSS_S_NO_CRED) + +/* + * Determine the authentication identity from the application supplied + * GSS credential, the application supplied identity, and the default + * GSS credential, in that order. Then, acquire credentials. + */ +static int +gs2_get_init_creds(context_t *text, + sasl_client_params_t *params, + sasl_interact_t **prompt_need, + sasl_out_params_t *oparams) +{ + int result = SASL_OK; + const char *authid = NULL, *userid = NULL; + int user_result = SASL_OK; + int auth_result = SASL_OK; + int pass_result = SASL_OK; + OM_uint32 maj_stat = GSS_S_COMPLETE, min_stat = 0; + gss_OID_set_desc mechs; + gss_buffer_desc cred_authid = GSS_C_EMPTY_BUFFER; + gss_buffer_desc name_buf = GSS_C_EMPTY_BUFFER; + + mechs.count = 1; + mechs.elements = (gss_OID)text->mechanism; + + /* + * Get the authentication identity from the application. + */ + if (oparams->authid == NULL) { + auth_result = _plug_get_authid(params->utils, &authid, prompt_need); + if (auth_result != SASL_OK && auth_result != SASL_INTERACT) { + result = auth_result; + goto cleanup; + } + } + + /* + * Get the authorization identity from the application. + */ + if (oparams->user == NULL) { + user_result = _plug_get_userid(params->utils, &userid, prompt_need); + if (user_result != SASL_OK && user_result != SASL_INTERACT) { + result = user_result; + goto cleanup; + } + } + + /* + * Canonicalize the authentication and authorization identities before + * calling GSS_Import_name. + */ + if (auth_result == SASL_OK && user_result == SASL_OK && + oparams->authid == NULL) { + if (userid == NULL || userid[0] == '\0') { + result = params->canon_user(params->utils->conn, authid, 0, + SASL_CU_AUTHID | SASL_CU_AUTHZID, + oparams); + } else { + result = params->canon_user(params->utils->conn, + authid, 0, SASL_CU_AUTHID, oparams); + if (result != SASL_OK) + goto cleanup; + + result = params->canon_user(params->utils->conn, + userid, 0, SASL_CU_AUTHZID, oparams); + if (result != SASL_OK) + goto cleanup; + } + + if (oparams->authid != NULL) { + name_buf.length = strlen(oparams->authid); + name_buf.value = (void *)oparams->authid; + + assert(text->client_name == GSS_C_NO_NAME); + + maj_stat = gss_import_name(&min_stat, + &name_buf, + GSS_C_NT_USER_NAME, + &text->client_name); + if (GSS_ERROR(maj_stat)) + goto cleanup; + } + } + + /* + * If application didn't provide an authid, then use the default + * credential. If that doesn't work, give up. + */ + if (!GOT_CREDS(text, params) && oparams->authid == NULL) { + maj_stat = gss_acquire_cred(&min_stat, + GSS_C_NO_NAME, + GSS_C_INDEFINITE, + &mechs, + GSS_C_INITIATE, + &text->client_creds, + NULL, + &text->lifetime); + if (GSS_ERROR(maj_stat)) + goto cleanup; + + assert(text->client_name == GSS_C_NO_NAME); + + maj_stat = gss_inquire_cred(&min_stat, + params->gss_creds + ? (gss_cred_id_t)params->gss_creds + : text->client_creds, + &text->client_name, + NULL, + NULL, + NULL); + if (GSS_ERROR(maj_stat)) + goto cleanup; + + maj_stat = gss_display_name(&min_stat, + text->client_name, + &cred_authid, + NULL); + if (GSS_ERROR(maj_stat)) + goto cleanup; + + if (userid == NULL || userid[0] == '\0') { + result = params->canon_user(params->utils->conn, + cred_authid.value, cred_authid.length, + SASL_CU_AUTHID | SASL_CU_AUTHZID, + oparams); + } else { + result = params->canon_user(params->utils->conn, + cred_authid.value, cred_authid.length, + SASL_CU_AUTHID, oparams); + if (result != SASL_OK) + goto cleanup; + + result = params->canon_user(params->utils->conn, + cred_authid.value, cred_authid.length, + SASL_CU_AUTHZID, oparams); + if (result != SASL_OK) + goto cleanup; + } + } + + /* + * Armed with the authentication identity, try to get a credential without + * a password. + */ + if (!GOT_CREDS(text, params) && text->client_name != GSS_C_NO_NAME) { + maj_stat = gss_acquire_cred(&min_stat, + text->client_name, + GSS_C_INDEFINITE, + &mechs, + GSS_C_INITIATE, + &text->client_creds, + NULL, + &text->lifetime); + if (GSS_ERROR(maj_stat) && !CRED_ERROR(maj_stat)) + goto cleanup; + } + + /* + * If that failed, try to get a credential with a password. + */ + if (!GOT_CREDS(text, params)) { + if (text->password == NULL) { + pass_result = _plug_get_password(params->utils, &text->password, + &text->free_password, prompt_need); + if (pass_result != SASL_OK && pass_result != SASL_INTERACT) { + result = pass_result; + goto cleanup; + } + } + + if (text->password != NULL) { + gss_buffer_desc password_buf; + + password_buf.length = text->password->len; + password_buf.value = text->password->data; + + maj_stat = gss_acquire_cred_with_password(&min_stat, + text->client_name, + &password_buf, + GSS_C_INDEFINITE, + &mechs, + GSS_C_INITIATE, + &text->client_creds, + NULL, + &text->lifetime); + if (GSS_ERROR(maj_stat)) + goto cleanup; + } + } + + maj_stat = GSS_S_COMPLETE; + + /* free prompts we got */ + if (prompt_need && *prompt_need) { + params->utils->free(*prompt_need); + *prompt_need = NULL; + } + + /* if there are prompts not filled in */ + if (user_result == SASL_INTERACT || auth_result == SASL_INTERACT || + pass_result == SASL_INTERACT) { + /* make the prompt list */ + result = + _plug_make_prompts(params->utils, prompt_need, + user_result == SASL_INTERACT ? + "Please enter your authorization name" : NULL, + NULL, + auth_result == SASL_INTERACT ? + "Please enter your authentication name" : NULL, + NULL, + pass_result == SASL_INTERACT ? + "Please enter your password" : NULL, NULL, + NULL, NULL, NULL, + NULL, + NULL, NULL); + if (result == SASL_OK) + result = SASL_INTERACT; + } + +cleanup: + if (result == SASL_OK && maj_stat != GSS_S_COMPLETE) { + sasl_gs2_seterror(text->utils, maj_stat, min_stat); + result = SASL_FAIL; + } + + gss_release_buffer(&min_stat, &cred_authid); + + return result; +} + +static int +sasl_gs2_seterror_(const sasl_utils_t *utils, OM_uint32 maj, OM_uint32 min, + int logonly) +{ + OM_uint32 maj_stat, min_stat; + gss_buffer_desc msg; + OM_uint32 msg_ctx; + int ret; + char *out = NULL; + unsigned int len, curlen = 0; + const char prefix[] = "GS2 Error: "; + + len = sizeof(prefix); + ret = _plug_buf_alloc(utils, &out, &curlen, 256); + if (ret != SASL_OK) + return SASL_OK; + + strcpy(out, prefix); + + msg_ctx = 0; + while (1) { + maj_stat = gss_display_status(&min_stat, maj, + GSS_C_GSS_CODE, GSS_C_NULL_OID, + &msg_ctx, &msg); + + if (GSS_ERROR(maj_stat)) { + if (logonly) { + utils->log(utils->conn, SASL_LOG_FAIL, + "GS2 Failure: (could not get major error message)"); + } else { + utils->seterror(utils->conn, 0, + "GS2 Failure " + "(could not get major error message)"); + } + utils->free(out); + return SASL_OK; + } + + len += len + msg.length; + ret = _plug_buf_alloc(utils, &out, &curlen, len); + if (ret != SASL_OK) { + utils->free(out); + return SASL_OK; + } + + strcat(out, msg.value); + + gss_release_buffer(&min_stat, &msg); + + if (!msg_ctx) + break; + } + + /* Now get the minor status */ + + len += 2; + ret = _plug_buf_alloc(utils, &out, &curlen, len); + if (ret != SASL_OK) { + utils->free(out); + return SASL_NOMEM; + } + + strcat(out, " ("); + + msg_ctx = 0; + while (1) { + maj_stat = gss_display_status(&min_stat, min, + GSS_C_MECH_CODE, GSS_C_NULL_OID, + &msg_ctx, &msg); + + if (GSS_ERROR(maj_stat)) { + if (logonly) { + utils->log(utils->conn, SASL_LOG_FAIL, + "GS2 Failure: (could not get minor error message)"); + } else { + utils->seterror(utils->conn, 0, + "GS2 Failure " + "(could not get minor error message)"); + } + utils->free(out); + return SASL_OK; + } + + len += len + msg.length; + + ret = _plug_buf_alloc(utils, &out, &curlen, len); + if (ret != SASL_OK) { + utils->free(out); + return SASL_NOMEM; + } + + strcat(out, msg.value); + + gss_release_buffer(&min_stat, &msg); + + if (!msg_ctx) + break; + } + + len += 1; + ret = _plug_buf_alloc(utils, &out, &curlen, len); + if (ret != SASL_OK) { + utils->free(out); + return SASL_NOMEM; + } + + strcat(out, ")"); + + if (logonly) { + utils->log(utils->conn, SASL_LOG_FAIL, out); + } else { + utils->seterror(utils->conn, 0, out); + } + utils->free(out); + + return SASL_OK; +} From 09dfc509a129221f38fdbaaf44df64dfa6e2e7d2 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Thu, 7 Apr 2011 08:50:31 +0000 Subject: [PATCH 080/796] Fixed the name of an OpenSSL library used to build SCRAM --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 55caf13b..c635f975 100644 --- a/configure.in +++ b/configure.in @@ -1,7 +1,7 @@ dnl configure.in for the SASL library dnl Rob Siemborski dnl Rob Earhart -dnl $Id: configure.in,v 1.219 2011/04/05 14:50:07 mel Exp $ +dnl $Id: configure.in,v 1.220 2011/04/07 08:50:31 mel Exp $ dnl dnl Copyright (c) 2001 Carnegie Mellon University. All rights reserved. dnl @@ -439,7 +439,7 @@ fi AC_MSG_CHECKING(SCRAM) if test "$scram" != no; then AC_MSG_RESULT(enabled) - SCRAM_LIBS="-lisode_crypto $LIB_RSAREF" + SCRAM_LIBS="-lcrypto $LIB_RSAREF" SASL_MECHS="$SASL_MECHS libscram.la" if test "$enable_static" = yes; then From c447f2d472feb0540d66246ba687e333befd027c Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Tue, 12 Apr 2011 10:29:59 +0000 Subject: [PATCH 081/796] LDAPDB build fixes from Dan White --- plugins/Makefile.am | 4 ++-- plugins/makeinit.sh | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/Makefile.am b/plugins/Makefile.am index df228f4c..3ca32222 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -1,7 +1,7 @@ # Makefile.am for the SASL plugins # Rob Siemborski # Rob Earhart -# $Id: Makefile.am,v 1.82 2011/04/05 14:50:07 mel Exp $ +# $Id: Makefile.am,v 1.83 2011/04/12 10:29:59 mel Exp $ # ################################################################ # Copyright (c) 2000 Carnegie Mellon University. All rights reserved. @@ -127,7 +127,7 @@ libsasldb_la_LIBADD = ../sasldb/libsasldb.la $(SASL_DB_LIB) $(COMPAT_OBJS) libldapdb_la_SOURCES = ldapdb.c ldapdb_init.c $(common_sources) libldapdb_la_DEPENDENCIES = $(COMPAT_OBJS) -libldapdb_la_LIBADD = $(COMPAT_OBJS) +libldapdb_la_LIBADD = $(LIB_LDAP) $(COMPAT_OBJS) libsql_la_SOURCES = sql.c sql_init.c $(common_sources) libsql_la_LDFLAGS = $(LIB_MYSQL) $(LIB_PGSQL) $(LIB_SQLITE) $(AM_LDFLAGS) diff --git a/plugins/makeinit.sh b/plugins/makeinit.sh index 3d889641..cc65f7d0 100644 --- a/plugins/makeinit.sh +++ b/plugins/makeinit.sh @@ -90,4 +90,4 @@ SASL_AUXPROP_PLUG_INIT( $auxprop ) done # ldapdb is also a canon_user plugin -echo "SASL_CANONUSER_PLUG_INIT( ldap )" >> ldapdb_init.c +echo "SASL_CANONUSER_PLUG_INIT( ldapdb )" >> ldapdb_init.c From bb2df2a195128c4dc9fc2e82f3ed4ca8ee14e536 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Tue, 12 Apr 2011 10:46:31 +0000 Subject: [PATCH 082/796] Additional LDAPDB build fixes --- plugins/ldapdb.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/ldapdb.c b/plugins/ldapdb.c index 1217ddc8..ddead7f3 100644 --- a/plugins/ldapdb.c +++ b/plugins/ldapdb.c @@ -249,7 +249,9 @@ static int ldapdb_auxprop_lookup(void *glob_context, result = SASL_UNAVAIL; break; +#if defined(LDAP_PROXY_AUTHZ_FAILURE) case LDAP_PROXY_AUTHZ_FAILURE: +#endif case LDAP_INAPPROPRIATE_AUTH: case LDAP_INVALID_CREDENTIALS: case LDAP_INSUFFICIENT_ACCESS: @@ -445,7 +447,7 @@ ldapdb_canon_client(void *glob_context, return SASL_FAIL; } - if (ulen > out_umax) return SASL_BUFOVER; + if (ulen > out_max) return SASL_BUFOVER; memcpy(out, user, ulen); out[ulen] = '\0'; From 7b0dca009518f5fcc2cfa9c2b7cac80ae1384ab8 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Mon, 18 Apr 2011 16:14:57 +0000 Subject: [PATCH 083/796] Added gs2_token.h for the make dist target (patch by Dan White) --- plugins/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/Makefile.am b/plugins/Makefile.am index 3ca32222..1d6f0e59 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -1,7 +1,7 @@ # Makefile.am for the SASL plugins # Rob Siemborski # Rob Earhart -# $Id: Makefile.am,v 1.83 2011/04/12 10:29:59 mel Exp $ +# $Id: Makefile.am,v 1.84 2011/04/18 16:14:57 mel Exp $ # ################################################################ # Copyright (c) 2000 Carnegie Mellon University. All rights reserved. @@ -80,7 +80,7 @@ libkerberos4_la_SOURCES = kerberos4.c kerberos4_init.c $(common_sources) libkerberos4_la_DEPENDENCIES = $(COMPAT_OBJS) libkerberos4_la_LIBADD = $(SASL_KRB_LIB) $(LIB_SOCKET) $(COMPAT_OBJS) -libgs2_la_SOURCES = gs2.c gs2_init.c gs2_token.c $(common_sources) +libgs2_la_SOURCES = gs2.c gs2_init.c gs2_token.c gs2_token.h $(common_sources) libgs2_la_DEPENDENCIES = $(COMPAT_OBJS) libgs2_la_LIBADD = $(GSSAPIBASE_LIBS) $(GSSAPI_LIBS) $(LIB_SOCKET) $(COMPAT_OBJS) From 95e05c68c718f6e5148a61c308b2546ad8944179 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Tue, 19 Apr 2011 09:19:18 +0000 Subject: [PATCH 084/796] Fix to build GSSAPI with Heimdal (patch from Russ Allbery from Debian) --- plugins/gssapi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/gssapi.c b/plugins/gssapi.c index c555a196..114ebedb 100644 --- a/plugins/gssapi.c +++ b/plugins/gssapi.c @@ -1,7 +1,7 @@ /* GSSAPI SASL plugin * Leif Johansson * Rob Siemborski (SASL v2 Conversion) - * $Id: gssapi.c,v 1.111 2010/10/26 11:08:02 mel Exp $ + * $Id: gssapi.c,v 1.112 2011/04/19 09:19:18 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -82,11 +82,11 @@ /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: gssapi.c,v 1.111 2010/10/26 11:08:02 mel Exp $"; +static const char plugin_id[] = "$Id: gssapi.c,v 1.112 2011/04/19 09:19:18 mel Exp $"; static const char * GSSAPI_BLANK_STRING = ""; -#ifndef HAVE_GSS_C_NT_HOSTBASED_SERVICE +#if !defined(HAVE_GSS_C_NT_HOSTBASED_SERVICE) && !defined(GSS_C_NT_HOSTBASED_SERVICE) extern gss_OID gss_nt_service_name; #define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name #endif From 883cfe1d71c5c8560d9f64743512f0967af66ff9 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Tue, 19 Apr 2011 09:31:10 +0000 Subject: [PATCH 085/796] Updated with the fixes in the last 2 weeks --- ChangeLog | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/ChangeLog b/ChangeLog index f8f086f7..1a4744e8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2011-04-19 Alexey Melnikov + * plugins/gssapi.c: Fix to build GSSAPI with Heimdal (patch from + Russ Allbery from Debian) + +2011-04-18 Alexey Melnikov + * plugins/gs2_token.h: Added gs2_token.h for the "make dist" target + (patch by Dan White) + +2011-04-13 Alexey Melnikov + * cmulocal/sasl2.m4: Only enable GS2 plugin if + gss_inquire_mech_for_saslname is defined in gssapi.h + +2011-04-12 Alexey Melnikov + * plugins/Makefile.am, plugins/makeinit.sh, plugins/ldapdb.c: + LDAPDB build fixes from Dan White + 2011-04-05 Alexey Melnikov * configure.in, plugins/Makefile.am, plugins/NTMakefile, plugins/makeinit.sh, lib/staticopen.h, win32/include/config.h: From 37a42016a6af56bfc73ccb494732d1e5d14d6534 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Tue, 19 Apr 2011 15:23:52 +0000 Subject: [PATCH 086/796] Added missing LIB_SQLITE3 (patch by Dan White) --- plugins/Makefile.am | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/Makefile.am b/plugins/Makefile.am index 1d6f0e59..d97c6790 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -1,7 +1,7 @@ # Makefile.am for the SASL plugins # Rob Siemborski # Rob Earhart -# $Id: Makefile.am,v 1.84 2011/04/18 16:14:57 mel Exp $ +# $Id: Makefile.am,v 1.85 2011/04/19 15:23:52 mel Exp $ # ################################################################ # Copyright (c) 2000 Carnegie Mellon University. All rights reserved. @@ -130,7 +130,8 @@ libldapdb_la_DEPENDENCIES = $(COMPAT_OBJS) libldapdb_la_LIBADD = $(LIB_LDAP) $(COMPAT_OBJS) libsql_la_SOURCES = sql.c sql_init.c $(common_sources) -libsql_la_LDFLAGS = $(LIB_MYSQL) $(LIB_PGSQL) $(LIB_SQLITE) $(AM_LDFLAGS) +libsql_la_LDFLAGS = $(LIB_MYSQL) $(LIB_PGSQL) $(LIB_SQLITE) $(LIB_SQLITE3) \ + $(AM_LDFLAGS) libsql_la_DEPENDENCIES = $(COMPAT_OBJS) libsql_la_LIBADD = $(COMPAT_OBJS) From b5a886db239ded54a0316c4421d98f349c0f0e26 Mon Sep 17 00:00:00 2001 From: Ken Murchison Date: Fri, 13 May 2011 19:16:32 +0000 Subject: [PATCH 087/796] was never committed with HTTP Digest client-side code --- sample/http_digest_client.c | 254 ++++++++++++++++++++++++++++++++++++ 1 file changed, 254 insertions(+) create mode 100644 sample/http_digest_client.c diff --git a/sample/http_digest_client.c b/sample/http_digest_client.c new file mode 100644 index 00000000..0e94f2a0 --- /dev/null +++ b/sample/http_digest_client.c @@ -0,0 +1,254 @@ +/* + * Cheesy HTTP 1.1 client used for testing HTTP Digest (RFC 2617) + * variant of DIGEST-MD5 plugin + * + * XXX This client REQUIRES a persistent connection and + * WILL NOT accept a body in any HTTP response + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#define SUCCESS 0 +#define ERROR 1 + +#define BUFFER_SIZE 8192 + +#define DIGEST_AUTH_HEADER "\r\nWWW-Authenticate: Digest " +#define DIGEST_OK_HEADER "\r\nAuthentication-Info: " + +void interact(sasl_interact_t *ilist) +{ + while (ilist->id != SASL_CB_LIST_END) { + switch (ilist->id) { + + case SASL_CB_AUTHNAME: /* auth as current uid */ + ilist->result = strdup(getpwuid(getuid())->pw_name); + break; + + case SASL_CB_PASS: /* prompt for password */ + printf("%s: ", ilist->prompt); + ilist->result = strdup(getpass("")); + break; + } + ilist->len = strlen(ilist->result); + + ilist++; + } +} + +int main(int argc __attribute__((unused)), char *argv[]) +{ + const char *hostname = "localhost"; + int port = 80; + + int sd, rc, status; + struct sockaddr_in localAddr, servAddr; + struct hostent *h; + + const char *sasl_impl, *sasl_ver; + sasl_conn_t *saslconn; + sasl_interact_t *interactions = NULL; + sasl_security_properties_t secprops = { 0, /* min SSF ("auth") */ + 1, /* max SSF ("auth-int") */ + 0, /* don't need maxbuf */ + 0, /* security flags */ + NULL, + NULL }; + sasl_http_request_t httpreq = { "HEAD", /* Method */ + "/", /* URI */ + (u_char *) "", /* Empty body */ + 0, /* Zero-length body */ + 0 }; /* Persistent cxn */ + sasl_callback_t callbacks[] = { + { SASL_CB_AUTHNAME, NULL, NULL }, + { SASL_CB_PASS, NULL, NULL }, + { SASL_CB_LIST_END, NULL, NULL } + }; + + const char *response = NULL; + unsigned int resplen = 0; + char buffer[BUFFER_SIZE+1], *request, *challenge, *p; + int i, code; + + printf("\n-- Hostname = %s , Port = %d , URI = %s\n", + hostname, port, httpreq.uri); + + h = gethostbyname(hostname); + if(h == NULL) { + printf("unknown host: %s \n ", hostname); + exit(ERROR); + } + + servAddr.sin_family = h->h_addrtype; + memcpy((char *) &servAddr.sin_addr.s_addr, h->h_addr_list[0], h->h_length); + servAddr.sin_port = htons(port); + + /* create socket */ + printf("-- Create socket... "); + sd = socket(AF_INET, SOCK_STREAM, 0); + if (sd < 0) { + perror("cannot open socket "); + exit(ERROR); + } + + /* bind port number */ + printf("Bind port number... "); + + localAddr.sin_family = AF_INET; + localAddr.sin_addr.s_addr = htonl(INADDR_ANY); + localAddr.sin_port = htons(0); + + rc = bind(sd, (struct sockaddr *) &localAddr, sizeof(localAddr)); + if (rc < 0) { + printf("%s: cannot bind port TCP %u\n",argv[0],port); + perror("error "); + exit(ERROR); + } + + /* connect to server */ + printf("Connect to server...\n"); + rc = connect(sd, (struct sockaddr *) &servAddr, sizeof(servAddr)); + if (rc < 0) { + perror("cannot connect "); + exit(ERROR); + } + + /* get SASL version info */ + sasl_version_info(&sasl_impl, &sasl_ver, NULL, NULL, NULL, NULL); + + /* initialize client-side of SASL */ + status = sasl_client_init(callbacks); + + /* request the URI twice, so we test both initial auth and reauth */ + for (i = 0; i < 2; i++) { + /* initialize a client exchange + * + * SASL_NEED_HTTP: forces HTTP Digest mode (REQUIRED) + * SASL_SUCCESS_DATA: HTTP supports success data in + * Authentication-Info header (REQUIRED) + */ + status = sasl_client_new("http", hostname, NULL, NULL, NULL, + SASL_NEED_HTTP | SASL_SUCCESS_DATA, &saslconn); + if (status != SASL_OK) { + perror("sasl_client_new() failed "); + exit(ERROR); + } + + /* Set security peoperties as specified above */ + sasl_setprop(saslconn, SASL_SEC_PROPS, &secprops); + + /* Set HTTP request as specified above (REQUIRED) */ + sasl_setprop(saslconn, SASL_HTTP_REQUEST, &httpreq); + + do { + /* start the Digest exchange */ + status = sasl_client_start(saslconn, "DIGEST-MD5", &interactions, + &response, &resplen, NULL); + if (status == SASL_INTERACT) interact(interactions); + } while (status == SASL_INTERACT); + + if ((status != SASL_OK) && (status != SASL_CONTINUE)) { + perror("sasl_client_start() failed "); + exit(ERROR); + } + + do { + /* send request (with Auth data if we have it ) */ + request = buffer; + request += sprintf(request, "%s %s HTTP/1.1\r\n", + httpreq.method, httpreq.uri); + request += sprintf(request, "Host: %s\r\n", hostname); + request += sprintf(request, "User-Agent: HTTP Digest Test Client" + " (%s/%s)\r\n", sasl_impl, sasl_ver); + request += sprintf(request, "Connection: keep-alive\r\n"); + request += sprintf(request, "Keep-Alive: 300\r\n"); + if (response) { + request += sprintf(request, "Authorization: Digest %s\r\n", + response); + } + request += sprintf(request, "\r\n"); + request = buffer; + + printf("\n-- Send HTTP request:\n\n%s", request); + rc = write(sd, request, strlen(request)); + if (rc < 0) { + perror("cannot send data "); + close(sd); + exit(ERROR); + } + + /* display response */ + printf("-- Received response:\n\tfrom server: http://%s%s, IP = %s,\n\n", + hostname, httpreq.uri, inet_ntoa(servAddr.sin_addr)); + rc = read(sd, buffer, BUFFER_SIZE); + if (rc <= 0) { + perror("cannot read data "); + close(sd); + exit(ERROR); + } + buffer[rc] = '\0'; + + printf("%s", buffer); + + /* get response code */ + sscanf(buffer, "HTTP/1.1 %d ", &code); + + if (code == 401) { + /* find Digest challenge */ + challenge = strstr(buffer, DIGEST_AUTH_HEADER); + if (!challenge) break; + challenge += strlen(DIGEST_AUTH_HEADER); + p = strchr(challenge, '\r'); + *p = '\0'; + + do { + /* do the next step in the exchange */ + status = sasl_client_step(saslconn, + challenge, strlen(challenge), + &interactions, + &response, &resplen); + if (status == SASL_INTERACT) interact(interactions); + } while (status == SASL_INTERACT); + + if ((status != SASL_OK) && (status != SASL_CONTINUE)) { + perror("sasl_client_step failed "); + exit(ERROR); + } + } + } while (code == 401); + + if ((code == 200) && (status == SASL_CONTINUE)) { + /* find Digest response */ + challenge = strstr(buffer, DIGEST_OK_HEADER); + if (challenge) { + challenge += strlen(DIGEST_OK_HEADER); + p = strchr(challenge, '\r'); + *p = '\0'; + + /* do the final step in the exchange (server auth) */ + status = sasl_client_step(saslconn, + challenge, strlen(challenge), + &interactions, &response, &resplen); + } + } + + sasl_dispose(&saslconn); + } + + sasl_client_done(); + + close(sd); + return SUCCESS; +} From bf4be43aca292f97eaa02f450fca803bf3a54f76 Mon Sep 17 00:00:00 2001 From: Ken Murchison Date: Fri, 13 May 2011 19:18:37 +0000 Subject: [PATCH 088/796] Allow for non-persistent connections when using DIGEST-MD5 plugin for server-side HTTP Digest (RFC 2617). Also make sure that an HTTP request is handed to plugin when required. --- ChangeLog | 6 ++++ include/sasl.h | 9 +++--- plugins/digestmd5.c | 75 +++++++++++++++++++++++++++++++++++---------- 3 files changed, 69 insertions(+), 21 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1a4744e8..2789d210 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-05-13 Ken Murchison + * include/sasl.h, plugins/digest-md5.c: + Allow for non-persistent connections when using DIGEST-MD5 plugin + for server-side HTTP Digest (RFC 2617). Also make sure that an + HTTP request is handed to plugin when required. + 2011-04-19 Alexey Melnikov * plugins/gssapi.c: Fix to build GSSAPI with Heimdal (patch from Russ Allbery from Debian) diff --git a/include/sasl.h b/include/sasl.h index cf5cc241..ef067071 100755 --- a/include/sasl.h +++ b/include/sasl.h @@ -838,10 +838,11 @@ typedef struct sasl_channel_binding { /* HTTP Request (RFC 2616) - ONLY used for HTTP Digest Auth (RFC 2617) */ typedef struct sasl_http_request { - const char *method; - const char *uri; - const unsigned char *entity; - unsigned long elen; + const char *method; /* HTTP Method */ + const char *uri; /* request-URI */ + const unsigned char *entity; /* entity-body */ + unsigned long elen; /* entity-body length */ + unsigned non_persist; /* Is it a non-persistent connection? */ } sasl_http_request_t; #define SASL_HTTP_REQUEST 22 diff --git a/plugins/digestmd5.c b/plugins/digestmd5.c index 64c6fae1..be1652c0 100644 --- a/plugins/digestmd5.c +++ b/plugins/digestmd5.c @@ -3,7 +3,7 @@ * Rob Siemborski * Tim Martin * Alexey Melnikov - * $Id: digestmd5.c,v 1.204 2011/01/25 20:36:42 murch Exp $ + * $Id: digestmd5.c,v 1.205 2011/05/13 19:18:37 murch Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -122,7 +122,7 @@ extern int gethostname(char *, int); /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: digestmd5.c,v 1.204 2011/01/25 20:36:42 murch Exp $"; +static const char plugin_id[] = "$Id: digestmd5.c,v 1.205 2011/05/13 19:18:37 murch Exp $"; /* Definitions */ #define NONCE_SIZE (32) /* arbitrary */ @@ -1786,7 +1786,7 @@ static char *create_response(context_t * text, memcpy(result, Response, HASHHEXLEN); result[HASHHEXLEN] = 0; - /* Calculate response value for mutal auth with the client (NO Method) */ + /* Calculate response value for mutual auth with the client (NO Method) */ if (response_value != NULL) { char * new_response_value; @@ -1899,6 +1899,12 @@ static int digestmd5_server_mech_new(void *glob_context, { context_t *text; + if ((sparams->flags & SASL_NEED_HTTP) && !sparams->http_request) { + SETERROR(sparams->utils, + "DIGEST-MD5 unavailable due to lack of HTTP request"); + return SASL_BADPARAM; + } + /* holds state are in -- allocate server size */ text = sparams->utils->malloc(sizeof(server_context_t)); if (text == NULL) @@ -2111,10 +2117,29 @@ digestmd5_server_mech_step1(server_context_t *stext, "internal error: out of memory when saving realm"); return SASL_FAIL; } - text->nonce = nonce; - text->nonce_count = 1; - text->cnonce = NULL; - stext->timestamp = time(0); + + if (text->http_mode && sparams->http_request->non_persist && + sparams->utils->mutex_lock(text->reauth->mutex) == SASL_OK) { /* LOCK */ + + /* Create an initial cache entry for non-persistent HTTP connections */ + unsigned val = hash((char *) nonce) % text->reauth->size; + + clear_reauth_entry(&text->reauth->e[val], SERVER, sparams->utils); + text->reauth->e[val].authid = NULL; + text->reauth->e[val].realm = text->realm; text->realm = NULL; + text->reauth->e[val].nonce = nonce; + text->reauth->e[val].nonce_count = 1; + text->reauth->e[val].cnonce = NULL; + text->reauth->e[val].u.s.timestamp = time(0); + + sparams->utils->mutex_unlock(text->reauth->mutex); /* UNLOCK */ + } + else { + text->nonce = nonce; + text->nonce_count = 1; + text->cnonce = NULL; + stext->timestamp = time(0); + } *serveroutlen = (unsigned) strlen(text->out_buf); *serverout = text->out_buf; @@ -2195,6 +2220,7 @@ static int digestmd5_server_mech_step2(server_context_t *stext, rfc2831_request.uri = NULL; /* to be filled in below from response */ rfc2831_request.entity = NULL; rfc2831_request.elen = 0; + rfc2831_request.non_persist = 0; request = &rfc2831_request; } @@ -2409,20 +2435,27 @@ static int digestmd5_server_mech_step2(server_context_t *stext, } if (text->state == 1) { - unsigned val = hash(username) % text->reauth->size; + unsigned val = hash((char *) nonce) % text->reauth->size; - /* reauth attempt, see if we have any info for this user */ + /* reauth attempt or continuation of HTTP Digest on a + non-persistent connection, see if we have any info for this nonce */ if (sparams->utils->mutex_lock(text->reauth->mutex) == SASL_OK) { /* LOCK */ - if (text->reauth->e[val].authid && - !strcmp(username, text->reauth->e[val].authid)) { + if (text->reauth->e[val].realm && + !strcmp(realm, text->reauth->e[val].realm) && + ((text->reauth->e[val].nonce_count == 1) || + (text->reauth->e[val].authid && + !strcmp(username, text->reauth->e[val].authid)))) { _plug_strdup(sparams->utils, text->reauth->e[val].realm, &text->realm, NULL); _plug_strdup(sparams->utils, (char *) text->reauth->e[val].nonce, (char **) &text->nonce, NULL); - text->nonce_count = ++text->reauth->e[val].nonce_count; + text->nonce_count = text->reauth->e[val].nonce_count; +#if 0 /* XXX Neither RFC 2617 nor RFC 2831 state that the cnonce + needs to remain constant for subsequent authentication to work */ _plug_strdup(sparams->utils, (char *) text->reauth->e[val].cnonce, (char **) &text->cnonce, NULL); +#endif stext->timestamp = text->reauth->e[val].u.s.timestamp; } sparams->utils->mutex_unlock(text->reauth->mutex); /* UNLOCK */ @@ -2431,7 +2464,7 @@ static int digestmd5_server_mech_step2(server_context_t *stext, if (!text->nonce) { /* we don't have any reauth info, so bail */ sparams->utils->log(sparams->utils->conn, SASL_LOG_DEBUG, - "No reauth info for '%s' found", username); + "No reauth info for '%s' found", nonce); result = SASL_FAIL; goto FreeAllMem; } @@ -2849,7 +2882,7 @@ static int digestmd5_server_mech_step2(server_context_t *stext, } if (add_to_challenge(sparams->utils, &text->out_buf, &text->out_buf_len, &resplen, - "qop", (unsigned char *) qop, FALSE) != SASL_OK) { + "qop", (unsigned char *) qop, TRUE) != SASL_OK) { result = SASL_FAIL; goto FreeAllMem; } @@ -2871,8 +2904,9 @@ static int digestmd5_server_mech_step2(server_context_t *stext, if (clientinlen > 0 && text->reauth->timeout && sparams->utils->mutex_lock(text->reauth->mutex) == SASL_OK) { /* LOCK */ - /* Look for an entry for our the username value as received */ - unsigned val = hash(username) % text->reauth->size; + + /* Look for an entry for the nonce value */ + unsigned val = hash((char *) nonce) % text->reauth->size; switch (result) { case SASL_OK: @@ -2890,7 +2924,7 @@ static int digestmd5_server_mech_step2(server_context_t *stext, clear_reauth_entry(&text->reauth->e[val], SERVER, sparams->utils); } else { - text->reauth->e[val].nonce_count = text->nonce_count; + text->reauth->e[val].nonce_count = ++text->nonce_count; text->reauth->e[val].u.s.timestamp = time(0); } break; @@ -3388,6 +3422,7 @@ static int make_client_response(context_t *text, rfc2831_request.uri = digesturi; rfc2831_request.entity = NULL; rfc2831_request.elen = 0; + rfc2831_request.non_persist = 0; request = &rfc2831_request; } @@ -4149,6 +4184,12 @@ static int digestmd5_client_mech_new(void *glob_context, { context_t *text; + if ((params->flags & SASL_NEED_HTTP) && !params->http_request) { + SETERROR(params->utils, + "DIGEST-MD5 unavailable due to lack of HTTP request"); + return SASL_BADPARAM; + } + /* holds state are in -- allocate client size */ text = params->utils->malloc(sizeof(client_context_t)); if (text == NULL) From 6a5b679755d525d086067e9681e1992c2e6d19a9 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Mon, 23 May 2011 14:45:40 +0000 Subject: [PATCH 089/796] Merge from Luke Howard: Use draft-josefsson-gss-capsulate-01 if present. Negative SASL errors are fatal. --- ChangeLog | 5 ++ plugins/gs2.c | 66 ++++++++-------- plugins/gs2_token.c | 182 +++++++++++++++++++++++++++++++++++--------- plugins/gs2_token.h | 41 ++++++---- 4 files changed, 205 insertions(+), 89 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2789d210..d1af176d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-05-23 Alexey Melnikov + * plugins/gs2.c, plugins/gs2_token.c, plugins/gs2_token.h, + cmulocal/sasl2.m4: Use draft-josefsson-gss-capsulate-01 if present. + Negative SASL errors are fatal. (Patch from Luke Howard.) + 2011-05-13 Ken Murchison * include/sasl.h, plugins/digest-md5.c: Allow for non-persistent connections when using DIGEST-MD5 plugin diff --git a/plugins/gs2.c b/plugins/gs2.c index 5afe7bbb..025f7fcf 100644 --- a/plugins/gs2.c +++ b/plugins/gs2.c @@ -539,7 +539,7 @@ gs2_server_mech_step(void *conn_context, sasl_gs2_seterror(text->utils, maj_stat, min_stat); ret = SASL_FAIL; } - if (ret != SASL_OK && ret != SASL_CONTINUE) + if (ret < SASL_OK) sasl_gs2_free_context_contents(text); return ret; @@ -842,7 +842,7 @@ static int gs2_client_mech_step(void *conn_context, sasl_gs2_seterror(text->utils, maj_stat, min_stat); ret = SASL_FAIL; } - if (ret != SASL_OK && ret != SASL_CONTINUE) + if (ret < SASL_OK) sasl_gs2_free_context_contents(text); return ret; @@ -1013,6 +1013,7 @@ gs2_verify_initial_message(context_t *text, unsigned inlen, gss_buffer_t token) { + OM_uint32 major, minor; char *p = (char *)in; unsigned remain = inlen; int ret; @@ -1088,32 +1089,29 @@ gs2_verify_initial_message(context_t *text, if (ret != SASL_OK) return ret; - buf.length = remain; - buf.value = p; - if (text->gs2_flags & GS2_NONSTD_FLAG) { - token->value = text->utils->malloc(buf.length); - if (token->value == NULL) - return SASL_NOMEM; - - token->length = buf.length; - memcpy(token->value, buf.value, buf.length); + buf.length = remain; + buf.value = p; } else { - unsigned int token_size; + gss_buffer_desc tmp; - /* create a properly formed GSS token */ - token_size = gs2_token_size(text->mechanism, buf.length); - token->value = text->utils->malloc(token_size); - if (token->value == NULL) + tmp.length = remain; + tmp.value = p; + + major = gss_encapsulate_token(&tmp, text->mechanism, &buf); + if (GSS_ERROR(major)) return SASL_NOMEM; + } + + token->value = text->utils->malloc(buf.length); + if (token->value == NULL) + return SASL_NOMEM; - token->length = token_size; + token->length = buf.length; + memcpy(token->value, buf.value, buf.length); - p = (char *)token->value; - gs2_make_token_header(text->mechanism, buf.length, - (unsigned char **)&p); - memcpy(p, buf.value, buf.length); - } + if ((text->gs2_flags & GS2_NONSTD_FLAG) == 0) + gss_release_buffer(&minor, &buf); return SASL_OK; } @@ -1231,36 +1229,32 @@ gs2_make_message(context_t *text, unsigned *outlen) { OM_uint32 major, minor; - unsigned char *mech_token_data; - size_t mech_token_size; - char *p; - unsigned header_len = 0; int ret; - - mech_token_size = token->length; - mech_token_data = (unsigned char *)token->value; + unsigned header_len = 0; + gss_buffer_desc decap_token = GSS_C_EMPTY_BUFFER; if (initialContextToken) { header_len = *outlen; - major = gs2_verify_token_header(&minor, text->mechanism, - &mech_token_size, &mech_token_data, - token->length); + major = gss_decapsulate_token(token, text->mechanism, &decap_token); if ((major == GSS_S_DEFECTIVE_TOKEN && (text->plug.client->features & SASL_FEAT_GSS_FRAMING)) || GSS_ERROR(major)) return SASL_FAIL; + + token = &decap_token; } ret = _plug_buf_alloc(text->utils, out, outlen, - header_len + mech_token_size); + header_len + token->length); if (ret != 0) return ret; - p = *out + header_len; - memcpy(p, mech_token_data, mech_token_size); + memcpy(*out + header_len, token->value, token->length); + *outlen = header_len + token->length; - *outlen = header_len + mech_token_size; + if (initialContextToken) + gss_release_buffer(&minor, &decap_token); return SASL_OK; } diff --git a/plugins/gs2_token.c b/plugins/gs2_token.c index c8c33aa4..2c492981 100644 --- a/plugins/gs2_token.c +++ b/plugins/gs2_token.c @@ -1,3 +1,34 @@ +/* + * Copyright (c) 2011, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ /* * Copyright 1993 by OpenVision Technologies, Inc. * @@ -20,14 +51,17 @@ * PERFORMANCE OF THIS SOFTWARE. */ +#include #include -#include +#include + #include "gs2_token.h" /* - * $Id: gs2_token.c,v 1.1 2011/03/25 11:54:49 mel Exp $ + * $Id: gs2_token.c,v 1.2 2011/05/23 14:45:40 mel Exp $ */ +#ifndef HAVE_GSS_ENCAPSULATE_TOKEN /* XXXX this code currently makes the assumption that a mech oid will never be longer than 127 bytes. This assumption is not inherent in the interfaces, so the code can be fixed if the OSI namespace @@ -95,6 +129,65 @@ der_write_length(unsigned char **buf, size_t length) } } +/* returns the length of a token, given the mech oid and the body size */ + +static size_t +token_size(const gss_OID_desc *mech, size_t body_size) +{ + /* set body_size to sequence contents size */ + body_size += 2 + (size_t) mech->length; /* NEED overflow check */ + return 1 + der_length_size(body_size) + body_size; +} + +/* fills in a buffer with the token header. The buffer is assumed to + be the right size. buf is advanced past the token header */ + +static void +make_token_header( + const gss_OID_desc *mech, + size_t body_size, + unsigned char **buf) +{ + *(*buf)++ = 0x60; + der_write_length(buf, 2 + mech->length + body_size); + *(*buf)++ = 0x06; + *(*buf)++ = (unsigned char)mech->length; + memcpy(*buf, mech->elements, mech->length); + *buf += mech->length; +} + +OM_uint32 +gs2_encapsulate_token(const gss_buffer_t input_token, + const gss_OID token_oid, + gss_buffer_t output_token) +{ + size_t tokenSize; + unsigned char *buf; + + if (input_token == GSS_C_NO_BUFFER || token_oid == GSS_C_NO_OID) + return GSS_S_CALL_INACCESSIBLE_READ; + + if (output_token == GSS_C_NO_BUFFER) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + tokenSize = token_size(token_oid, input_token->length); + + output_token->value = malloc(tokenSize); + if (output_token->value == NULL) + return GSS_S_FAILURE; + + buf = output_token->value; + + make_token_header(token_oid, input_token->length, &buf); + memcpy(buf, input_token->value, input_token->length); + output_token->length = tokenSize; + + return GSS_S_COMPLETE; +} +#endif + + +#ifndef HAVE_GSS_DECAPSULATE_TOKEN /* returns decoded length, or < 0 on failure. Advances buf and decrements bufsize */ @@ -126,33 +219,6 @@ der_read_length(unsigned char **buf, ssize_t *bufsize) return ret; } -/* returns the length of a token, given the mech oid and the body size */ - -size_t -gs2_token_size(const gss_OID_desc *mech, size_t body_size) -{ - /* set body_size to sequence contents size */ - body_size += 2 + (size_t) mech->length; /* NEED overflow check */ - return 1 + der_length_size(body_size) + body_size; -} - -/* fills in a buffer with the token header. The buffer is assumed to - be the right size. buf is advanced past the token header */ - -void -gs2_make_token_header( - const gss_OID_desc *mech, - size_t body_size, - unsigned char **buf) -{ - *(*buf)++ = 0x60; - der_write_length(buf, 2 + mech->length + body_size); - *(*buf)++ = 0x06; - *(*buf)++ = (unsigned char)mech->length; - memcpy(*buf, mech->elements, mech->length); - *buf += mech->length; -} - /* * Given a buffer containing a token, reads and verifies the token, * leaving buf advanced past the token header, and setting body_size @@ -162,12 +228,12 @@ gs2_make_token_header( * *body_size are left unmodified on error. */ -OM_uint32 -gs2_verify_token_header(OM_uint32 *minor, - gss_const_OID mech, - size_t *body_size, - unsigned char **buf_in, - size_t toksize_in) +static OM_uint32 +verify_token_header(OM_uint32 *minor, + const gss_OID mech, + size_t *body_size, + unsigned char **buf_in, + size_t toksize_in) { unsigned char *buf = *buf_in; ssize_t seqsize; @@ -206,11 +272,53 @@ gs2_verify_token_header(OM_uint32 *minor, toid.elements = buf; buf += toid.length; - if (!g_OID_equal(&toid, mech)) - return GSS_S_BAD_MECH; + if (!gss_oid_equal(&toid, mech)) + return GSS_S_DEFECTIVE_TOKEN; *buf_in = buf; *body_size = toksize; return GSS_S_COMPLETE; } + +OM_uint32 +gs2_decapsulate_token(const gss_buffer_t input_token, + const gss_OID token_oid, + gss_buffer_t output_token) +{ + OM_uint32 major, minor; + size_t body_size = 0; + unsigned char *buf_in; + + if (input_token == GSS_C_NO_BUFFER || token_oid == GSS_C_NO_OID) + return GSS_S_CALL_INACCESSIBLE_READ; + + if (output_token == GSS_C_NO_BUFFER) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + buf_in = input_token->value; + + major = verify_token_header(&minor, token_oid, &body_size, &buf_in, + input_token->length); + if (minor != 0) + return GSS_S_DEFECTIVE_TOKEN; + + output_token->value = malloc(body_size); + if (output_token->value == NULL) + return GSS_S_FAILURE; + + memcpy(output_token->value, buf_in, body_size); + output_token->length = body_size; + + return GSS_S_COMPLETE; +} +#endif + +#ifndef HAVE_GSS_OID_EQUAL +int +gs2_oid_equal(const gss_OID o1, const gss_OID o2) +{ + return o1->length == o2->length && + (memcmp(o1->elements, o2->elements, o1->length) == 0); +} +#endif diff --git a/plugins/gs2_token.h b/plugins/gs2_token.h index a83e2642..52cb3902 100644 --- a/plugins/gs2_token.h +++ b/plugins/gs2_token.h @@ -23,24 +23,33 @@ #ifndef _GS2_TOKEN_H_ #define _GS2_TOKEN_H_ 1 -#define g_OID_equal(o1, o2) \ - (((o1)->length == (o2)->length) && \ - (memcmp((o1)->elements, (o2)->elements, (o1)->length) == 0)) +#include -extern OM_uint32 -gs2_verify_token_header(OM_uint32 *minor, - gss_const_OID mech, - size_t *body_size, - unsigned char **buf_in, - size_t toksize_in); +#include +#ifdef HAVE_GSSAPI_GSSAPI_EXT_H +#include +#endif -extern void -gs2_make_token_header( - const gss_OID_desc *mech, - size_t body_size, - unsigned char **buf); +#ifndef HAVE_GSS_DECAPSULATE_TOKEN +OM_uint32 +gs2_decapsulate_token(const gss_buffer_t input_token, + const gss_OID token_oid, + gss_buffer_t output_token); +#define gss_decapsulate_token gs2_decapsulate_token +#endif -extern size_t -gs2_token_size(const gss_OID_desc *mech, size_t body_size); +#ifndef HAVE_GSS_ENCAPSULATE_TOKEN +OM_uint32 +gs2_encapsulate_token(const gss_buffer_t input_token, + const gss_OID token_oid, + gss_buffer_t output_token); +#define gss_encapsulate_token gs2_encapsulate_token +#endif + +#ifndef HAVE_GSS_OID_EQUAL +int +gs2_oid_equal(const gss_OID o1, const gss_OID o2); +#define gss_oid_equal gs2_oid_equal +#endif #endif /* _GS2_TOKEN_H_ */ From 175ecd9c51a8c93074fceaeb0ce64e34c334f695 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Thu, 1 Sep 2011 12:18:05 +0000 Subject: [PATCH 090/796] Better server plugin API mismatch reporting --- lib/server.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/server.c b/lib/server.c index cca2c2b6..a32d451a 100644 --- a/lib/server.c +++ b/lib/server.c @@ -1,7 +1,7 @@ /* SASL server API implementation * Rob Siemborski * Tim Martin - * $Id: server.c,v 1.171 2011/01/21 15:19:36 mel Exp $ + * $Id: server.c,v 1.172 2011/09/01 12:18:05 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -447,8 +447,11 @@ int sasl_server_add_plugin(const char *plugname, /* Make sure plugin is using the same SASL version as us */ if (version != SASL_SERVER_PLUG_VERSION) { - _sasl_log(NULL, SASL_LOG_ERR, - "version mismatch on plugin"); + _sasl_log(NULL, + SASL_LOG_ERR, + "version mismatch on plugin: %d expected, but %d reported", + SASL_SERVER_PLUG_VERSION, + version); return SASL_BADVERS; } From 7c78c9e3ded9b7e3565e7b63fbc05f903295347c Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Thu, 1 Sep 2011 14:12:18 +0000 Subject: [PATCH 091/796] Fixed GCC warnings about function pointers not being prototypes (patch by Dave Cridland) --- include/md5.h | 7 +++---- include/sasl.h | 2 +- include/saslplug.h | 31 ++++++++++++++++--------------- lib/auxprop.c | 8 +++++--- lib/canonusr.c | 6 +++--- lib/client.c | 6 +++--- lib/common.c | 30 +++++++++++++++--------------- lib/saslint.h | 4 ++-- lib/server.c | 18 +++++++++--------- lib/seterror.c | 6 +++--- plugins/otp.c | 6 +++--- plugins/plugin_common.c | 10 +++++----- sample/sample-client.c | 19 ++++++++++--------- sample/sample-server.c | 7 ++++--- sasldb/db_berkeley.c | 4 ++-- utils/pluginviewer.c | 8 ++++---- utils/sasldblistusers.c | 4 ++-- utils/saslpasswd.c | 2 +- utils/testsuite.c | 24 +++++++++++------------- 19 files changed, 102 insertions(+), 100 deletions(-) diff --git a/include/md5.h b/include/md5.h index 15b46ea5..2f3745dc 100644 --- a/include/md5.h +++ b/include/md5.h @@ -33,10 +33,9 @@ typedef struct { extern "C" { #endif -void _sasl_MD5Init PROTO_LIST ((MD5_CTX *)); -void _sasl_MD5Update PROTO_LIST - ((MD5_CTX *, const unsigned char *, unsigned int)); -void _sasl_MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *)); +void _sasl_MD5Init (MD5_CTX *); +void _sasl_MD5Update (MD5_CTX *, const unsigned char *, unsigned int); +void _sasl_MD5Final (unsigned char [16], MD5_CTX *); #ifdef __cplusplus } diff --git a/include/sasl.h b/include/sasl.h index ef067071..6bdf2d3c 100755 --- a/include/sasl.h +++ b/include/sasl.h @@ -353,7 +353,7 @@ typedef struct sasl_callback { * Mechanisms must ignore callbacks with id's they don't recognize. */ unsigned long id; - int (*proc)(); /* Callback function. Types of arguments vary by 'id' */ + int (*proc)(void); /* Callback function. Types of arguments vary by 'id' */ void *context; } sasl_callback_t; diff --git a/include/saslplug.h b/include/saslplug.h index 00e26719..29302e8d 100755 --- a/include/saslplug.h +++ b/include/saslplug.h @@ -33,9 +33,10 @@ extern "C" { * SASL_FAIL -- unable to find a callback of the requested type * SASL_INTERACT -- caller must use interaction to get data */ +typedef int (*sasl_callback_ft)(void); typedef int sasl_getcallback_t(sasl_conn_t *conn, unsigned long callbackid, - int (**pproc)(), + sasl_callback_ft * pproc, void **pcontext); /* The sasl_utils structure will remain backwards compatible unless @@ -132,7 +133,7 @@ typedef struct sasl_utils { void (*seterror)(sasl_conn_t *conn, unsigned flags, const char *fmt, ...); /* spare function pointer */ - int *(*spare_fptr)(); + int *(*spare_fptr)(void); /* auxiliary property utilities */ struct propctx *(*prop_new)(unsigned estimate); @@ -154,8 +155,8 @@ typedef struct sasl_utils { struct propctx *ctx, const char *user); /* for additions which don't require a version upgrade; set to 0 */ - int (*spare_fptr1)(); - int (*spare_fptr2)(); + int (*spare_fptr1)(void); + int (*spare_fptr2)(void); } sasl_utils_t; /* @@ -196,8 +197,8 @@ typedef struct sasl_out_params { const void *gss_peer_name; const void *gss_local_name; const char *cbindingname; /* channel binding name from packet */ - int (*spare_fptr1)(); - int (*spare_fptr2)(); + int (*spare_fptr1)(void); + int (*spare_fptr2)(void); unsigned int cbindingdisp; /* channel binding disposition from client */ int spare_int2; int spare_int3; @@ -301,7 +302,7 @@ typedef struct sasl_client_params { unsigned flags, sasl_out_params_t *oparams); - int (*spare_fptr1)(); + int (*spare_fptr1)(void); unsigned int cbindingdisp; int spare_int2; @@ -429,8 +430,8 @@ typedef struct sasl_client_plug { sasl_client_params_t *cparams); /* for additions which don't require a version upgrade; set to 0 */ - int (*spare_fptr1)(); - int (*spare_fptr2)(); + int (*spare_fptr1)(void); + int (*spare_fptr2)(void); } sasl_client_plug_t; #define SASL_CLIENT_PLUG_VERSION 4 @@ -582,8 +583,8 @@ typedef struct sasl_server_params { const sasl_channel_binding_t *cbinding; /* server channel binding */ const sasl_http_request_t *http_request;/* HTTP Digest request method */ void *spare_ptr4; - int (*spare_fptr1)(); - int (*spare_fptr2)(); + int (*spare_fptr1)(void); + int (*spare_fptr2)(void); int spare_int1; int spare_int2; int spare_int3; @@ -767,7 +768,7 @@ typedef struct sasl_server_plug { void **conn_context); /* for additions which don't require a version upgrade; set to 0 */ - int (*spare_fptr2)(); + int (*spare_fptr2)(void); } sasl_server_plug_t; #define SASL_SERVER_PLUG_VERSION 4 @@ -873,9 +874,9 @@ typedef struct sasl_canonuser { unsigned out_max, unsigned *out_len); /* for additions which don't require a version upgrade; set to 0 */ - int (*spare_fptr1)(); - int (*spare_fptr2)(); - int (*spare_fptr3)(); + int (*spare_fptr1)(void); + int (*spare_fptr2)(void); + int (*spare_fptr3)(void); } sasl_canonuser_plug_t; #define SASL_CANONUSER_PLUG_VERSION 5 diff --git a/lib/auxprop.c b/lib/auxprop.c index eb371b03..0644e5fb 100644 --- a/lib/auxprop.c +++ b/lib/auxprop.c @@ -1,6 +1,6 @@ /* auxprop.c - auxilliary property support * Rob Siemborski - * $Id: auxprop.c,v 1.20 2011/01/19 09:04:29 mel Exp $ + * $Id: auxprop.c,v 1.21 2011/09/01 14:12:53 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -913,7 +913,9 @@ int _sasl_auxprop_lookup(sasl_server_params_t *sparams, int result = SASL_NOMECH; if(_sasl_getcallback(sparams->utils->conn, - SASL_CB_GETOPT, &getopt, &context) == SASL_OK) { + SASL_CB_GETOPT, + (sasl_callback_ft *)&getopt, + &context) == SASL_OK) { ret = getopt(context, NULL, "auxprop_plugin", &plist, NULL); if(ret != SASL_OK) plist = NULL; } @@ -999,7 +1001,7 @@ int sasl_auxprop_store(sasl_conn_t *conn, } /* Pickup getopt callback from the connection, if conn is not NULL */ - if(_sasl_getcallback(conn, SASL_CB_GETOPT, &getopt, &context) == SASL_OK) { + if(_sasl_getcallback(conn, SASL_CB_GETOPT, (sasl_callback_ft *)&getopt, &context) == SASL_OK) { ret = getopt(context, NULL, "auxprop_plugin", &plist, NULL); if(ret != SASL_OK) plist = NULL; } diff --git a/lib/canonusr.c b/lib/canonusr.c index 7f994b48..8ed49811 100644 --- a/lib/canonusr.c +++ b/lib/canonusr.c @@ -1,6 +1,6 @@ /* canonusr.c - user canonicalization support * Rob Siemborski - * $Id: canonusr.c,v 1.20 2009/03/10 16:27:52 mel Exp $ + * $Id: canonusr.c,v 1.21 2011/09/01 14:12:53 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -102,7 +102,7 @@ int _sasl_canon_user(sasl_conn_t *conn, /* check to see if we have a callback to make*/ result = _sasl_getcallback(conn, SASL_CB_CANON_USER, - &cuser_cb, &context); + (sasl_callback_ft *)&cuser_cb, &context); if(result == SASL_OK && cuser_cb) { result = cuser_cb(conn, context, user, ulen, @@ -121,7 +121,7 @@ int _sasl_canon_user(sasl_conn_t *conn, /* which plugin are we supposed to use? */ result = _sasl_getcallback(conn, SASL_CB_GETOPT, - &getopt, &context); + (sasl_callback_ft *)&getopt, &context); if(result == SASL_OK && getopt) { getopt(context, NULL, "canon_user_plugin", &plugin_name, NULL); } diff --git a/lib/client.c b/lib/client.c index 9ec49e87..a6cc7ab8 100644 --- a/lib/client.c +++ b/lib/client.c @@ -1,7 +1,7 @@ /* SASL client API implementation * Rob Siemborski * Tim Martin - * $Id: client.c,v 1.85 2011/01/25 20:36:42 murch Exp $ + * $Id: client.c,v 1.86 2011/09/01 14:12:53 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -437,7 +437,7 @@ int sasl_client_new(const char *service, utils->conn= *pconn; conn->cparams->utils = utils; - if(_sasl_getcallback(*pconn, SASL_CB_GETOPT, (sasl_callback_t *)&getopt, &context) == SASL_OK) { + if(_sasl_getcallback(*pconn, SASL_CB_GETOPT, (sasl_callback_ft *)&getopt, &context) == SASL_OK) { getopt(context, NULL, "client_mech_list", &mlist, NULL); } @@ -530,7 +530,7 @@ static int have_prompts(sasl_conn_t *conn, }; const unsigned long *prompt; - int (*pproc)(); + sasl_callback_ft pproc; void *pcontext; int result; diff --git a/lib/common.c b/lib/common.c index 6d8bdb93..8977c1e7 100644 --- a/lib/common.c +++ b/lib/common.c @@ -1,7 +1,7 @@ /* common.c - Functions that are common to server and clinet * Rob Siemborski * Tim Martin - * $Id: common.c,v 1.132 2011/01/25 20:36:42 murch Exp $ + * $Id: common.c,v 1.133 2011/09/01 14:12:53 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -113,10 +113,10 @@ int _sasl_allocation_locked = 0; /* Default getpath/getconfpath callbacks. These can be edited by sasl_set_path(). */ static sasl_callback_t default_getpath_cb = { - SASL_CB_GETPATH, &_sasl_getpath, NULL + SASL_CB_GETPATH, (sasl_callback_ft)&_sasl_getpath, NULL }; static sasl_callback_t default_getconfpath_cb = { - SASL_CB_GETCONFPATH, &_sasl_getconfpath, NULL + SASL_CB_GETCONFPATH, (sasl_callback_ft)&_sasl_getconfpath, NULL }; static char * default_plugin_path = NULL; @@ -229,7 +229,7 @@ int sasl_set_path (int path_type, char * path) } /* Update the default getpath_t callback */ - default_getpath_cb.proc = (int (*)()) &_sasl_getpath_simple; + default_getpath_cb.proc = (sasl_callback_ft)&_sasl_getpath_simple; break; case SASL_PATH_TYPE_CONFIG: @@ -243,7 +243,7 @@ int sasl_set_path (int path_type, char * path) } /* Update the default getpath_t callback */ - default_getconfpath_cb.proc = (int (*)()) &_sasl_getconfpath_simple; + default_getconfpath_cb.proc = (sasl_callback_ft)&_sasl_getconfpath_simple; break; default: @@ -913,7 +913,7 @@ int sasl_getprop(sasl_conn_t *conn, int propnum, const void **pvalue) *(unsigned **)pvalue = &conn->oparams.maxoutbuf; break; case SASL_GETOPTCTX: - result = _sasl_getcallback(conn, SASL_CB_GETOPT, &getopt, &context); + result = _sasl_getcallback(conn, SASL_CB_GETOPT, (sasl_callback_ft *)&getopt, &context); if(result != SASL_OK) break; *(void **)pvalue = context; @@ -1710,7 +1710,7 @@ _sasl_proxy_policy(sasl_conn_t *conn, int _sasl_getcallback(sasl_conn_t * conn, unsigned long callbackid, - int (**pproc)(), + sasl_callback_ft *pproc, void **pcontext) { const sasl_callback_t *callback; @@ -1725,10 +1725,10 @@ int _sasl_getcallback(sasl_conn_t * conn, INTERROR(conn, SASL_FAIL); case SASL_CB_GETOPT: if (conn) { - *pproc = &_sasl_conn_getopt; + *pproc = (sasl_callback_ft)&_sasl_conn_getopt; *pcontext = conn; } else { - *pproc = &_sasl_global_getopt; + *pproc = (sasl_callback_ft)&_sasl_global_getopt; *pcontext = NULL; } return SASL_OK; @@ -1773,7 +1773,7 @@ int _sasl_getcallback(sasl_conn_t * conn, switch (callbackid) { #ifdef HAVE_SYSLOG case SASL_CB_LOG: - *pproc = (int (*)()) &_sasl_syslog; + *pproc = (sasl_callback_ft)&_sasl_syslog; *pcontext = conn; return SASL_OK; #endif /* HAVE_SYSLOG */ @@ -1786,15 +1786,15 @@ int _sasl_getcallback(sasl_conn_t * conn, *pcontext = default_getconfpath_cb.context; return SASL_OK; case SASL_CB_AUTHNAME: - *pproc = (int (*)()) &_sasl_getsimple; + *pproc = (sasl_callback_ft)&_sasl_getsimple; *pcontext = conn; return SASL_OK; case SASL_CB_VERIFYFILE: - *pproc = & _sasl_verifyfile; + *pproc = (sasl_callback_ft)&_sasl_verifyfile; *pcontext = NULL; return SASL_OK; case SASL_CB_PROXY_POLICY: - *pproc = (int (*)()) &_sasl_proxy_policy; + *pproc = (sasl_callback_ft)&_sasl_proxy_policy; *pcontext = NULL; return SASL_OK; } @@ -1842,7 +1842,7 @@ _sasl_log (sasl_conn_t *conn, formatlen = strlen(fmt); /* See if we have a logging callback... */ - result = _sasl_getcallback(conn, SASL_CB_LOG, &log_cb, &log_ctx); + result = _sasl_getcallback(conn, SASL_CB_LOG, (sasl_callback_ft *)&log_cb, &log_ctx); if (result == SASL_OK && ! log_cb) result = SASL_FAIL; if (result != SASL_OK) goto done; @@ -2150,7 +2150,7 @@ _sasl_find_verifyfile_callback(const sasl_callback_t *callbacks) { static const sasl_callback_t default_verifyfile_cb = { SASL_CB_VERIFYFILE, - &_sasl_verifyfile, + (sasl_callback_ft)&_sasl_verifyfile, NULL }; diff --git a/lib/saslint.h b/lib/saslint.h index 8c7bca00..7643e298 100644 --- a/lib/saslint.h +++ b/lib/saslint.h @@ -1,7 +1,7 @@ /* saslint.h - internal SASL library definitions * Rob Siemborski * Tim Martin - * $Id: saslint.h,v 1.72 2011/01/21 15:19:36 mel Exp $ + * $Id: saslint.h,v 1.73 2011/09/01 14:12:53 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -404,7 +404,7 @@ extern int _sasl_free_utils(const sasl_utils_t ** utils); extern int _sasl_getcallback(sasl_conn_t * conn, unsigned long callbackid, - int (**pproc)(), + sasl_callback_ft * pproc, void **pcontext); extern void diff --git a/lib/server.c b/lib/server.c index a32d451a..3e0be89d 100644 --- a/lib/server.c +++ b/lib/server.c @@ -1,7 +1,7 @@ /* SASL server API implementation * Rob Siemborski * Tim Martin - * $Id: server.c,v 1.172 2011/09/01 12:18:05 mel Exp $ + * $Id: server.c,v 1.173 2011/09/01 14:12:53 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -200,7 +200,7 @@ int sasl_setpass(sasl_conn_t *conn, /* call userdb callback function */ tmpresult = _sasl_getcallback(conn, SASL_CB_SERVER_USERDB_SETPASS, - &setpass_cb, &context); + (sasl_callback_ft *)&setpass_cb, &context); if (tmpresult == SASL_OK && setpass_cb) { tried_setpass++; @@ -889,7 +889,7 @@ int sasl_server_init(const sasl_callback_t *callbacks, #ifdef PIC /* delayed loading of plugins? (DSO only, as it doesn't * make much [any] sense to delay in the static library case) */ - if (_sasl_getcallback(NULL, SASL_CB_GETOPT, &getopt, &context) + if (_sasl_getcallback(NULL, SASL_CB_GETOPT, (sasl_callback_ft *)&getopt, &context) == SASL_OK) { /* No sasl_conn_t was given to getcallback, so we provide the * global callbacks structure */ @@ -958,7 +958,7 @@ _sasl_transition(sasl_conn_t * conn, PARAMERROR(conn); /* check if this is enabled: default to false */ - if (_sasl_getcallback(conn, SASL_CB_GETOPT, &getopt, &context) == SASL_OK) + if (_sasl_getcallback(conn, SASL_CB_GETOPT, (sasl_callback_ft *)&getopt, &context) == SASL_OK) { getopt(context, NULL, "auto_transition", &dotrans, NULL); if (dotrans == NULL) dotrans = "n"; @@ -1099,7 +1099,7 @@ int sasl_server_new(const char *service, serverconn->sparams->callbacks = callbacks; log_level = auto_trans = NULL; - if(_sasl_getcallback(*pconn, SASL_CB_GETOPT, &getopt, &context) == SASL_OK) { + if(_sasl_getcallback(*pconn, SASL_CB_GETOPT, (sasl_callback_ft *)&getopt, &context) == SASL_OK) { getopt(context, NULL, "log_level", &log_level, NULL); getopt(context, NULL, "auto_transition", &auto_trans, NULL); getopt(context, NULL, "mech_list", &mlist, NULL); @@ -1334,7 +1334,7 @@ static int do_authorization(sasl_server_conn_t *s_conn) /* check the proxy callback */ if (_sasl_getcallback(&s_conn->base, SASL_CB_PROXY_POLICY, - &authproc, &auth_context) != SASL_OK) { + (sasl_callback_ft *)&authproc, &auth_context) != SASL_OK) { INTERROR(&s_conn->base, SASL_NOAUTHZ); } @@ -1874,7 +1874,7 @@ static int _sasl_checkpass(sasl_conn_t *conn, /* call userdb callback function, if available */ result = _sasl_getcallback(conn, SASL_CB_SERVER_USERDB_CHECKPASS, - &checkpass_cb, &context); + (sasl_callback_ft *)&checkpass_cb, &context); if(result == SASL_OK && checkpass_cb) { result = checkpass_cb(conn, context, user, pass, passlen, s_conn->sparams->propctx); @@ -1883,7 +1883,7 @@ static int _sasl_checkpass(sasl_conn_t *conn, } /* figure out how to check (i.e. auxprop or saslauthd or pwcheck) */ - if (_sasl_getcallback(conn, SASL_CB_GETOPT, &getopt, &context) + if (_sasl_getcallback(conn, SASL_CB_GETOPT, (sasl_callback_ft *)&getopt, &context) == SASL_OK) { getopt(context, NULL, "pwcheck_method", &mlist, NULL); } @@ -2007,7 +2007,7 @@ int sasl_user_exists(sasl_conn_t *conn, if(!service) service = conn->service; /* figure out how to check (i.e. auxprop or saslauthd or pwcheck) */ - if (_sasl_getcallback(conn, SASL_CB_GETOPT, &getopt, &context) + if (_sasl_getcallback(conn, SASL_CB_GETOPT, (sasl_callback_ft *)&getopt, &context) == SASL_OK) { getopt(context, NULL, "pwcheck_method", &mlist, NULL); } diff --git a/lib/seterror.c b/lib/seterror.c index 5980ea7c..54300f55 100644 --- a/lib/seterror.c +++ b/lib/seterror.c @@ -3,7 +3,7 @@ * Rob Siemborski * Tim Martin * split from common.c by Rolf Braun - * $Id: seterror.c,v 1.9 2003/12/12 17:30:18 rjs3 Exp $ + * $Id: seterror.c,v 1.10 2011/09/01 14:12:53 mel Exp $ */ /* @@ -120,7 +120,7 @@ void sasl_seterror(sasl_conn_t *conn, #ifndef SASL_OSX_CFMGLUE if(!(flags & SASL_NOLOG)) { /* See if we have a logging callback... */ - result = _sasl_getcallback(NULL, SASL_CB_LOG, &log_cb, &log_ctx); + result = _sasl_getcallback(NULL, SASL_CB_LOG, (sasl_callback_ft *)&log_cb, &log_ctx); if (result == SASL_OK && ! log_cb) result = SASL_FAIL; if (result != SASL_OK) @@ -251,7 +251,7 @@ void sasl_seterror(sasl_conn_t *conn, #ifndef SASL_OSX_CFMGLUE if(!(flags & SASL_NOLOG)) { /* See if we have a logging callback... */ - result = _sasl_getcallback(conn, SASL_CB_LOG, &log_cb, &log_ctx); + result = _sasl_getcallback(conn, SASL_CB_LOG, (sasl_callback_ft *)&log_cb, &log_ctx); if (result == SASL_OK && ! log_cb) result = SASL_FAIL; if (result != SASL_OK) diff --git a/plugins/otp.c b/plugins/otp.c index 58e01a31..255a6bcf 100644 --- a/plugins/otp.c +++ b/plugins/otp.c @@ -1,6 +1,6 @@ /* OTP SASL plugin * Ken Murchison - * $Id: otp.c,v 1.42 2010/11/30 11:41:47 mel Exp $ + * $Id: otp.c,v 1.43 2011/09/01 14:12:18 mel Exp $ */ /* * Copyright (c) 1998-2009 Carnegie Mellon University. All rights reserved. @@ -68,7 +68,7 @@ /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: otp.c,v 1.42 2010/11/30 11:41:47 mel Exp $"; +static const char plugin_id[] = "$Id: otp.c,v 1.43 2011/09/01 14:12:18 mel Exp $"; #define OTP_SEQUENCE_MAX 9999 #define OTP_SEQUENCE_DEFAULT 499 @@ -1527,7 +1527,7 @@ static int otp_client_mech_step1(client_context_t *text, /* try to get the secret pass-phrase if we don't have a chalprompt */ if ((params->utils->getcallback(params->utils->conn, SASL_CB_ECHOPROMPT, - &echo_cb, &echo_context) == SASL_FAIL) && + (sasl_callback_ft *)&echo_cb, &echo_context) == SASL_FAIL) && (text->password == NULL)) { pass_result = _plug_get_password(params->utils, &text->password, &text->free_password, prompt_need); diff --git a/plugins/plugin_common.c b/plugins/plugin_common.c index 45d83e90..741c3d7b 100644 --- a/plugins/plugin_common.c +++ b/plugins/plugin_common.c @@ -1,6 +1,6 @@ /* Generic SASL plugin utility functions * Rob Siemborski - * $Id: plugin_common.c,v 1.21 2008/10/29 13:10:38 mel Exp $ + * $Id: plugin_common.c,v 1.22 2011/09/01 14:12:18 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -343,7 +343,7 @@ int _plug_get_simple(const sasl_utils_t *utils, unsigned int id, int required, } /* Try to get the callback... */ - ret = utils->getcallback(utils->conn, id, &simple_cb, &simple_context); + ret = utils->getcallback(utils->conn, id, (sasl_callback_ft *)&simple_cb, &simple_context); if (ret == SASL_FAIL && !required) return SASL_OK; @@ -405,7 +405,7 @@ int _plug_get_password(const sasl_utils_t *utils, sasl_secret_t **password, /* Try to get the callback... */ ret = utils->getcallback(utils->conn, SASL_CB_PASS, - &pass_cb, &pass_context); + (sasl_callback_ft *)&pass_cb, &pass_context); if (ret == SASL_OK && pass_cb) { ret = pass_cb(utils->conn, pass_context, SASL_CB_PASS, password); @@ -451,7 +451,7 @@ int _plug_challenge_prompt(const sasl_utils_t *utils, unsigned int id, /* Try to get the callback... */ ret = utils->getcallback(utils->conn, id, - &chalprompt_cb, &chalprompt_context); + (sasl_callback_ft *)&chalprompt_cb, &chalprompt_context); if (ret == SASL_OK && chalprompt_cb) { ret = chalprompt_cb(chalprompt_context, id, @@ -497,7 +497,7 @@ int _plug_get_realm(const sasl_utils_t *utils, const char **availrealms, /* Try to get the callback... */ ret = utils->getcallback(utils->conn, SASL_CB_GETREALM, - &realm_cb, &realm_context); + (sasl_callback_ft *)&realm_cb, &realm_context); if (ret == SASL_OK && realm_cb) { ret = realm_cb(realm_context, SASL_CB_GETREALM, availrealms, realm); diff --git a/sample/sample-client.c b/sample/sample-client.c index 7a962a66..5de7e079 100644 --- a/sample/sample-client.c +++ b/sample/sample-client.c @@ -1,6 +1,6 @@ /* sample-client.c -- sample SASL client * Rob Earhart - * $Id: sample-client.c,v 1.32 2009/05/04 21:35:51 mel Exp $ + * $Id: sample-client.c,v 1.33 2011/09/01 14:12:18 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -55,6 +55,7 @@ __declspec(dllimport) int getsubopt(char **optionp, const char * const *tokens, # include #endif /* WIN32 */ #include +#include #include #ifdef macintosh @@ -653,14 +654,14 @@ main(int argc, char *argv[]) /* log */ callback->id = SASL_CB_LOG; - callback->proc = &sasl_my_log; + callback->proc = (sasl_callback_ft)&sasl_my_log; callback->context = NULL; ++callback; /* getpath */ if (searchpath) { callback->id = SASL_CB_GETPATH; - callback->proc = &getpath; + callback->proc = (sasl_callback_ft)&getpath; callback->context = searchpath; ++callback; } @@ -668,7 +669,7 @@ main(int argc, char *argv[]) /* user */ if (userid) { callback->id = SASL_CB_USER; - callback->proc = &simple; + callback->proc = (sasl_callback_ft)&simple; callback->context = userid; ++callback; } @@ -676,7 +677,7 @@ main(int argc, char *argv[]) /* authname */ if (authid) { callback->id = SASL_CB_AUTHNAME; - callback->proc = &simple; + callback->proc = (sasl_callback_ft)&simple; callback->context = authid; ++callback; } @@ -684,26 +685,26 @@ main(int argc, char *argv[]) if (realm!=NULL) { callback->id = SASL_CB_GETREALM; - callback->proc = &getrealm; + callback->proc = (sasl_callback_ft)&getrealm; callback->context = realm; callback++; } /* password */ callback->id = SASL_CB_PASS; - callback->proc = &getsecret; + callback->proc = (sasl_callback_ft)&getsecret; callback->context = NULL; ++callback; /* echoprompt */ callback->id = SASL_CB_ECHOPROMPT; - callback->proc = &prompt; + callback->proc = (sasl_callback_ft)&prompt; callback->context = NULL; ++callback; /* noechoprompt */ callback->id = SASL_CB_NOECHOPROMPT; - callback->proc = &prompt; + callback->proc = (sasl_callback_ft)&prompt; callback->context = NULL; ++callback; diff --git a/sample/sample-server.c b/sample/sample-server.c index db13d55c..0da3de02 100644 --- a/sample/sample-server.c +++ b/sample/sample-server.c @@ -1,6 +1,6 @@ /* sample-server.c -- sample SASL server * Rob Earhart - * $Id: sample-server.c,v 1.33 2009/05/04 21:35:51 mel Exp $ + * $Id: sample-server.c,v 1.34 2011/09/01 14:12:18 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -63,6 +63,7 @@ __declspec(dllimport) int getsubopt(char **optionp, const char * const *tokens, # include #endif /* WIN32 */ #include +#include #include #ifndef HAVE_GETSUBOPT @@ -185,9 +186,9 @@ getpath(void *context __attribute__((unused)), static sasl_callback_t callbacks[] = { { - SASL_CB_LOG, &sasl_my_log, NULL + SASL_CB_LOG, (sasl_callback_ft)&sasl_my_log, NULL }, { - SASL_CB_GETPATH, &getpath, NULL + SASL_CB_GETPATH, (sasl_callback_ft)&getpath, NULL }, { SASL_CB_LIST_END, NULL, NULL } diff --git a/sasldb/db_berkeley.c b/sasldb/db_berkeley.c index 0bd6953f..8f0b4f27 100644 --- a/sasldb/db_berkeley.c +++ b/sasldb/db_berkeley.c @@ -1,7 +1,7 @@ /* db_berkeley.c--SASL berkeley db interface * Rob Siemborski * Tim Martin - * $Id: db_berkeley.c,v 1.9 2008/10/23 19:24:46 mel Exp $ + * $Id: db_berkeley.c,v 1.10 2011/09/01 14:12:18 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -377,7 +377,7 @@ int _sasl_check_db(const sasl_utils_t *utils, } ret = utils->getcallback(conn, SASL_CB_VERIFYFILE, - &vf, &cntxt); + (sasl_callback_ft *)&vf, &cntxt); if (ret != SASL_OK) { utils->seterror(conn, 0, "verifyfile failed"); return ret; diff --git a/utils/pluginviewer.c b/utils/pluginviewer.c index c257f795..3164acdc 100644 --- a/utils/pluginviewer.c +++ b/utils/pluginviewer.c @@ -1,7 +1,7 @@ /* pluginviewer.c -- Plugin Viewer for CMU SASL * Alexey Melnikov, Isode Ltd. * - * $Id: pluginviewer.c,v 1.10 2011/01/19 12:01:42 mel Exp $ + * $Id: pluginviewer.c,v 1.11 2011/09/01 14:12:18 mel Exp $ */ /* * Copyright (c) 2004 Carnegie Mellon University. All rights reserved. @@ -551,14 +551,14 @@ main(int argc, char *argv[]) /* log */ callback->id = SASL_CB_LOG; - callback->proc = &sasl_my_log; + callback->proc = (sasl_callback_ft)&sasl_my_log; callback->context = NULL; ++callback; /* getpath */ if (searchpath) { callback->id = SASL_CB_GETPATH; - callback->proc = &getpath; + callback->proc = (sasl_callback_ft)&getpath; callback->context = searchpath; ++callback; } @@ -567,7 +567,7 @@ main(int argc, char *argv[]) /* NOTE: this will return "sasl_mech" option, however this HAS NO EFFECT on client side SASL plugins, which just never query this option */ callback->id = SASL_CB_GETOPT; - callback->proc = &plugview_sasl_getopt; + callback->proc = (sasl_callback_ft)&plugview_sasl_getopt; callback->context = NULL; ++callback; diff --git a/utils/sasldblistusers.c b/utils/sasldblistusers.c index bc639817..1b4d1e57 100644 --- a/utils/sasldblistusers.c +++ b/utils/sasldblistusers.c @@ -1,5 +1,5 @@ /* sasldblistusers.c -- list users in sasldb - * $Id: sasldblistusers.c,v 1.23 2009/01/25 13:03:07 mel Exp $ + * $Id: sasldblistusers.c,v 1.24 2011/09/01 14:12:18 mel Exp $ * Rob Siemborski * Tim Martin */ @@ -84,7 +84,7 @@ int good_getopt(void *context __attribute__((unused)), } static struct sasl_callback goodsasl_cb[] = { - { SASL_CB_GETOPT, &good_getopt, NULL }, + { SASL_CB_GETOPT, (sasl_callback_ft)&good_getopt, NULL }, { SASL_CB_LIST_END, NULL, NULL } }; diff --git a/utils/saslpasswd.c b/utils/saslpasswd.c index 50d47b18..b3902f5f 100644 --- a/utils/saslpasswd.c +++ b/utils/saslpasswd.c @@ -251,7 +251,7 @@ int good_getopt(void *context __attribute__((unused)), } static struct sasl_callback goodsasl_cb[] = { - { SASL_CB_GETOPT, &good_getopt, NULL }, + { SASL_CB_GETOPT, (sasl_callback_ft)&good_getopt, NULL }, { SASL_CB_LIST_END, NULL, NULL } }; diff --git a/utils/testsuite.c b/utils/testsuite.c index 9a8b911d..b01a041c 100644 --- a/utils/testsuite.c +++ b/utils/testsuite.c @@ -1,7 +1,7 @@ /* testsuite.c -- Stress the library a little * Rob Siemborski * Tim Martin - * $Id: testsuite.c,v 1.47 2008/10/30 14:16:51 mel Exp $ + * $Id: testsuite.c,v 1.48 2011/09/01 14:12:18 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -63,11 +63,9 @@ #include #include +#include #include #include -#include -#include -#include #ifdef HAVE_UNISTD_H #include @@ -206,13 +204,13 @@ int test_getsimple(void *context __attribute__((unused)), int id, /* callbacks we support */ static sasl_callback_t client_callbacks[] = { { - SASL_CB_GETREALM, test_getrealm, NULL + SASL_CB_GETREALM, (sasl_callback_ft)test_getrealm, NULL }, { - SASL_CB_USER, test_getsimple, NULL + SASL_CB_USER, (sasl_callback_ft)test_getsimple, NULL }, { - SASL_CB_AUTHNAME, test_getsimple, NULL + SASL_CB_AUTHNAME, (sasl_callback_ft)test_getsimple, NULL }, { - SASL_CB_PASS, test_getsecret, NULL + SASL_CB_PASS, (sasl_callback_ft)test_getsecret, NULL }, { SASL_CB_LIST_END, NULL, NULL } @@ -479,7 +477,7 @@ int good_getopt(void *context __attribute__((unused)), } static struct sasl_callback goodsasl_cb[] = { - { SASL_CB_GETOPT, &good_getopt, NULL }, + { SASL_CB_GETOPT, (sasl_callback_ft)&good_getopt, NULL }, { SASL_CB_LIST_END, NULL, NULL } }; @@ -497,7 +495,7 @@ int givebadpath(void * context __attribute__((unused)), } static struct sasl_callback withbadpathsasl_cb[] = { - { SASL_CB_GETPATH, &givebadpath, NULL }, + { SASL_CB_GETPATH, (sasl_callback_ft)&givebadpath, NULL }, { SASL_CB_LIST_END, NULL, NULL } }; @@ -510,7 +508,7 @@ int giveokpath(void * context __attribute__((unused)), } static struct sasl_callback withokpathsasl_cb[] = { - { SASL_CB_GETPATH, &giveokpath, NULL }, + { SASL_CB_GETPATH, (sasl_callback_ft)&giveokpath, NULL }, { SASL_CB_LIST_END, NULL, NULL } }; @@ -543,8 +541,8 @@ static int proxy_authproc(sasl_conn_t *conn, } static struct sasl_callback goodsaslproxy_cb[] = { - { SASL_CB_PROXY_POLICY, &proxy_authproc, NULL }, - { SASL_CB_GETOPT, &good_getopt, NULL }, + { SASL_CB_PROXY_POLICY, (sasl_callback_ft)&proxy_authproc, NULL }, + { SASL_CB_GETOPT, (sasl_callback_ft)&good_getopt, NULL }, { SASL_CB_LIST_END, NULL, NULL } }; From 7a1e30987d5ea06bbe7dd3a57c2a1abf63c98390 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Thu, 1 Sep 2011 14:47:53 +0000 Subject: [PATCH 092/796] Fixed a crash caused by aborted SASL authentication and initiation of another one using the same SASL context --- lib/server.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/server.c b/lib/server.c index 3e0be89d..1f6dfde9 100644 --- a/lib/server.c +++ b/lib/server.c @@ -1,7 +1,7 @@ /* SASL server API implementation * Rob Siemborski * Tim Martin - * $Id: server.c,v 1.173 2011/09/01 14:12:53 mel Exp $ + * $Id: server.c,v 1.174 2011/09/01 14:47:53 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -1466,6 +1466,12 @@ int sasl_server_start(sasl_conn_t *conn, } } + if (conn->context) { + s_conn->mech->m.plug->mech_dispose(conn->context, + s_conn->sparams->utils); + conn->context = NULL; + } + /* We used to setup sparams HERE, but now it's done inside of mech_permitted (which is called above) */ prev = &s_conn->mech_contexts; From 10da356f87e8937cd2b661764849a1103673ad6e Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Thu, 1 Sep 2011 14:49:25 +0000 Subject: [PATCH 093/796] Fix size_t * v. unsigned * bug (patch by Kurt Zeilenga) --- plugins/scram.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/scram.c b/plugins/scram.c index 5433ed26..3f06ad68 100644 --- a/plugins/scram.c +++ b/plugins/scram.c @@ -1,6 +1,6 @@ /* SCRAM-SHA-1 SASL plugin * Alexey Melnikov - * $Id: scram.c,v 1.22 2011/01/21 15:37:44 mel Exp $ + * $Id: scram.c,v 1.23 2011/09/01 14:49:25 mel Exp $ */ /* * Copyright (c) 2009-2010 Carnegie Mellon University. All rights reserved. @@ -69,7 +69,7 @@ /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: scram.c,v 1.22 2011/01/21 15:37:44 mel Exp $"; +static const char plugin_id[] = "$Id: scram.c,v 1.23 2011/09/01 14:49:25 mel Exp $"; #define NONCE_SIZE (32) /* arbitrary */ #define SALT_SIZE (16) /* arbitrary */ @@ -1089,7 +1089,7 @@ scram_server_mech_step2(server_context_t *text, char *channel_binding = NULL; size_t channel_binding_len = 0; char *binary_channel_binding = NULL; - size_t binary_channel_binding_len = 0; + unsigned binary_channel_binding_len = 0; char *client_proof = NULL; char *inbuf = NULL; char *p; From 6557ed5f6767df60c8ee04d8b29ebce96c5ce40e Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Thu, 1 Sep 2011 14:50:24 +0000 Subject: [PATCH 094/796] Fixed some additional Windows warnings and a memory leak in SCRAM --- plugins/scram.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/plugins/scram.c b/plugins/scram.c index 3f06ad68..1fd2348c 100644 --- a/plugins/scram.c +++ b/plugins/scram.c @@ -1,6 +1,6 @@ /* SCRAM-SHA-1 SASL plugin * Alexey Melnikov - * $Id: scram.c,v 1.23 2011/09/01 14:49:25 mel Exp $ + * $Id: scram.c,v 1.24 2011/09/01 14:50:24 mel Exp $ */ /* * Copyright (c) 2009-2010 Carnegie Mellon University. All rights reserved. @@ -69,7 +69,7 @@ /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: scram.c,v 1.23 2011/09/01 14:49:25 mel Exp $"; +static const char plugin_id[] = "$Id: scram.c,v 1.24 2011/09/01 14:50:24 mel Exp $"; #define NONCE_SIZE (32) /* arbitrary */ #define SALT_SIZE (16) /* arbitrary */ @@ -1184,7 +1184,7 @@ scram_server_mech_step2(server_context_t *text, switch (text->cb_flags & SCRAM_CB_FLAG_MASK) { case SCRAM_CB_FLAG_P: - binary_channel_binding_len -= text->gs2_header_length; + binary_channel_binding_len -= (unsigned)text->gs2_header_length; if (binary_channel_binding_len == 0) { SETERROR(sparams->utils, "Channel bindings data expected in " SCRAM_SASL_MECH); result = SASL_BADPROT; @@ -1833,7 +1833,7 @@ scram_client_mech_step1(client_context_t *text, char * freeme = NULL; char * freeme2 = NULL; char channel_binding_state = 'n'; - char * channel_binding_name = NULL; + const char * channel_binding_name = NULL; char * encoded_authorization_id = NULL; /* check if sec layer strong enough */ @@ -1949,6 +1949,7 @@ scram_client_mech_step1(client_context_t *text, case SASL_CB_DISP_USED: if (!SASL_CB_PRESENT(params)) { result = SASL_BADPARAM; + sparams->utils->free(salt); goto cleanup; } channel_binding_name = params->cbinding->name; @@ -2082,7 +2083,7 @@ scram_client_mech_step2(client_context_t *text, size_t cb_bin_length; size_t channel_binding_data_len = 0; size_t cb_encoded_length; - char * channel_binding_data = NULL; + const char * channel_binding_data = NULL; char * cb_encoded = NULL; char * cb_bin = NULL; int result; From 9381eff0a030f7af1bef96e76c1c4a7a1b2db588 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Thu, 1 Sep 2011 15:02:36 +0000 Subject: [PATCH 095/796] Fix SASL's libtool MacOS/X 64-bit file magic (patch by Kurt Zeilenga) --- config/ltconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/ltconfig b/config/ltconfig index 5b61f704..20327d6a 100755 --- a/config/ltconfig +++ b/config/ltconfig @@ -1940,7 +1940,7 @@ darwin* | rhapsody*) version_type=darwin need_lib_prefix=no need_version=no - deplibs_check_method='file_magic Mach-O dynamically linked shared library' + deplibs_check_method='file_magic Mach-O (64-bit )?dynamically linked shared library' file_magic_cmd='/usr/bin/file -L' case "$host_os" in rhapsody* | darwin1.[012]) From 261c1a8e5af7561a38d47c2ac0f1f1fc8fd36845 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Thu, 1 Sep 2011 15:14:10 +0000 Subject: [PATCH 096/796] Updated as per changes commited today --- ChangeLog | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/ChangeLog b/ChangeLog index d1af176d..12ad3a27 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,33 @@ +2011-09-01 Alexey Melnikov + * config/ltconfig: Fix SASL's libtool MacOS/X 64-bit file magic. + (Patch by Kurt Zeilenga) + +2011-09-01 Alexey Melnikov + * plugins/scram.c: Fixed some additional Windows warnings and + a memory leak in SCRAM. + +2011-09-01 Alexey Melnikov + * plugins/scram.c: Fix size_t * v. unsigned * bug. + (Patch by Kurt Zeilenga) + +2011-09-01 Alexey Melnikov + * lib/server.c: Fixed a crash caused by aborted SASL authentication + and initiation of another one using the same SASL context. + +2011-09-01 Alexey Melnikov + * include/md5.h, include/sasl.h, include/saslplug.h, lib/auxprop.c, + lib/canonusr.c, lib/client.c, lib/common.c, lib/saslint.h, lib/server.c, + lib/seterror.c, plugins/otp.c, plugins/plugin_common.c, + sasldb/db_berkeley.c, sample/sample-client.c, sample/sample-server.c, + utils/pluginviewer.c, utils/sasldblistusers.c, utils/saslpasswd.c, + utils/testsuite.c: Many of the SASL includes define function pointers + without specifying arguments. In C, the () is treated as unspecified, + rather than (void), hence this is technically not a prototype, + and gcc warns about it. (Patch by Dave Cridland and Alexey Melnikov) + +2011-09-01 Alexey Melnikov + * lib/server.c: Better server plugin API mismatch reporting + 2011-05-23 Alexey Melnikov * plugins/gs2.c, plugins/gs2_token.c, plugins/gs2_token.h, cmulocal/sasl2.m4: Use draft-josefsson-gss-capsulate-01 if present. From 6ce8e90e9a599c37e254be9d9cbb0e3c7e3717b2 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Thu, 1 Sep 2011 16:31:19 +0000 Subject: [PATCH 097/796] Fixed some aspects of mech_avail callback handling in the server side SASL code --- lib/server.c | 49 ++++++++++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/lib/server.c b/lib/server.c index 1f6dfde9..8af38344 100644 --- a/lib/server.c +++ b/lib/server.c @@ -1,7 +1,7 @@ /* SASL server API implementation * Rob Siemborski * Tim Martin - * $Id: server.c,v 1.174 2011/09/01 14:47:53 mel Exp $ + * $Id: server.c,v 1.175 2011/09/01 16:31:19 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -1189,7 +1189,8 @@ static int mech_permitted(sasl_conn_t *conn, int ret; int myflags; context_list_t *cur; - void *context; + context_list_t *mech_context_list_entry = NULL; + void *context = NULL; sasl_ssf_t minssf = 0; if(!conn) return SASL_NOMECH; @@ -1209,10 +1210,15 @@ static int mech_permitted(sasl_conn_t *conn, s_conn->sparams->external_ssf=conn->external.ssf; /* Check if we have banished this one already */ - for(cur = s_conn->mech_contexts; cur; cur=cur->next) { - if(cur->mech == mech) { + for (cur = s_conn->mech_contexts; cur; cur=cur->next) { + if (cur->mech == mech) { /* If it's not mech_avail'd, then stop now */ - if(!cur->context) return SASL_NOMECH; + if (!cur->context) { + return SASL_NOMECH; + } else { + context = cur->context; + mech_context_list_entry = cur; + } break; } } @@ -1230,7 +1236,6 @@ static int mech_permitted(sasl_conn_t *conn, return SASL_TOOWEAK; /* too weak */ } - context = NULL; if (plug->mech_avail && (ret = plug->mech_avail(plug->glob_context, s_conn->sparams, @@ -1253,16 +1258,21 @@ static int mech_permitted(sasl_conn_t *conn, /* Error should be set by mech_avail call */ return SASL_NOMECH; } else if (context) { - /* Save this context */ - cur = sasl_ALLOC(sizeof(context_list_t)); - if (!cur) { - MEMERROR(conn); - return SASL_NOMECH; + if (mech_context_list_entry != NULL) { + /* Update the context. It shouldn't have changed, but who knows */ + mech_context_list_entry->context = context; + } else { + /* Save this context */ + cur = sasl_ALLOC(sizeof(context_list_t)); + if (!cur) { + MEMERROR(conn); + return SASL_NOMECH; + } + cur->context = context; + cur->mech = mech; + cur->next = s_conn->mech_contexts; + s_conn->mech_contexts = cur; } - cur->context = context; - cur->mech = mech; - cur->next = s_conn->mech_contexts; - s_conn->mech_contexts = cur; } /* Generic mechanism */ @@ -1475,18 +1485,19 @@ int sasl_server_start(sasl_conn_t *conn, /* We used to setup sparams HERE, but now it's done inside of mech_permitted (which is called above) */ prev = &s_conn->mech_contexts; - for(cur = *prev; cur; prev=&cur->next,cur=cur->next) { - if(cur->mech == m) { - if(!cur->context) { + for (cur = *prev; cur; prev=&cur->next,cur=cur->next) { + if (cur->mech == m) { + if (!cur->context) { sasl_seterror(conn, 0, "Got past mech_permitted with a disallowed mech!"); return SASL_NOMECH; } /* If we find it, we need to pull cur out of the list so it won't be freed later! */ - (*prev)->next = cur->next; + *prev = cur->next; conn->context = cur->context; sasl_FREE(cur); + break; } } From ea97caa90e268080e08c724e6fa8e368575e350e Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Thu, 1 Sep 2011 16:33:10 +0000 Subject: [PATCH 098/796] Make sure that a failed authorization doesn't preclude further SASL authentication attempts from working --- lib/server.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/server.c b/lib/server.c index 8af38344..d9c23877 100644 --- a/lib/server.c +++ b/lib/server.c @@ -1,7 +1,7 @@ /* SASL server API implementation * Rob Siemborski * Tim Martin - * $Id: server.c,v 1.175 2011/09/01 16:31:19 mel Exp $ + * $Id: server.c,v 1.176 2011/09/01 16:33:10 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -1558,6 +1558,7 @@ int sasl_server_start(sasl_conn_t *conn, s_conn->sparams->utils); conn->context = NULL; } + conn->oparams.doneflag = 0; } RETURN(conn,result); @@ -1677,14 +1678,15 @@ int sasl_server_step(sasl_conn_t *conn, } } - if( ret != SASL_OK + if ( ret != SASL_OK && ret != SASL_CONTINUE && ret != SASL_INTERACT) { - if(conn->context) { + if (conn->context) { s_conn->mech->m.plug->mech_dispose(conn->context, s_conn->sparams->utils); conn->context = NULL; } + conn->oparams.doneflag = 0; } RETURN(conn, ret); From 4be9813878f04af2685b6588a8f43554ee71f015 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Thu, 1 Sep 2011 16:33:42 +0000 Subject: [PATCH 099/796] Reformatting change --- lib/canonusr.c | 45 +++++++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/lib/canonusr.c b/lib/canonusr.c index 8ed49811..ccbda6b5 100644 --- a/lib/canonusr.c +++ b/lib/canonusr.c @@ -1,6 +1,6 @@ /* canonusr.c - user canonicalization support * Rob Siemborski - * $Id: canonusr.c,v 1.21 2011/09/01 14:12:53 mel Exp $ + * $Id: canonusr.c,v 1.22 2011/09/01 16:33:42 mel Exp $ */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. @@ -101,15 +101,22 @@ int _sasl_canon_user(sasl_conn_t *conn, if(!ulen) ulen = (unsigned int)strlen(user); /* check to see if we have a callback to make*/ - result = _sasl_getcallback(conn, SASL_CB_CANON_USER, - (sasl_callback_ft *)&cuser_cb, &context); + result = _sasl_getcallback(conn, + SASL_CB_CANON_USER, + (sasl_callback_ft *)&cuser_cb, + &context); if(result == SASL_OK && cuser_cb) { - result = cuser_cb(conn, context, - user, ulen, - flags, (conn->type == SASL_CONN_SERVER ? + result = cuser_cb(conn, + context, + user, + ulen, + flags, + (conn->type == SASL_CONN_SERVER ? sconn->user_realm : NULL), - user_buf, CANON_BUF_SIZE, lenp); + user_buf, + CANON_BUF_SIZE, + lenp); if (result != SASL_OK) return result; @@ -120,32 +127,34 @@ int _sasl_canon_user(sasl_conn_t *conn, } /* which plugin are we supposed to use? */ - result = _sasl_getcallback(conn, SASL_CB_GETOPT, - (sasl_callback_ft *)&getopt, &context); - if(result == SASL_OK && getopt) { + result = _sasl_getcallback(conn, + SASL_CB_GETOPT, + (sasl_callback_ft *)&getopt, + &context); + if (result == SASL_OK && getopt) { getopt(context, NULL, "canon_user_plugin", &plugin_name, NULL); } - if(!plugin_name) { + if (!plugin_name) { /* Use Default */ plugin_name = "INTERNAL"; } - for(ptr = canonuser_head; ptr; ptr = ptr->next) { + for (ptr = canonuser_head; ptr; ptr = ptr->next) { /* A match is if we match the internal name of the plugin, or if * we match the filename (old-style) */ - if((ptr->plug->name && !strcmp(plugin_name, ptr->plug->name)) + if ((ptr->plug->name && !strcmp(plugin_name, ptr->plug->name)) || !strcmp(plugin_name, ptr->name)) break; } /* We clearly don't have this one! */ - if(!ptr) { + if (!ptr) { sasl_seterror(conn, 0, "desired canon_user plugin %s not found", plugin_name); return SASL_NOMECH; } - if(sconn) { + if (sconn) { /* we're a server */ result = ptr->plug->canon_user_server(ptr->plug->glob_context, sconn->sparams, @@ -163,9 +172,9 @@ int _sasl_canon_user(sasl_conn_t *conn, CANON_BUF_SIZE, lenp); } - if(result != SASL_OK) return result; + if (result != SASL_OK) return result; - if((flags & SASL_CU_AUTHID) && (flags & SASL_CU_AUTHZID)) { + if ((flags & SASL_CU_AUTHID) && (flags & SASL_CU_AUTHZID)) { /* We did both, so we need to copy the result into * the buffer for the authzid from the buffer for the authid */ memcpy(conn->user_buf, conn->authid_buf, CANON_BUF_SIZE); @@ -173,7 +182,7 @@ int _sasl_canon_user(sasl_conn_t *conn, } /* Set the appropriate oparams (lengths have already been set by lenp) */ - if(flags & SASL_CU_AUTHID) { + if (flags & SASL_CU_AUTHID) { oparams->authid = conn->authid_buf; } From 8c67a4458210ad2f0ce1b3ac9f8c11dfc242762f Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Thu, 1 Sep 2011 16:35:15 +0000 Subject: [PATCH 100/796] Fix SASL's libtool MacOS/X 64-bit file magic (patch by Kurt Zeilenga) --- saslauthd/config/ltconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/saslauthd/config/ltconfig b/saslauthd/config/ltconfig index 5b61f704..20327d6a 100755 --- a/saslauthd/config/ltconfig +++ b/saslauthd/config/ltconfig @@ -1940,7 +1940,7 @@ darwin* | rhapsody*) version_type=darwin need_lib_prefix=no need_version=no - deplibs_check_method='file_magic Mach-O dynamically linked shared library' + deplibs_check_method='file_magic Mach-O (64-bit )?dynamically linked shared library' file_magic_cmd='/usr/bin/file -L' case "$host_os" in rhapsody* | darwin1.[012]) From b63188769e400991c4987fe319da4433eadb10c2 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Thu, 1 Sep 2011 16:35:49 +0000 Subject: [PATCH 101/796] Additional updates --- ChangeLog | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 12ad3a27..bf1d3668 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,14 @@ 2011-09-01 Alexey Melnikov - * config/ltconfig: Fix SASL's libtool MacOS/X 64-bit file magic. - (Patch by Kurt Zeilenga) + * lib/server.c: Make sure that a failed authorization doesn't preclude + further SASL authentication attempts from working. + +2011-09-01 Alexey Melnikov + * lib/server.c: Fixed some aspects of mech_avail callback handling + in the server side SASL code. + +2011-09-01 Alexey Melnikov + * config/ltconfig, saslauthd/config/ltconfig: Fix SASL's libtool + MacOS/X 64-bit file magic. (Patch by Kurt Zeilenga) 2011-09-01 Alexey Melnikov * plugins/scram.c: Fixed some additional Windows warnings and From 4d0f574976aceb44102ee7589e3cffcd3f15f598 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Fri, 2 Sep 2011 10:52:50 +0000 Subject: [PATCH 102/796] Updated config.* to the latest GNU snapshot --- ChangeLog | 4 + config/config.guess | 1226 +++++++++++++++++++-------------- config/config.sub | 683 ++++++++++++++---- saslauthd/config/config.guess | 1226 +++++++++++++++++++-------------- saslauthd/config/config.sub | 683 ++++++++++++++---- 5 files changed, 2520 insertions(+), 1302 deletions(-) diff --git a/ChangeLog b/ChangeLog index bf1d3668..a1d1e98b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-09-02 Alexey Melnikov + * config/config.guess, config/config.sub, saslauthd/config/config.guess, + saslauthd/config/config.sub: Updated config to the latest GNU snapshot. + 2011-09-01 Alexey Melnikov * lib/server.c: Make sure that a failed authorization doesn't preclude further SASL authentication attempts from working. diff --git a/config/config.guess b/config/config.guess index 6012b396..f7dd69ec 100755 --- a/config/config.guess +++ b/config/config.guess @@ -1,9 +1,10 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 -# Free Software Foundation, Inc. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011 Free Software Foundation, Inc. -timestamp='2001-07-12' +timestamp='2011-08-20' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -17,22 +18,25 @@ timestamp='2001-07-12' # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. -# Written by Per Bothner . -# Please send patches to . + +# Originally written by Per Bothner. Please send patches (context +# diff format) to and include a ChangeLog +# entry. # # This script attempts to guess a canonical system name similar to # config.sub. If it succeeds, it prints the system name on stdout, and # exits with 0. Otherwise, it exits with 1. # -# The plan is that this can be called by configure scripts if you -# don't specify an explicit build system type. +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD me=`echo "$0" | sed -e 's,.*/,,'` @@ -52,8 +56,9 @@ version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 -Free Software Foundation, Inc. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free +Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -65,11 +70,11 @@ Try \`$me --help' for more information." while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) - echo "$timestamp" ; exit 0 ;; + echo "$timestamp" ; exit ;; --version | -v ) - echo "$version" ; exit 0 ;; + echo "$version" ; exit ;; --help | --h* | -h ) - echo "$usage"; exit 0 ;; + echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. @@ -87,30 +92,42 @@ if test $# != 0; then exit 1 fi +trap 'exit 1' 1 2 15 -dummy=dummy-$$ -trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15 +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. -# CC_FOR_BUILD -- compiler used by this script. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. -set_cc_for_build='case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int dummy(){}" > $dummy.c ; - for c in cc gcc c89 ; do - ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ; - if test $? = 0 ; then +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; - rm -f $dummy.c $dummy.o $dummy.rel ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac' +esac ; set_cc_for_build= ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) @@ -127,32 +144,34 @@ UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) - # Netbsd (nbsd) targets should (where applicable) match one or + # NetBSD (nbsd) targets should (where applicable) match one or # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. - # Determine the machine/vendor (is the vendor relevant). - case "${UNAME_MACHINE}" in - amiga) machine=m68k-unknown ;; - arm32) machine=arm-unknown ;; - atari*) machine=m68k-atari ;; - sun3*) machine=m68k-sun ;; - mac68k) machine=m68k-apple ;; - macppc) machine=powerpc-apple ;; - hp3[0-9][05]) machine=m68k-hp ;; - ibmrt|romp-ibm) machine=romp-ibm ;; - *) machine=${UNAME_MACHINE}-unknown ;; + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. - case "${UNAME_MACHINE}" in - i386|sparc|amiga|arm*|hp300|mvme68k|vax|atari|luna68k|mac68k|news68k|next68k|pc532|sun3*|x68k) + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep __ELF__ >/dev/null + | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? @@ -162,121 +181,135 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in fi ;; *) - os=netbsd + os=netbsd ;; esac # The OS release - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" - exit 0 ;; + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; alpha:OSF1:*:*) - if test $UNAME_RELEASE = "V4.0"; then + case $UNAME_RELEASE in + *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` - fi + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. - cat <$dummy.s - .data -\$Lformat: - .byte 37,100,45,37,120,10,0 # "%d-%x\n" - - .text - .globl main - .align 4 - .ent main -main: - .frame \$30,16,\$26,0 - ldgp \$29,0(\$27) - .prologue 1 - .long 0x47e03d80 # implver \$0 - lda \$2,-1 - .long 0x47e20c21 # amask \$2,\$1 - lda \$16,\$Lformat - mov \$0,\$17 - not \$1,\$18 - jsr \$26,printf - ldgp \$29,0(\$26) - mov 0,\$16 - jsr \$26,exit - .end main -EOF - eval $set_cc_for_build - $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null - if test "$?" = 0 ; then - case `./$dummy` in - 0-0) - UNAME_MACHINE="alpha" - ;; - 1-0) - UNAME_MACHINE="alphaev5" - ;; - 1-1) - UNAME_MACHINE="alphaev56" - ;; - 1-101) - UNAME_MACHINE="alphapca56" - ;; - 2-303) - UNAME_MACHINE="alphaev6" - ;; - 2-307) - UNAME_MACHINE="alphaev67" - ;; - esac - fi - rm -f $dummy.s $dummy - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - exit 0 ;; + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix - exit 0 ;; + exit ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 - exit 0 ;; + exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 - exit 0;; - amiga:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; + exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos - exit 0 ;; - arc64:OpenBSD:*:*) - echo mips64el-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - arc:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - hkmips:OpenBSD:*:*) - echo mips-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - pmax:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - sgi:OpenBSD:*:*) - echo mips-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - wgrisc:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; *:OS/390:*:*) echo i370-ibm-openedition - exit 0 ;; + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} - exit 0;; + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp - exit 0;; + exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then @@ -284,25 +317,51 @@ EOF else echo pyramid-pyramid-bsd fi - exit 0 ;; + exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 - exit 0 ;; + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; + exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - i86pc:SunOS:5.*:*) - echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; + exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) @@ -311,12 +370,12 @@ EOF esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` - exit 0 ;; + exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} - exit 0 ;; + exit ;; sun*:*:4.2BSD:*) - UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) @@ -326,13 +385,10 @@ EOF echo sparc-sun-sunos${UNAME_RELEASE} ;; esac - exit 0 ;; + exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} - exit 0 ;; - atari*:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; + exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor @@ -342,51 +398,43 @@ EOF # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit 0 ;; + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} - exit 0 ;; + exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit 0 ;; + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} - exit 0 ;; + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} - exit 0 ;; + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} - exit 0 ;; - sun3*:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mac68k:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mvme68k:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mvme88k:OpenBSD:*:*) - echo m88k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} - exit 0 ;; + exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 - exit 0 ;; + exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} - exit 0 ;; + exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} - exit 0 ;; + exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} - exit 0 ;; + exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ @@ -408,31 +456,36 @@ EOF exit (-1); } EOF - eval $set_cc_for_build - $CC_FOR_BUILD $dummy.c -o $dummy \ - && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ - && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos${UNAME_RELEASE} - exit 0 ;; + exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax - exit 0 ;; + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix - exit 0 ;; + exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 - exit 0 ;; + exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 - exit 0 ;; + exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 - exit 0 ;; + exit ;; AViiON:dgux:*:*) - # DG/UX returns AViiON for all architectures - UNAME_PROCESSOR=`/usr/bin/uname -p` + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ @@ -445,29 +498,29 @@ EOF else echo i586-dg-dgux${UNAME_RELEASE} fi - exit 0 ;; + exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 - exit 0 ;; + exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 - exit 0 ;; + exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 - exit 0 ;; + exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd - exit 0 ;; + exit ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` - exit 0 ;; + exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. - echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id - exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix - exit 0 ;; + exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` @@ -475,9 +528,10 @@ EOF IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} - exit 0 ;; + exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include @@ -489,18 +543,20 @@ EOF exit(0); } EOF - eval $set_cc_for_build - $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy - echo rs6000-ibm-aix3.2.5 + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi - exit 0 ;; - *:AIX:*:[45]) - IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'` + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else @@ -512,97 +568,116 @@ EOF IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} - exit 0 ;; + exit ;; *:AIX:*:*) echo rs6000-ibm-aix - exit 0 ;; + exit ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 - exit 0 ;; + exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to - exit 0 ;; # report: romp-ibm BSD 4.3 + exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx - exit 0 ;; + exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 - exit 0 ;; + exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd - exit 0 ;; + exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 - exit 0 ;; + exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) - case "${HPUX_REV}" in - 11.[0-9][0-9]) - if [ -x /usr/bin/getconf ]; then - sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` - sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in - 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 - 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 - 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in - 32) HP_ARCH="hppa2.0n" ;; - 64) HP_ARCH="hppa2.0w" ;; - esac ;; - esac - fi ;; - esac - if [ "${HP_ARCH}" = "" ]; then - sed 's/^ //' << EOF >$dummy.c + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c - #define _HPUX_SOURCE - #include - #include + #define _HPUX_SOURCE + #include + #include - int main () - { - #if defined(_SC_KERNEL_BITS) - long bits = sysconf(_SC_KERNEL_BITS); - #endif - long cpu = sysconf (_SC_CPU_VERSION); + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1"); break; - case CPU_PA_RISC2_0: - #if defined(_SC_KERNEL_BITS) - switch (bits) - { - case 64: puts ("hppa2.0w"); break; - case 32: puts ("hppa2.0n"); break; - default: puts ("hppa2.0"); break; - } break; - #else /* !defined(_SC_KERNEL_BITS) */ - puts ("hppa2.0"); break; - #endif - default: puts ("hppa1.0"); break; - } - exit (0); - } + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } EOF - eval $set_cc_for_build - (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy` - if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi - rm -f $dummy.c $dummy - fi ;; + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} - exit 0 ;; + exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} - exit 0 ;; + exit ;; 3050*:HI-UX:*:*) + eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int @@ -628,156 +703,163 @@ EOF exit (0); } EOF - eval $set_cc_for_build - $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 - exit 0 ;; + exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd - exit 0 ;; + exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd - exit 0 ;; + exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix - exit 0 ;; + exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf - exit 0 ;; + exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf - exit 0 ;; + exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi - exit 0 ;; + exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites - exit 0 ;; - hppa*:OpenBSD:*:*) - echo hppa-unknown-openbsd - exit 0 ;; + exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd - exit 0 ;; + exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi - exit 0 ;; + exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd - exit 0 ;; + exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd - exit 0 ;; + exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd - exit 0 ;; - CRAY*X-MP:*:*:*) - echo xmp-cray-unicos - exit 0 ;; + exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; + exit ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' - exit 0 ;; + exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY*T3D:*:*:*) - echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; + exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; + exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY-2:*:*:*) - echo cray2-cray-unicos - exit 0 ;; + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` - echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit 0 ;; - hp300:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} - exit 0 ;; + exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} - exit 0 ;; + exit ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} - exit 0 ;; + exit ;; *:FreeBSD:*:*) - echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` - exit 0 ;; - *:OpenBSD:*:*) - echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` - exit 0 ;; + UNAME_PROCESSOR=`/usr/bin/uname -p` + case ${UNAME_PROCESSOR} in + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin - exit 0 ;; - i*:MINGW*:*) + exit ;; + *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 - exit 0 ;; + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 - exit 0 ;; + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? - echo i386-pc-interix - exit 0 ;; + echo i586-pc-interix + exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin - exit 0 ;; + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin - exit 0 ;; + exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; + exit ;; *:GNU:*:*) + # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` - exit 0 ;; + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix - exit 0 ;; - arm*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; - ia64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux - exit 0 ;; - m68*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; - mips:Linux:*:*) - case `sed -n '/^byte/s/^.*: \(.*\) endian/\1/p' < /proc/cpuinfo` in - big) echo mips-unknown-linux-gnu && exit 0 ;; - little) echo mipsel-unknown-linux-gnu && exit 0 ;; - esac - ;; - ppc:Linux:*:*) - echo powerpc-unknown-linux-gnu - exit 0 ;; + exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; @@ -786,12 +868,88 @@ EOF PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; - EV68*) UNAME_MACHINE=alphaev67 ;; - esac - objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} - exit 0 ;; + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-gnu + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo ${UNAME_MACHINE}-unknown-linux-gnueabi + else + echo ${UNAME_MACHINE}-unknown-linux-gnueabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + LIBC=gnu + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-gnu + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in @@ -799,92 +957,71 @@ EOF PA8*) echo hppa2.0-unknown-linux-gnu ;; *) echo hppa-unknown-linux-gnu ;; esac - exit 0 ;; - parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-gnu - exit 0 ;; + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux - exit 0 ;; + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; + exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; + exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; x86_64:Linux:*:*) echo x86_64-unknown-linux-gnu - exit 0 ;; - i*86:Linux:*:*) - # The BFD linker knows what the default object file format is, so - # first see if it will tell us. cd to the root directory to prevent - # problems with other programs or directories called `ld' in the path. - ld_supported_targets=`cd /; ld --help 2>&1 \ - | sed -ne '/supported targets:/!d - s/[ ][ ]*/ /g - s/.*supported targets: *// - s/ .*// - p'` - case "$ld_supported_targets" in - elf32-i386) - TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" - ;; - a.out-i386-linux) - echo "${UNAME_MACHINE}-pc-linux-gnuaout" - exit 0 ;; - coff-i386) - echo "${UNAME_MACHINE}-pc-linux-gnucoff" - exit 0 ;; - "") - # Either a pre-BFD a.out linker (linux-gnuoldld) or - # one that does not give us useful --help. - echo "${UNAME_MACHINE}-pc-linux-gnuoldld" - exit 0 ;; - esac - # Determine whether the default compiler is a.out or elf - cat >$dummy.c < -#ifdef __cplusplus -#include /* for printf() prototype */ - int main (int argc, char *argv[]) { -#else - int main (argc, argv) int argc; char *argv[]; { -#endif -#ifdef __ELF__ -# ifdef __GLIBC__ -# if __GLIBC__ >= 2 - printf ("%s-pc-linux-gnu\n", argv[1]); -# else - printf ("%s-pc-linux-gnulibc1\n", argv[1]); -# endif -# else - printf ("%s-pc-linux-gnulibc1\n", argv[1]); -# endif -#else - printf ("%s-pc-linux-gnuaout\n", argv[1]); -#endif - return 0; -} -EOF - eval $set_cc_for_build - $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy - test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 - ;; + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 - exit 0 ;; + exit ;; i*86:UNIX_SV:4.2MP:2.*) - # Unixware is an offshoot of SVR4, but it has its own version - # number series starting with 2... - # I am not positive that other SVR4 systems won't match this, + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. - # Use sysv4.2uw... so that sysv4* matches it. + # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} - exit 0 ;; + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then @@ -892,99 +1029,113 @@ EOF else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi - exit 0 ;; - i*86:*:5:[78]*) + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} - exit 0 ;; + exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then - UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')` - (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 - (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 - (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \ + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 - (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \ + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi - exit 0 ;; - i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp - exit 0 ;; + exit ;; pc:*:*:*) # Left here for compatibility: - # uname -m prints for DJGPP always 'pc', but it prints nothing about - # the processor, so we play safe by assuming i386. - echo i386-pc-msdosdjgpp - exit 0 ;; + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 - exit 0 ;; + exit ;; paragon:*:*:*) echo i860-intel-osf1 - exit 0 ;; + exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi - exit 0 ;; + exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv - exit 0 ;; - M68*:*:R3V[567]*:*) - test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; - 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0) + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && echo i486-ncr-sysv4.3${OS_REL} && exit 0 + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && echo i486-ncr-sysv4 && exit 0 ;; + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; + exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 - exit 0 ;; - i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) - echo i386-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; + exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; + exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; + exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} - exit 0 ;; + exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 - exit 0 ;; + exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 - exit 0 ;; + exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` @@ -992,78 +1143,123 @@ EOF else echo ns32k-sni-sysv fi - exit 0 ;; - PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort - # says - echo i586-unisys-sysv4 - exit 0 ;; + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 - exit 0 ;; + exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 - exit 0 ;; + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} - exit 0 ;; + exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 - exit 0 ;; + exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} + echo mips-nec-sysv${UNAME_RELEASE} else - echo mips-unknown-sysv${UNAME_RELEASE} + echo mips-unknown-sysv${UNAME_RELEASE} fi - exit 0 ;; + exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos - exit 0 ;; + exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos - exit 0 ;; + exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos - exit 0 ;; + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} - exit 0 ;; + exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} - exit 0 ;; + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} - exit 0 ;; + exit ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} - exit 0 ;; + exit ;; *:Darwin:*:*) - echo `uname -p`-apple-darwin${UNAME_RELEASE} - exit 0 ;; + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + i386) + eval $set_cc_for_build + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + UNAME_PROCESSOR="x86_64" + fi + fi ;; + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) - if test "${UNAME_MACHINE}" = "x86pc"; then + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi - echo `uname -p`-${UNAME_MACHINE}-nto-qnx - exit 0 ;; + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; *:QNX:*:4*) echo i386-pc-qnx - exit 0 ;; - NSR-[KW]:NONSTOP_KERNEL:*:*) + exit ;; + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} - exit 0 ;; + exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux - exit 0 ;; + exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv - exit 0 ;; + exit ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} - exit 0 ;; + exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 @@ -1074,35 +1270,56 @@ EOF UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 - exit 0 ;; - i*86:OS/2:*:*) - # If we were able to find `uname', then EMX Unix compatibility - # is probably installed. - echo ${UNAME_MACHINE}-pc-os2-emx - exit 0 ;; + exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 - exit 0 ;; + exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex - exit 0 ;; + exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 - exit 0 ;; + exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 - exit 0 ;; + exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 - exit 0 ;; + exit ;; *:ITS:*:*) echo pdp10-unknown-its - exit 0 ;; + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 #echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 +eval $set_cc_for_build cat >$dummy.c < @@ -1119,16 +1336,16 @@ main () #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 - "4" + "4" #else - "" + "" #endif - ); exit (0); + ); exit (0); #endif #endif #if defined (__arm) && defined (__acorn) && defined (__unix) - printf ("arm-acorn-riscix"); exit (0); + printf ("arm-acorn-riscix\n"); exit (0); #endif #if defined (hp300) && !defined (hpux) @@ -1217,13 +1434,12 @@ main () } EOF -eval $set_cc_for_build -$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0 -rm -f $dummy.c $dummy +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } # Apollos put the system type in the environment. -test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } # Convex versions that predate uname can use getsysinfo(1) @@ -1232,22 +1448,22 @@ then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd - exit 0 ;; + exit ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi - exit 0 ;; + exit ;; c34*) echo c34-convex-bsd - exit 0 ;; + exit ;; c38*) echo c38-convex-bsd - exit 0 ;; + exit ;; c4*) echo c4-convex-bsd - exit 0 ;; + exit ;; esac fi @@ -1258,7 +1474,9 @@ This script, last modified $timestamp, has failed to recognize the operating system you are using. It is advised that you download the most up to date version of the config scripts from - ftp://ftp.gnu.org/pub/gnu/config/ + http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD +and + http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD If the version you run ($0) is already up to date, please send the following data and any information you think might be diff --git a/config/config.sub b/config/config.sub index 578b3027..da19a880 100755 --- a/config/config.sub +++ b/config/config.sub @@ -1,9 +1,10 @@ #! /bin/sh # Configuration validation subroutine script. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 -# Free Software Foundation, Inc. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011 Free Software Foundation, Inc. -timestamp='2001-06-08' +timestamp='2011-08-23' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software @@ -21,21 +22,26 @@ timestamp='2001-06-08' # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. -# Please send patches to . + +# Please send patches to . Submit a context +# diff and a properly formatted GNU ChangeLog entry. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. @@ -69,8 +75,9 @@ Report bugs and patches to ." version="\ GNU config.sub ($timestamp) -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 -Free Software Foundation, Inc. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free +Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -82,11 +89,11 @@ Try \`$me --help' for more information." while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) - echo "$timestamp" ; exit 0 ;; + echo "$timestamp" ; exit ;; --version | -v ) - echo "$version" ; exit 0 ;; + echo "$version" ; exit ;; --help | --h* | -h ) - echo "$usage"; exit 0 ;; + echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. @@ -98,7 +105,7 @@ while test $# -gt 0 ; do *local*) # First pass through any local machine types. echo $1 - exit 0;; + exit ;; * ) break ;; @@ -117,7 +124,11 @@ esac # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in - nto-qnx* | linux-gnu* | storm-chaos* | os2-emx* | windows32-*) + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; @@ -143,10 +154,13 @@ case $os in -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis) + -apple | -axis | -knuth | -cray | -microblaze) os= basic_machine=$1 ;; + -bluegene*) + os=-cnk + ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 @@ -161,13 +175,17 @@ case $os in os=-chorusos basic_machine=$1 ;; - -chorusrdb) - os=-chorusrdb + -chorusrdb) + os=-chorusrdb basic_machine=$1 - ;; + ;; -hiux*) os=-hiuxwe2 ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` @@ -184,6 +202,10 @@ case $os in # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` @@ -223,35 +245,100 @@ esac case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. - tahoe | i860 | ia64 | m32r | m68k | m68000 | m88k | ns32k | arc \ - | arm | arme[lb] | arm[bl]e | armv[2345] | armv[345][lb] | strongarm | xscale \ - | pyramid | mn10200 | mn10300 | tron | a29k \ - | 580 | i960 | h8300 \ - | x86 | ppcbe | mipsbe | mipsle | shbe | shle \ - | hppa | hppa1.0 | hppa1.1 | hppa2.0 | hppa2.0w | hppa2.0n \ - | hppa64 \ - | alpha | alphaev[4-8] | alphaev56 | alphapca5[67] \ - | alphaev6[78] \ - | we32k | ns16k | clipper | i370 | sh | sh[34] \ - | powerpc | powerpcle \ - | 1750a | dsp16xx | pdp10 | pdp11 \ - | mips16 | mips64 | mipsel | mips64el \ - | mips64orion | mips64orionel | mipstx39 | mipstx39el \ - | mips64vr4300 | mips64vr4300el | mips64vr4100 | mips64vr4100el \ - | mips64vr5000 | mips64vr5000el | mcore | s390 | s390x \ - | sparc | sparclet | sparclite | sparc64 | sparcv9 | sparcv9b \ - | v850 | c4x \ - | thumb | d10v | d30v | fr30 | avr | openrisc | tic80 \ - | pj | pjl | h8500 | z8k) + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | be32 | be64 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 \ + | ns16k | ns32k \ + | open8 \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pyramid \ + | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | we32k \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) basic_machine=$basic_machine-unknown ;; - m6811 | m68hc11 | m6812 | m68hc12) + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12 | picochip) # Motorola 68HC11/12. basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and @@ -265,31 +352,80 @@ case $basic_machine in exit 1 ;; # Recognize the basic CPU types with company name. - # FIXME: clean up the formatting here. - vax-* | tahoe-* | i*86-* | i860-* | ia64-* | m32r-* | m68k-* | m68000-* \ - | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | c[123]* \ - | arm-* | armbe-* | armle-* | armv*-* | strongarm-* | xscale-* \ - | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \ - | power-* | none-* | 580-* | cray2-* | h8300-* | h8500-* | i960-* \ - | xmp-* | ymp-* \ - | x86-* | ppcbe-* | mipsbe-* | mipsle-* | shbe-* | shle-* \ - | hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* | hppa2.0w-* \ - | hppa2.0n-* | hppa64-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphapca5[67]-* \ - | alphaev6[78]-* \ - | we32k-* | cydra-* | ns16k-* | pn-* | np1-* | xps100-* \ - | clipper-* | orion-* \ - | sparclite-* | pdp10-* | pdp11-* | sh-* | sh[34]-* | sh[34]eb-* \ - | powerpc-* | powerpcle-* | sparc64-* | sparcv9-* | sparcv9b-* | sparc86x-* \ - | mips16-* | mips64-* | mipsel-* \ - | mips64el-* | mips64orion-* | mips64orionel-* \ - | mips64vr4100-* | mips64vr4100el-* | mips64vr4300-* | mips64vr4300el-* \ - | mipstx39-* | mipstx39el-* | mcore-* \ - | f30[01]-* | f700-* | s390-* | s390x-* | sv1-* | t3e-* \ - | [cjt]90-* \ - | m88110-* | m680[01234]0-* | m683?2-* | m68360-* | z8k-* | d10v-* \ - | thumb-* | v850-* | d30v-* | tic30-* | tic80-* | c30-* | fr30-* \ - | bs2000-* | tic54x-* | c54x-* | x86_64-* | pj-* | pjl-*) + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pyramid-* \ + | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. @@ -307,6 +443,9 @@ case $basic_machine in basic_machine=a29k-amd os=-udi ;; + abacus) + basic_machine=abacus-unknown + ;; adobe68k) basic_machine=m68010-adobe os=-scout @@ -321,6 +460,12 @@ case $basic_machine in basic_machine=a29k-none os=-bsd ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; amdahl) basic_machine=580-amdahl os=-sysv @@ -344,6 +489,10 @@ case $basic_machine in basic_machine=m68k-apollo os=-bsd ;; + aros) + basic_machine=i386-pc + os=-aros + ;; aux) basic_machine=m68k-apple os=-aux @@ -352,6 +501,35 @@ case $basic_machine in basic_machine=ns32k-sequent os=-dynix ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; convex-c1) basic_machine=c1-convex os=-bsd @@ -372,30 +550,45 @@ case $basic_machine in basic_machine=c38-convex os=-bsd ;; - cray | ymp) - basic_machine=ymp-cray + cray | j90) + basic_machine=j90-cray os=-unicos ;; - cray2) - basic_machine=cray2-cray - os=-unicos + craynv) + basic_machine=craynv-cray + os=-unicosmp ;; - [cjt]90) - basic_machine=${basic_machine}-cray - os=-unicos + cr16 | cr16-*) + basic_machine=cr16-unknown + os=-elf ;; crds | unos) basic_machine=m68k-crds ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola @@ -404,6 +597,14 @@ case $basic_machine in basic_machine=m88k-motorola os=-sysv3 ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx @@ -554,6 +755,14 @@ case $basic_machine in basic_machine=m68k-isi os=-sysv ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; m88k-omron*) basic_machine=m88k-omron ;; @@ -565,10 +774,17 @@ case $basic_machine in basic_machine=ns32k-utek os=-sysv ;; + microblaze) + basic_machine=microblaze-xilinx + ;; mingw32) basic_machine=i386-pc os=-mingw32 ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; miniframe) basic_machine=m68000-convergent ;; @@ -576,36 +792,35 @@ case $basic_machine in basic_machine=m68k-atari os=-mint ;; - mipsel*-linux*) - basic_machine=mipsel-unknown - os=-linux-gnu - ;; - mips*-linux*) - basic_machine=mips-unknown - os=-linux-gnu - ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; - mmix*) - basic_machine=mmix-knuth - os=-mmixware - ;; monitor) basic_machine=m68k-rom68k os=-coff ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; msdos) basic_machine=i386-pc os=-msdos ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; mvs) basic_machine=i370-ibm os=-mvs ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; ncr3000) basic_machine=i486-ncr os=-sysv4 @@ -670,6 +885,12 @@ case $basic_machine in np1) basic_machine=np1-gould ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; nsr-tandem) basic_machine=nsr-tandem ;; @@ -677,6 +898,13 @@ case $basic_machine in basic_machine=hppa1.1-oki os=-proelf ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose @@ -693,48 +921,79 @@ case $basic_machine in basic_machine=i860-intel os=-osf ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; - pc532 | pc532-*) + pc532 | pc532-*) basic_machine=ns32k-pc532 ;; - pentium | p5 | k5 | k6 | nexgen) + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; - pentiumpro | p6 | 6x86 | athlon) + pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; - pentiumii | pentium2) + pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; - pentium-* | p5-* | k5-* | k6-* | nexgen-*) + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; - pentiumii-* | pentium2-*) + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; - ppc) basic_machine=powerpc-unknown - ;; - ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ppc | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown - ;; + ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; ps2) basic_machine=i386-ibm ;; @@ -742,6 +1001,10 @@ case $basic_machine in basic_machine=i586-unknown os=-pw32 ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; rom68k) basic_machine=m68k-rom68k os=-coff @@ -752,10 +1015,30 @@ case $basic_machine in rtpc | rtpc-*) basic_machine=romp-ibm ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; sa29200) basic_machine=a29k-amd os=-udi ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; sequent) basic_machine=i386-sequent ;; @@ -763,7 +1046,13 @@ case $basic_machine in basic_machine=sh-hitachi os=-hms ;; - sparclite-wrs) + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; @@ -781,6 +1070,9 @@ case $basic_machine in basic_machine=i860-stratus os=-sysv4 ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; sun2) basic_machine=m68000-sun ;; @@ -830,12 +1122,16 @@ case $basic_machine in os=-dynix ;; t3e) - basic_machine=t3e-cray + basic_machine=alphaev5-cray os=-unicos ;; - tic54x | c54x*) - basic_machine=tic54x-unknown - os=-coff + t90) + basic_machine=t90-cray + os=-unicos + ;; + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown @@ -843,9 +1139,17 @@ case $basic_machine in tx39el) basic_machine=mipstx39el-unknown ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; tower | tower-32) basic_machine=m68k-ncr ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; udi29k) basic_machine=a29k-amd os=-udi @@ -867,8 +1171,8 @@ case $basic_machine in os=-vms ;; vpp*|vx|vx-*) - basic_machine=f301-fujitsu - ;; + basic_machine=f301-fujitsu + ;; vxworks960) basic_machine=i960-wrs os=-vxworks @@ -889,21 +1193,28 @@ case $basic_machine in basic_machine=hppa1.1-winbond os=-proelf ;; - windows32) - basic_machine=i386-pc - os=-windows32-msvcrt - ;; - xmp) - basic_machine=xmp-cray - os=-unicos + xbox) + basic_machine=i686-pc + os=-mingw32 ;; - xps | xps100) + xps | xps100) basic_machine=xps100-honeywell ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; none) basic_machine=none-none os=-none @@ -920,16 +1231,12 @@ case $basic_machine in op60c) basic_machine=hppa1.1-oki ;; - mips) - if [ x$os = x-linux-gnu ]; then - basic_machine=mips-unknown - else - basic_machine=mips-mips - fi - ;; romp) basic_machine=romp-ibm ;; + mmix) + basic_machine=mmix-knuth + ;; rs6000) basic_machine=rs6000-ibm ;; @@ -946,13 +1253,13 @@ case $basic_machine in we32k) basic_machine=we32k-att ;; - sh3 | sh4) + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; - sparc | sparcv9 | sparcv9b) + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; - cydra) + cydra) basic_machine=cydra-cydrome ;; orion) @@ -967,10 +1274,6 @@ case $basic_machine in pmac | pmac-mpw) basic_machine=powerpc-apple ;; - c4x*) - basic_machine=c4x-none - os=-coff - ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; @@ -997,9 +1300,12 @@ esac if [ x"$os" != x"" ] then case $os in - # First match some system type aliases - # that might get confused with valid system types. + # First match some system type aliases + # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; @@ -1020,22 +1326,31 @@ case $os in # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ - | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* \ + | -aos* | -aros* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ - | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* \ + | -chorusos* | -chorusrdb* | -cegcc* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ - | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \ + | -mingw32* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ - | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* | -os2*) + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) @@ -1047,16 +1362,21 @@ case $os in ;; esac ;; + -nto-qnx*) + ;; -nto*) - os=-nto-qnx + os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; @@ -1069,6 +1389,9 @@ case $os in -opened*) os=-openedition ;; + -os400*) + os=-os400 + ;; -wince*) os=-wince ;; @@ -1087,14 +1410,23 @@ case $os in -acis*) os=-aos ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; + -nova*) + os=-rtmk-nova + ;; -ns2 ) - os=-nextstep2 + os=-nextstep2 ;; -nsk*) os=-nsk @@ -1106,6 +1438,9 @@ case $os in -sinix*) os=-sysv4 ;; + -tpf*) + os=-tpf + ;; -triton*) os=-sysv3 ;; @@ -1133,8 +1468,22 @@ case $os in -xenix) os=-xenix ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - os=-mint + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -nacl*) ;; -none) ;; @@ -1158,6 +1507,12 @@ else # system, and we'll never get to this point. case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; *-acorn) os=-riscix1.2 ;; @@ -1167,10 +1522,23 @@ case $basic_machine in arm*-semi) os=-aout ;; + c4x-* | tic4x-*) + os=-coff + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; + # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; - pdp11-*) + pdp11-*) os=-none ;; *-dec | vax-*) @@ -1191,12 +1559,18 @@ case $basic_machine in m68*-cisco) os=-aout ;; + mep-*) + os=-elf + ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; + or32-*) + os=-coff + ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; @@ -1206,9 +1580,15 @@ case $basic_machine in *-be) os=-beos ;; + *-haiku) + os=-haiku + ;; *-ibm) os=-aix ;; + *-knuth) + os=-mmixware + ;; *-wec) os=-proelf ;; @@ -1260,19 +1640,19 @@ case $basic_machine in *-next) os=-nextstep3 ;; - *-gould) + *-gould) os=-sysv ;; - *-highlevel) + *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; - *-sgi) + *-sgi) os=-irix ;; - *-siemens) + *-siemens) os=-sysv4 ;; *-masscomp) @@ -1311,7 +1691,7 @@ case $basic_machine in -sunos*) vendor=sun ;; - -aix*) + -cnk*|-aix*) vendor=ibm ;; -beos*) @@ -1341,10 +1721,16 @@ case $basic_machine in -mvs* | -opened*) vendor=ibm ;; + -os400*) + vendor=ibm + ;; -ptx*) vendor=sequent ;; - -vxsim* | -vxworks*) + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) @@ -1359,13 +1745,16 @@ case $basic_machine in -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; + -vos*) + vendor=stratus + ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os -exit 0 +exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) diff --git a/saslauthd/config/config.guess b/saslauthd/config/config.guess index 6012b396..f7dd69ec 100755 --- a/saslauthd/config/config.guess +++ b/saslauthd/config/config.guess @@ -1,9 +1,10 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 -# Free Software Foundation, Inc. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011 Free Software Foundation, Inc. -timestamp='2001-07-12' +timestamp='2011-08-20' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -17,22 +18,25 @@ timestamp='2001-07-12' # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. -# Written by Per Bothner . -# Please send patches to . + +# Originally written by Per Bothner. Please send patches (context +# diff format) to and include a ChangeLog +# entry. # # This script attempts to guess a canonical system name similar to # config.sub. If it succeeds, it prints the system name on stdout, and # exits with 0. Otherwise, it exits with 1. # -# The plan is that this can be called by configure scripts if you -# don't specify an explicit build system type. +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD me=`echo "$0" | sed -e 's,.*/,,'` @@ -52,8 +56,9 @@ version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 -Free Software Foundation, Inc. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free +Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -65,11 +70,11 @@ Try \`$me --help' for more information." while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) - echo "$timestamp" ; exit 0 ;; + echo "$timestamp" ; exit ;; --version | -v ) - echo "$version" ; exit 0 ;; + echo "$version" ; exit ;; --help | --h* | -h ) - echo "$usage"; exit 0 ;; + echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. @@ -87,30 +92,42 @@ if test $# != 0; then exit 1 fi +trap 'exit 1' 1 2 15 -dummy=dummy-$$ -trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15 +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. -# CC_FOR_BUILD -- compiler used by this script. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. -set_cc_for_build='case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int dummy(){}" > $dummy.c ; - for c in cc gcc c89 ; do - ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ; - if test $? = 0 ; then +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; - rm -f $dummy.c $dummy.o $dummy.rel ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac' +esac ; set_cc_for_build= ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) @@ -127,32 +144,34 @@ UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) - # Netbsd (nbsd) targets should (where applicable) match one or + # NetBSD (nbsd) targets should (where applicable) match one or # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. - # Determine the machine/vendor (is the vendor relevant). - case "${UNAME_MACHINE}" in - amiga) machine=m68k-unknown ;; - arm32) machine=arm-unknown ;; - atari*) machine=m68k-atari ;; - sun3*) machine=m68k-sun ;; - mac68k) machine=m68k-apple ;; - macppc) machine=powerpc-apple ;; - hp3[0-9][05]) machine=m68k-hp ;; - ibmrt|romp-ibm) machine=romp-ibm ;; - *) machine=${UNAME_MACHINE}-unknown ;; + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. - case "${UNAME_MACHINE}" in - i386|sparc|amiga|arm*|hp300|mvme68k|vax|atari|luna68k|mac68k|news68k|next68k|pc532|sun3*|x68k) + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep __ELF__ >/dev/null + | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? @@ -162,121 +181,135 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in fi ;; *) - os=netbsd + os=netbsd ;; esac # The OS release - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" - exit 0 ;; + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; alpha:OSF1:*:*) - if test $UNAME_RELEASE = "V4.0"; then + case $UNAME_RELEASE in + *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` - fi + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. - cat <$dummy.s - .data -\$Lformat: - .byte 37,100,45,37,120,10,0 # "%d-%x\n" - - .text - .globl main - .align 4 - .ent main -main: - .frame \$30,16,\$26,0 - ldgp \$29,0(\$27) - .prologue 1 - .long 0x47e03d80 # implver \$0 - lda \$2,-1 - .long 0x47e20c21 # amask \$2,\$1 - lda \$16,\$Lformat - mov \$0,\$17 - not \$1,\$18 - jsr \$26,printf - ldgp \$29,0(\$26) - mov 0,\$16 - jsr \$26,exit - .end main -EOF - eval $set_cc_for_build - $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null - if test "$?" = 0 ; then - case `./$dummy` in - 0-0) - UNAME_MACHINE="alpha" - ;; - 1-0) - UNAME_MACHINE="alphaev5" - ;; - 1-1) - UNAME_MACHINE="alphaev56" - ;; - 1-101) - UNAME_MACHINE="alphapca56" - ;; - 2-303) - UNAME_MACHINE="alphaev6" - ;; - 2-307) - UNAME_MACHINE="alphaev67" - ;; - esac - fi - rm -f $dummy.s $dummy - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - exit 0 ;; + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix - exit 0 ;; + exit ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 - exit 0 ;; + exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 - exit 0;; - amiga:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; + exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos - exit 0 ;; - arc64:OpenBSD:*:*) - echo mips64el-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - arc:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - hkmips:OpenBSD:*:*) - echo mips-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - pmax:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - sgi:OpenBSD:*:*) - echo mips-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - wgrisc:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; *:OS/390:*:*) echo i370-ibm-openedition - exit 0 ;; + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} - exit 0;; + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp - exit 0;; + exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then @@ -284,25 +317,51 @@ EOF else echo pyramid-pyramid-bsd fi - exit 0 ;; + exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 - exit 0 ;; + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; + exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - i86pc:SunOS:5.*:*) - echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; + exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) @@ -311,12 +370,12 @@ EOF esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` - exit 0 ;; + exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} - exit 0 ;; + exit ;; sun*:*:4.2BSD:*) - UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) @@ -326,13 +385,10 @@ EOF echo sparc-sun-sunos${UNAME_RELEASE} ;; esac - exit 0 ;; + exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} - exit 0 ;; - atari*:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; + exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor @@ -342,51 +398,43 @@ EOF # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit 0 ;; + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} - exit 0 ;; + exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit 0 ;; + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} - exit 0 ;; + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} - exit 0 ;; + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} - exit 0 ;; - sun3*:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mac68k:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mvme68k:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mvme88k:OpenBSD:*:*) - echo m88k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} - exit 0 ;; + exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 - exit 0 ;; + exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} - exit 0 ;; + exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} - exit 0 ;; + exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} - exit 0 ;; + exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ @@ -408,31 +456,36 @@ EOF exit (-1); } EOF - eval $set_cc_for_build - $CC_FOR_BUILD $dummy.c -o $dummy \ - && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ - && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos${UNAME_RELEASE} - exit 0 ;; + exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax - exit 0 ;; + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix - exit 0 ;; + exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 - exit 0 ;; + exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 - exit 0 ;; + exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 - exit 0 ;; + exit ;; AViiON:dgux:*:*) - # DG/UX returns AViiON for all architectures - UNAME_PROCESSOR=`/usr/bin/uname -p` + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ @@ -445,29 +498,29 @@ EOF else echo i586-dg-dgux${UNAME_RELEASE} fi - exit 0 ;; + exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 - exit 0 ;; + exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 - exit 0 ;; + exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 - exit 0 ;; + exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd - exit 0 ;; + exit ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` - exit 0 ;; + exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. - echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id - exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix - exit 0 ;; + exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` @@ -475,9 +528,10 @@ EOF IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} - exit 0 ;; + exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include @@ -489,18 +543,20 @@ EOF exit(0); } EOF - eval $set_cc_for_build - $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy - echo rs6000-ibm-aix3.2.5 + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi - exit 0 ;; - *:AIX:*:[45]) - IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'` + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else @@ -512,97 +568,116 @@ EOF IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} - exit 0 ;; + exit ;; *:AIX:*:*) echo rs6000-ibm-aix - exit 0 ;; + exit ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 - exit 0 ;; + exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to - exit 0 ;; # report: romp-ibm BSD 4.3 + exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx - exit 0 ;; + exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 - exit 0 ;; + exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd - exit 0 ;; + exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 - exit 0 ;; + exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) - case "${HPUX_REV}" in - 11.[0-9][0-9]) - if [ -x /usr/bin/getconf ]; then - sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` - sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in - 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 - 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 - 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in - 32) HP_ARCH="hppa2.0n" ;; - 64) HP_ARCH="hppa2.0w" ;; - esac ;; - esac - fi ;; - esac - if [ "${HP_ARCH}" = "" ]; then - sed 's/^ //' << EOF >$dummy.c + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c - #define _HPUX_SOURCE - #include - #include + #define _HPUX_SOURCE + #include + #include - int main () - { - #if defined(_SC_KERNEL_BITS) - long bits = sysconf(_SC_KERNEL_BITS); - #endif - long cpu = sysconf (_SC_CPU_VERSION); + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1"); break; - case CPU_PA_RISC2_0: - #if defined(_SC_KERNEL_BITS) - switch (bits) - { - case 64: puts ("hppa2.0w"); break; - case 32: puts ("hppa2.0n"); break; - default: puts ("hppa2.0"); break; - } break; - #else /* !defined(_SC_KERNEL_BITS) */ - puts ("hppa2.0"); break; - #endif - default: puts ("hppa1.0"); break; - } - exit (0); - } + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } EOF - eval $set_cc_for_build - (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy` - if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi - rm -f $dummy.c $dummy - fi ;; + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} - exit 0 ;; + exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} - exit 0 ;; + exit ;; 3050*:HI-UX:*:*) + eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int @@ -628,156 +703,163 @@ EOF exit (0); } EOF - eval $set_cc_for_build - $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 - exit 0 ;; + exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd - exit 0 ;; + exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd - exit 0 ;; + exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix - exit 0 ;; + exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf - exit 0 ;; + exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf - exit 0 ;; + exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi - exit 0 ;; + exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites - exit 0 ;; - hppa*:OpenBSD:*:*) - echo hppa-unknown-openbsd - exit 0 ;; + exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd - exit 0 ;; + exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi - exit 0 ;; + exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd - exit 0 ;; + exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd - exit 0 ;; + exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd - exit 0 ;; - CRAY*X-MP:*:*:*) - echo xmp-cray-unicos - exit 0 ;; + exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; + exit ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' - exit 0 ;; + exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY*T3D:*:*:*) - echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; + exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; + exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY-2:*:*:*) - echo cray2-cray-unicos - exit 0 ;; + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` - echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit 0 ;; - hp300:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} - exit 0 ;; + exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} - exit 0 ;; + exit ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} - exit 0 ;; + exit ;; *:FreeBSD:*:*) - echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` - exit 0 ;; - *:OpenBSD:*:*) - echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` - exit 0 ;; + UNAME_PROCESSOR=`/usr/bin/uname -p` + case ${UNAME_PROCESSOR} in + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin - exit 0 ;; - i*:MINGW*:*) + exit ;; + *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 - exit 0 ;; + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 - exit 0 ;; + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? - echo i386-pc-interix - exit 0 ;; + echo i586-pc-interix + exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin - exit 0 ;; + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin - exit 0 ;; + exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; + exit ;; *:GNU:*:*) + # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` - exit 0 ;; + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix - exit 0 ;; - arm*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; - ia64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux - exit 0 ;; - m68*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; - mips:Linux:*:*) - case `sed -n '/^byte/s/^.*: \(.*\) endian/\1/p' < /proc/cpuinfo` in - big) echo mips-unknown-linux-gnu && exit 0 ;; - little) echo mipsel-unknown-linux-gnu && exit 0 ;; - esac - ;; - ppc:Linux:*:*) - echo powerpc-unknown-linux-gnu - exit 0 ;; + exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; @@ -786,12 +868,88 @@ EOF PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; - EV68*) UNAME_MACHINE=alphaev67 ;; - esac - objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} - exit 0 ;; + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-gnu + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo ${UNAME_MACHINE}-unknown-linux-gnueabi + else + echo ${UNAME_MACHINE}-unknown-linux-gnueabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + LIBC=gnu + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-gnu + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in @@ -799,92 +957,71 @@ EOF PA8*) echo hppa2.0-unknown-linux-gnu ;; *) echo hppa-unknown-linux-gnu ;; esac - exit 0 ;; - parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-gnu - exit 0 ;; + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux - exit 0 ;; + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; + exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; + exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; x86_64:Linux:*:*) echo x86_64-unknown-linux-gnu - exit 0 ;; - i*86:Linux:*:*) - # The BFD linker knows what the default object file format is, so - # first see if it will tell us. cd to the root directory to prevent - # problems with other programs or directories called `ld' in the path. - ld_supported_targets=`cd /; ld --help 2>&1 \ - | sed -ne '/supported targets:/!d - s/[ ][ ]*/ /g - s/.*supported targets: *// - s/ .*// - p'` - case "$ld_supported_targets" in - elf32-i386) - TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" - ;; - a.out-i386-linux) - echo "${UNAME_MACHINE}-pc-linux-gnuaout" - exit 0 ;; - coff-i386) - echo "${UNAME_MACHINE}-pc-linux-gnucoff" - exit 0 ;; - "") - # Either a pre-BFD a.out linker (linux-gnuoldld) or - # one that does not give us useful --help. - echo "${UNAME_MACHINE}-pc-linux-gnuoldld" - exit 0 ;; - esac - # Determine whether the default compiler is a.out or elf - cat >$dummy.c < -#ifdef __cplusplus -#include /* for printf() prototype */ - int main (int argc, char *argv[]) { -#else - int main (argc, argv) int argc; char *argv[]; { -#endif -#ifdef __ELF__ -# ifdef __GLIBC__ -# if __GLIBC__ >= 2 - printf ("%s-pc-linux-gnu\n", argv[1]); -# else - printf ("%s-pc-linux-gnulibc1\n", argv[1]); -# endif -# else - printf ("%s-pc-linux-gnulibc1\n", argv[1]); -# endif -#else - printf ("%s-pc-linux-gnuaout\n", argv[1]); -#endif - return 0; -} -EOF - eval $set_cc_for_build - $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy - test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 - ;; + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 - exit 0 ;; + exit ;; i*86:UNIX_SV:4.2MP:2.*) - # Unixware is an offshoot of SVR4, but it has its own version - # number series starting with 2... - # I am not positive that other SVR4 systems won't match this, + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. - # Use sysv4.2uw... so that sysv4* matches it. + # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} - exit 0 ;; + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then @@ -892,99 +1029,113 @@ EOF else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi - exit 0 ;; - i*86:*:5:[78]*) + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} - exit 0 ;; + exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then - UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')` - (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 - (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 - (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \ + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 - (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \ + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi - exit 0 ;; - i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp - exit 0 ;; + exit ;; pc:*:*:*) # Left here for compatibility: - # uname -m prints for DJGPP always 'pc', but it prints nothing about - # the processor, so we play safe by assuming i386. - echo i386-pc-msdosdjgpp - exit 0 ;; + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 - exit 0 ;; + exit ;; paragon:*:*:*) echo i860-intel-osf1 - exit 0 ;; + exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi - exit 0 ;; + exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv - exit 0 ;; - M68*:*:R3V[567]*:*) - test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; - 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0) + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && echo i486-ncr-sysv4.3${OS_REL} && exit 0 + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && echo i486-ncr-sysv4 && exit 0 ;; + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; + exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 - exit 0 ;; - i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) - echo i386-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; + exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; + exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; + exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} - exit 0 ;; + exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 - exit 0 ;; + exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 - exit 0 ;; + exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` @@ -992,78 +1143,123 @@ EOF else echo ns32k-sni-sysv fi - exit 0 ;; - PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort - # says - echo i586-unisys-sysv4 - exit 0 ;; + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 - exit 0 ;; + exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 - exit 0 ;; + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} - exit 0 ;; + exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 - exit 0 ;; + exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} + echo mips-nec-sysv${UNAME_RELEASE} else - echo mips-unknown-sysv${UNAME_RELEASE} + echo mips-unknown-sysv${UNAME_RELEASE} fi - exit 0 ;; + exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos - exit 0 ;; + exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos - exit 0 ;; + exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos - exit 0 ;; + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} - exit 0 ;; + exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} - exit 0 ;; + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} - exit 0 ;; + exit ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} - exit 0 ;; + exit ;; *:Darwin:*:*) - echo `uname -p`-apple-darwin${UNAME_RELEASE} - exit 0 ;; + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + i386) + eval $set_cc_for_build + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + UNAME_PROCESSOR="x86_64" + fi + fi ;; + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) - if test "${UNAME_MACHINE}" = "x86pc"; then + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi - echo `uname -p`-${UNAME_MACHINE}-nto-qnx - exit 0 ;; + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; *:QNX:*:4*) echo i386-pc-qnx - exit 0 ;; - NSR-[KW]:NONSTOP_KERNEL:*:*) + exit ;; + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} - exit 0 ;; + exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux - exit 0 ;; + exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv - exit 0 ;; + exit ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} - exit 0 ;; + exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 @@ -1074,35 +1270,56 @@ EOF UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 - exit 0 ;; - i*86:OS/2:*:*) - # If we were able to find `uname', then EMX Unix compatibility - # is probably installed. - echo ${UNAME_MACHINE}-pc-os2-emx - exit 0 ;; + exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 - exit 0 ;; + exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex - exit 0 ;; + exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 - exit 0 ;; + exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 - exit 0 ;; + exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 - exit 0 ;; + exit ;; *:ITS:*:*) echo pdp10-unknown-its - exit 0 ;; + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 #echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 +eval $set_cc_for_build cat >$dummy.c < @@ -1119,16 +1336,16 @@ main () #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 - "4" + "4" #else - "" + "" #endif - ); exit (0); + ); exit (0); #endif #endif #if defined (__arm) && defined (__acorn) && defined (__unix) - printf ("arm-acorn-riscix"); exit (0); + printf ("arm-acorn-riscix\n"); exit (0); #endif #if defined (hp300) && !defined (hpux) @@ -1217,13 +1434,12 @@ main () } EOF -eval $set_cc_for_build -$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0 -rm -f $dummy.c $dummy +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } # Apollos put the system type in the environment. -test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } # Convex versions that predate uname can use getsysinfo(1) @@ -1232,22 +1448,22 @@ then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd - exit 0 ;; + exit ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi - exit 0 ;; + exit ;; c34*) echo c34-convex-bsd - exit 0 ;; + exit ;; c38*) echo c38-convex-bsd - exit 0 ;; + exit ;; c4*) echo c4-convex-bsd - exit 0 ;; + exit ;; esac fi @@ -1258,7 +1474,9 @@ This script, last modified $timestamp, has failed to recognize the operating system you are using. It is advised that you download the most up to date version of the config scripts from - ftp://ftp.gnu.org/pub/gnu/config/ + http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD +and + http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD If the version you run ($0) is already up to date, please send the following data and any information you think might be diff --git a/saslauthd/config/config.sub b/saslauthd/config/config.sub index 578b3027..da19a880 100755 --- a/saslauthd/config/config.sub +++ b/saslauthd/config/config.sub @@ -1,9 +1,10 @@ #! /bin/sh # Configuration validation subroutine script. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 -# Free Software Foundation, Inc. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011 Free Software Foundation, Inc. -timestamp='2001-06-08' +timestamp='2011-08-23' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software @@ -21,21 +22,26 @@ timestamp='2001-06-08' # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. -# Please send patches to . + +# Please send patches to . Submit a context +# diff and a properly formatted GNU ChangeLog entry. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. @@ -69,8 +75,9 @@ Report bugs and patches to ." version="\ GNU config.sub ($timestamp) -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 -Free Software Foundation, Inc. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free +Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -82,11 +89,11 @@ Try \`$me --help' for more information." while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) - echo "$timestamp" ; exit 0 ;; + echo "$timestamp" ; exit ;; --version | -v ) - echo "$version" ; exit 0 ;; + echo "$version" ; exit ;; --help | --h* | -h ) - echo "$usage"; exit 0 ;; + echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. @@ -98,7 +105,7 @@ while test $# -gt 0 ; do *local*) # First pass through any local machine types. echo $1 - exit 0;; + exit ;; * ) break ;; @@ -117,7 +124,11 @@ esac # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in - nto-qnx* | linux-gnu* | storm-chaos* | os2-emx* | windows32-*) + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; @@ -143,10 +154,13 @@ case $os in -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis) + -apple | -axis | -knuth | -cray | -microblaze) os= basic_machine=$1 ;; + -bluegene*) + os=-cnk + ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 @@ -161,13 +175,17 @@ case $os in os=-chorusos basic_machine=$1 ;; - -chorusrdb) - os=-chorusrdb + -chorusrdb) + os=-chorusrdb basic_machine=$1 - ;; + ;; -hiux*) os=-hiuxwe2 ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` @@ -184,6 +202,10 @@ case $os in # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` @@ -223,35 +245,100 @@ esac case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. - tahoe | i860 | ia64 | m32r | m68k | m68000 | m88k | ns32k | arc \ - | arm | arme[lb] | arm[bl]e | armv[2345] | armv[345][lb] | strongarm | xscale \ - | pyramid | mn10200 | mn10300 | tron | a29k \ - | 580 | i960 | h8300 \ - | x86 | ppcbe | mipsbe | mipsle | shbe | shle \ - | hppa | hppa1.0 | hppa1.1 | hppa2.0 | hppa2.0w | hppa2.0n \ - | hppa64 \ - | alpha | alphaev[4-8] | alphaev56 | alphapca5[67] \ - | alphaev6[78] \ - | we32k | ns16k | clipper | i370 | sh | sh[34] \ - | powerpc | powerpcle \ - | 1750a | dsp16xx | pdp10 | pdp11 \ - | mips16 | mips64 | mipsel | mips64el \ - | mips64orion | mips64orionel | mipstx39 | mipstx39el \ - | mips64vr4300 | mips64vr4300el | mips64vr4100 | mips64vr4100el \ - | mips64vr5000 | mips64vr5000el | mcore | s390 | s390x \ - | sparc | sparclet | sparclite | sparc64 | sparcv9 | sparcv9b \ - | v850 | c4x \ - | thumb | d10v | d30v | fr30 | avr | openrisc | tic80 \ - | pj | pjl | h8500 | z8k) + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | be32 | be64 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 \ + | ns16k | ns32k \ + | open8 \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pyramid \ + | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | we32k \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) basic_machine=$basic_machine-unknown ;; - m6811 | m68hc11 | m6812 | m68hc12) + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12 | picochip) # Motorola 68HC11/12. basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and @@ -265,31 +352,80 @@ case $basic_machine in exit 1 ;; # Recognize the basic CPU types with company name. - # FIXME: clean up the formatting here. - vax-* | tahoe-* | i*86-* | i860-* | ia64-* | m32r-* | m68k-* | m68000-* \ - | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | c[123]* \ - | arm-* | armbe-* | armle-* | armv*-* | strongarm-* | xscale-* \ - | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \ - | power-* | none-* | 580-* | cray2-* | h8300-* | h8500-* | i960-* \ - | xmp-* | ymp-* \ - | x86-* | ppcbe-* | mipsbe-* | mipsle-* | shbe-* | shle-* \ - | hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* | hppa2.0w-* \ - | hppa2.0n-* | hppa64-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphapca5[67]-* \ - | alphaev6[78]-* \ - | we32k-* | cydra-* | ns16k-* | pn-* | np1-* | xps100-* \ - | clipper-* | orion-* \ - | sparclite-* | pdp10-* | pdp11-* | sh-* | sh[34]-* | sh[34]eb-* \ - | powerpc-* | powerpcle-* | sparc64-* | sparcv9-* | sparcv9b-* | sparc86x-* \ - | mips16-* | mips64-* | mipsel-* \ - | mips64el-* | mips64orion-* | mips64orionel-* \ - | mips64vr4100-* | mips64vr4100el-* | mips64vr4300-* | mips64vr4300el-* \ - | mipstx39-* | mipstx39el-* | mcore-* \ - | f30[01]-* | f700-* | s390-* | s390x-* | sv1-* | t3e-* \ - | [cjt]90-* \ - | m88110-* | m680[01234]0-* | m683?2-* | m68360-* | z8k-* | d10v-* \ - | thumb-* | v850-* | d30v-* | tic30-* | tic80-* | c30-* | fr30-* \ - | bs2000-* | tic54x-* | c54x-* | x86_64-* | pj-* | pjl-*) + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pyramid-* \ + | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. @@ -307,6 +443,9 @@ case $basic_machine in basic_machine=a29k-amd os=-udi ;; + abacus) + basic_machine=abacus-unknown + ;; adobe68k) basic_machine=m68010-adobe os=-scout @@ -321,6 +460,12 @@ case $basic_machine in basic_machine=a29k-none os=-bsd ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; amdahl) basic_machine=580-amdahl os=-sysv @@ -344,6 +489,10 @@ case $basic_machine in basic_machine=m68k-apollo os=-bsd ;; + aros) + basic_machine=i386-pc + os=-aros + ;; aux) basic_machine=m68k-apple os=-aux @@ -352,6 +501,35 @@ case $basic_machine in basic_machine=ns32k-sequent os=-dynix ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; convex-c1) basic_machine=c1-convex os=-bsd @@ -372,30 +550,45 @@ case $basic_machine in basic_machine=c38-convex os=-bsd ;; - cray | ymp) - basic_machine=ymp-cray + cray | j90) + basic_machine=j90-cray os=-unicos ;; - cray2) - basic_machine=cray2-cray - os=-unicos + craynv) + basic_machine=craynv-cray + os=-unicosmp ;; - [cjt]90) - basic_machine=${basic_machine}-cray - os=-unicos + cr16 | cr16-*) + basic_machine=cr16-unknown + os=-elf ;; crds | unos) basic_machine=m68k-crds ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola @@ -404,6 +597,14 @@ case $basic_machine in basic_machine=m88k-motorola os=-sysv3 ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx @@ -554,6 +755,14 @@ case $basic_machine in basic_machine=m68k-isi os=-sysv ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; m88k-omron*) basic_machine=m88k-omron ;; @@ -565,10 +774,17 @@ case $basic_machine in basic_machine=ns32k-utek os=-sysv ;; + microblaze) + basic_machine=microblaze-xilinx + ;; mingw32) basic_machine=i386-pc os=-mingw32 ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; miniframe) basic_machine=m68000-convergent ;; @@ -576,36 +792,35 @@ case $basic_machine in basic_machine=m68k-atari os=-mint ;; - mipsel*-linux*) - basic_machine=mipsel-unknown - os=-linux-gnu - ;; - mips*-linux*) - basic_machine=mips-unknown - os=-linux-gnu - ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; - mmix*) - basic_machine=mmix-knuth - os=-mmixware - ;; monitor) basic_machine=m68k-rom68k os=-coff ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; msdos) basic_machine=i386-pc os=-msdos ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; mvs) basic_machine=i370-ibm os=-mvs ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; ncr3000) basic_machine=i486-ncr os=-sysv4 @@ -670,6 +885,12 @@ case $basic_machine in np1) basic_machine=np1-gould ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; nsr-tandem) basic_machine=nsr-tandem ;; @@ -677,6 +898,13 @@ case $basic_machine in basic_machine=hppa1.1-oki os=-proelf ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose @@ -693,48 +921,79 @@ case $basic_machine in basic_machine=i860-intel os=-osf ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; - pc532 | pc532-*) + pc532 | pc532-*) basic_machine=ns32k-pc532 ;; - pentium | p5 | k5 | k6 | nexgen) + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; - pentiumpro | p6 | 6x86 | athlon) + pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; - pentiumii | pentium2) + pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; - pentium-* | p5-* | k5-* | k6-* | nexgen-*) + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; - pentiumii-* | pentium2-*) + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; - ppc) basic_machine=powerpc-unknown - ;; - ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ppc | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown - ;; + ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; ps2) basic_machine=i386-ibm ;; @@ -742,6 +1001,10 @@ case $basic_machine in basic_machine=i586-unknown os=-pw32 ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; rom68k) basic_machine=m68k-rom68k os=-coff @@ -752,10 +1015,30 @@ case $basic_machine in rtpc | rtpc-*) basic_machine=romp-ibm ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; sa29200) basic_machine=a29k-amd os=-udi ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; sequent) basic_machine=i386-sequent ;; @@ -763,7 +1046,13 @@ case $basic_machine in basic_machine=sh-hitachi os=-hms ;; - sparclite-wrs) + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; @@ -781,6 +1070,9 @@ case $basic_machine in basic_machine=i860-stratus os=-sysv4 ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; sun2) basic_machine=m68000-sun ;; @@ -830,12 +1122,16 @@ case $basic_machine in os=-dynix ;; t3e) - basic_machine=t3e-cray + basic_machine=alphaev5-cray os=-unicos ;; - tic54x | c54x*) - basic_machine=tic54x-unknown - os=-coff + t90) + basic_machine=t90-cray + os=-unicos + ;; + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown @@ -843,9 +1139,17 @@ case $basic_machine in tx39el) basic_machine=mipstx39el-unknown ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; tower | tower-32) basic_machine=m68k-ncr ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; udi29k) basic_machine=a29k-amd os=-udi @@ -867,8 +1171,8 @@ case $basic_machine in os=-vms ;; vpp*|vx|vx-*) - basic_machine=f301-fujitsu - ;; + basic_machine=f301-fujitsu + ;; vxworks960) basic_machine=i960-wrs os=-vxworks @@ -889,21 +1193,28 @@ case $basic_machine in basic_machine=hppa1.1-winbond os=-proelf ;; - windows32) - basic_machine=i386-pc - os=-windows32-msvcrt - ;; - xmp) - basic_machine=xmp-cray - os=-unicos + xbox) + basic_machine=i686-pc + os=-mingw32 ;; - xps | xps100) + xps | xps100) basic_machine=xps100-honeywell ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; none) basic_machine=none-none os=-none @@ -920,16 +1231,12 @@ case $basic_machine in op60c) basic_machine=hppa1.1-oki ;; - mips) - if [ x$os = x-linux-gnu ]; then - basic_machine=mips-unknown - else - basic_machine=mips-mips - fi - ;; romp) basic_machine=romp-ibm ;; + mmix) + basic_machine=mmix-knuth + ;; rs6000) basic_machine=rs6000-ibm ;; @@ -946,13 +1253,13 @@ case $basic_machine in we32k) basic_machine=we32k-att ;; - sh3 | sh4) + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; - sparc | sparcv9 | sparcv9b) + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; - cydra) + cydra) basic_machine=cydra-cydrome ;; orion) @@ -967,10 +1274,6 @@ case $basic_machine in pmac | pmac-mpw) basic_machine=powerpc-apple ;; - c4x*) - basic_machine=c4x-none - os=-coff - ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; @@ -997,9 +1300,12 @@ esac if [ x"$os" != x"" ] then case $os in - # First match some system type aliases - # that might get confused with valid system types. + # First match some system type aliases + # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; @@ -1020,22 +1326,31 @@ case $os in # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ - | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* \ + | -aos* | -aros* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ - | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* \ + | -chorusos* | -chorusrdb* | -cegcc* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ - | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \ + | -mingw32* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ - | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* | -os2*) + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) @@ -1047,16 +1362,21 @@ case $os in ;; esac ;; + -nto-qnx*) + ;; -nto*) - os=-nto-qnx + os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; @@ -1069,6 +1389,9 @@ case $os in -opened*) os=-openedition ;; + -os400*) + os=-os400 + ;; -wince*) os=-wince ;; @@ -1087,14 +1410,23 @@ case $os in -acis*) os=-aos ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; + -nova*) + os=-rtmk-nova + ;; -ns2 ) - os=-nextstep2 + os=-nextstep2 ;; -nsk*) os=-nsk @@ -1106,6 +1438,9 @@ case $os in -sinix*) os=-sysv4 ;; + -tpf*) + os=-tpf + ;; -triton*) os=-sysv3 ;; @@ -1133,8 +1468,22 @@ case $os in -xenix) os=-xenix ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - os=-mint + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -nacl*) ;; -none) ;; @@ -1158,6 +1507,12 @@ else # system, and we'll never get to this point. case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; *-acorn) os=-riscix1.2 ;; @@ -1167,10 +1522,23 @@ case $basic_machine in arm*-semi) os=-aout ;; + c4x-* | tic4x-*) + os=-coff + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; + # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; - pdp11-*) + pdp11-*) os=-none ;; *-dec | vax-*) @@ -1191,12 +1559,18 @@ case $basic_machine in m68*-cisco) os=-aout ;; + mep-*) + os=-elf + ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; + or32-*) + os=-coff + ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; @@ -1206,9 +1580,15 @@ case $basic_machine in *-be) os=-beos ;; + *-haiku) + os=-haiku + ;; *-ibm) os=-aix ;; + *-knuth) + os=-mmixware + ;; *-wec) os=-proelf ;; @@ -1260,19 +1640,19 @@ case $basic_machine in *-next) os=-nextstep3 ;; - *-gould) + *-gould) os=-sysv ;; - *-highlevel) + *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; - *-sgi) + *-sgi) os=-irix ;; - *-siemens) + *-siemens) os=-sysv4 ;; *-masscomp) @@ -1311,7 +1691,7 @@ case $basic_machine in -sunos*) vendor=sun ;; - -aix*) + -cnk*|-aix*) vendor=ibm ;; -beos*) @@ -1341,10 +1721,16 @@ case $basic_machine in -mvs* | -opened*) vendor=ibm ;; + -os400*) + vendor=ibm + ;; -ptx*) vendor=sequent ;; - -vxsim* | -vxworks*) + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) @@ -1359,13 +1745,16 @@ case $basic_machine in -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; + -vos*) + vendor=stratus + ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os -exit 0 +exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) From 7d2b61769de0f06740718b0739df58b68374322d Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Fri, 2 Sep 2011 14:25:52 +0000 Subject: [PATCH 103/796] Removed an error introduced by an incorrectly applied patch --- plugins/scram.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/plugins/scram.c b/plugins/scram.c index 1fd2348c..81985960 100644 --- a/plugins/scram.c +++ b/plugins/scram.c @@ -1,6 +1,6 @@ /* SCRAM-SHA-1 SASL plugin * Alexey Melnikov - * $Id: scram.c,v 1.24 2011/09/01 14:50:24 mel Exp $ + * $Id: scram.c,v 1.25 2011/09/02 14:25:52 mel Exp $ */ /* * Copyright (c) 2009-2010 Carnegie Mellon University. All rights reserved. @@ -69,7 +69,7 @@ /***************************** Common Section *****************************/ -static const char plugin_id[] = "$Id: scram.c,v 1.24 2011/09/01 14:50:24 mel Exp $"; +static const char plugin_id[] = "$Id: scram.c,v 1.25 2011/09/02 14:25:52 mel Exp $"; #define NONCE_SIZE (32) /* arbitrary */ #define SALT_SIZE (16) /* arbitrary */ @@ -1949,7 +1949,6 @@ scram_client_mech_step1(client_context_t *text, case SASL_CB_DISP_USED: if (!SASL_CB_PRESENT(params)) { result = SASL_BADPARAM; - sparams->utils->free(salt); goto cleanup; } channel_binding_name = params->cbinding->name; From 989fdd1316737a1b3c790f4a34df0eb16481f5ac Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Fri, 2 Sep 2011 17:15:28 +0000 Subject: [PATCH 104/796] Bumped the version number to 2.1.25 --- include/sasl.h | 2 +- win32/common.mak | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/sasl.h b/include/sasl.h index 6bdf2d3c..5bbbbfbc 100755 --- a/include/sasl.h +++ b/include/sasl.h @@ -124,7 +124,7 @@ /* Keep in sync with win32/common.mak */ #define SASL_VERSION_MAJOR 2 #define SASL_VERSION_MINOR 1 -#define SASL_VERSION_STEP 24 +#define SASL_VERSION_STEP 25 /* A convenience macro: same as was defined in the OpenLDAP LDAPDB */ #define SASL_VERSION_FULL ((SASL_VERSION_MAJOR << 16) |\ diff --git a/win32/common.mak b/win32/common.mak index 41d41030..69a39931 100644 --- a/win32/common.mak +++ b/win32/common.mak @@ -2,7 +2,7 @@ #Keep in sync with include/sasl.h and win32/include/config.h SASL_VERSION_MAJOR=2 SASL_VERSION_MINOR=1 -SASL_VERSION_STEP=24 +SASL_VERSION_STEP=25 !IF "$(STATIC)" == "" STATIC=yes From 67489da96df1ee528a6fbf9bdd856e084b37342c Mon Sep 17 00:00:00 2001 From: Ken Murchison Date: Mon, 5 Sep 2011 14:18:10 +0000 Subject: [PATCH 105/796] Getting ready for 2.1.25 --- configure.in | 4 ++-- lib/Makefile.am | 4 ++-- plugins/Makefile.am | 4 ++-- saslauthd/configure.in | 2 +- sasldb/Makefile.am | 4 ++-- win32/include/config.h | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/configure.in b/configure.in index c635f975..9de4c9e9 100644 --- a/configure.in +++ b/configure.in @@ -1,7 +1,7 @@ dnl configure.in for the SASL library dnl Rob Siemborski dnl Rob Earhart -dnl $Id: configure.in,v 1.220 2011/04/07 08:50:31 mel Exp $ +dnl $Id: configure.in,v 1.221 2011/09/05 14:18:10 murch Exp $ dnl dnl Copyright (c) 2001 Carnegie Mellon University. All rights reserved. dnl @@ -59,7 +59,7 @@ dnl dnl REMINDER: When changing the version number here, please also update dnl the values in win32/include/config.h and include/sasl.h as well. dnl -AM_INIT_AUTOMAKE(cyrus-sasl, 2.1.24) +AM_INIT_AUTOMAKE(cyrus-sasl, 2.1.25) CMU_INIT_AUTOMAKE # and include our config dir scripts diff --git a/lib/Makefile.am b/lib/Makefile.am index b73e45cd..6e1b8c57 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1,6 +1,6 @@ # Makefile.am for the SASL library # Rob Earhart -# $Id: Makefile.am,v 1.87 2009/05/20 12:24:49 murch Exp $ +# $Id: Makefile.am,v 1.88 2011/09/05 14:18:10 murch Exp $ # Copyright (c) 2000 Carnegie Mellon University. All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -41,7 +41,7 @@ # # Library version info - here at the top, for sanity -sasl_version = 2:24:0 +sasl_version = 2:25:0 INCLUDES=-I$(top_srcdir)/include -I$(top_srcdir)/plugins -I$(top_builddir)/include -I$(top_srcdir)/sasldb diff --git a/plugins/Makefile.am b/plugins/Makefile.am index d97c6790..b00915fc 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -1,7 +1,7 @@ # Makefile.am for the SASL plugins # Rob Siemborski # Rob Earhart -# $Id: Makefile.am,v 1.85 2011/04/19 15:23:52 mel Exp $ +# $Id: Makefile.am,v 1.86 2011/09/05 14:18:10 murch Exp $ # ################################################################ # Copyright (c) 2000 Carnegie Mellon University. All rights reserved. @@ -46,7 +46,7 @@ # Library version info - here at the top, for sanity # CURRENT:REVISION:AGE -plugin_version = 2:24:0 +plugin_version = 2:25:0 INCLUDES=-I$(top_srcdir)/include -I$(top_srcdir)/lib -I$(top_srcdir)/sasldb -I$(top_builddir)/include AM_LDFLAGS = -module -export-dynamic -rpath $(plugindir) -version-info $(plugin_version) diff --git a/saslauthd/configure.in b/saslauthd/configure.in index 31ec6577..f79d65d7 100644 --- a/saslauthd/configure.in +++ b/saslauthd/configure.in @@ -15,7 +15,7 @@ AC_ARG_WITH(saslauthd, [ --with-saslauthd=DIR enable use of the saslauth dae AC_DEFINE_UNQUOTED(PATH_SASLAUTHD_RUNDIR, "$with_saslauthd",[Location of saslauthd socket]) AM_CONDITIONAL(SASLAUTHD, test "$with_saslauthd" != no) -AM_INIT_AUTOMAKE(saslauthd,2.1.24) +AM_INIT_AUTOMAKE(saslauthd,2.1.25) CMU_INIT_AUTOMAKE dnl Checks for programs. diff --git a/sasldb/Makefile.am b/sasldb/Makefile.am index ed200b41..067477cb 100644 --- a/sasldb/Makefile.am +++ b/sasldb/Makefile.am @@ -1,6 +1,6 @@ # Makefile.am for the SASLdb library # Rob Siemborski -# $Id: Makefile.am,v 1.32 2009/05/07 13:49:31 murch Exp $ +# $Id: Makefile.am,v 1.33 2011/09/05 14:18:10 murch Exp $ # Copyright (c) 2000 Carnegie Mellon University. All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -42,7 +42,7 @@ # Library version info - here at the top, for sanity # Note that this doesn't necessaraly follow the libsasl2 verison info -sasl_version = 1:24:0 +sasl_version = 1:25:0 INCLUDES=-I$(top_srcdir)/include -I$(top_builddir)/include @SASL_DB_INC@ diff --git a/win32/include/config.h b/win32/include/config.h index aa4a5297..5c35c98b 100644 --- a/win32/include/config.h +++ b/win32/include/config.h @@ -55,7 +55,7 @@ #define PACKAGE "cyrus-sasl" /* Our version */ -#define VERSION "2.1.24" +#define VERSION "2.1.25" /* Visual Studio supports prototypes */ #define PROTOTYPES 1 From d868b96ad4340904ca6a8850988a181164d78dbf Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Wed, 7 Sep 2011 12:32:07 +0000 Subject: [PATCH 106/796] Getting ready for 2.1.25 --- NEWS | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/NEWS b/NEWS index 9bd50a81..b4eb0395 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,55 @@ +New in 2.1.25 +------------- + +* Make sure that a failed authorization doesn't preclude + further server-side SASL authentication attempts from working. +* Fixed a crash caused by aborted SASL authentication + and initiation of another one using the same SASL context. +* (Windows) Fixed the random number generator to actually produce random + output on each run. +* Be protective against calling sasl_server_step once authentication + has failed (multiple SASL plugins) +* Fixed several bugs in the mech_avail callback handling + in the server side code. +* Added support for channel bindings +* Added support for ordering SASL mechanisms by strength (on the client side), + or using the "client_mech_list" option. +* server_idle needs to obey server's SASL mechanism list from the server + context. +* Better server plugin API mismatch reporting +* Build: + - Updated config to the latest GNU snapshot + - Fixed SASL's libtool MacOS/X 64-bit file magic +* New SASL plugin: SCRAM +* New SASL plugin: GS2 +* DIGEST-MD5 plugin: + - Allow DIGEST-MD5 plugin to be used for client-side and + server-side HTTP Digest, including running over non-persistent + connections (RFC 2617) + - Use the same username for reauthentication cache lookup and update + - Minimize the number of auxprop lookups in the server side DIGEST-MD5 + plugin for the most common case when authentication and authorization + identities are the same. + - Updated digestmd5_server_mech_step2() to be more defensive against + empty client input. + - Fixed some memory leaks on failed plugin initialization. + Prevent potential race condition when freeding plugin state. + Set the freed reauthentication cache mutex to NULL, to make errors + due to mutex access after free more obvious. + - Test against broken UTF-8 based hashes if calculation using special + ISO-8859-1 code fails. + - Fixed an interop problem with some LDAP clients ignoring server + advertised realm and providing their own. +* GSSAPI plugin: + - Fix to build GSSAPI with Heimdal + - Properly set serveroutlen to 0 in one place. + Don't send empty challenge once server context establishment is done, + as this is in violation of the RFC 2222 and its successor. + - Don't send maxbuf, if no security layer can be established. + Added additional checks for buffer lengths. +* LDAPDB plugin: + - build fixes + New in 2.1.24 ------------- @@ -82,6 +134,7 @@ New in 2.1.24 New in 2.1.23 ------------- + * Fixed CERT VU#238019 (make sure sasl_encode64() always NUL terminates output or returns SASL_BUFOVER) From 8787bfd2e0648a7f6f4005c06049cbeaa48e1e4a Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Wed, 7 Sep 2011 12:41:51 +0000 Subject: [PATCH 107/796] Mention sasl_client_done/sasl_server_done whenever sasl_done is also mentioned. --- doc/plugprog.html | 6 +++--- doc/programming.html | 12 +++++++++++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/doc/plugprog.html b/doc/plugprog.html index 274195ea..b1b7a3aa 100644 --- a/doc/plugprog.html +++ b/doc/plugprog.html @@ -1,6 +1,6 @@ SASL Plugin Programmer's Guide - +

SASL Plugin Programmer's Guide

@@ -184,7 +184,7 @@

NOTE: This is a work in progress. Any contributions would be This is only called when the connection will no longer be used (e.g. when sasl_dispose is called)
  • mech_free - Called when the sasl library is shutting down - (by sasl_done). + (by sasl_client_done/sasl_server_done/sasl_done). Intended to free any global state of the plugin.
  • Server Plugins

    @@ -239,7 +239,7 @@

    NOTE: This is a work in progress. Any contributions would be This is only called when the connection will no longer be used (e.g. when sasl_dispose is called)
  • mech_free - Called when the sasl library is shutting down - (by sasl_done). + (by sasl_client_done/sasl_server_done/sasl_done). Intended to free any global state of the plugin.
  • setpass - Called to set a user's password. This allows mechanisms to support their own internal password or secret diff --git a/doc/programming.html b/doc/programming.html index e6b0ac4f..00fac386 100644 --- a/doc/programming.html +++ b/doc/programming.html @@ -467,10 +467,20 @@

    How does this look in code

    example):
    -            sasl_done();         
    +            sasl_client_done();
          
     
    +Or if your application is both a SASL client and a SASL server: + +
    +            sasl_done();
    +     
    +
    + +But note that applications should be using sasl_client_done()/sasl_server_done() whenever possible. + +

    sasl_client_init

    
    From 7506f11a221fc5d1c4bfe8cb7edbda8b8cd90b42 Mon Sep 17 00:00:00 2001
    From: Ken Murchison 
    Date: Wed, 7 Sep 2011 13:19:44 +0000
    Subject: [PATCH 108/796] Allow cmusaslCRAM property to be disabled
    
    ---
     ChangeLog          |  4 ++++
     configure.in       | 11 ++++++++++-
     plugins/NTMakefile |  4 +++-
     plugins/cram.c     | 15 +++++++++++----
     4 files changed, 28 insertions(+), 6 deletions(-)
    
    diff --git a/ChangeLog b/ChangeLog
    index a1d1e98b..c9f886a5 100644
    --- a/ChangeLog
    +++ b/ChangeLog
    @@ -1,3 +1,7 @@
    +2011-09-07  Alexey Melnikov 
    +	* configure.in, plugins/NTMakefile, plugins/cramd.c:
    +	  Allow cmusaslCRAM property to be disabled.
    +
     2011-09-02  Alexey Melnikov 
     	* config/config.guess, config/config.sub, saslauthd/config/config.guess,
     	  saslauthd/config/config.sub: Updated config to the latest GNU snapshot.
    diff --git a/configure.in b/configure.in
    index 9de4c9e9..60fb1542 100644
    --- a/configure.in
    +++ b/configure.in
    @@ -1,7 +1,7 @@
     dnl configure.in for the SASL library
     dnl Rob Siemborski
     dnl Rob Earhart
    -dnl $Id: configure.in,v 1.221 2011/09/05 14:18:10 murch Exp $
    +dnl $Id: configure.in,v 1.222 2011/09/07 13:19:44 murch Exp $
     dnl
     dnl Copyright (c) 2001 Carnegie Mellon University.  All rights reserved.
     dnl
    @@ -78,6 +78,12 @@ AC_ARG_ENABLE(sample,
                                   [compile sample code [[yes]]])],
                   enable_sample=yes)
     
    +AC_ARG_ENABLE(obsolete_cram_attr,
    +              [AC_HELP_STRING([--enable-obsolete_cram_attr],
    +                              [enable support for cmusaslsecretCRAM-MD5 auxprop property [[yes]]])],
    +              enable_obsolete_cram_attr=$enableval,
    +              enable_obsolete_cram_attr=yes)
    +
     AC_PROG_CC
     AC_PROG_CPP
     AC_PROG_AWK
    @@ -382,6 +388,9 @@ AC_MSG_CHECKING(CRAM-MD5)
     if test "$cram" != no; then
       AC_MSG_RESULT(enabled)
       SASL_MECHS="$SASL_MECHS libcrammd5.la"
    +  if test "$enable_obsolete_cram_attr" = yes; then
    +    CPPFLAGS="$CPPFLAGS -DOBSOLETE_CRAM_ATTR=1"
    +  fi
       if test "$enable_static" = yes; then
         SASL_STATIC_OBJS="$SASL_STATIC_OBJS cram.o"
         SASL_STATIC_SRCS="$SASL_STATIC_SRCS \$(top_srcdir)/plugins/cram.c"
    diff --git a/plugins/NTMakefile b/plugins/NTMakefile
    index ffd0ef50..0b7665ef 100755
    --- a/plugins/NTMakefile
    +++ b/plugins/NTMakefile
    @@ -125,6 +125,8 @@ GSS_FLAGS=
     GSS_LIBS=
     !ENDIF 
     
    +CRAM_FLAGS=/DOBSOLETE_CRAM_ATTR=1
    +
     DIGEST_FLAGS=/D "WITH_RC4"
     
     # Auxprop Plugin
    @@ -145,7 +147,7 @@ DB_FLAGS = /I $(DB_INCLUDE) /I "..\sasldb" /D "LIBSASL_EXPORTS" /D "KEEP_DB_OPEN
     EXTRA_FLAGS = /D TARGET_WIN_SYSTEM=$(TARGET_WIN_SYSTEM) $(EXTRA_FLAGS)
     !ENDIF
     
    -EXTRA_FLAGS=$(EXTRA_FLAGS) $(DB_FLAGS) $(OPENSSL_FLAGS) $(GSS_FLAGS) $(SRP_FLAGS) $(SQL_FLAGS) $(DIGEST_FLAGS) $(LDAP_FLAGS)
    +EXTRA_FLAGS=$(EXTRA_FLAGS) $(DB_FLAGS) $(OPENSSL_FLAGS) $(GSS_FLAGS) $(SRP_FLAGS) $(SQL_FLAGS) $(DIGEST_FLAGS) $(CRAM_FLAGS) $(LDAP_FLAGS)
     CPPFLAGS = /I "..\win32\include" /I "." /I "..\include" $(EXTRA_FLAGS) /D "WIN32" /D "_WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL"
     
     DB_LIBS=/libpath:$(DB_LIBPATH) $(DB_LIB)
    diff --git a/plugins/cram.c b/plugins/cram.c
    index 6da3fb07..8fe33cfb 100644
    --- a/plugins/cram.c
    +++ b/plugins/cram.c
    @@ -1,7 +1,7 @@
     /* CRAM-MD5 SASL plugin
      * Rob Siemborski
      * Tim Martin 
    - * $Id: cram.c,v 1.86 2010/11/30 11:41:47 mel Exp $
    + * $Id: cram.c,v 1.87 2011/09/07 13:19:44 murch Exp $
      */
     /* 
      * Copyright (c) 1998-2003 Carnegie Mellon University.  All rights reserved.
    @@ -65,7 +65,7 @@
     
     /*****************************  Common Section  *****************************/
     
    -static const char plugin_id[] = "$Id: cram.c,v 1.86 2010/11/30 11:41:47 mel Exp $";
    +static const char plugin_id[] = "$Id: cram.c,v 1.87 2011/09/07 13:19:44 murch Exp $";
     
     /* convert a string of 8bit chars to it's representation in hex
      * using lowercase letters
    @@ -224,7 +224,9 @@ crammd5_server_mech_step2(server_context_t *text,
         size_t len;
         int result = SASL_FAIL;
         const char *password_request[] = { SASL_AUX_PASSWORD,
    +#if defined(OBSOLETE_CRAM_ATTR)
     				       "*cmusaslsecretCRAM-MD5",
    +#endif
     				       NULL };
         struct propval auxprop_values[3];
         HMAC_MD5_CTX tmphmac;
    @@ -265,8 +267,11 @@ crammd5_server_mech_step2(server_context_t *text,
     					   password_request,
     					   auxprop_values);
         if (result < 0 ||
    -	((!auxprop_values[0].name || !auxprop_values[0].values) &&
    -	 (!auxprop_values[1].name || !auxprop_values[1].values))) {
    +	((!auxprop_values[0].name || !auxprop_values[0].values)
    +#if defined(OBSOLETE_CRAM_ATTR)
    +	  && (!auxprop_values[1].name || !auxprop_values[1].values)
    +#endif
    +	)) {
     	/* We didn't find this username */
     	sparams->utils->seterror(sparams->utils->conn,0,
     				 "no secret in database");
    @@ -294,10 +299,12 @@ crammd5_server_mech_step2(server_context_t *text,
     	sparams->utils->hmac_md5_precalc(&md5state, /* OUT */
     					 sec->data,
     					 sec->len);
    +#if defined(OBSOLETE_CRAM_ATTR)
         } else if (auxprop_values[1].name && auxprop_values[1].values) {
     	/* We have a precomputed secret */
     	memcpy(&md5state, auxprop_values[1].values[0],
     	       sizeof(HMAC_MD5_STATE));
    +#endif
         } else {
     	sparams->utils->seterror(sparams->utils->conn, 0,
     				 "Have neither type of secret");
    
    From 89173b72832d668f74d820bd19d9b66f3578cf21 Mon Sep 17 00:00:00 2001
    From: Ken Murchison 
    Date: Wed, 7 Sep 2011 16:09:40 +0000
    Subject: [PATCH 109/796] Fixed 3 memory leaks in SCRAM
    
    ---
     ChangeLog       |  3 +++
     plugins/scram.c | 29 +++++++++++++++++++++--------
     2 files changed, 24 insertions(+), 8 deletions(-)
    
    diff --git a/ChangeLog b/ChangeLog
    index c9f886a5..a7414a0d 100644
    --- a/ChangeLog
    +++ b/ChangeLog
    @@ -1,3 +1,6 @@
    +2011-09-07  Ken Murchison 
    +	* plugins/scram.c:
    +	  Fixed 3 memory leaks in SCRAM
     2011-09-07  Alexey Melnikov 
     	* configure.in, plugins/NTMakefile, plugins/cramd.c:
     	  Allow cmusaslCRAM property to be disabled.
    diff --git a/plugins/scram.c b/plugins/scram.c
    index 81985960..62a101c9 100644
    --- a/plugins/scram.c
    +++ b/plugins/scram.c
    @@ -1,6 +1,6 @@
     /* SCRAM-SHA-1 SASL plugin
      * Alexey Melnikov
    - * $Id: scram.c,v 1.25 2011/09/02 14:25:52 mel Exp $
    + * $Id: scram.c,v 1.26 2011/09/07 16:09:40 murch Exp $
      */
     /* 
      * Copyright (c) 2009-2010 Carnegie Mellon University.  All rights reserved.
    @@ -69,7 +69,7 @@
     
     /*****************************  Common Section  *****************************/
     
    -static const char plugin_id[] = "$Id: scram.c,v 1.25 2011/09/02 14:25:52 mel Exp $";
    +static const char plugin_id[] = "$Id: scram.c,v 1.26 2011/09/07 16:09:40 murch Exp $";
     
     #define NONCE_SIZE (32)		    /* arbitrary */
     #define SALT_SIZE  (16)		    /* arbitrary */
    @@ -445,6 +445,7 @@ typedef struct server_context {
         char * authorization_id;
     
         char * out_buf;
    +    unsigned out_buf_len;
         char * auth_message;
         size_t auth_message_len;
         char * nonce;
    @@ -1028,8 +1029,11 @@ scram_server_mech_step1(server_context_t *text,
     			      base64len +
     			      ITERATION_COUNTER_BUF_LEN +
     			      strlen("r=,s=,i=");
    -    text->out_buf = (char *) sparams->utils->malloc(estimated_challenge_len + 1);
    -    if (text->out_buf == NULL) {
    +    result = _plug_buf_alloc(sparams->utils,
    +			     &(text->out_buf),
    +			     &(text->out_buf_len),
    +			     (unsigned) estimated_challenge_len + 1);
    +    if (result != SASL_OK) {
     	MEMERROR( sparams->utils );
     	result = SASL_NOMEM;
     	goto cleanup;
    @@ -1362,8 +1366,11 @@ scram_server_mech_step2(server_context_t *text,
         }
     
         server_proof_len = (SCRAM_HASH_SIZE / 3 * 4 + (SCRAM_HASH_SIZE % 3 ? 4 : 0));
    -    text->out_buf = (char *) sparams->utils->malloc(server_proof_len + strlen("v=") + 1);
    -    if (text->out_buf == NULL) {
    +    result = _plug_buf_alloc(sparams->utils,
    +			     &(text->out_buf),
    +			     &(text->out_buf_len),
    +			     (unsigned) server_proof_len + strlen("v=") + 1);
    +    if (result != SASL_OK) {
     	MEMERROR( sparams->utils );
     	result = SASL_NOMEM;
     	goto cleanup;
    @@ -1417,6 +1424,9 @@ scram_server_mech_step2(server_context_t *text,
         result = SASL_OK;
         
     cleanup:
    +    if (inbuf != NULL) {
    +	sparams->utils->free(inbuf);
    +    }
         if (binary_channel_binding != NULL) {
     	sparams->utils->free(binary_channel_binding);
         }
    @@ -2314,8 +2324,11 @@ scram_client_mech_step2(client_context_t *text,
     			     strlen(text->nonce)+
     			     client_proof_len +
     			     strlen("c=,r=,p=");
    -    text->out_buf = (char *) params->utils->malloc(estimated_response_len + 1);
    -    if (text->out_buf == NULL) {
    +    result = _plug_buf_alloc(params->utils,
    +			     &(text->out_buf),
    +			     &(text->out_buf_len),
    +			     (unsigned) estimated_response_len + 1);
    +    if (result != SASL_OK) {
     	MEMERROR( params->utils );
     	result = SASL_NOMEM;
     	goto cleanup;
    
    From ee063a3c4326cee27685dc490cae08e49a800059 Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Wed, 7 Sep 2011 16:20:41 +0000
    Subject: [PATCH 110/796] Minor cleanup in description
    
    ---
     ChangeLog | 5 +++--
     1 file changed, 3 insertions(+), 2 deletions(-)
    
    diff --git a/ChangeLog b/ChangeLog
    index a7414a0d..d0920434 100644
    --- a/ChangeLog
    +++ b/ChangeLog
    @@ -1,9 +1,10 @@
     2011-09-07  Ken Murchison 
     	* plugins/scram.c:
     	  Fixed 3 memory leaks in SCRAM
    +
     2011-09-07  Alexey Melnikov 
    -	* configure.in, plugins/NTMakefile, plugins/cramd.c:
    -	  Allow cmusaslCRAM property to be disabled.
    +	* configure.in, plugins/NTMakefile, plugins/cram.c:
    +	  Allow use of cmusaslsecretCRAM-MD5 property to be disabled.
     
     2011-09-02  Alexey Melnikov 
     	* config/config.guess, config/config.sub, saslauthd/config/config.guess,
    
    From 42babc06e9928760f83e16c3f64931e8763f6304 Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Fri, 9 Sep 2011 09:50:00 +0000
    Subject: [PATCH 111/796] Updated the copyright year to 2011
    
    ---
     lib/NTMakefile     | 2 +-
     plugins/NTMakefile | 2 +-
     2 files changed, 2 insertions(+), 2 deletions(-)
    
    diff --git a/lib/NTMakefile b/lib/NTMakefile
    index 14d485a1..b7357763 100755
    --- a/lib/NTMakefile
    +++ b/lib/NTMakefile
    @@ -99,7 +99,7 @@ BEGIN
                 VALUE "FileDescription", "CMU SASL API v2\0"
                 VALUE "FileVersion", "$(SASL_VERSION_MAJOR).$(SASL_VERSION_MINOR).$(SASL_VERSION_STEP).0\0"
                 VALUE "InternalName", "libsasl\0"
    -            VALUE "LegalCopyright", "Copyright (c) Carnegie Mellon University 2002-2009\0"
    +            VALUE "LegalCopyright", "Copyright (c) Carnegie Mellon University 2002-2011\0"
                 VALUE "OriginalFilename", "libsasl.dll\0"
                 VALUE "ProductName", "Carnegie Mellon University SASL\0"
                 VALUE "ProductVersion", "$(SASL_VERSION_MAJOR).$(SASL_VERSION_MINOR).$(SASL_VERSION_STEP)-0"
    diff --git a/plugins/NTMakefile b/plugins/NTMakefile
    index 0b7665ef..fc547512 100755
    --- a/plugins/NTMakefile
    +++ b/plugins/NTMakefile
    @@ -309,7 +309,7 @@ BEGIN
                 VALUE "FileDescription", "CMU SASL $(@B) plugin\0"
                 VALUE "FileVersion", "$(SASL_VERSION_MAJOR).$(SASL_VERSION_MINOR).$(SASL_VERSION_STEP).0\0"
                 VALUE "InternalName", "$(@B)\0"
    -            VALUE "LegalCopyright", "Copyright (c) Carnegie Mellon University 2002-2009\0"
    +            VALUE "LegalCopyright", "Copyright (c) Carnegie Mellon University 2002-2011\0"
                 VALUE "OriginalFilename", "$(@B).dll\0"
                 VALUE "ProductName", "Carnegie Mellon University SASL\0"
                 VALUE "ProductVersion", "$(SASL_VERSION_MAJOR).$(SASL_VERSION_MINOR).$(SASL_VERSION_STEP)-0"
    
    From 75549cd2a90fa246658b0bb807c62e316238b253 Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Fri, 9 Sep 2011 10:29:41 +0000
    Subject: [PATCH 112/796] SCRAM always needs OpenSSL, make sure OPENSSL_FLAGS
     is alway used
    
    ---
     plugins/NTMakefile | 4 +++-
     1 file changed, 3 insertions(+), 1 deletion(-)
    
    diff --git a/plugins/NTMakefile b/plugins/NTMakefile
    index fc547512..c024c7d4 100755
    --- a/plugins/NTMakefile
    +++ b/plugins/NTMakefile
    @@ -1,5 +1,7 @@
     !INCLUDE ..\win32\common.mak
     
    +SCRAM=1
    +
     !IF "$(NTLM)" == "1"
     PLUGINS_EXT=saslNTLM.dll
     !ELSE 
    @@ -111,7 +113,7 @@ saslLDAPDB_sources = ldapdb.c $(common_sources)
     saslLDAPDB_objs = ldapdb.obj $(common_objs)
     saslLDAPDB_out = saslLDAPDB.dll saslLDAPDB.exp saslLDAPDB.lib
     
    -!IF "$(NTLM)" == "1" || "$(SRP)" == "1" || "$(OTP)" == "1"
    +!IF "$(NTLM)" == "1" || "$(SRP)" == "1" || "$(OTP)" == "1" || "$(SCRAM)" == "1"
     OPENSSL_FLAGS= /I $(OPENSSL_INCLUDE)
     !ELSE 
     OPENSSL_FLAGS=
    
    From f0187d4aecc41bae4df7854f085bf1c304df9f7c Mon Sep 17 00:00:00 2001
    From: Ken Murchison 
    Date: Fri, 9 Sep 2011 10:43:01 +0000
    Subject: [PATCH 113/796] added NTMakefile and http_digest_client.c to dist
     target
    
    ---
     sample/Makefile.in | 606 +++++++++++++++++++++++++++++++++++++++++++++
     1 file changed, 606 insertions(+)
     create mode 100644 sample/Makefile.in
    
    diff --git a/sample/Makefile.in b/sample/Makefile.in
    new file mode 100644
    index 00000000..bfe9286f
    --- /dev/null
    +++ b/sample/Makefile.in
    @@ -0,0 +1,606 @@
    +# Makefile.in generated by automake 1.11 from Makefile.am.
    +# @configure_input@
    +
    +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
    +# 2003, 2004, 2005, 2006, 2007, 2008, 2009  Free Software Foundation,
    +# Inc.
    +# This Makefile.in is free software; the Free Software Foundation
    +# gives unlimited permission to copy and/or distribute it,
    +# with or without modifications, as long as this notice is preserved.
    +
    +# This program is distributed in the hope that it will be useful,
    +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
    +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
    +# PARTICULAR PURPOSE.
    +
    +@SET_MAKE@
    +
    +# Makefile.am -- automake input for sample SASL programs
    +# Rob Earhart
    +#
    +################################################################
    +# Copyright (c) 2000 Carnegie Mellon University.  All rights reserved.
    +#
    +# Redistribution and use in source and binary forms, with or without
    +# modification, are permitted provided that the following conditions
    +# are met:
    +#
    +# 1. Redistributions of source code must retain the above copyright
    +#    notice, this list of conditions and the following disclaimer. 
    +#
    +# 2. Redistributions in binary form must reproduce the above copyright
    +#    notice, this list of conditions and the following disclaimer in
    +#    the documentation and/or other materials provided with the
    +#    distribution.
    +#
    +# 3. The name "Carnegie Mellon University" must not be used to
    +#    endorse or promote products derived from this software without
    +#    prior written permission. For permission or any other legal
    +#    details, please contact  
    +#      Office of Technology Transfer
    +#      Carnegie Mellon University
    +#      5000 Forbes Avenue
    +#      Pittsburgh, PA  15213-3890
    +#      (412) 268-4387, fax: (412) 268-7395
    +#      tech-transfer@andrew.cmu.edu
    +#
    +# 4. Redistributions of any form whatsoever must retain the following
    +#    acknowledgment:
    +#    "This product includes software developed by Computing Services
    +#     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
    +#
    +# CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
    +# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
    +# AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
    +# FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
    +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
    +# AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
    +# OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    +#
    +################################################################
    +
    +VPATH = @srcdir@
    +pkgdatadir = $(datadir)/@PACKAGE@
    +pkgincludedir = $(includedir)/@PACKAGE@
    +pkglibdir = $(libdir)/@PACKAGE@
    +pkglibexecdir = $(libexecdir)/@PACKAGE@
    +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
    +install_sh_DATA = $(install_sh) -c -m 644
    +install_sh_PROGRAM = $(install_sh) -c
    +install_sh_SCRIPT = $(install_sh) -c
    +INSTALL_HEADER = $(INSTALL_DATA)
    +transform = $(program_transform_name)
    +NORMAL_INSTALL = :
    +PRE_INSTALL = :
    +POST_INSTALL = :
    +NORMAL_UNINSTALL = :
    +PRE_UNINSTALL = :
    +POST_UNINSTALL = :
    +build_triplet = @build@
    +host_triplet = @host@
    +target_triplet = @target@
    +noinst_PROGRAMS = client$(EXEEXT) server$(EXEEXT)
    +EXTRA_PROGRAMS = sample-client$(EXEEXT) sample-server$(EXEEXT)
    +subdir = sample
    +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in $(srcdir)/NTMakefile
    +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
    +am__aclocal_m4_deps = $(top_srcdir)/config/kerberos_v4.m4 \
    +	$(top_srcdir)/config/libtool.m4 $(top_srcdir)/config/plain.m4 \
    +	$(top_srcdir)/config/sasldb.m4 \
    +	$(top_srcdir)/cmulocal/berkdb.m4 \
    +	$(top_srcdir)/cmulocal/bsd_sockets.m4 \
    +	$(top_srcdir)/cmulocal/c-attribute.m4 \
    +	$(top_srcdir)/cmulocal/common.m4 \
    +	$(top_srcdir)/cmulocal/cyrus.m4 \
    +	$(top_srcdir)/cmulocal/init_automake.m4 \
    +	$(top_srcdir)/cmulocal/ipv6.m4 \
    +	$(top_srcdir)/cmulocal/openldap.m4 \
    +	$(top_srcdir)/cmulocal/openssl.m4 \
    +	$(top_srcdir)/cmulocal/sasl2.m4 $(top_srcdir)/configure.in
    +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
    +	$(ACLOCAL_M4)
    +mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
    +CONFIG_HEADER = $(top_builddir)/config.h
    +CONFIG_CLEAN_FILES =
    +CONFIG_CLEAN_VPATH_FILES =
    +PROGRAMS = $(noinst_PROGRAMS)
    +am_client_OBJECTS = client.$(OBJEXT) common.$(OBJEXT)
    +client_OBJECTS = $(am_client_OBJECTS)
    +am__DEPENDENCIES_1 =
    +client_DEPENDENCIES = ../lib/libsasl2.la $(am__DEPENDENCIES_1) \
    +	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
    +am_sample_client_OBJECTS = sample-client.$(OBJEXT)
    +sample_client_OBJECTS = $(am_sample_client_OBJECTS)
    +sample_client_DEPENDENCIES = ../lib/libsasl2.la $(am__DEPENDENCIES_1) \
    +	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
    +am_sample_server_OBJECTS = sample-server.$(OBJEXT)
    +sample_server_OBJECTS = $(am_sample_server_OBJECTS)
    +sample_server_DEPENDENCIES = ../lib/libsasl2.la $(am__DEPENDENCIES_1) \
    +	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
    +am_server_OBJECTS = server.$(OBJEXT) common.$(OBJEXT)
    +server_OBJECTS = $(am_server_OBJECTS)
    +server_DEPENDENCIES = ../lib/libsasl2.la $(am__DEPENDENCIES_1) \
    +	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
    +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
    +depcomp = $(SHELL) $(top_srcdir)/config/depcomp
    +am__depfiles_maybe = depfiles
    +am__mv = mv -f
    +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
    +	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
    +LTCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
    +	--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
    +	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
    +CCLD = $(CC)
    +LINK = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \
    +	$(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
    +SOURCES = $(client_SOURCES) $(sample_client_SOURCES) \
    +	$(sample_server_SOURCES) $(server_SOURCES)
    +DIST_SOURCES = $(client_SOURCES) $(sample_client_SOURCES) \
    +	$(sample_server_SOURCES) $(server_SOURCES) $(srcdir)/http_digest_client.c
    +ETAGS = etags
    +CTAGS = ctags
    +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
    +ACLOCAL = @ACLOCAL@
    +AMTAR = @AMTAR@
    +AUTOCONF = @AUTOCONF@
    +AUTOHEADER = @AUTOHEADER@
    +AUTOMAKE = @AUTOMAKE@
    +AWK = @AWK@
    +CC = @CC@
    +CCDEPMODE = @CCDEPMODE@
    +CFLAGS = @CFLAGS@
    +CMU_LIB_SUBDIR = @CMU_LIB_SUBDIR@
    +CPP = @CPP@
    +CPPFLAGS = @CPPFLAGS@
    +CYGPATH_W = @CYGPATH_W@
    +DEFS = @DEFS@
    +DEPDIR = @DEPDIR@
    +DIRS = @DIRS@
    +DMALLOC_LIBS = @DMALLOC_LIBS@
    +ECHO_C = @ECHO_C@
    +ECHO_N = @ECHO_N@
    +ECHO_T = @ECHO_T@
    +EGREP = @EGREP@
    +EXEEXT = @EXEEXT@
    +GETADDRINFOOBJS = @GETADDRINFOOBJS@
    +GETNAMEINFOOBJS = @GETNAMEINFOOBJS@
    +GETSUBOPT = @GETSUBOPT@
    +GREP = @GREP@
    +GSSAPIBASE_LIBS = @GSSAPIBASE_LIBS@
    +GSSAPI_LIBS = @GSSAPI_LIBS@
    +INSTALL = @INSTALL@
    +INSTALL_DATA = @INSTALL_DATA@
    +INSTALL_PROGRAM = @INSTALL_PROGRAM@
    +INSTALL_SCRIPT = @INSTALL_SCRIPT@
    +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
    +IPCTYPE = @IPCTYPE@
    +JAVAC = @JAVAC@
    +JAVADOC = @JAVADOC@
    +JAVAH = @JAVAH@
    +JAVAROOT = @JAVAROOT@
    +JAVA_INCLUDES = @JAVA_INCLUDES@
    +LDFLAGS = @LDFLAGS@
    +LIBOBJS = @LIBOBJS@
    +LIBS = @LIBS@
    +LIBTOOL = @LIBTOOL@
    +LIB_CRYPT = @LIB_CRYPT@
    +LIB_DES = @LIB_DES@
    +LIB_DOOR = @LIB_DOOR@
    +LIB_LDAP = @LIB_LDAP@
    +LIB_MYSQL = @LIB_MYSQL@
    +LIB_PGSQL = @LIB_PGSQL@
    +LIB_SOCKET = @LIB_SOCKET@
    +LIB_SQLITE = @LIB_SQLITE@
    +LIB_SQLITE3 = @LIB_SQLITE3@
    +LN_S = @LN_S@
    +LTGETADDRINFOOBJS = @LTGETADDRINFOOBJS@
    +LTGETNAMEINFOOBJS = @LTGETNAMEINFOOBJS@
    +LTLIBOBJS = @LTLIBOBJS@
    +LTSNPRINTFOBJS = @LTSNPRINTFOBJS@
    +MAKEINFO = @MAKEINFO@
    +MKDIR_P = @MKDIR_P@
    +NM = @NM@
    +NTLM_LIBS = @NTLM_LIBS@
    +OBJEXT = @OBJEXT@
    +OTP_LIBS = @OTP_LIBS@
    +PACKAGE = @PACKAGE@
    +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
    +PACKAGE_NAME = @PACKAGE_NAME@
    +PACKAGE_STRING = @PACKAGE_STRING@
    +PACKAGE_TARNAME = @PACKAGE_TARNAME@
    +PACKAGE_VERSION = @PACKAGE_VERSION@
    +PASSDSS_LIBS = @PASSDSS_LIBS@
    +PATH_SEPARATOR = @PATH_SEPARATOR@
    +PLAIN_LIBS = @PLAIN_LIBS@
    +PURECOV = @PURECOV@
    +PURIFY = @PURIFY@
    +PWCHECKMETH = @PWCHECKMETH@
    +RANLIB = @RANLIB@
    +SASL_DB_BACKEND = @SASL_DB_BACKEND@
    +SASL_DB_BACKEND_STATIC = @SASL_DB_BACKEND_STATIC@
    +SASL_DB_INC = @SASL_DB_INC@
    +SASL_DB_LIB = @SASL_DB_LIB@
    +SASL_DB_MANS = @SASL_DB_MANS@
    +SASL_DB_UTILS = @SASL_DB_UTILS@
    +SASL_DL_LIB = @SASL_DL_LIB@
    +SASL_KRB_LIB = @SASL_KRB_LIB@
    +SASL_MECHS = @SASL_MECHS@
    +SASL_STATIC_LIBS = @SASL_STATIC_LIBS@
    +SASL_STATIC_OBJS = @SASL_STATIC_OBJS@
    +SASL_STATIC_SRCS = @SASL_STATIC_SRCS@
    +SASL_UTIL_HEADERS_EXTRA = @SASL_UTIL_HEADERS_EXTRA@
    +SASL_UTIL_LIBS_EXTRA = @SASL_UTIL_LIBS_EXTRA@
    +SCRAM_LIBS = @SCRAM_LIBS@
    +SET_MAKE = @SET_MAKE@
    +SFIO_INC_FLAGS = @SFIO_INC_FLAGS@
    +SFIO_LIB_FLAGS = @SFIO_LIB_FLAGS@
    +SHELL = @SHELL@
    +SMTPTEST_PROGRAM = @SMTPTEST_PROGRAM@
    +SNPRINTFOBJS = @SNPRINTFOBJS@
    +SRP_LIBS = @SRP_LIBS@
    +STRIP = @STRIP@
    +VERSION = @VERSION@
    +abs_builddir = @abs_builddir@
    +abs_srcdir = @abs_srcdir@
    +abs_top_builddir = @abs_top_builddir@
    +abs_top_srcdir = @abs_top_srcdir@
    +ac_ct_CC = @ac_ct_CC@
    +am__include = @am__include@
    +am__leading_dot = @am__leading_dot@
    +am__quote = @am__quote@
    +am__tar = @am__tar@
    +am__untar = @am__untar@
    +bindir = @bindir@
    +build = @build@
    +build_alias = @build_alias@
    +build_cpu = @build_cpu@
    +build_os = @build_os@
    +build_vendor = @build_vendor@
    +builddir = @builddir@
    +configdir = @configdir@
    +datadir = @datadir@
    +datarootdir = @datarootdir@
    +docdir = @docdir@
    +dvidir = @dvidir@
    +exec_prefix = @exec_prefix@
    +host = @host@
    +host_alias = @host_alias@
    +host_cpu = @host_cpu@
    +host_os = @host_os@
    +host_vendor = @host_vendor@
    +htmldir = @htmldir@
    +includedir = @includedir@
    +infodir = @infodir@
    +install_sh = @install_sh@
    +libdir = @libdir@
    +libexecdir = @libexecdir@
    +localedir = @localedir@
    +localstatedir = @localstatedir@
    +mandir = @mandir@
    +mkdir_p = @mkdir_p@
    +oldincludedir = @oldincludedir@
    +pdfdir = @pdfdir@
    +plugindir = @plugindir@
    +prefix = @prefix@
    +program_transform_name = @program_transform_name@
    +psdir = @psdir@
    +sbindir = @sbindir@
    +sharedstatedir = @sharedstatedir@
    +srcdir = @srcdir@
    +subdirs = @subdirs@
    +sysconfdir = @sysconfdir@
    +target = @target@
    +target_alias = @target_alias@
    +target_cpu = @target_cpu@
    +target_os = @target_os@
    +target_vendor = @target_vendor@
    +top_build_prefix = @top_build_prefix@
    +top_builddir = @top_builddir@
    +top_srcdir = @top_srcdir@
    +INCLUDES = -I$(top_srcdir)/include
    +CLEANFILES = sample-client sample-server ./.libs/*sample-client ./.libs/*sample-server
    +sample_client_SOURCES = sample-client.c
    +sample_server_SOURCES = sample-server.c
    +server_SOURCES = server.c common.c common.h
    +client_SOURCES = client.c common.c common.h
    +server_LDADD = ../lib/libsasl2.la $(GSSAPIBASE_LIBS) $(GSSAPI_LIBS) $(LIB_SOCKET)
    +client_LDADD = ../lib/libsasl2.la $(GSSAPIBASE_LIBS) $(GSSAPI_LIBS) $(LIB_SOCKET)
    +sample_client_LDADD = ../lib/libsasl2.la $(GSSAPIBASE_LIBS) $(GSSAPI_LIBS) $(LIB_SOCKET)
    +sample_server_LDADD = ../lib/libsasl2.la $(GSSAPIBASE_LIBS) $(GSSAPI_LIBS) $(LIB_SOCKET)
    +all: all-am
    +
    +.SUFFIXES:
    +.SUFFIXES: .c .lo .o .obj
    +$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
    +	@for dep in $?; do \
    +	  case '$(am__configure_deps)' in \
    +	    *$$dep*) \
    +	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
    +	        && { if test -f $@; then exit 0; else break; fi; }; \
    +	      exit 1;; \
    +	  esac; \
    +	done; \
    +	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu sample/Makefile'; \
    +	$(am__cd) $(top_srcdir) && \
    +	  $(AUTOMAKE) --gnu sample/Makefile
    +.PRECIOUS: Makefile
    +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
    +	@case '$?' in \
    +	  *config.status*) \
    +	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
    +	  *) \
    +	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
    +	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
    +	esac;
    +
    +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
    +	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
    +
    +$(top_srcdir)/configure:  $(am__configure_deps)
    +	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
    +$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
    +	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
    +$(am__aclocal_m4_deps):
    +
    +clean-noinstPROGRAMS:
    +	@list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \
    +	echo " rm -f" $$list; \
    +	rm -f $$list || exit $$?; \
    +	test -n "$(EXEEXT)" || exit 0; \
    +	list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
    +	echo " rm -f" $$list; \
    +	rm -f $$list
    +client$(EXEEXT): $(client_OBJECTS) $(client_DEPENDENCIES) 
    +	@rm -f client$(EXEEXT)
    +	$(LINK) $(client_OBJECTS) $(client_LDADD) $(LIBS)
    +sample-client$(EXEEXT): $(sample_client_OBJECTS) $(sample_client_DEPENDENCIES) 
    +	@rm -f sample-client$(EXEEXT)
    +	$(LINK) $(sample_client_OBJECTS) $(sample_client_LDADD) $(LIBS)
    +sample-server$(EXEEXT): $(sample_server_OBJECTS) $(sample_server_DEPENDENCIES) 
    +	@rm -f sample-server$(EXEEXT)
    +	$(LINK) $(sample_server_OBJECTS) $(sample_server_LDADD) $(LIBS)
    +server$(EXEEXT): $(server_OBJECTS) $(server_DEPENDENCIES) 
    +	@rm -f server$(EXEEXT)
    +	$(LINK) $(server_OBJECTS) $(server_LDADD) $(LIBS)
    +
    +mostlyclean-compile:
    +	-rm -f *.$(OBJEXT)
    +
    +distclean-compile:
    +	-rm -f *.tab.c
    +
    +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/client.Po@am__quote@
    +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common.Po@am__quote@
    +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sample-client.Po@am__quote@
    +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sample-server.Po@am__quote@
    +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server.Po@am__quote@
    +
    +.c.o:
    +@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
    +@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
    +@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
    +@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    +@am__fastdepCC_FALSE@	$(COMPILE) -c $<
    +
    +.c.obj:
    +@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
    +@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
    +@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
    +@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    +@am__fastdepCC_FALSE@	$(COMPILE) -c `$(CYGPATH_W) '$<'`
    +
    +.c.lo:
    +@am__fastdepCC_TRUE@	$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
    +@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
    +@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
    +@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    +@am__fastdepCC_FALSE@	$(LTCOMPILE) -c -o $@ $<
    +
    +mostlyclean-libtool:
    +	-rm -f *.lo
    +
    +clean-libtool:
    +	-rm -rf .libs _libs
    +
    +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
    +	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
    +	unique=`for i in $$list; do \
    +	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
    +	  done | \
    +	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
    +	      END { if (nonempty) { for (i in files) print i; }; }'`; \
    +	mkid -fID $$unique
    +tags: TAGS
    +
    +TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
    +		$(TAGS_FILES) $(LISP)
    +	set x; \
    +	here=`pwd`; \
    +	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
    +	unique=`for i in $$list; do \
    +	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
    +	  done | \
    +	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
    +	      END { if (nonempty) { for (i in files) print i; }; }'`; \
    +	shift; \
    +	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
    +	  test -n "$$unique" || unique=$$empty_fix; \
    +	  if test $$# -gt 0; then \
    +	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
    +	      "$$@" $$unique; \
    +	  else \
    +	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
    +	      $$unique; \
    +	  fi; \
    +	fi
    +ctags: CTAGS
    +CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
    +		$(TAGS_FILES) $(LISP)
    +	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
    +	unique=`for i in $$list; do \
    +	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
    +	  done | \
    +	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
    +	      END { if (nonempty) { for (i in files) print i; }; }'`; \
    +	test -z "$(CTAGS_ARGS)$$unique" \
    +	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
    +	     $$unique
    +
    +GTAGS:
    +	here=`$(am__cd) $(top_builddir) && pwd` \
    +	  && $(am__cd) $(top_srcdir) \
    +	  && gtags -i $(GTAGS_ARGS) "$$here"
    +
    +distclean-tags:
    +	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
    +
    +distdir: $(DISTFILES)
    +	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
    +	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
    +	list='$(DISTFILES)'; \
    +	  dist_files=`for file in $$list; do echo $$file; done | \
    +	  sed -e "s|^$$srcdirstrip/||;t" \
    +	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
    +	case $$dist_files in \
    +	  */*) $(MKDIR_P) `echo "$$dist_files" | \
    +			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
    +			   sort -u` ;; \
    +	esac; \
    +	for file in $$dist_files; do \
    +	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
    +	  if test -d $$d/$$file; then \
    +	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
    +	    if test -d "$(distdir)/$$file"; then \
    +	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
    +	    fi; \
    +	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
    +	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
    +	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
    +	    fi; \
    +	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
    +	  else \
    +	    test -f "$(distdir)/$$file" \
    +	    || cp -p $$d/$$file "$(distdir)/$$file" \
    +	    || exit 1; \
    +	  fi; \
    +	done
    +check-am: all-am
    +check: check-am
    +all-am: Makefile $(PROGRAMS)
    +installdirs:
    +install: install-am
    +install-exec: install-exec-am
    +install-data: install-data-am
    +uninstall: uninstall-am
    +
    +install-am: all-am
    +	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
    +
    +installcheck: installcheck-am
    +install-strip:
    +	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
    +	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
    +	  `test -z '$(STRIP)' || \
    +	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
    +mostlyclean-generic:
    +
    +clean-generic:
    +	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
    +
    +distclean-generic:
    +	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
    +	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
    +
    +maintainer-clean-generic:
    +	@echo "This command is intended for maintainers to use"
    +	@echo "it deletes files that may require special tools to rebuild."
    +clean: clean-am
    +
    +clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \
    +	mostlyclean-am
    +
    +distclean: distclean-am
    +	-rm -rf ./$(DEPDIR)
    +	-rm -f Makefile
    +distclean-am: clean-am distclean-compile distclean-generic \
    +	distclean-tags
    +
    +dvi: dvi-am
    +
    +dvi-am:
    +
    +html: html-am
    +
    +html-am:
    +
    +info: info-am
    +
    +info-am:
    +
    +install-data-am:
    +
    +install-dvi: install-dvi-am
    +
    +install-dvi-am:
    +
    +install-exec-am:
    +
    +install-html: install-html-am
    +
    +install-html-am:
    +
    +install-info: install-info-am
    +
    +install-info-am:
    +
    +install-man:
    +
    +install-pdf: install-pdf-am
    +
    +install-pdf-am:
    +
    +install-ps: install-ps-am
    +
    +install-ps-am:
    +
    +installcheck-am:
    +
    +maintainer-clean: maintainer-clean-am
    +	-rm -rf ./$(DEPDIR)
    +	-rm -f Makefile
    +maintainer-clean-am: distclean-am maintainer-clean-generic
    +
    +mostlyclean: mostlyclean-am
    +
    +mostlyclean-am: mostlyclean-compile mostlyclean-generic \
    +	mostlyclean-libtool
    +
    +pdf: pdf-am
    +
    +pdf-am:
    +
    +ps: ps-am
    +
    +ps-am:
    +
    +uninstall-am:
    +
    +.MAKE: install-am install-strip
    +
    +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
    +	clean-libtool clean-noinstPROGRAMS ctags distclean \
    +	distclean-compile distclean-generic distclean-libtool \
    +	distclean-tags distdir dvi dvi-am html html-am info info-am \
    +	install install-am install-data install-data-am install-dvi \
    +	install-dvi-am install-exec install-exec-am install-html \
    +	install-html-am install-info install-info-am install-man \
    +	install-pdf install-pdf-am install-ps install-ps-am \
    +	install-strip installcheck installcheck-am installdirs \
    +	maintainer-clean maintainer-clean-generic mostlyclean \
    +	mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
    +	pdf pdf-am ps ps-am tags uninstall uninstall-am
    +
    +
    +# Tell versions [3.59,3.63) of GNU make to not export all variables.
    +# Otherwise a system limit (for SysV at least) may be exceeded.
    +.NOEXPORT:
    
    From f87f4ed793776702f6892a19c6e68ecd1c4972cd Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Mon, 12 Sep 2011 08:48:21 +0000
    Subject: [PATCH 114/796] Make sure that copied .c files are only rebuilt when
     changed
    
    ---
     lib/NTMakefile     | 4 ++--
     plugins/NTMakefile | 8 ++++----
     2 files changed, 6 insertions(+), 6 deletions(-)
    
    diff --git a/lib/NTMakefile b/lib/NTMakefile
    index b7357763..80dfd6d4 100755
    --- a/lib/NTMakefile
    +++ b/lib/NTMakefile
    @@ -53,10 +53,10 @@ libsasl.dll: $(libsasl_objs) $(libsasl_res)
     	IF EXIST $@.manifest mt -manifest $@.manifest -outputresource:$@;2
     
     plugin_common.c: ..\plugins\plugin_common.c plugin_common.h
    -	copy ..\plugins\plugin_common.c .
    +	xcopy /D /Y ..\plugins\plugin_common.c .
     
     plugin_common.h: ..\plugins\plugin_common.h
    -	copy ..\plugins\plugin_common.h .
    +	xcopy /D /Y ..\plugins\plugin_common.h .
     
     auxprop.obj checkpw.obj client.obj common.obj external.obj plugin_common.obj server.obj seterror.obj: ..\include\saslplug.h
     
    diff --git a/plugins/NTMakefile b/plugins/NTMakefile
    index c024c7d4..cc74bb12 100755
    --- a/plugins/NTMakefile
    +++ b/plugins/NTMakefile
    @@ -177,16 +177,16 @@ install: $(PLUGINS)
     all-recursive : $(PLUGINS)
     
     getaddrinfo.c: ..\lib\getaddrinfo.c
    -	copy ..\lib\getaddrinfo.c .
    +	xcopy /D /Y ..\lib\getaddrinfo.c .
     
     getnameinfo.c: ..\lib\getnameinfo.c
    -	copy ..\lib\getnameinfo.c .
    +	xcopy /D /Y ..\lib\getnameinfo.c .
     
     allockey.c: ..\sasldb\allockey.c
    -	copy ..\sasldb\allockey.c .
    +	xcopy /D /Y ..\sasldb\allockey.c .
     
     db_berkeley.c: ..\sasldb\db_berkeley.c
    -	copy ..\sasldb\db_berkeley.c .
    +	xcopy /D /Y ..\sasldb\db_berkeley.c .
     
     #Add /pdb: option?
     
    
    From ed328a01888fa09298ddc909c92eff86fc9e52ff Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Mon, 12 Sep 2011 08:50:47 +0000
    Subject: [PATCH 115/796] Fixed warnings about incompatible callback types
    
    ---
     sasldb/db_berkeley.c | 6 +++---
     1 file changed, 3 insertions(+), 3 deletions(-)
    
    diff --git a/sasldb/db_berkeley.c b/sasldb/db_berkeley.c
    index 8f0b4f27..8778312a 100644
    --- a/sasldb/db_berkeley.c
    +++ b/sasldb/db_berkeley.c
    @@ -1,7 +1,7 @@
     /* db_berkeley.c--SASL berkeley db interface
      * Rob Siemborski
      * Tim Martin
    - * $Id: db_berkeley.c,v 1.10 2011/09/01 14:12:18 mel Exp $
    + * $Id: db_berkeley.c,v 1.11 2011/09/12 08:50:47 mel Exp $
      */
     /* 
      * Copyright (c) 1998-2003 Carnegie Mellon University.  All rights reserved.
    @@ -79,7 +79,7 @@ static int berkeleydb_open(const sasl_utils_t *utils,
     #endif
     
         if (utils->getcallback(conn, SASL_CB_GETOPT,
    -			  &getopt, &cntxt) == SASL_OK) {
    +			   (sasl_callback_ft *)&getopt, &cntxt) == SASL_OK) {
     	const char *p;
     	if (getopt(cntxt, NULL, "sasldb_path", &p, NULL) == SASL_OK 
     	    && p != NULL && *p != 0) {
    @@ -368,7 +368,7 @@ int _sasl_check_db(const sasl_utils_t *utils,
         if (!utils) return SASL_BADPARAM;
     
         if (utils->getcallback(conn, SASL_CB_GETOPT,
    -			  &getopt, &cntxt) == SASL_OK) {
    +			   (sasl_callback_ft *)&getopt, &cntxt) == SASL_OK) {
     	const char *p;
     	if (getopt(cntxt, NULL, "sasldb_path", &p, NULL) == SASL_OK 
     	    && p != NULL && *p != 0) {
    
    From 25ca0065b0032aa358292450cf50a61227e2d9b9 Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Mon, 12 Sep 2011 08:52:47 +0000
    Subject: [PATCH 116/796] Add _CRT_SECURE_NO_DEPRECATE define to suppress
     warnings about use of strdup, snprintf, etc.
    
    ---
     win32/common.mak | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    diff --git a/win32/common.mak b/win32/common.mak
    index 69a39931..ac30f2fd 100644
    --- a/win32/common.mak
    +++ b/win32/common.mak
    @@ -173,7 +173,7 @@ CODEGEN=/MD
     ENABLE_WIN64_WARNINGS=/Wp64
     !ENDIF
     
    -CPP_PROJ= $(CODEGEN) /W3 $(EXCEPTHANDLING) /O2 $(ENABLE_WIN64_WARNINGS) /Zi /D "NDEBUG" $(CPPFLAGS) /FD /c 
    +CPP_PROJ= $(CODEGEN) /W3 $(EXCEPTHANDLING) /O2 $(ENABLE_WIN64_WARNINGS) /Zi /D "NDEBUG" /D _CRT_SECURE_NO_DEPRECATE=1 $(CPPFLAGS) /FD /c
     
     incremental=no
     
    @@ -194,7 +194,7 @@ CODEGEN=/MDd
     !ENDIF 
     !ENDIF 
     
    -CPP_PROJ=$(CODEGEN) /W3 /Gm $(EXCEPTHANDLING) /ZI /Od /D "_DEBUG" $(CPPFLAGS) /FD /GZ /c 
    +CPP_PROJ=$(CODEGEN) /W3 /Gm $(EXCEPTHANDLING) /ZI /Od /D "_DEBUG" /D _CRT_SECURE_NO_DEPRECATE=1 $(CPPFLAGS) /FD /GZ /c
     
     incremental=yes
     
    
    From 32d9663d97f84545974d153e047ea4a31a053576 Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Mon, 12 Sep 2011 08:57:16 +0000
    Subject: [PATCH 117/796] Updated as per today's commits. Marked the last
     significant commit in Cyrus SASL 2.1.25
    
    ---
     ChangeLog | 19 ++++++++++++++++---
     1 file changed, 16 insertions(+), 3 deletions(-)
    
    diff --git a/ChangeLog b/ChangeLog
    index d0920434..4d0a2ddb 100644
    --- a/ChangeLog
    +++ b/ChangeLog
    @@ -1,14 +1,27 @@
    +2011-09-12  Alexey Melnikov 
    +	* win32/common.mak: Add _CRT_SECURE_NO_DEPRECATE define
    +	to suppress warnings about use of strdup, snprintf, etc.
    +
    +2011-09-12  Alexey Melnikov 
    +	* sasldb/db_berkeley.c:
    +	  Fixed warnings about incompatible callback types.
    +
    +2011-09-12  Alexey Melnikov 
    +	* lib/NTMakefile plugins/NTMakefile:
    +	  Make sure that copied .c files are only rebuilt when changed.
    +
     2011-09-07  Ken Murchison 
     	* plugins/scram.c:
    -	  Fixed 3 memory leaks in SCRAM
    +	  Fixed 3 memory leaks in SCRAM. Final 2.1.25.
     
     2011-09-07  Alexey Melnikov 
     	* configure.in, plugins/NTMakefile, plugins/cram.c:
     	  Allow use of cmusaslsecretCRAM-MD5 property to be disabled.
     
     2011-09-02  Alexey Melnikov 
    -	* config/config.guess, config/config.sub, saslauthd/config/config.guess,
    -	  saslauthd/config/config.sub: Updated config to the latest GNU snapshot.
    +	* config/config.guess, config/config.sub,
    +	  saslauthd/config/config.guess, saslauthd/config/config.sub:
    +	  Updated config to the latest GNU snapshot.
     
     2011-09-01  Alexey Melnikov 
     	* lib/server.c: Make sure that a failed authorization doesn't preclude
    
    From f372879898ad7a05191aed76c85356e50901f253 Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Tue, 13 Sep 2011 16:30:23 +0000
    Subject: [PATCH 118/796] MacOS related build fixes from Chris Ridd
    
    ---
     ChangeLog        | 6 ++++++
     config/ltconfig  | 6 +++---
     config/ltmain.sh | 7 ++++---
     configure.in     | 4 ++--
     4 files changed, 15 insertions(+), 8 deletions(-)
    
    diff --git a/ChangeLog b/ChangeLog
    index 4d0a2ddb..94d626e1 100644
    --- a/ChangeLog
    +++ b/ChangeLog
    @@ -1,3 +1,9 @@
    +2011-09-13  Alexey Melnikov 
    +	* configure.in, config/ltconfig, config/ltmain.sh:
    +	  MacOS X related build fixes: use .plugin when building
    +	  SASL plugins, fixed version number calculation.
    +	  Also use LD_RUN_PATH as rpath. (patches by Chris Ridd)
    +
     2011-09-12  Alexey Melnikov 
     	* win32/common.mak: Add _CRT_SECURE_NO_DEPRECATE define
     	to suppress warnings about use of strdup, snprintf, etc.
    diff --git a/config/ltconfig b/config/ltconfig
    index 20327d6a..ea4c6cdb 100755
    --- a/config/ltconfig
    +++ b/config/ltconfig
    @@ -1385,7 +1385,7 @@ else
       # Mac OS X v10.2 uses bash for /bin/sh instead of zsh, and the quoting syntax is incompatible
       darwin*)
         allow_undefined_flag='-undefined error'
    -    archive_cmds='$CC $(test x$module = xyes && echo -bundle || echo -dynamiclib) $allow_undefined_flag -o $lib $libobjs $deplibs $linkopts $(test x$module != xyes && echo -install_name $rpath/$soname $tmp_verstring)'
    +    archive_cmds='$CC $(test x$module = xyes && echo -bundle || echo -dynamiclib) $allow_undefined_flag -o $lib $libobjs $deplibs $linkopts $(test x$module != xyes && echo -install_name $LD_RUN_PATH/$soname $tmp_verstring)'
         # We need to add '_' to the symbols in $export_symbols first
         #archive_expsym_cmds="$archive_cmds"' && strip -s $export_symbols $lib'
         hardcode_direct=yes
    @@ -1950,8 +1950,8 @@ darwin* | rhapsody*)
         file_magic_test_file='/usr/lib/libSystem.dylib'
         ;;
       esac
    -  library_names_spec='${libname}${release}${versuffix}.$(test x$module = xyes && echo so || echo dylib) ${libname}${release}${major}.$(test x$module = xyes && echo so || echo dylib) ${libname}.$(test x$module = xyes && echo so || echo dylib)'
    -  soname_spec='${libname}${release}${major}.$(test x$module = xyes && echo so || echo dylib)'
    +  library_names_spec='${libname}.$(test x$module = xyes && echo plugin || echo dylib)'
    +  soname_spec='${libname}.$(test x$module = xyes && echo plugin || echo dylib)'
       shlibpath_overrides_runpath=yes
       shlibpath_var=DYLD_LIBRARY_PATH
       ;;
    diff --git a/config/ltmain.sh b/config/ltmain.sh
    index 710f1929..76124818 100644
    --- a/config/ltmain.sh
    +++ b/config/ltmain.sh
    @@ -1775,11 +1775,12 @@ compiler."
     	darwin)
     	  # Like Linux, but with the current version available in
     	  # verstring for coding it into the library header
    -	  major=.`expr $current - $age`
    -	  versuffix="$major.$age.$revision"
    +	  major=`expr $current - $age`
    +	  versuffix=".$major.$age.$revision"
     	  # Darwin ld doesn't like 0 for these options...
     	  minor_current=`expr $current + 1`
    -	  verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"
    +	  verstring="-compatibility_version $major -current_version $major.$age.$revision"
    +	  major=".$major"
     	  ;;
     
     	*)
    diff --git a/configure.in b/configure.in
    index 60fb1542..15a01247 100644
    --- a/configure.in
    +++ b/configure.in
    @@ -1,7 +1,7 @@
     dnl configure.in for the SASL library
     dnl Rob Siemborski
     dnl Rob Earhart
    -dnl $Id: configure.in,v 1.222 2011/09/07 13:19:44 murch Exp $
    +dnl $Id: configure.in,v 1.223 2011/09/13 16:30:23 mel Exp $
     dnl
     dnl Copyright (c) 2001 Carnegie Mellon University.  All rights reserved.
     dnl
    @@ -1399,7 +1399,7 @@ struct sockaddr_storage {
     #endif /* CONFIG_H */
     ])
     
    -AC_CONFIG_HEADERS(config.h)
    +AM_CONFIG_HEADER(config.h)
     
     AC_OUTPUT(Makefile
     include/Makefile
    
    From 4a587464d5eb6f6386a739c22f0af6acca56a61c Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Tue, 13 Sep 2011 16:37:28 +0000
    Subject: [PATCH 119/796] MacOS related build fixes from Chris Ridd (updated)
    
    ---
     ChangeLog | 3 ++-
     1 file changed, 2 insertions(+), 1 deletion(-)
    
    diff --git a/ChangeLog b/ChangeLog
    index 94d626e1..812ccb08 100644
    --- a/ChangeLog
    +++ b/ChangeLog
    @@ -1,7 +1,8 @@
     2011-09-13  Alexey Melnikov 
     	* configure.in, config/ltconfig, config/ltmain.sh:
     	  MacOS X related build fixes: use .plugin when building
    -	  SASL plugins, fixed version number calculation.
    +	  SASL plugins, fixed version number calculation,
    +	  don't generate multiple symlinks.
     	  Also use LD_RUN_PATH as rpath. (patches by Chris Ridd)
     
     2011-09-12  Alexey Melnikov 
    
    From ce5f5b6fc5de9bca5551fa47b8e4c3023c593caa Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Thu, 15 Sep 2011 09:31:49 +0000
    Subject: [PATCH 120/796] Added additional typecasts to kill warnings about
     incompatible callback types
    
    ---
     ChangeLog       |  4 ++++
     sample/client.c | 11 ++++++-----
     2 files changed, 10 insertions(+), 5 deletions(-)
    
    diff --git a/ChangeLog b/ChangeLog
    index 812ccb08..2a954e94 100644
    --- a/ChangeLog
    +++ b/ChangeLog
    @@ -1,3 +1,7 @@
    +2011-09-15  Alexey Melnikov 
    +	* sample/client.c: Added additional typecasts to kill warnings
    +	  about incompatible callback types
    +
     2011-09-13  Alexey Melnikov 
     	* configure.in, config/ltconfig, config/ltmain.sh:
     	  MacOS X related build fixes: use .plugin when building
    diff --git a/sample/client.c b/sample/client.c
    index e0cf2e27..d568be53 100644
    --- a/sample/client.c
    +++ b/sample/client.c
    @@ -1,4 +1,4 @@
    -/* $Id: client.c,v 1.8 2010/12/01 14:51:53 mel Exp $ */
    +/* $Id: client.c,v 1.9 2011/09/15 09:31:49 mel Exp $ */
     /* 
      * Copyright (c) 1998-2003 Carnegie Mellon University.  All rights reserved.
      *
    @@ -60,6 +60,7 @@
     #include 
     
     #include 
    +#include 
     
     #include "common.h"
     
    @@ -184,13 +185,13 @@ getsecret(sasl_conn_t *conn,
     /* callbacks we support */
     static sasl_callback_t callbacks[] = {
       {
    -    SASL_CB_GETREALM, &getrealm, NULL
    +    SASL_CB_GETREALM, (sasl_callback_ft)&getrealm, NULL
       }, {
    -    SASL_CB_USER, &simple, NULL
    +    SASL_CB_USER, (sasl_callback_ft)&simple, NULL
       }, {
    -    SASL_CB_AUTHNAME, &simple, NULL
    +    SASL_CB_AUTHNAME, (sasl_callback_ft)&simple, NULL
       }, {
    -    SASL_CB_PASS, &getsecret, NULL
    +    SASL_CB_PASS, (sasl_callback_ft)&getsecret, NULL
       }, {
         SASL_CB_LIST_END, NULL, NULL
       }
    
    From 31d9a564f2bceaf1af460aef6d6799df7cc8487a Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Thu, 22 Sep 2011 14:38:00 +0000
    Subject: [PATCH 121/796] Fixed Cyrus SASL build on some versions of Mac OS
    
    ---
     config/ltconfig           | 2 +-
     saslauthd/config/ltconfig | 2 +-
     2 files changed, 2 insertions(+), 2 deletions(-)
    
    diff --git a/config/ltconfig b/config/ltconfig
    index ea4c6cdb..a91118e9 100755
    --- a/config/ltconfig
    +++ b/config/ltconfig
    @@ -1374,7 +1374,7 @@ else
     
       darwin[15]* | rhapsody*)
         allow_undefined_flag='-undefined error'
    -    archive_cmds='$CC $(test x$module = xyes && echo -bundle || echo -dynamiclib) $allow_undefined_flag -o $lib $libobjs $deplibs $linkopts -install_name $rpath/$soname $(test -n "$verstring" -a x$verstring != x0.0 && echo $verstring)'
    +    archive_cmds='$CC $(test x$module = xyes && echo -bundle || echo -dynamiclib) $allow_undefined_flag -o $lib $libobjs $deplibs $linkopts $(test x$module != xyes && echo -install_name $rpath/$soname) $(test -n "$verstring" -a x$verstring != x0.0 && echo $verstring)'
         # We need to add '_' to the symbols in $export_symbols first
         #archive_expsym_cmds="$archive_cmds"' && strip -s $export_symbols $lib'
         hardcode_direct=yes
    diff --git a/saslauthd/config/ltconfig b/saslauthd/config/ltconfig
    index 20327d6a..ba8bb1cd 100755
    --- a/saslauthd/config/ltconfig
    +++ b/saslauthd/config/ltconfig
    @@ -1374,7 +1374,7 @@ else
     
       darwin[15]* | rhapsody*)
         allow_undefined_flag='-undefined error'
    -    archive_cmds='$CC $(test x$module = xyes && echo -bundle || echo -dynamiclib) $allow_undefined_flag -o $lib $libobjs $deplibs $linkopts -install_name $rpath/$soname $(test -n "$verstring" -a x$verstring != x0.0 && echo $verstring)'
    +    archive_cmds='$CC $(test x$module = xyes && echo -bundle || echo -dynamiclib) $allow_undefined_flag -o $lib $libobjs $deplibs $linkopts $(test x$module != xyes && echo -install_name $rpath/$soname) $(test -n "$verstring" -a x$verstring != x0.0 && echo $verstring)'
         # We need to add '_' to the symbols in $export_symbols first
         #archive_expsym_cmds="$archive_cmds"' && strip -s $export_symbols $lib'
         hardcode_direct=yes
    
    From 3aebcea4f746e02d78319f571b85ce346faeb884 Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Thu, 22 Sep 2011 14:39:03 +0000
    Subject: [PATCH 122/796] qstring incorrectly appending the closing double
     quote, which might be causing crashes
    
    ---
     saslauthd/auth_rimap.c | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    diff --git a/saslauthd/auth_rimap.c b/saslauthd/auth_rimap.c
    index 72ec4032..1bf2deb3 100644
    --- a/saslauthd/auth_rimap.c
    +++ b/saslauthd/auth_rimap.c
    @@ -53,7 +53,7 @@
      * END SYNOPSIS */
     
     #ifdef __GNUC__
    -#ident "$Id: auth_rimap.c,v 1.13 2008/01/23 19:54:54 murch Exp $"
    +#ident "$Id: auth_rimap.c,v 1.14 2011/09/22 14:39:03 mel Exp $"
     #endif
     
     /* PUBLIC DEPENDENCIES */
    @@ -199,7 +199,7 @@ qstring (
     	}
     	*p2++ = *p1++;
         }
    -    strcat(p2, "\"");
    +    strcpy(p2, "\"");
         return c;
     }
     
    
    From f68e8b00dcc07902dd3b4a77539e4f77a73e3b63 Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Thu, 22 Sep 2011 14:40:30 +0000
    Subject: [PATCH 123/796] unlock the mutex in sasl_dispose if the context was
     freed by another thread
    
    ---
     lib/common.c | 8 ++++++--
     1 file changed, 6 insertions(+), 2 deletions(-)
    
    diff --git a/lib/common.c b/lib/common.c
    index 8977c1e7..013e3bbd 100644
    --- a/lib/common.c
    +++ b/lib/common.c
    @@ -1,7 +1,7 @@
     /* common.c - Functions that are common to server and clinet
      * Rob Siemborski
      * Tim Martin
    - * $Id: common.c,v 1.133 2011/09/01 14:12:53 mel Exp $
    + * $Id: common.c,v 1.134 2011/09/22 14:40:30 mel Exp $
      */
     /* 
      * Copyright (c) 1998-2003 Carnegie Mellon University.  All rights reserved.
    @@ -842,7 +842,11 @@ void sasl_dispose(sasl_conn_t **pconn)
       if (result!=SASL_OK) return;
       
       /* *pconn might have become NULL by now */
    -  if (! (*pconn)) return;
    +  if (! (*pconn))
    +  {
    +	sasl_MUTEX_UNLOCK(free_mutex);
    +	return;
    +  }
     
       (*pconn)->destroy_conn(*pconn);
       sasl_FREE(*pconn);
    
    From 5611d43e27098f659f84155271cf42f46aab1caf Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Thu, 22 Sep 2011 14:41:12 +0000
    Subject: [PATCH 124/796] lib should be built before plugins (Patch from
     marcandre.lureau@redhat.com)
    
    ---
     Makefile.am | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/Makefile.am b/Makefile.am
    index d6005fb5..b35164e7 100644
    --- a/Makefile.am
    +++ b/Makefile.am
    @@ -69,7 +69,7 @@ else
     INSTALLOSX = 
     endif
     
    -SUBDIRS=include sasldb plugins lib utils doc man $(PWC) $(SAM) $(JAV) $(SAD)
    +SUBDIRS=include sasldb lib plugins utils doc man $(PWC) $(SAM) $(JAV) $(SAD)
     EXTRA_DIST=config cmulocal win32 mac dlcompat-20010505 NTMakefile INSTALL.TXT
     
     dist-hook:
    
    From 03e8817a3d09a1cee616c2f5b556a45c7983a5c5 Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Thu, 22 Sep 2011 14:43:01 +0000
    Subject: [PATCH 125/796] MINGW32 doesn't have rand_s (Patch from
     marcandre.lureau@redhat.com)
    
    ---
     lib/saslutil.c | 10 ++++++----
     1 file changed, 6 insertions(+), 4 deletions(-)
    
    diff --git a/lib/saslutil.c b/lib/saslutil.c
    index 035c718f..fc5b7741 100644
    --- a/lib/saslutil.c
    +++ b/lib/saslutil.c
    @@ -1,7 +1,7 @@
     /* saslutil.c
      * Rob Siemborski
      * Tim Martin
    - * $Id: saslutil.c,v 1.51 2010/12/01 14:25:53 mel Exp $
    + * $Id: saslutil.c,v 1.52 2011/09/22 14:43:01 mel Exp $
      */
     /* 
      * Copyright (c) 1998-2003 Carnegie Mellon University.  All rights reserved.
    @@ -436,7 +436,7 @@ static void randinit(sasl_rand_t *rpool)
     	srandom(*foo);
         }
     #endif /* HAVE_JRAND48 */
    -#else if defined(WIN32)
    +#elif defined(WIN32)
         {
     	unsigned int *foo = (unsigned int *)rpool->pool;
     	srand(*foo);
    @@ -449,7 +449,7 @@ static void randinit(sasl_rand_t *rpool)
     void sasl_rand (sasl_rand_t *rpool, char *buf, unsigned len)
     {
         unsigned int lup;
    -#if defined(WIN32)
    +#if defined(WIN32) && !defined(__MINGW32__)
         unsigned int randomValue;
     #endif
     
    @@ -460,7 +460,9 @@ void sasl_rand (sasl_rand_t *rpool, char *buf, unsigned len)
         randinit(rpool);
     
         for (lup = 0; lup < len; lup++) {
    -#if defined(WIN32)
    +#if defined(__MINGW32__)
    +	buf[lup] = (char) (rand() >> 8);
    +#elif defined(WIN32)
     	if (rand_s(&randomValue) != 0) {
     	    randomValue = rand();
     	}
    
    From b5c47ac532015ec0e5a239b2b2725e10817c502d Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Thu, 22 Sep 2011 14:44:15 +0000
    Subject: [PATCH 126/796] Various build fixes for MINGW32 (Patch from
     marcandre.lureau@redhat.com)
    
    ---
     configure.in | 25 +++++++++++++++++++------
     1 file changed, 19 insertions(+), 6 deletions(-)
    
    diff --git a/configure.in b/configure.in
    index 15a01247..cc5750d1 100644
    --- a/configure.in
    +++ b/configure.in
    @@ -1,7 +1,7 @@
     dnl configure.in for the SASL library
     dnl Rob Siemborski
     dnl Rob Earhart
    -dnl $Id: configure.in,v 1.223 2011/09/13 16:30:23 mel Exp $
    +dnl $Id: configure.in,v 1.224 2011/09/22 14:44:15 mel Exp $
     dnl
     dnl Copyright (c) 2001 Carnegie Mellon University.  All rights reserved.
     dnl
    @@ -1268,7 +1268,8 @@ AH_BOTTOM([
     
     
     /* Create a struct iovec if we need one */
    -#if !defined(_WIN32) && !defined(HAVE_SYS_UIO_H)
    +#if !defined(_WIN32)
    +#if !defined(HAVE_SYS_UIO_H)
     /* (win32 is handled in sasl.h) */
     struct iovec {
         char *iov_base;
    @@ -1278,6 +1279,7 @@ struct iovec {
     #include 
     #include 
     #endif
    +#endif
     
     /* location of the random number generator */
     #ifdef DEV_RANDOM
    @@ -1315,9 +1317,10 @@ struct iovec {
     
     #include 
     #include 
    -#include 
     #ifndef WIN32
    +# include 
     # include 
    +# include 
     # ifdef HAVE_SYS_PARAM_H
     #  include 
     # endif
    @@ -1326,13 +1329,11 @@ struct iovec {
     #endif /* WIN32 */
     #include 
     
    -#include 
    -
     #ifndef HAVE_SOCKLEN_T
     typedef unsigned int socklen_t;
     #endif /* HAVE_SOCKLEN_T */
     
    -#ifndef HAVE_STRUCT_SOCKADDR_STORAGE
    +#if !defined(HAVE_STRUCT_SOCKADDR_STORAGE) && !defined(WIN32)
     #define	_SS_MAXSIZE	128	/* Implementation specific max size */
     #define	_SS_PADSIZE	(_SS_MAXSIZE - sizeof (struct sockaddr))
     
    @@ -1396,6 +1397,18 @@ struct sockaddr_storage {
     #define HIER_DELIMITER '/'
     #endif
     
    +#ifdef WIN32
    +#define SASL_ROOT_KEY "SOFTWARE\\Carnegie Mellon\\Project Cyrus\\SASL Library"
    +#define SASL_PLUGIN_PATH_ATTR "SearchPath"
    +#define SASL_CONF_PATH_ATTR "ConfFile"
    +
    +#include 
    +inline static unsigned int sleep(unsigned int seconds) {
    +       Sleep(seconds * 1000);
    +       return 0;
    +}
    +#endif
    +
     #endif /* CONFIG_H */
     ])
     
    
    From 6f776f8a9bd504219b6600599da60e053899e329 Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Fri, 7 Oct 2011 11:21:23 +0000
    Subject: [PATCH 127/796] Updated the ChangeLog due to merge of some Mingw
     related patches
    
    ---
     ChangeLog | 25 +++++++++++++++++++++++++
     1 file changed, 25 insertions(+)
    
    diff --git a/ChangeLog b/ChangeLog
    index 2a954e94..638d71cf 100644
    --- a/ChangeLog
    +++ b/ChangeLog
    @@ -1,3 +1,28 @@
    +2011-09-22  Alexey Melnikov 
    +	* config/ltconfig, saslauthd/config/ltconfig: Fixed Cyrus SASL
    +	  build on some versions of Mac OS.
    +
    +2011-09-22  Alexey Melnikov 
    +	* saslauthd/auth_rimap.c: qstring incorrectly appending
    +	  the closing double quote. (Merge from RedHat)
    +
    +2011-09-22  Alexey Melnikov 
    +	* lib/common.c: unlock the mutex in sasl_dispose if the context
    +	  was freed by another thread. (Merge from RedHat)
    +
    +2011-09-22  Alexey Melnikov 
    +	* Makefile.am: "lib" should be built before "plugins"
    +	  (Patch from marcandre.lureau@redhat.com)
    +
    +2011-09-22  Alexey Melnikov 
    +	* lib/saslutil.c: MINGW32 doesn't have rand_s
    +	  (Patch from marcandre.lureau@redhat.com)
    +
    +2011-09-22  Alexey Melnikov 
    +	* configure.in: Various build fixes for MINGW32
    +	  (including defining sleep())
    +	  (Patch from marcandre.lureau@redhat.com)
    +
     2011-09-15  Alexey Melnikov 
     	* sample/client.c: Added additional typecasts to kill warnings
     	  about incompatible callback types
    
    From fa289f15ceb2b9c64bdcf057a75469808454190d Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Fri, 7 Oct 2011 11:22:47 +0000
    Subject: [PATCH 128/796] Fixed a segfault in gssapi.c (Patch by Phil Pennock)
    
    ---
     ChangeLog        | 4 ++++
     plugins/gssapi.c | 8 +++++---
     2 files changed, 9 insertions(+), 3 deletions(-)
    
    diff --git a/ChangeLog b/ChangeLog
    index 638d71cf..24d80a8e 100644
    --- a/ChangeLog
    +++ b/ChangeLog
    @@ -1,3 +1,7 @@
    +2011-10-07  Alexey Melnikov 
    +	* plugins/gssapi.c: Fixed a segfault in gssapi.c
    +	  (patch by Phil Pennock)
    +
     2011-09-22  Alexey Melnikov 
     	* config/ltconfig, saslauthd/config/ltconfig: Fixed Cyrus SASL
     	  build on some versions of Mac OS.
    diff --git a/plugins/gssapi.c b/plugins/gssapi.c
    index 114ebedb..2f69ee8b 100644
    --- a/plugins/gssapi.c
    +++ b/plugins/gssapi.c
    @@ -1,7 +1,7 @@
     /* GSSAPI SASL plugin
      * Leif Johansson
      * Rob Siemborski (SASL v2 Conversion)
    - * $Id: gssapi.c,v 1.112 2011/04/19 09:19:18 mel Exp $
    + * $Id: gssapi.c,v 1.113 2011/10/07 11:22:47 mel Exp $
      */
     /* 
      * Copyright (c) 1998-2003 Carnegie Mellon University.  All rights reserved.
    @@ -82,7 +82,7 @@
     
     /*****************************  Common Section  *****************************/
     
    -static const char plugin_id[] = "$Id: gssapi.c,v 1.112 2011/04/19 09:19:18 mel Exp $";
    +static const char plugin_id[] = "$Id: gssapi.c,v 1.113 2011/10/07 11:22:47 mel Exp $";
     
     static const char * GSSAPI_BLANK_STRING = "";
     
    @@ -370,7 +370,7 @@ sasl_gss_encode(void *context, const struct iovec *invec, unsigned numiov,
         }
         
         if (output_token->value && output) {
    -	unsigned char * p = (unsigned char *) text->encode_buf;
    +	unsigned char * p;
     	
     	ret = _plug_buf_alloc(text->utils,
     			      &(text->encode_buf),
    @@ -383,6 +383,8 @@ sasl_gss_encode(void *context, const struct iovec *invec, unsigned numiov,
     	    GSS_UNLOCK_MUTEX(text->utils);
     	    return ret;
     	}
    +
    +	p = (unsigned char *) text->encode_buf;
     	
     	p[0] = (output_token->length>>24) & 0xFF;
     	p[1] = (output_token->length>>16) & 0xFF;
    
    From c1aeb73c57ba936cb0d9b45b90e9d9476deb5c0f Mon Sep 17 00:00:00 2001
    From: Ken Murchison 
    Date: Tue, 8 Nov 2011 17:22:40 +0000
    Subject: [PATCH 129/796] Added sasl_config_done() to plug a memory leak when
     using an application specific config file
    
    ---
     ChangeLog          |  5 +++++
     include/saslutil.h |  2 ++
     lib/config.c       | 20 +++++++++++++++++---
     lib/server.c       |  4 +++-
     4 files changed, 27 insertions(+), 4 deletions(-)
    
    diff --git a/ChangeLog b/ChangeLog
    index 24d80a8e..eb9236bb 100644
    --- a/ChangeLog
    +++ b/ChangeLog
    @@ -1,3 +1,8 @@
    +2011-11-08  Ken Murchison 
    +	* include/saslutil.h, lib/config.c, lib/server.c
    +	  Added sasl_config_done() to plug a memory leak when using an
    +	  application specific config file
    +
     2011-10-07  Alexey Melnikov 
     	* plugins/gssapi.c: Fixed a segfault in gssapi.c
     	  (patch by Phil Pennock)
    diff --git a/include/saslutil.h b/include/saslutil.h
    index 6e5e2818..e0fa47c5 100755
    --- a/include/saslutil.h
    +++ b/include/saslutil.h
    @@ -82,6 +82,8 @@ LIBSASL_API char *sasl_strlower (char *val);
     
     LIBSASL_API int sasl_config_init(const char *filename);
     
    +LIBSASL_API void sasl_config_done(void);
    +
     #ifdef WIN32
     /* Just in case a different DLL defines this as well */
     #if defined(NEED_GETOPT)
    diff --git a/lib/config.c b/lib/config.c
    index 732162c4..c901bd83 100644
    --- a/lib/config.c
    +++ b/lib/config.c
    @@ -1,7 +1,7 @@
     /* SASL Config file API
      * Rob Siemborski
      * Tim Martin (originally in Cyrus distribution)
    - * $Id: config.c,v 1.18 2009/02/14 14:01:24 mel Exp $
    + * $Id: config.c,v 1.19 2011/11/08 17:22:40 murch Exp $
      */
     /* 
      * Copyright (c) 1998-2009 Carnegie Mellon University.  All rights reserved.
    @@ -55,8 +55,8 @@ struct configlist {
         char *value;
     };
     
    -static struct configlist *configlist;
    -static int nconfiglist;
    +static struct configlist *configlist = NULL;
    +static int nconfiglist = 0;
     
     #define CONFIGLISTGROWSIZE 100
     
    @@ -141,3 +141,17 @@ const char *sasl_config_getstring(const char *key,const char *def)
         }
         return def;
     }
    +
    +void sasl_config_done(void)
    +{
    +    int opt;
    +
    +    for (opt = 0; opt < nconfiglist; opt++) {
    +	if (configlist[opt].key) sasl_FREE(configlist[opt].key);
    +	if (configlist[opt].value) sasl_FREE(configlist[opt].value);
    +    }
    +
    +    sasl_FREE(configlist);
    +    configlist = NULL;
    +    nconfiglist = 0;
    +}
    diff --git a/lib/server.c b/lib/server.c
    index d9c23877..9858d7ea 100644
    --- a/lib/server.c
    +++ b/lib/server.c
    @@ -1,7 +1,7 @@
     /* SASL server API implementation
      * Rob Siemborski
      * Tim Martin
    - * $Id: server.c,v 1.176 2011/09/01 16:33:10 mel Exp $
    + * $Id: server.c,v 1.177 2011/11/08 17:22:40 murch Exp $
      */
     /* 
      * Copyright (c) 1998-2003 Carnegie Mellon University.  All rights reserved.
    @@ -564,6 +564,8 @@ static int server_done(void) {
       global_callbacks.callbacks = NULL;
       global_callbacks.appname = NULL;
     
    +  sasl_config_done();
    +
       return SASL_OK;
     }
     
    
    From e44097e34fee71908ccb24e85734de8572d2891b Mon Sep 17 00:00:00 2001
    From: Ken Murchison 
    Date: Tue, 8 Nov 2011 17:31:55 +0000
    Subject: [PATCH 130/796] Flag client-side of NTLM plugin as HTTP-ready
    
    ---
     ChangeLog      | 3 +++
     plugins/ntlm.c | 7 ++++---
     2 files changed, 7 insertions(+), 3 deletions(-)
    
    diff --git a/ChangeLog b/ChangeLog
    index eb9236bb..128c96f5 100644
    --- a/ChangeLog
    +++ b/ChangeLog
    @@ -1,3 +1,6 @@
    +2011-11-08  Ken Murchison 
    +	* plugins/ntlm.c: Flag client-side of NTLM plugin as HTTP-ready
    +
     2011-11-08  Ken Murchison 
     	* include/saslutil.h, lib/config.c, lib/server.c
     	  Added sasl_config_done() to plug a memory leak when using an
    diff --git a/plugins/ntlm.c b/plugins/ntlm.c
    index c7533ca8..79ea47ca 100644
    --- a/plugins/ntlm.c
    +++ b/plugins/ntlm.c
    @@ -1,6 +1,6 @@
     /* NTLM SASL plugin
      * Ken Murchison
    - * $Id: ntlm.c,v 1.36 2011/01/14 14:35:57 murch Exp $
    + * $Id: ntlm.c,v 1.37 2011/11/08 17:31:55 murch Exp $
      *
      * References:
      *   http://www.innovation.ch/java/ntlm.html
    @@ -100,7 +100,7 @@
     
     /*****************************  Common Section  *****************************/
     
    -static const char plugin_id[] = "$Id: ntlm.c,v 1.36 2011/01/14 14:35:57 murch Exp $";
    +static const char plugin_id[] = "$Id: ntlm.c,v 1.37 2011/11/08 17:31:55 murch Exp $";
     
     #ifdef WIN32
     static ssize_t writev (SOCKET fd, const struct iovec *iov, size_t iovcnt);
    @@ -2142,7 +2142,8 @@ static sasl_client_plug_t ntlm_client_plugins[] =
     	0,				/* max_ssf */
     	SASL_SEC_NOPLAINTEXT
     	| SASL_SEC_NOANONYMOUS,		/* security_flags */
    -	SASL_FEAT_WANT_CLIENT_FIRST,	/* features */
    +	SASL_FEAT_WANT_CLIENT_FIRST
    +	| SASL_FEAT_SUPPORTS_HTTP,	/* features */
     	NULL,				/* required_prompts */
     	NULL,				/* glob_context */
     	&ntlm_client_mech_new,		/* mech_new */
    
    From 4e8eddd71a44f92675e43da04e4479476df8f52a Mon Sep 17 00:00:00 2001
    From: Ken Murchison 
    Date: Wed, 9 Nov 2011 15:49:47 +0000
    Subject: [PATCH 131/796] Added GSS-SPNEGO plugin which can also be used for
     HTTP Negotiate auth (RFC 4559)
    
    ---
     ChangeLog         |    5 +
     plugins/gssapi.c  | 1187 +++++++++++++++++++++++++--------------------
     utils/testsuite.c |   18 +-
     3 files changed, 675 insertions(+), 535 deletions(-)
    
    diff --git a/ChangeLog b/ChangeLog
    index 128c96f5..312ecdee 100644
    --- a/ChangeLog
    +++ b/ChangeLog
    @@ -1,3 +1,8 @@
    +2011-11-09  Ken Murchison 
    +	* cmulocal/sasl2.m4, plugins/gssapi.c, utils/testsuite.c:
    +	  Added GSS-SPNEGO plugin which can also be used for HTTP
    +	  Negotiate authentication (RFC 4559)
    +
     2011-11-08  Ken Murchison 
     	* plugins/ntlm.c: Flag client-side of NTLM plugin as HTTP-ready
     
    diff --git a/plugins/gssapi.c b/plugins/gssapi.c
    index 2f69ee8b..6bfb3351 100644
    --- a/plugins/gssapi.c
    +++ b/plugins/gssapi.c
    @@ -1,7 +1,7 @@
     /* GSSAPI SASL plugin
      * Leif Johansson
      * Rob Siemborski (SASL v2 Conversion)
    - * $Id: gssapi.c,v 1.113 2011/10/07 11:22:47 mel Exp $
    + * $Id: gssapi.c,v 1.114 2011/11/09 15:49:47 murch Exp $
      */
     /* 
      * Copyright (c) 1998-2003 Carnegie Mellon University.  All rights reserved.
    @@ -79,13 +79,16 @@
     #endif
     
     #include 
    +#include 
     
     /*****************************  Common Section  *****************************/
     
    -static const char plugin_id[] = "$Id: gssapi.c,v 1.113 2011/10/07 11:22:47 mel Exp $";
    +static const char plugin_id[] = "$Id: gssapi.c,v 1.114 2011/11/09 15:49:47 murch Exp $";
     
     static const char * GSSAPI_BLANK_STRING = "";
     
    +static gss_OID_desc gss_spnego_oid = { 6, (void *) "\x2b\x06\x01\x05\x05\x02" };
    +
     #if !defined(HAVE_GSS_C_NT_HOSTBASED_SERVICE) && !defined(GSS_C_NT_HOSTBASED_SERVICE)
     extern gss_OID gss_nt_service_name;
     #define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name
    @@ -141,6 +144,9 @@ static void *gss_mutex = NULL;
     
     typedef struct context {
         int state;
    +
    +    gss_OID mech_type;		     /* GSS-SPNEGO or GSSAPI */
    +    int http_mode;		     /* use RFC 4559 compatible protocol? */
         
         gss_ctx_id_t gss_ctx;
         gss_name_t   client_name;
    @@ -638,562 +644,663 @@ gssapi_server_mech_new(void *glob_context __attribute__((unused)),
         text->client_creds = GSS_C_NO_CREDENTIAL;
         text->state = SASL_GSSAPI_STATE_AUTHNEG;
         
    +    text->http_mode = (params->flags & SASL_NEED_HTTP);
    +
         *conn_context = text;
         
         return SASL_OK;
     }
     
     static int 
    -gssapi_server_mech_step(void *conn_context,
    -			sasl_server_params_t *params,
    -			const char *clientin,
    -			unsigned clientinlen,
    -			const char **serverout,
    -			unsigned *serveroutlen,
    -			sasl_out_params_t *oparams)
    +gssapi_server_mech_authneg(context_t *text,
    +			   sasl_server_params_t *params,
    +			   const char *clientin,
    +			   unsigned clientinlen,
    +			   const char **serverout,
    +			   unsigned *serveroutlen,
    +			   sasl_out_params_t *oparams __attribute__((unused)))
     {
    -    context_t *text = (context_t *)conn_context;
         gss_buffer_t input_token, output_token;
         gss_buffer_desc real_input_token, real_output_token;
         OM_uint32 maj_stat = 0, min_stat = 0;
    -    OM_uint32 max_input;
         gss_buffer_desc name_token;
    -    int ret, out_flags = 0 ;
    -    gss_cred_id_t server_creds = params->gss_creds;
    -    
    +    int ret, equal = 0;
    +    unsigned out_flags = 0;
    +    gss_cred_id_t server_creds = (gss_cred_id_t) params->gss_creds;
    +    gss_buffer_desc name_without_realm;
    +    gss_name_t client_name_MN = NULL, without = NULL;
    +    gss_OID mech_type;
    +	
         input_token = &real_input_token;
         output_token = &real_output_token;
         output_token->value = NULL; output_token->length = 0;
         input_token->value = NULL; input_token->length = 0;
         
    -    if(!serverout) {
    -	PARAMERROR(text->utils);
    -	return SASL_BADPARAM;
    -    }
    -    
    -    *serverout = NULL;
    -    *serveroutlen = 0;	
    -	    
    -    if (text == NULL) {
    -	return SASL_BADPROT;
    -    }
    +    if (text->server_name == GSS_C_NO_NAME) { /* only once */
    +	if (params->serverFQDN == NULL
    +	    || strlen(params->serverFQDN) == 0) {
    +	    SETERROR(text->utils, "GSSAPI Failure: no serverFQDN");
    +	    sasl_gss_free_context_contents(text);
    +	    return SASL_FAIL;
    +	}
    +	name_token.length = strlen(params->service) + 1 + strlen(params->serverFQDN);
    +	name_token.value = (char *)params->utils->malloc((name_token.length + 1) * sizeof(char));
    +	if (name_token.value == NULL) {
    +	    MEMERROR(text->utils);
    +	    sasl_gss_free_context_contents(text);
    +	    return SASL_NOMEM;
    +	}
    +	sprintf(name_token.value,"%s@%s", params->service, params->serverFQDN);
     
    -    switch (text->state) {
    +	GSS_LOCK_MUTEX(params->utils);
    +	maj_stat = gss_import_name (&min_stat,
    +				    &name_token,
    +				    GSS_C_NT_HOSTBASED_SERVICE,
    +				    &text->server_name);
    +	GSS_UNLOCK_MUTEX(params->utils);
     
    -    case SASL_GSSAPI_STATE_AUTHNEG:
    -	if (text->server_name == GSS_C_NO_NAME) { /* only once */
    -	    if (params->serverFQDN == NULL
    -		|| strlen(params->serverFQDN) == 0) {
    -		SETERROR(text->utils, "GSSAPI Failure: no serverFQDN");
    -		sasl_gss_free_context_contents(text);
    -		return SASL_FAIL;
    -	    }
    -	    name_token.length = strlen(params->service) + 1 + strlen(params->serverFQDN);
    -	    name_token.value = (char *)params->utils->malloc((name_token.length + 1) * sizeof(char));
    -	    if (name_token.value == NULL) {
    -		MEMERROR(text->utils);
    -		sasl_gss_free_context_contents(text);
    -		return SASL_NOMEM;
    -	    }
    -	    sprintf(name_token.value,"%s@%s", params->service, params->serverFQDN);
    -	    
    +	params->utils->free(name_token.value);
    +	name_token.value = NULL;
    +
    +	if (GSS_ERROR(maj_stat)) {
    +	    sasl_gss_seterror(text->utils, maj_stat, min_stat);
    +	    sasl_gss_free_context_contents(text);
    +	    return SASL_FAIL;
    +	}
    +
    +	if ( text->server_creds != GSS_C_NO_CREDENTIAL) {
     	    GSS_LOCK_MUTEX(params->utils);
    -	    maj_stat = gss_import_name (&min_stat,
    -					&name_token,
    -					GSS_C_NT_HOSTBASED_SERVICE,
    -					&text->server_name);
    +	    maj_stat = gss_release_cred(&min_stat, &text->server_creds);
     	    GSS_UNLOCK_MUTEX(params->utils);
    -	    
    -	    params->utils->free(name_token.value);
    -	    name_token.value = NULL;
    -	    
    +	    text->server_creds = GSS_C_NO_CREDENTIAL;
    +	}
    +
    +	/* If caller didn't provide creds already */
    +	if ( server_creds == GSS_C_NO_CREDENTIAL) {
    +	    GSS_LOCK_MUTEX(params->utils);
    +	    maj_stat = gss_acquire_cred(&min_stat, 
    +					text->server_name,
    +					GSS_C_INDEFINITE, 
    +					GSS_C_NO_OID_SET,
    +					GSS_C_ACCEPT,
    +					&text->server_creds, 
    +					NULL, 
    +					NULL);
    +	    GSS_UNLOCK_MUTEX(params->utils);
    +
     	    if (GSS_ERROR(maj_stat)) {
     		sasl_gss_seterror(text->utils, maj_stat, min_stat);
     		sasl_gss_free_context_contents(text);
     		return SASL_FAIL;
     	    }
    -	    
    -	    if ( text->server_creds != GSS_C_NO_CREDENTIAL) {
    -	    	GSS_LOCK_MUTEX(params->utils);
    -		maj_stat = gss_release_cred(&min_stat, &text->server_creds);
    -	    	GSS_UNLOCK_MUTEX(params->utils);
    -		text->server_creds = GSS_C_NO_CREDENTIAL;
    -	    }
    -
    -	    /* If caller didn't provide creds already */
    -	    if ( server_creds == GSS_C_NO_CREDENTIAL) {
    -		GSS_LOCK_MUTEX(params->utils);
    -		maj_stat = gss_acquire_cred(&min_stat, 
    -					    text->server_name,
    -					    GSS_C_INDEFINITE, 
    -					    GSS_C_NO_OID_SET,
    -					    GSS_C_ACCEPT,
    -					    &text->server_creds, 
    -					    NULL, 
    -					    NULL);
    -		GSS_UNLOCK_MUTEX(params->utils);
    -	    
    -		if (GSS_ERROR(maj_stat)) {
    -		    sasl_gss_seterror(text->utils, maj_stat, min_stat);
    -		    sasl_gss_free_context_contents(text);
    -		    return SASL_FAIL;
    -		}
    -		server_creds = text->server_creds;
    -	    }
    -	}
    -	
    -	if (clientinlen) {
    -	    real_input_token.value = (void *)clientin;
    -	    real_input_token.length = clientinlen;
    +	    server_creds = text->server_creds;
     	}
    +    }
     	
    -	
    -	GSS_LOCK_MUTEX(params->utils);
    -	maj_stat =
    -	    gss_accept_sec_context(&min_stat,
    -				   &(text->gss_ctx),
    -				   server_creds,
    -				   input_token,
    -				   GSS_C_NO_CHANNEL_BINDINGS,
    -				   &text->client_name,
    -				   NULL,	/* resulting mech_name */
    -				   output_token,
    -				   &out_flags,
    -				   NULL,	/* context validity period */
    -				   &(text->client_creds));
    -	GSS_UNLOCK_MUTEX(params->utils);
    -	
    -	if (GSS_ERROR(maj_stat)) {
    -	    sasl_gss_log(text->utils, maj_stat, min_stat);
    -	    text->utils->seterror(text->utils->conn, SASL_NOLOG, "GSSAPI Failure: gss_accept_sec_context");
    -	    if (output_token->value) {
    -		GSS_LOCK_MUTEX(params->utils);
    -		gss_release_buffer(&min_stat, output_token);
    -		GSS_UNLOCK_MUTEX(params->utils);
    -	    }
    -	    sasl_gss_free_context_contents(text);
    -	    return SASL_BADAUTH;
    +    if (clientinlen) {
    +	real_input_token.value = (void *)clientin;
    +	real_input_token.length = clientinlen;
    +    }
    +
    +
    +    GSS_LOCK_MUTEX(params->utils);
    +    maj_stat =
    +	gss_accept_sec_context(&min_stat,
    +			       &(text->gss_ctx),
    +			       server_creds,
    +			       input_token,
    +			       GSS_C_NO_CHANNEL_BINDINGS,
    +			       &text->client_name,
    +			       &mech_type,
    +			       output_token,
    +			       &out_flags,
    +			       NULL,	/* context validity period */
    +			       &(text->client_creds));
    +    GSS_UNLOCK_MUTEX(params->utils);
    +
    +    if (GSS_ERROR(maj_stat)) {
    +	sasl_gss_log(text->utils, maj_stat, min_stat);
    +	text->utils->seterror(text->utils->conn, SASL_NOLOG, "GSSAPI Failure: gss_accept_sec_context");
    +	if (output_token->value) {
    +	    GSS_LOCK_MUTEX(params->utils);
    +	    gss_release_buffer(&min_stat, output_token);
    +	    GSS_UNLOCK_MUTEX(params->utils);
     	}
    +	sasl_gss_free_context_contents(text);
    +	return SASL_BADAUTH;
    +    }
     
    -	/* When GSS_Accept_sec_context returns GSS_S_COMPLETE, the server
    -	   examines the context to ensure that it provides a level of protection
    -	   permitted by the server's security policy.  In particular, if the
    -	   integ_avail flag is not set in the context, then no security layer
    -	   can be offered or accepted.  If the conf_avail flag is not set in the
    -	   context, then no security layer with confidentiality can be offered
    +    /* When GSS_Accept_sec_context returns GSS_S_COMPLETE, the server
    +       examines the context to ensure that it provides a level of protection
    +       permitted by the server's security policy.  In particular, if the
    +       integ_avail flag is not set in the context, then no security layer
    +       can be offered or accepted.  If the conf_avail flag is not set in the
    +       context, then no security layer with confidentiality can be offered
    +       or accepted. */
    +    if ((out_flags & GSS_C_INTEG_FLAG) == 0) {
    +	/* if the integ_avail flag is not set in the context,
    +	   then no security layer can be offered or accepted. */
    +	text->qop = LAYER_NONE;
    +    } else if ((out_flags & GSS_C_CONF_FLAG) == 0) {
    +	/* If the conf_avail flag is not set in the context,
    +	   then no security layer with confidentiality can be offered
     	   or accepted. */
    -	if ((out_flags & GSS_C_INTEG_FLAG) == 0) {
    -	    /* if the integ_avail flag is not set in the context,
    -	       then no security layer can be offered or accepted. */
    -	    text->qop = LAYER_NONE;
    -	} else if ((out_flags & GSS_C_CONF_FLAG) == 0) {
    -	    /* If the conf_avail flag is not set in the context,
    -	       then no security layer with confidentiality can be offered
    -	       or accepted. */
    -	    text->qop = LAYER_NONE | LAYER_INTEGRITY;
    -	} else {
    -	    text->qop = LAYER_NONE | LAYER_INTEGRITY | LAYER_CONFIDENTIALITY;
    -	}
    +	text->qop = LAYER_NONE | LAYER_INTEGRITY;
    +    } else {
    +	text->qop = LAYER_NONE | LAYER_INTEGRITY | LAYER_CONFIDENTIALITY;
    +    }
     
    -	if ((params->props.security_flags & SASL_SEC_PASS_CREDENTIALS) &&
    -	    (!(out_flags & GSS_C_DELEG_FLAG) ||
    -	     text->client_creds == GSS_C_NO_CREDENTIAL) ) 
    +    if ((params->props.security_flags & SASL_SEC_PASS_CREDENTIALS) &&
    +	(!(out_flags & GSS_C_DELEG_FLAG) ||
    +	 text->client_creds == GSS_C_NO_CREDENTIAL) ) 
     	{
     	    text->utils->seterror(text->utils->conn, SASL_LOG_WARN,
     				  "GSSAPI warning: no credentials were passed");
     	    /* continue with authentication */
     	}
    -	    
    -	if (serveroutlen)
    -	    *serveroutlen = output_token->length;
    -	if (output_token->value) {
    -	    if (serverout) {
    -		ret = _plug_buf_alloc(text->utils, &(text->out_buf),
    -				      &(text->out_buf_len), *serveroutlen);
    -		if(ret != SASL_OK) {
    -		    GSS_LOCK_MUTEX(params->utils);
    -		    gss_release_buffer(&min_stat, output_token);
    -		    GSS_UNLOCK_MUTEX(params->utils);
    -		    return ret;
    -		}
    -		memcpy(text->out_buf, output_token->value, *serveroutlen);
    -		*serverout = text->out_buf;
    +
    +    if (serveroutlen)
    +	*serveroutlen = output_token->length;
    +    if (output_token->value) {
    +	if (serverout) {
    +	    ret = _plug_buf_alloc(text->utils, &(text->out_buf),
    +				  &(text->out_buf_len), *serveroutlen);
    +	    if(ret != SASL_OK) {
    +		GSS_LOCK_MUTEX(params->utils);
    +		gss_release_buffer(&min_stat, output_token);
    +		GSS_UNLOCK_MUTEX(params->utils);
    +		return ret;
     	    }
    -	    
    -	    GSS_LOCK_MUTEX(params->utils);
    -	    gss_release_buffer(&min_stat, output_token);
    -	    GSS_UNLOCK_MUTEX(params->utils);
    -	} else {
    -	    /* No output token, send an empty string */
    -	    *serverout = GSSAPI_BLANK_STRING;
    -	    *serveroutlen = 0;
    +	    memcpy(text->out_buf, output_token->value, *serveroutlen);
    +	    *serverout = text->out_buf;
     	}
     
    -	if (maj_stat == GSS_S_COMPLETE) {
    -	    /* Switch to ssf negotiation */
    -	    text->state = SASL_GSSAPI_STATE_SSFCAP;
    +	GSS_LOCK_MUTEX(params->utils);
    +	gss_release_buffer(&min_stat, output_token);
    +	GSS_UNLOCK_MUTEX(params->utils);
    +    } else {
    +	/* No output token, send an empty string */
    +	*serverout = GSSAPI_BLANK_STRING;
    +	*serveroutlen = 0;
    +    }
     
    -	    if (*serveroutlen != 0) {
    -		return SASL_CONTINUE;
    -	    }
    +    if (maj_stat == GSS_S_CONTINUE_NEEDED) {
    +	/* Context isn't complete */
    +        return SASL_CONTINUE;
    +    }
     
    -	    /* Pretend that we just got an empty response from the client */
    -	    clientinlen = 0;
    +    assert(maj_stat == GSS_S_COMPLETE);
     
    -	    /* fall through */
    -	} else {
    -	    return SASL_CONTINUE;
    -	}
    +    GSS_LOCK_MUTEX(params->utils);
    +    maj_stat = gss_canonicalize_name(&min_stat,
    +				     text->client_name,
    +				     mech_type,
    +				     &client_name_MN);
    +    GSS_UNLOCK_MUTEX(params->utils);
     
    -    case SASL_GSSAPI_STATE_SSFCAP: {
    -	unsigned char sasldata[4];
    -	gss_buffer_desc name_token;
    -	gss_buffer_desc name_without_realm;
    -	gss_name_t without = NULL;
    -	int equal;
    -	
    -	name_token.value = NULL;
    -	name_without_realm.value = NULL;
    -	
    -	if (clientinlen != 0) {
    -	    SETERROR(text->utils, "GSSAPI server is not expecting data at this stage");
    -	    sasl_gss_free_context_contents(text);
    -	    return SASL_BADAUTH;
    +    if (GSS_ERROR(maj_stat)) {
    +	SETERROR(text->utils, "GSSAPI Failure: gss_canonicalize_name");
    +	sasl_gss_free_context_contents(text);
    +	return SASL_BADAUTH;
    +    }
    +
    +    name_token.value = NULL;
    +    name_without_realm.value = NULL;
    +
    +    GSS_LOCK_MUTEX(params->utils);
    +    maj_stat = gss_display_name (&min_stat,
    +				 client_name_MN,
    +				 &name_token,
    +				 NULL);
    +    GSS_UNLOCK_MUTEX(params->utils);
    +
    +    if (GSS_ERROR(maj_stat)) {
    +	SETERROR(text->utils, "GSSAPI Failure: gss_display_name");
    +	sasl_gss_free_context_contents(text);
    +	ret = SASL_BADAUTH;
    +	goto cleanup;
    +    }
    +
    +    /* If the id contains a realm get the identifier for the user
    +       without the realm and see if it's the same id (i.e. 
    +       tmartin == tmartin@ANDREW.CMU.EDU. If this is the case we just want
    +       to return the id (i.e. just "tmartin" */
    +    if (strchr((char *) name_token.value, (int) '@') != NULL) {
    +	/* NOTE: libc malloc, as it is freed below by a gssapi internal
    +	 *       function! */
    +	name_without_realm.value = params->utils->malloc(strlen(name_token.value)+1);
    +	if (name_without_realm.value == NULL) {
    +	    MEMERROR(text->utils);
    +	    ret = SASL_NOMEM;
    +	    goto cleanup;
     	}
    -	
    +
    +	strcpy(name_without_realm.value, name_token.value);
    +
    +	/* cut off string at '@' */
    +	(strchr(name_without_realm.value,'@'))[0] = '\0';
    +
    +	name_without_realm.length = strlen( (char *) name_without_realm.value );
    +
     	GSS_LOCK_MUTEX(params->utils);
    -	maj_stat = gss_display_name (&min_stat,
    -				     text->client_name,
    -				     &name_token,
    -				     NULL);
    -	GSS_UNLOCK_MUTEX(params->utils);
    -	
    -	if (GSS_ERROR(maj_stat)) {
    -	    SETERROR(text->utils, "GSSAPI Failure");
    -	    sasl_gss_free_context_contents(text);
    -	    return SASL_BADAUTH;
    -	}
    -	
    -	/* If the id contains a realm get the identifier for the user
    -	   without the realm and see if it's the same id (i.e. 
    -	   tmartin == tmartin@ANDREW.CMU.EDU. If this is the case we just want
    -	   to return the id (i.e. just "tmartin" */
    -	if (strchr((char *) name_token.value, (int) '@') != NULL) {
    -	    /* NOTE: libc malloc, as it is freed below by a gssapi internal
    -	     *       function! */
    -	    name_without_realm.value = params->utils->malloc(strlen(name_token.value)+1);
    -	    if (name_without_realm.value == NULL) {
    -		if (name_token.value) {
    -	    	    GSS_LOCK_MUTEX(params->utils);
    -		    gss_release_buffer(&min_stat, &name_token);
    -	    	    GSS_UNLOCK_MUTEX(params->utils);
    -		}
    -		MEMERROR(text->utils);
    -		return SASL_NOMEM;
    -	    }
    -	    
    -	    strcpy(name_without_realm.value, name_token.value);
    -	    
    -	    /* cut off string at '@' */
    -	    (strchr(name_without_realm.value,'@'))[0] = '\0';
    -	    
    -	    name_without_realm.length = strlen( (char *) name_without_realm.value );
    -	    
    -	    GSS_LOCK_MUTEX(params->utils);
    -	    maj_stat = gss_import_name (&min_stat,
    -					&name_without_realm,
    +	maj_stat = gss_import_name (&min_stat,
    +				    &name_without_realm,
     	    /* Solaris 8/9 gss_import_name doesn't accept GSS_C_NULL_OID here,
     	       so use GSS_C_NT_USER_NAME instead if available.  */
     #ifdef HAVE_GSS_C_NT_USER_NAME
    -					GSS_C_NT_USER_NAME,
    +				    GSS_C_NT_USER_NAME,
     #else
    -					GSS_C_NULL_OID,
    +				    GSS_C_NULL_OID,
     #endif
    -					&without);
    -	    GSS_UNLOCK_MUTEX(params->utils);
    -	    
    -	    if (GSS_ERROR(maj_stat)) {
    -		params->utils->free(name_without_realm.value);
    -		if (name_token.value) {
    -	    	    GSS_LOCK_MUTEX(params->utils);
    -		    gss_release_buffer(&min_stat, &name_token);
    -	    	    GSS_UNLOCK_MUTEX(params->utils);
    -		}
    -		SETERROR(text->utils, "GSSAPI Failure");
    -		sasl_gss_free_context_contents(text);
    -		return SASL_BADAUTH;
    -	    }
    -	    
    -	    GSS_LOCK_MUTEX(params->utils);
    -	    maj_stat = gss_compare_name(&min_stat,
    -					text->client_name,
    -					without,
    -					&equal);
    -	    GSS_UNLOCK_MUTEX(params->utils);
    -	    
    -	    if (GSS_ERROR(maj_stat)) {
    -		params->utils->free(name_without_realm.value);
    -		if (name_token.value) {
    -	    	    GSS_LOCK_MUTEX(params->utils);
    -		    gss_release_buffer(&min_stat, &name_token);
    -	    	    GSS_UNLOCK_MUTEX(params->utils);
    -		}
    -		if (without) {
    -	    	    GSS_LOCK_MUTEX(params->utils);
    -		    gss_release_name(&min_stat, &without);
    -	    	    GSS_UNLOCK_MUTEX(params->utils);
    -		}
    -		SETERROR(text->utils, "GSSAPI Failure");
    -		sasl_gss_free_context_contents(text);
    -		return SASL_BADAUTH;
    -	    }
    -	    
    -	    GSS_LOCK_MUTEX(params->utils);
    -	    gss_release_name(&min_stat,&without);
    -	    GSS_UNLOCK_MUTEX(params->utils);
    +				    &without);
    +	GSS_UNLOCK_MUTEX(params->utils);
     
    -	} else {
    -	    equal = 0;
    -	}
    -	
    -	if (equal) {
    -	    text->authid = strdup(name_without_realm.value);
    -	    
    -	    if (text->authid == NULL) {
    -		MEMERROR(params->utils);
    -		return SASL_NOMEM;
    -	    }
    -	} else {
    -	    text->authid = strdup(name_token.value);
    -	    
    -	    if (text->authid == NULL) {
    -		MEMERROR(params->utils);
    -		return SASL_NOMEM;
    -	    }
    -	}
    -	
    -	if (name_token.value) {
    -	    GSS_LOCK_MUTEX(params->utils);
    -	    gss_release_buffer(&min_stat, &name_token);
    -	    GSS_UNLOCK_MUTEX(params->utils);
    -	}
    -	if (name_without_realm.value) {
    -	    params->utils->free(name_without_realm.value);
    +	if (GSS_ERROR(maj_stat)) {
    +	    SETERROR(text->utils, "GSSAPI Failure: gss_import_name");
    +	    sasl_gss_free_context_contents(text);
    +	    ret = SASL_BADAUTH;
    +	    goto cleanup;
     	}
     
    -	/* we have to decide what sort of encryption/integrity/etc.,
    -	   we support */
    -	if (params->props.max_ssf < params->external_ssf) {
    -	    text->limitssf = 0;
    -	} else {
    -	    text->limitssf = params->props.max_ssf - params->external_ssf;
    +	GSS_LOCK_MUTEX(params->utils);
    +	maj_stat = gss_compare_name(&min_stat,
    +				    client_name_MN,
    +				    without,
    +				    &equal);
    +	GSS_UNLOCK_MUTEX(params->utils);
    +
    +	if (GSS_ERROR(maj_stat)) {
    +	    SETERROR(text->utils, "GSSAPI Failure: gss_compare_name");
    +	    sasl_gss_free_context_contents(text);
    +	    ret = SASL_BADAUTH;
    +	    goto cleanup;
     	}
    -	if (params->props.min_ssf < params->external_ssf) {
    -	    text->requiressf = 0;
    +
    +    } else {
    +	equal = 0;
    +    }
    +
    +    if (equal) {
    +	text->authid = strdup(name_without_realm.value);
    +    } else {
    +	text->authid = strdup(name_token.value);
    +    }
    +
    +    if (text->authid == NULL) {
    +	MEMERROR(params->utils);
    +	ret = SASL_NOMEM;
    +	goto cleanup;
    +    }
    +
    +    if (text->http_mode) {
    +	/* HTTP doesn't do any ssf negotiation */
    +	text->state = SASL_GSSAPI_STATE_AUTHENTICATED;
    +	ret = SASL_OK;
    +    }
    +    else {
    +	/* Switch to ssf negotiation */
    +	text->state = SASL_GSSAPI_STATE_SSFCAP;
    +	ret = SASL_CONTINUE;
    +    }
    +
    +  cleanup:
    +    if (client_name_MN) {
    +	GSS_LOCK_MUTEX(params->utils);
    +	gss_release_name(&min_stat, &client_name_MN);
    +	GSS_UNLOCK_MUTEX(params->utils);
    +    }
    +    if (name_token.value) {
    +	GSS_LOCK_MUTEX(params->utils);
    +	gss_release_buffer(&min_stat, &name_token);
    +	GSS_UNLOCK_MUTEX(params->utils);
    +    }
    +    if (name_without_realm.value) {
    +	params->utils->free(name_without_realm.value);
    +    }
    +    if (without) {
    +	GSS_LOCK_MUTEX(params->utils);
    +	gss_release_name(&min_stat, &without);
    +	GSS_UNLOCK_MUTEX(params->utils);
    +    }
    +
    +    return ret;
    +}
    +
    +static int 
    +gssapi_server_mech_ssfcap(context_t *text,
    +			  sasl_server_params_t *params,
    +			  const char *clientin __attribute__((unused)),
    +			  unsigned clientinlen,
    +			  const char **serverout,
    +			  unsigned *serveroutlen,
    +			  sasl_out_params_t *oparams __attribute__((unused)))
    +{
    +    gss_buffer_t input_token, output_token;
    +    gss_buffer_desc real_input_token, real_output_token;
    +    OM_uint32 maj_stat = 0, min_stat = 0;
    +    unsigned char sasldata[4];
    +    int ret;
    +
    +    input_token = &real_input_token;
    +    output_token = &real_output_token;
    +    output_token->value = NULL; output_token->length = 0;
    +    
    +
    +    if (clientinlen != 0) {
    +	SETERROR(text->utils, "GSSAPI server is not expecting data at this stage");
    +	sasl_gss_free_context_contents(text);
    +	return SASL_BADAUTH;
    +    }
    +
    +    /* we have to decide what sort of encryption/integrity/etc.,
    +       we support */
    +    if (params->props.max_ssf < params->external_ssf) {
    +	text->limitssf = 0;
    +    } else {
    +	text->limitssf = params->props.max_ssf - params->external_ssf;
    +    }
    +    if (params->props.min_ssf < params->external_ssf) {
    +	text->requiressf = 0;
    +    } else {
    +	text->requiressf = params->props.min_ssf - params->external_ssf;
    +    }
    +
    +    /* build up our security properties token */
    +    if (text->requiressf != 0 &&
    +	(text->qop & (LAYER_INTEGRITY|LAYER_CONFIDENTIALITY))) {
    +	if (params->props.maxbufsize > 0xFFFFFF) {
    +	    /* make sure maxbufsize isn't too large */
    +	    /* maxbufsize = 0xFFFFFF */
    +	    sasldata[1] = sasldata[2] = sasldata[3] = 0xFF;
     	} else {
    -	    text->requiressf = params->props.min_ssf - params->external_ssf;
    +	    sasldata[1] = (params->props.maxbufsize >> 16) & 0xFF;
    +	    sasldata[2] = (params->props.maxbufsize >> 8) & 0xFF;
    +	    sasldata[3] = (params->props.maxbufsize >> 0) & 0xFF;
     	}
    -	
    -	/* build up our security properties token */
    -	if (text->requiressf != 0 &&
    -	    (text->qop & (LAYER_INTEGRITY|LAYER_CONFIDENTIALITY))) {
    -	    if (params->props.maxbufsize > 0xFFFFFF) {
    -		/* make sure maxbufsize isn't too large */
    -		/* maxbufsize = 0xFFFFFF */
    -		sasldata[1] = sasldata[2] = sasldata[3] = 0xFF;
    -	    } else {
    -		sasldata[1] = (params->props.maxbufsize >> 16) & 0xFF;
    -		sasldata[2] = (params->props.maxbufsize >> 8) & 0xFF;
    -		sasldata[3] = (params->props.maxbufsize >> 0) & 0xFF;
    -	    }
    -	} else {
    -	    /* From RFC 4752: "The client verifies that the server maximum buffer is 0
    -	       if the server does not advertise support for any security layer." */
    -	    sasldata[1] = sasldata[2] = sasldata[3] = 0;
    +    } else {
    +	/* From RFC 4752: "The client verifies that the server maximum buffer is 0
    +	   if the server does not advertise support for any security layer." */
    +	sasldata[1] = sasldata[2] = sasldata[3] = 0;
    +    }
    +
    +    sasldata[0] = 0;
    +    if(text->requiressf != 0 && !params->props.maxbufsize) {
    +	params->utils->seterror(params->utils->conn, 0,
    +				"GSSAPI needs a security layer but one is forbidden");
    +	return SASL_TOOWEAK;
    +    }
    +
    +    if (text->requiressf == 0) {
    +	sasldata[0] |= LAYER_NONE; /* authentication */
    +    }
    +    if ((text->qop & LAYER_INTEGRITY) &&
    +	text->requiressf <= 1 &&
    +	text->limitssf >= 1 &&
    +	params->props.maxbufsize) {
    +	sasldata[0] |= LAYER_INTEGRITY;
    +    }
    +    if ((text->qop & LAYER_CONFIDENTIALITY) &&
    +	text->requiressf <= K5_MAX_SSF &&
    +	text->limitssf >= K5_MAX_SSF &&
    +	params->props.maxbufsize) {
    +	sasldata[0] |= LAYER_CONFIDENTIALITY;
    +    }
    +
    +    /* Remember what we want and can offer */
    +    text->qop = sasldata[0];
    +
    +    real_input_token.value = (void *)sasldata;
    +    real_input_token.length = 4;
    +
    +    GSS_LOCK_MUTEX(params->utils);
    +    maj_stat = gss_wrap(&min_stat,
    +			text->gss_ctx,
    +			0, /* Just integrity checking here */
    +			GSS_C_QOP_DEFAULT,
    +			input_token,
    +			NULL,
    +			output_token);
    +    GSS_UNLOCK_MUTEX(params->utils);
    +
    +    if (GSS_ERROR(maj_stat)) {
    +	sasl_gss_seterror(text->utils, maj_stat, min_stat);
    +	if (output_token->value) {
    +	    GSS_LOCK_MUTEX(params->utils);
    +	    gss_release_buffer(&min_stat, output_token);
    +	    GSS_UNLOCK_MUTEX(params->utils);
     	}
    +	sasl_gss_free_context_contents(text);
    +	return SASL_FAIL;
    +    }
     
    -	sasldata[0] = 0;
    -	if(text->requiressf != 0 && !params->props.maxbufsize) {
    -	    params->utils->seterror(params->utils->conn, 0,
    -				    "GSSAPI needs a security layer but one is forbidden");
    -	    return SASL_TOOWEAK;
    -	}
    -	
    -	if (text->requiressf == 0) {
    -	    sasldata[0] |= LAYER_NONE; /* authentication */
    -	}
    -	if ((text->qop & LAYER_INTEGRITY) &&
    -	    text->requiressf <= 1 &&
    -	    text->limitssf >= 1 &&
    -	    params->props.maxbufsize) {
    -	    sasldata[0] |= LAYER_INTEGRITY;
    -	}
    -	if ((text->qop & LAYER_CONFIDENTIALITY) &&
    -	    text->requiressf <= K5_MAX_SSF &&
    -	    text->limitssf >= K5_MAX_SSF &&
    -	    params->props.maxbufsize) {
    -	    sasldata[0] |= LAYER_CONFIDENTIALITY;
    -	}
    -	
    -	real_input_token.value = (void *)sasldata;
    -	real_input_token.length = 4;
    -	
    -	GSS_LOCK_MUTEX(params->utils);
    -	maj_stat = gss_wrap(&min_stat,
    -			    text->gss_ctx,
    -			    0, /* Just integrity checking here */
    -			    GSS_C_QOP_DEFAULT,
    -			    input_token,
    -			    NULL,
    -			    output_token);
    -	GSS_UNLOCK_MUTEX(params->utils);
    -	
    -	if (GSS_ERROR(maj_stat)) {
    -	    sasl_gss_seterror(text->utils, maj_stat, min_stat);
    -	    if (output_token->value) {
    +
    +    if (serveroutlen)
    +	*serveroutlen = output_token->length;
    +    if (output_token->value) {
    +	if (serverout) {
    +	    ret = _plug_buf_alloc(text->utils, &(text->out_buf),
    +				  &(text->out_buf_len), *serveroutlen);
    +	    if(ret != SASL_OK) {
     		GSS_LOCK_MUTEX(params->utils);
     		gss_release_buffer(&min_stat, output_token);
     		GSS_UNLOCK_MUTEX(params->utils);
    +		return ret;
     	    }
    -	    sasl_gss_free_context_contents(text);
    -	    return SASL_FAIL;
    -	}
    -	
    -	
    -	if (serveroutlen)
    -	    *serveroutlen = output_token->length;
    -	if (output_token->value) {
    -	    if (serverout) {
    -		ret = _plug_buf_alloc(text->utils, &(text->out_buf),
    -				      &(text->out_buf_len), *serveroutlen);
    -		if(ret != SASL_OK) {
    -		    GSS_LOCK_MUTEX(params->utils);
    -		    gss_release_buffer(&min_stat, output_token);
    -		    GSS_UNLOCK_MUTEX(params->utils);
    -		    return ret;
    -		}
    -		memcpy(text->out_buf, output_token->value, *serveroutlen);
    -		*serverout = text->out_buf;
    -	    }
    -	    
    -	    GSS_LOCK_MUTEX(params->utils);
    -	    gss_release_buffer(&min_stat, output_token);
    -	    GSS_UNLOCK_MUTEX(params->utils);
    +	    memcpy(text->out_buf, output_token->value, *serveroutlen);
    +	    *serverout = text->out_buf;
     	}
    -	
    -	/* Remember what we want and can offer */
    -	text->qop = sasldata[0];
     
    -	/* Wait for ssf request and authid */
    -	text->state = SASL_GSSAPI_STATE_SSFREQ; 
    -	
    -	return SASL_CONTINUE;
    +	GSS_LOCK_MUTEX(params->utils);
    +	gss_release_buffer(&min_stat, output_token);
    +	GSS_UNLOCK_MUTEX(params->utils);
         }
     
    -    case SASL_GSSAPI_STATE_SSFREQ: {
    -	int layerchoice;
    +    /* Wait for ssf request and authid */
    +    text->state = SASL_GSSAPI_STATE_SSFREQ; 
     	
    -	real_input_token.value = (void *)clientin;
    -	real_input_token.length = clientinlen;
    +    return SASL_CONTINUE;
    +}
    +
    +static int 
    +gssapi_server_mech_ssfreq(context_t *text,
    +			  sasl_server_params_t *params,
    +			  const char *clientin,
    +			  unsigned clientinlen,
    +			  const char **serverout __attribute__((unused)),
    +			  unsigned *serveroutlen __attribute__((unused)),
    +			  sasl_out_params_t *oparams)
    +{
    +    gss_buffer_t input_token, output_token;
    +    gss_buffer_desc real_input_token, real_output_token;
    +    OM_uint32 maj_stat = 0, min_stat = 0;
    +    OM_uint32 max_input;
    +    int layerchoice;
     	
    +    input_token = &real_input_token;
    +    output_token = &real_output_token;
    +    output_token->value = NULL; output_token->length = 0;
    +
    +    real_input_token.value = (void *)clientin;
    +    real_input_token.length = clientinlen;
    +
    +    GSS_LOCK_MUTEX(params->utils);
    +    maj_stat = gss_unwrap(&min_stat,
    +			  text->gss_ctx,
    +			  input_token,
    +			  output_token,
    +			  NULL,
    +			  NULL);
    +    GSS_UNLOCK_MUTEX(params->utils);
    +
    +    if (GSS_ERROR(maj_stat)) {
    +	sasl_gss_seterror(text->utils, maj_stat, min_stat);
    +	sasl_gss_free_context_contents(text);
    +	return SASL_FAIL;
    +    }
    +
    +    if (output_token->length < 4) {
    +	SETERROR(text->utils,
    +		 "token too short");
     	GSS_LOCK_MUTEX(params->utils);
    -	maj_stat = gss_unwrap(&min_stat,
    -			      text->gss_ctx,
    -			      input_token,
    -			      output_token,
    -			      NULL,
    -			      NULL);
    +	gss_release_buffer(&min_stat, output_token);
     	GSS_UNLOCK_MUTEX(params->utils);
    -	
    -	if (GSS_ERROR(maj_stat)) {
    -	    sasl_gss_seterror(text->utils, maj_stat, min_stat);
    -	    sasl_gss_free_context_contents(text);
    -	    return SASL_FAIL;
    -	}
    +	sasl_gss_free_context_contents(text);
    +	return SASL_FAIL;
    +    }
     
    -	if (output_token->length < 4) {
    -	    SETERROR(text->utils,
    -		     "token too short");
    +    layerchoice = (int)(((char *)(output_token->value))[0]);
    +    if (layerchoice == LAYER_NONE &&
    +	(text->qop & LAYER_NONE)) { /* no encryption */
    +	oparams->encode = NULL;
    +	oparams->decode = NULL;
    +	oparams->mech_ssf = 0;
    +    } else if (layerchoice == LAYER_INTEGRITY &&
    +	       (text->qop & LAYER_INTEGRITY)) { /* integrity */
    +	oparams->encode = &gssapi_integrity_encode;
    +	oparams->decode = &gssapi_decode;
    +	oparams->mech_ssf = 1;
    +    } else if ((layerchoice == LAYER_CONFIDENTIALITY ||
    +		/* For compatibility with broken clients setting both bits */
    +		layerchoice == (LAYER_CONFIDENTIALITY|LAYER_INTEGRITY)) &&
    +	       (text->qop & LAYER_CONFIDENTIALITY)) { /* privacy */
    +	oparams->encode = &gssapi_privacy_encode;
    +	oparams->decode = &gssapi_decode;
    +	/* FIX ME: Need to extract the proper value here */
    +	oparams->mech_ssf = K5_MAX_SSF;
    +    } else {
    +	/* not a supported encryption layer */
    +	SETERROR(text->utils,
    +		 "protocol violation: client requested invalid layer");
    +	/* Mark that we attempted negotiation */
    +	oparams->mech_ssf = 2;
    +	if (output_token->value) {
     	    GSS_LOCK_MUTEX(params->utils);
     	    gss_release_buffer(&min_stat, output_token);
     	    GSS_UNLOCK_MUTEX(params->utils);
    -	    sasl_gss_free_context_contents(text);
    -	    return SASL_FAIL;
     	}
    +	sasl_gss_free_context_contents(text);
    +	return SASL_FAIL;
    +    }
    +
    +    if (output_token->length > 4) {
    +	int ret;
    +
    +	ret = params->canon_user(params->utils->conn,
    +				 ((char *) output_token->value) + 4,
    +				 (output_token->length - 4) * sizeof(char),
    +				 SASL_CU_AUTHZID, oparams);
     	
    -	layerchoice = (int)(((char *)(output_token->value))[0]);
    -	if (layerchoice == LAYER_NONE &&
    -	    (text->qop & LAYER_NONE)) { /* no encryption */
    -	    oparams->encode = NULL;
    -	    oparams->decode = NULL;
    -	    oparams->mech_ssf = 0;
    -	} else if (layerchoice == LAYER_INTEGRITY &&
    -		   (text->qop & LAYER_INTEGRITY)) { /* integrity */
    -	    oparams->encode = &gssapi_integrity_encode;
    -	    oparams->decode = &gssapi_decode;
    -	    oparams->mech_ssf = 1;
    -	} else if ((layerchoice == LAYER_CONFIDENTIALITY ||
    -		    /* For compatibility with broken clients setting both bits */
    -		    layerchoice == (LAYER_CONFIDENTIALITY|LAYER_INTEGRITY)) &&
    -		   (text->qop & LAYER_CONFIDENTIALITY)) { /* privacy */
    -	    oparams->encode = &gssapi_privacy_encode;
    -	    oparams->decode = &gssapi_decode;
    -	    /* FIX ME: Need to extract the proper value here */
    -	    oparams->mech_ssf = K5_MAX_SSF;
    -	} else {
    -	    /* not a supported encryption layer */
    -	    SETERROR(text->utils,
    -		     "protocol violation: client requested invalid layer");
    -	    /* Mark that we attempted negotiation */
    -	    oparams->mech_ssf = 2;
    -	    if (output_token->value) {
    -		GSS_LOCK_MUTEX(params->utils);
    -		gss_release_buffer(&min_stat, output_token);
    -		GSS_UNLOCK_MUTEX(params->utils);
    -	    }
    +	if (ret != SASL_OK) {
     	    sasl_gss_free_context_contents(text);
    -	    return SASL_FAIL;
    +	    return ret;
     	}
    +    }
     	
    -	if (output_token->length > 4) {
    -	    int ret;
    -	    
    -	    ret = params->canon_user(params->utils->conn,
    -				     ((char *) output_token->value) + 4,
    -				     (output_token->length - 4) * sizeof(char),
    -				     SASL_CU_AUTHZID, oparams);
    -	    
    -	    if (ret != SASL_OK) {
    -		sasl_gss_free_context_contents(text);
    -		return ret;
    -	    }
    -	    
    -	    ret = params->canon_user(params->utils->conn,
    -				     text->authid,
    -				     0, /* strlen(text->authid) */
    -				     SASL_CU_AUTHID | SASL_CU_EXTERNALLY_VERIFIED, oparams);
    -	    if (ret != SASL_OK) {
    -		sasl_gss_free_context_contents(text);
    -		return ret;
    -	    }
    -	} else /* if (output_token->length == 4) */ {
    -	    /* null authzid */
    -	    int ret;
    -	    
    -	    ret = params->canon_user(params->utils->conn,
    -				     text->authid,
    -				     0, /* strlen(text->authid) */
    -				     SASL_CU_AUTHZID | SASL_CU_AUTHID | SASL_CU_EXTERNALLY_VERIFIED,
    -				     oparams);
    -	    
    -	    if (ret != SASL_OK) {
    -		sasl_gss_free_context_contents(text);
    -		return ret;
    -	    }
    -	}
    +    /* No matter what, set the rest of the oparams */
    +
    +    oparams->maxoutbuf =
    +	(((unsigned char *) output_token->value)[1] << 16) |
    +	(((unsigned char *) output_token->value)[2] << 8) |
    +	(((unsigned char *) output_token->value)[3] << 0);
    +
    +    if (oparams->mech_ssf) {
    +	maj_stat = gss_wrap_size_limit( &min_stat,
    +					text->gss_ctx,
    +					1,
    +					GSS_C_QOP_DEFAULT,
    +					(OM_uint32) oparams->maxoutbuf,
    +					&max_input);
    +
    +	if(max_input > oparams->maxoutbuf) {
    +	    /* Heimdal appears to get this wrong */
    +	    oparams->maxoutbuf -= (max_input - oparams->maxoutbuf);
    +	} else {
    +	    /* This code is actually correct */
    +	    oparams->maxoutbuf = max_input;
    +	}    
    +    }
     	
    -	/* No matter what, set the rest of the oparams */
    +    GSS_LOCK_MUTEX(params->utils);
    +    gss_release_buffer(&min_stat, output_token);
    +    GSS_UNLOCK_MUTEX(params->utils);
    +
    +    text->state = SASL_GSSAPI_STATE_AUTHENTICATED;
    +
    +    /* used by layers */
    +    _plug_decode_init(&text->decode_context,
    +		      text->utils,
    +		      (params->props.maxbufsize > 0xFFFFFF) ? 0xFFFFFF :
    +		      params->props.maxbufsize);
     	
    +    return SASL_OK;
    +}
    +
    +static int 
    +gssapi_server_mech_step(void *conn_context,
    +			sasl_server_params_t *params,
    +			const char *clientin,
    +			unsigned clientinlen,
    +			const char **serverout,
    +			unsigned *serveroutlen,
    +			sasl_out_params_t *oparams)
    +{
    +    context_t *text = (context_t *) conn_context;
    +    int ret;
    +
    +    if (!serverout) {
    +	PARAMERROR(text->utils);
    +	return SASL_BADPARAM;
    +    }
    +
    +    *serverout = NULL;
    +    *serveroutlen = 0;
    +
    +    if (text == NULL) return SASL_BADPROT;
    +
    +    params->utils->log(NULL, SASL_LOG_DEBUG,
    +		       "GSSAPI server step %d\n", text->state);
    +
    +    switch (text->state) {
    +
    +    case SASL_GSSAPI_STATE_AUTHNEG:
    +	ret = gssapi_server_mech_authneg(text, params, clientin, clientinlen,
    +					 serverout, serveroutlen, oparams);
    +	if (ret != SASL_CONTINUE || *serveroutlen) break;
    +
    +	/* Pretend that we just got an empty response from the client */
    +	clientinlen = 0;
    +
    +	/* fall through */
    +
    +    case SASL_GSSAPI_STATE_SSFCAP:
    +	ret = gssapi_server_mech_ssfcap(text, params, clientin, clientinlen,
    +					serverout, serveroutlen, oparams);
    +	break;
    +
    +    case SASL_GSSAPI_STATE_SSFREQ:
    +	ret = gssapi_server_mech_ssfreq(text, params, clientin, clientinlen,
    +					serverout, serveroutlen, oparams);
    +	break;
    +
    +    default:
    +	params->utils->log(NULL, SASL_LOG_ERR,
    +			   "Invalid GSSAPI server step %d\n", text->state);
    +	return SASL_FAIL;
    +    }
    +
    +    if (ret == SASL_OK) {
    +	ret = params->canon_user(params->utils->conn,
    +				 text->authid,
    +				 0, /* strlen(text->authid) */
    +				 (oparams->user ? 0 : SASL_CU_AUTHZID)
    +				 | SASL_CU_AUTHID | SASL_CU_EXTERNALLY_VERIFIED,
    +				 oparams);
    +
    +	if (ret != SASL_OK) {
    +	    sasl_gss_free_context_contents(text);
    +	    return ret;
    +	}
    +
     	if (text->client_creds != GSS_C_NO_CREDENTIAL)	{
     	    oparams->client_creds =  &text->client_creds;
     	}
    @@ -1201,52 +1308,10 @@ gssapi_server_mech_step(void *conn_context,
     	    oparams->client_creds = NULL;
     	}
     
    -        oparams->maxoutbuf =
    -	    (((unsigned char *) output_token->value)[1] << 16) |
    -            (((unsigned char *) output_token->value)[2] << 8) |
    -            (((unsigned char *) output_token->value)[3] << 0);
    -
    -	if (oparams->mech_ssf) {
    - 	    maj_stat = gss_wrap_size_limit( &min_stat,
    -					    text->gss_ctx,
    -					    1,
    -					    GSS_C_QOP_DEFAULT,
    -					    (OM_uint32) oparams->maxoutbuf,
    -					    &max_input);
    -
    -	    if(max_input > oparams->maxoutbuf) {
    -		/* Heimdal appears to get this wrong */
    -		oparams->maxoutbuf -= (max_input - oparams->maxoutbuf);
    -	    } else {
    -		/* This code is actually correct */
    -		oparams->maxoutbuf = max_input;
    -	    }    
    -	}
    -	
    -	GSS_LOCK_MUTEX(params->utils);
    -	gss_release_buffer(&min_stat, output_token);
    -	GSS_UNLOCK_MUTEX(params->utils);
    -	
    -	text->state = SASL_GSSAPI_STATE_AUTHENTICATED;
    -	
    -	/* used by layers */
    -	_plug_decode_init(&text->decode_context,
    -			  text->utils,
    -			  (params->props.maxbufsize > 0xFFFFFF) ? 0xFFFFFF :
    -			  params->props.maxbufsize);
    -	
     	oparams->doneflag = 1;
    -	
    -	return SASL_OK;
    -    }
    -    
    -    default:
    -	params->utils->log(NULL, SASL_LOG_ERR,
    -			   "Invalid GSSAPI server step %d\n", text->state);
    -	return SASL_FAIL;
         }
         
    -    return SASL_FAIL; /* should never get here */
    +    return ret;
     }
     
     static sasl_server_plug_t gssapi_server_plugins[] = 
    @@ -1273,6 +1338,31 @@ static sasl_server_plug_t gssapi_server_plugins[] =
     	NULL,				/* mech_avail */
     	NULL				/* spare */
         }
    +#ifdef HAVE_GSS_SPNEGO
    +    ,{
    +	"GSS-SPNEGO",			/* mech_name */
    +	K5_MAX_SSF,			/* max_ssf */
    +	SASL_SEC_NOPLAINTEXT
    +	| SASL_SEC_NOACTIVE
    +	| SASL_SEC_NOANONYMOUS
    +	| SASL_SEC_MUTUAL_AUTH		/* security_flags */
    +	| SASL_SEC_PASS_CREDENTIALS,
    +	SASL_FEAT_WANT_CLIENT_FIRST
    +	| SASL_FEAT_ALLOWS_PROXY
    +	| SASL_FEAT_DONTUSE_USERPASSWD
    +	| SASL_FEAT_SUPPORTS_HTTP,	/* features */
    +	NULL,				/* glob_context */
    +	&gssapi_server_mech_new,	/* mech_new */
    +	&gssapi_server_mech_step,	/* mech_step */
    +	&gssapi_common_mech_dispose,	/* mech_dispose */
    +	&gssapi_common_mech_free,	/* mech_free */
    +	NULL,				/* setpass */
    +	NULL,				/* user_query */
    +	NULL,				/* idle */
    +	NULL,				/* mech_avail */
    +	NULL				/* spare */
    +    }
    +#endif
     };
     
     int gssapiv2_server_plug_init(
    @@ -1325,7 +1415,11 @@ int gssapiv2_server_plug_init(
         
         *out_version = SASL_SERVER_PLUG_VERSION;
         *pluglist = gssapi_server_plugins;
    +#ifdef HAVE_GSS_SPNEGO
    +    *plugcount = 2;
    +#else
         *plugcount = 1;  
    +#endif
     
     #ifdef GSS_USE_MUTEXES
         if (!gss_mutex) {
    @@ -1341,7 +1435,7 @@ int gssapiv2_server_plug_init(
     
     /*****************************  Client Section  *****************************/
     
    -static int gssapi_client_mech_new(void *glob_context __attribute__((unused)), 
    +static int gssapi_client_mech_new(void *glob_context,
     				  sasl_client_params_t *params,
     				  void **conn_context)
     {
    @@ -1355,11 +1449,14 @@ static int gssapi_client_mech_new(void *glob_context __attribute__((unused)),
         }
         
         text->state = SASL_GSSAPI_STATE_AUTHNEG;
    +    text->mech_type = (gss_OID) glob_context;
         text->gss_ctx = GSS_C_NO_CONTEXT;
         text->client_name = GSS_C_NO_NAME;
         text->server_creds = GSS_C_NO_CREDENTIAL;
         text->client_creds  = GSS_C_NO_CREDENTIAL;
     
    +    text->http_mode = (params->flags & SASL_NEED_HTTP);
    +
         *conn_context = text;
         
         return SASL_OK;
    @@ -1392,6 +1489,9 @@ static int gssapi_client_mech_step(void *conn_context,
         *clientout = NULL;
         *clientoutlen = 0;
         
    +    params->utils->log(NULL, SASL_LOG_DEBUG,
    +		       "GSSAPI client step %d", text->state);
    +
         switch (text->state) {
     
         case SASL_GSSAPI_STATE_AUTHNEG:
    @@ -1504,7 +1604,7 @@ static int gssapi_client_mech_step(void *conn_context,
     					client_creds, /* GSS_C_NO_CREDENTIAL */
     					&text->gss_ctx,
     					text->server_name,
    -					GSS_C_NO_OID,
    +					text->mech_type,
     					req_flags,
     					0,
     					GSS_C_NO_CHANNEL_BINDINGS,
    @@ -1624,6 +1724,13 @@ static int gssapi_client_mech_step(void *conn_context,
     	    
     	    if (ret != SASL_OK) return ret;
     	    
    +	    if (text->http_mode) {
    +		/* HTTP doesn't do any ssf negotiation */
    +		text->state = SASL_GSSAPI_STATE_AUTHENTICATED;
    +		oparams->doneflag = 1;
    +		return SASL_OK;
    +	    }
    +
     	    /* Switch to ssf negotiation */
     	    text->state = SASL_GSSAPI_STATE_SSFCAP;
     	}
    @@ -1730,7 +1837,8 @@ static int gssapi_client_mech_step(void *conn_context,
     	    oparams->decode = &gssapi_decode;
     	    oparams->mech_ssf = 1;
     	    mychoice = LAYER_INTEGRITY;
    -	} else if (need <= 0 && (serverhas & LAYER_NONE)) {
    +	} else if ((text->qop & LAYER_NONE) &&
    +		   need <= 0 && (serverhas & LAYER_NONE)) {
     	    /* no layer */
     	    oparams->encode = NULL;
     	    oparams->decode = NULL;
    @@ -1882,7 +1990,7 @@ static int gssapi_client_mech_step(void *conn_context,
         return SASL_FAIL; /* should never get here */
     }
     
    -static const long gssapi_required_prompts[] = {
    +static const unsigned long gssapi_required_prompts[] = {
         SASL_CB_LIST_END
     };  
     
    @@ -1900,7 +2008,30 @@ static sasl_client_plug_t gssapi_client_plugins[] =
     	| SASL_FEAT_WANT_CLIENT_FIRST
     	| SASL_FEAT_ALLOWS_PROXY,	/* features */
     	gssapi_required_prompts,	/* required_prompts */
    -	NULL,				/* glob_context */
    +	GSS_C_NO_OID,			/* glob_context */
    +	&gssapi_client_mech_new,	/* mech_new */
    +	&gssapi_client_mech_step,	/* mech_step */
    +	&gssapi_common_mech_dispose,	/* mech_dispose */
    +	&gssapi_common_mech_free,	/* mech_free */
    +	NULL,				/* idle */
    +	NULL,				/* spare */
    +	NULL				/* spare */
    +    }
    +#ifdef HAVE_GSS_SPNEGO
    +    ,{
    +	"GSS-SPNEGO",			/* mech_name */
    +	K5_MAX_SSF,			/* max_ssf */
    +	SASL_SEC_NOPLAINTEXT
    +	| SASL_SEC_NOACTIVE
    +	| SASL_SEC_NOANONYMOUS
    +	| SASL_SEC_MUTUAL_AUTH 
    +	| SASL_SEC_PASS_CREDENTIALS,    /* security_flags */
    +	SASL_FEAT_NEEDSERVERFQDN
    +	| SASL_FEAT_WANT_CLIENT_FIRST
    +	| SASL_FEAT_ALLOWS_PROXY
    +	| SASL_FEAT_SUPPORTS_HTTP,	/* features */
    +	gssapi_required_prompts,	/* required_prompts */
    +	&gss_spnego_oid,		/* glob_context */
     	&gssapi_client_mech_new,	/* mech_new */
     	&gssapi_client_mech_step,	/* mech_step */
     	&gssapi_common_mech_dispose,	/* mech_dispose */
    @@ -1909,6 +2040,7 @@ static sasl_client_plug_t gssapi_client_plugins[] =
     	NULL,				/* spare */
     	NULL				/* spare */
         }
    +#endif
     };
     
     int gssapiv2_client_plug_init(const sasl_utils_t *utils __attribute__((unused)), 
    @@ -1924,7 +2056,11 @@ int gssapiv2_client_plug_init(const sasl_utils_t *utils __attribute__((unused)),
         
         *out_version = SASL_CLIENT_PLUG_VERSION;
         *pluglist = gssapi_client_plugins;
    +#ifdef HAVE_GSS_SPNEGO
    +    *plugcount = 2;
    +#else
         *plugcount = 1;
    +#endif
     
     #ifdef GSS_USE_MUTEXES
         if(!gss_mutex) {
    @@ -1937,4 +2073,3 @@ int gssapiv2_client_plug_init(const sasl_utils_t *utils __attribute__((unused)),
         
         return SASL_OK;
     }
    -
    diff --git a/utils/testsuite.c b/utils/testsuite.c
    index b01a041c..7e4e852a 100644
    --- a/utils/testsuite.c
    +++ b/utils/testsuite.c
    @@ -1,7 +1,7 @@
     /* testsuite.c -- Stress the library a little
      * Rob Siemborski
      * Tim Martin
    - * $Id: testsuite.c,v 1.48 2011/09/01 14:12:18 mel Exp $
    + * $Id: testsuite.c,v 1.49 2011/11/09 15:49:47 murch Exp $
      */
     /* 
      * Copyright (c) 1998-2003 Carnegie Mellon University.  All rights reserved.
    @@ -95,10 +95,10 @@ char myhostname[1024+1];
     #define REALLY_LONG_LENGTH  32000
     #define REALLY_LONG_BACKOFF  2000
     
    -const char *username = "murch";
    +const char *username = "ken";
     const char *nonexistant_username = "ABCDEFGHIJ";
    -const char *authname = "murch";
    -const char *proxyasname = "murchproxy";
    +const char *authname = "ken";
    +const char *proxyasname = "kenproxy";
     const char *password = "1234";
     sasl_secret_t * g_secret = NULL;
     const char *cu_plugin = "INTERNAL";
    @@ -1324,7 +1324,7 @@ void sendbadsecond(char *mech, void *rock)
     
         printf("%s --> start\n",mech);
         
    -    if (strcmp(mech,"GSSAPI")==0) service = gssapi_service;
    +    if (strncmp(mech,"GSS",3)==0) service = gssapi_service;
     
         if (sasl_client_init(client_interactions)!=SASL_OK) fatal("Unable to init client");
     
    @@ -1574,7 +1574,7 @@ int doauth(char *mech, sasl_conn_t **server_conn, sasl_conn_t **client_conn,
     
         if(!server_conn || !client_conn) return SASL_BADPARAM;
         
    -    if (strcmp(mech,"GSSAPI")==0) service = gssapi_service;
    +    if (strncmp(mech,"GSS",3)==0) service = gssapi_service;
     
         result = sasl_client_init((c_calls ? c_calls : client_interactions));
         if (result!=SASL_OK) {
    @@ -1729,7 +1729,7 @@ int doauth_noclientfirst(char *mech, sasl_conn_t **server_conn,
     
         if(!server_conn || !client_conn) return SASL_BADPARAM;
         
    -    if (strcmp(mech,"GSSAPI")==0) service = gssapi_service;
    +    if (strncmp(mech,"GSS",3)==0) service = gssapi_service;
     
     
         if (sasl_client_init((c_calls ? c_calls : client_interactions))!=SASL_OK)
    @@ -1862,7 +1862,7 @@ int doauth_serverlast(char *mech, sasl_conn_t **server_conn,
     
         if(!server_conn || !client_conn) return SASL_BADPARAM;
         
    -    if (strcmp(mech,"GSSAPI")==0) service = gssapi_service;
    +    if (strncmp(mech,"GSS",3)==0) service = gssapi_service;
     
         if (sasl_client_init((c_calls ? c_calls : client_interactions))!=SASL_OK)
     	fatal("unable to init client");
    @@ -2000,7 +2000,7 @@ int doauth_noclientfirst_andserverlast(char *mech, sasl_conn_t **server_conn,
     
         if(!server_conn || !client_conn) return SASL_BADPARAM;
         
    -    if (strcmp(mech,"GSSAPI")==0) service = gssapi_service;
    +    if (strncmp(mech,"GSS",3)==0) service = gssapi_service;
     
         if (sasl_client_init((c_calls ? c_calls : client_interactions))!=SASL_OK)
     	fatal("unable to init client");
    
    From 8bb13256700e4a67030cb1eafa57b59caf775e93 Mon Sep 17 00:00:00 2001
    From: Ken Murchison 
    Date: Thu, 10 Nov 2011 21:39:49 +0000
    Subject: [PATCH 132/796] Add bdb version 4.8 to berkdb.m4 (#3139
    
    ---
     sample/Makefile.in | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    diff --git a/sample/Makefile.in b/sample/Makefile.in
    index bfe9286f..2d56bf3c 100644
    --- a/sample/Makefile.in
    +++ b/sample/Makefile.in
    @@ -82,7 +82,7 @@ target_triplet = @target@
     noinst_PROGRAMS = client$(EXEEXT) server$(EXEEXT)
     EXTRA_PROGRAMS = sample-client$(EXEEXT) sample-server$(EXEEXT)
     subdir = sample
    -DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in $(srcdir)/NTMakefile
    +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
     ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
     am__aclocal_m4_deps = $(top_srcdir)/config/kerberos_v4.m4 \
     	$(top_srcdir)/config/libtool.m4 $(top_srcdir)/config/plain.m4 \
    @@ -136,7 +136,7 @@ LINK = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \
     SOURCES = $(client_SOURCES) $(sample_client_SOURCES) \
     	$(sample_server_SOURCES) $(server_SOURCES)
     DIST_SOURCES = $(client_SOURCES) $(sample_client_SOURCES) \
    -	$(sample_server_SOURCES) $(server_SOURCES) $(srcdir)/http_digest_client.c
    +	$(sample_server_SOURCES) $(server_SOURCES)
     ETAGS = etags
     CTAGS = ctags
     DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
    
    From 4d0a2b5f85e5223e35ab37d88d7246622778166a Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Mon, 21 Nov 2011 15:12:35 +0000
    Subject: [PATCH 133/796] Only check out_flags once authentication is
     successfully completed
    
    ---
     ChangeLog        |  4 +++
     plugins/gssapi.c | 65 ++++++++++++++++++++++++------------------------
     2 files changed, 37 insertions(+), 32 deletions(-)
    
    diff --git a/ChangeLog b/ChangeLog
    index 312ecdee..29c0f207 100644
    --- a/ChangeLog
    +++ b/ChangeLog
    @@ -1,3 +1,7 @@
    +2011-11-21  Alexey Melnikov 
    +	* plugins/gssapi.c: Only check out_flags once authentication is
    +	  successfully completed
    +
     2011-11-09  Ken Murchison 
     	* cmulocal/sasl2.m4, plugins/gssapi.c, utils/testsuite.c:
     	  Added GSS-SPNEGO plugin which can also be used for HTTP
    diff --git a/plugins/gssapi.c b/plugins/gssapi.c
    index 6bfb3351..2fd1b3b7 100644
    --- a/plugins/gssapi.c
    +++ b/plugins/gssapi.c
    @@ -1,7 +1,7 @@
     /* GSSAPI SASL plugin
      * Leif Johansson
      * Rob Siemborski (SASL v2 Conversion)
    - * $Id: gssapi.c,v 1.114 2011/11/09 15:49:47 murch Exp $
    + * $Id: gssapi.c,v 1.115 2011/11/21 15:12:35 mel Exp $
      */
     /* 
      * Copyright (c) 1998-2003 Carnegie Mellon University.  All rights reserved.
    @@ -83,7 +83,7 @@
     
     /*****************************  Common Section  *****************************/
     
    -static const char plugin_id[] = "$Id: gssapi.c,v 1.114 2011/11/09 15:49:47 murch Exp $";
    +static const char plugin_id[] = "$Id: gssapi.c,v 1.115 2011/11/21 15:12:35 mel Exp $";
     
     static const char * GSSAPI_BLANK_STRING = "";
     
    @@ -770,37 +770,9 @@ gssapi_server_mech_authneg(context_t *text,
     	return SASL_BADAUTH;
         }
     
    -    /* When GSS_Accept_sec_context returns GSS_S_COMPLETE, the server
    -       examines the context to ensure that it provides a level of protection
    -       permitted by the server's security policy.  In particular, if the
    -       integ_avail flag is not set in the context, then no security layer
    -       can be offered or accepted.  If the conf_avail flag is not set in the
    -       context, then no security layer with confidentiality can be offered
    -       or accepted. */
    -    if ((out_flags & GSS_C_INTEG_FLAG) == 0) {
    -	/* if the integ_avail flag is not set in the context,
    -	   then no security layer can be offered or accepted. */
    -	text->qop = LAYER_NONE;
    -    } else if ((out_flags & GSS_C_CONF_FLAG) == 0) {
    -	/* If the conf_avail flag is not set in the context,
    -	   then no security layer with confidentiality can be offered
    -	   or accepted. */
    -	text->qop = LAYER_NONE | LAYER_INTEGRITY;
    -    } else {
    -	text->qop = LAYER_NONE | LAYER_INTEGRITY | LAYER_CONFIDENTIALITY;
    -    }
    -
    -    if ((params->props.security_flags & SASL_SEC_PASS_CREDENTIALS) &&
    -	(!(out_flags & GSS_C_DELEG_FLAG) ||
    -	 text->client_creds == GSS_C_NO_CREDENTIAL) ) 
    -	{
    -	    text->utils->seterror(text->utils->conn, SASL_LOG_WARN,
    -				  "GSSAPI warning: no credentials were passed");
    -	    /* continue with authentication */
    -	}
    -
    -    if (serveroutlen)
    +    if (serveroutlen) {
     	*serveroutlen = output_token->length;
    +    }
         if (output_token->value) {
     	if (serverout) {
     	    ret = _plug_buf_alloc(text->utils, &(text->out_buf),
    @@ -831,6 +803,35 @@ gssapi_server_mech_authneg(context_t *text,
     
         assert(maj_stat == GSS_S_COMPLETE);
     
    +    /* When GSS_Accept_sec_context returns GSS_S_COMPLETE, the server
    +       examines the context to ensure that it provides a level of protection
    +       permitted by the server's security policy.  In particular, if the
    +       integ_avail flag is not set in the context, then no security layer
    +       can be offered or accepted.  If the conf_avail flag is not set in the
    +       context, then no security layer with confidentiality can be offered
    +       or accepted. */
    +    if ((out_flags & GSS_C_INTEG_FLAG) == 0) {
    +	/* if the integ_avail flag is not set in the context,
    +	   then no security layer can be offered or accepted. */
    +	text->qop = LAYER_NONE;
    +    } else if ((out_flags & GSS_C_CONF_FLAG) == 0) {
    +	/* If the conf_avail flag is not set in the context,
    +	   then no security layer with confidentiality can be offered
    +	   or accepted. */
    +	text->qop = LAYER_NONE | LAYER_INTEGRITY;
    +    } else {
    +	text->qop = LAYER_NONE | LAYER_INTEGRITY | LAYER_CONFIDENTIALITY;
    +    }
    +
    +    if ((params->props.security_flags & SASL_SEC_PASS_CREDENTIALS) &&
    +	(!(out_flags & GSS_C_DELEG_FLAG) ||
    +	 text->client_creds == GSS_C_NO_CREDENTIAL) ) 
    +	{
    +	    text->utils->seterror(text->utils->conn, SASL_LOG_WARN,
    +				  "GSSAPI warning: no credentials were passed");
    +	    /* continue with authentication */
    +	}
    +
         GSS_LOCK_MUTEX(params->utils);
         maj_stat = gss_canonicalize_name(&min_stat,
     				     text->client_name,
    
    From dca5ab6cb278dd302727aa296e3c2f3aa61ce639 Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Fri, 25 Nov 2011 15:18:01 +0000
    Subject: [PATCH 134/796] Updated GS2 plugin not to lose minor GSS-API status
     codes on errors (based on a patch from Ralf Haferkamp )
    
    ---
     ChangeLog     |  5 ++++
     plugins/gs2.c | 71 ++++++++++++++++++++++++++++++++-------------------
     2 files changed, 50 insertions(+), 26 deletions(-)
    
    diff --git a/ChangeLog b/ChangeLog
    index 29c0f207..42689e94 100644
    --- a/ChangeLog
    +++ b/ChangeLog
    @@ -1,3 +1,8 @@
    +2011-11-25  Alexey Melnikov 
    +	* plugins/gs2.c: Updated GS2 plugin not to lose minor GSS-API
    +	  status codes on errors (based on a patch from Ralf Haferkamp
    +	  )
    +
     2011-11-21  Alexey Melnikov 
     	* plugins/gssapi.c: Only check out_flags once authentication is
     	  successfully completed
    diff --git a/plugins/gs2.c b/plugins/gs2.c
    index 025f7fcf..b35456bd 100644
    --- a/plugins/gs2.c
    +++ b/plugins/gs2.c
    @@ -336,7 +336,7 @@ gs2_server_mech_step(void *conn_context,
         gss_name_t without = GSS_C_NO_NAME;
         gss_OID_set_desc mechs;
         OM_uint32 out_flags = 0;
    -    int ret = 0, equal = 0;
    +    int ret = SASL_OK, equal = 0;
         int initialContextToken = (text->gss_ctx == GSS_C_NO_CONTEXT);
         char *p;
     
    @@ -463,14 +463,12 @@ gs2_server_mech_step(void *conn_context,
                                        GSS_C_NT_USER_NAME,
                                        &without);
             if (GSS_ERROR(maj_stat)) {
    -            ret = SASL_FAIL;
                 goto cleanup;
             }
     
             maj_stat = gss_compare_name(&min_stat, text->client_name,
                                         without, &equal);
             if (GSS_ERROR(maj_stat)) {
    -            ret = SASL_FAIL;
                 goto cleanup;
             }
     
    @@ -486,8 +484,9 @@ gs2_server_mech_step(void *conn_context,
             ret = params->canon_user(params->utils->conn,
                                      text->authzid, 0,
                                      SASL_CU_AUTHZID, oparams);
    -        if (ret != SASL_OK)
    +        if (ret != SASL_OK) {
                 goto cleanup;
    +	}
         }
     
         ret = params->canon_user(params->utils->conn,
    @@ -496,8 +495,9 @@ gs2_server_mech_step(void *conn_context,
                                     ? (SASL_CU_AUTHZID | SASL_CU_AUTHID)
                                     : SASL_CU_AUTHID,
                                  oparams);
    -    if (ret != SASL_OK)
    +    if (ret != SASL_OK) {
             goto cleanup;
    +    }
     
         switch (text->gs2_flags & GS2_CB_FLAG_MASK) {
         case GS2_CB_FLAG_N:
    @@ -528,19 +528,22 @@ gs2_server_mech_step(void *conn_context,
         ret = SASL_OK;
     
     cleanup:
    -    if (initialContextToken)
    +    if (ret == SASL_OK && maj_stat != GSS_S_COMPLETE) {
    +        sasl_gs2_seterror(text->utils, maj_stat, min_stat);
    +        ret = SASL_FAIL;
    +    }
    +
    +    if (initialContextToken) {
             gss_release_buffer(&min_stat, &input_token);
    +    }
         gss_release_buffer(&min_stat, &name_buf);
         gss_release_buffer(&min_stat, &short_name_buf);
         gss_release_buffer(&min_stat, &output_token);
         gss_release_name(&min_stat, &without);
     
    -    if (ret == SASL_OK && maj_stat != GSS_S_COMPLETE) {
    -        sasl_gs2_seterror(text->utils, maj_stat, min_stat);
    -        ret = SASL_FAIL;
    -    }
    -    if (ret < SASL_OK)
    +    if (ret < SASL_OK) {
             sasl_gs2_free_context_contents(text);
    +    }
     
         return ret;
     }
    @@ -698,12 +701,14 @@ static int gs2_client_mech_step(void *conn_context,
     
         if (text->gss_ctx == GSS_C_NO_CONTEXT) {
             ret = gs2_get_init_creds(text, params, prompt_need, oparams);
    -        if (ret != SASL_OK)
    +        if (ret != SASL_OK) {
                 goto cleanup;
    +	}
     
             initialContextToken = 1;
    -    } else
    +    } else {
             initialContextToken = 0;
    +    }
     
         if (text->server_name == GSS_C_NO_NAME) { /* only once */
             name_buf.length = strlen(params->service) + 1 + strlen(params->serverFQDN);
    @@ -729,8 +734,10 @@ static int gs2_client_mech_step(void *conn_context,
             params->utils->free(name_buf.value);
             name_buf.value = NULL;
     
    -        if (GSS_ERROR(maj_stat))
    +        if (GSS_ERROR(maj_stat)) {
    +	    ret = SASL_OK;
                 goto cleanup;
    +	}
         }
     
         /* From GSSAPI plugin: apparently this is for some IMAP bug workaround */
    @@ -762,8 +769,9 @@ static int gs2_client_mech_step(void *conn_context,
                                   strcmp(oparams->user, oparams->authid) ?
                                          (char *) oparams->user : NULL,
                                   &text->out_buf, &text->out_buf_len);
    -        if (ret != 0)
    +        if (ret != 0) {
                 goto cleanup;
    +	}
         }
     
         req_flags = GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG;
    @@ -783,13 +791,16 @@ static int gs2_client_mech_step(void *conn_context,
                                         &output_token,
                                         &ret_flags,
                                         &text->lifetime);
    -    if (GSS_ERROR(maj_stat))
    +    if (GSS_ERROR(maj_stat)) {
    +	ret = SASL_OK;
             goto cleanup;
    +    }
     
         ret = gs2_make_message(text, params, initialContextToken, &output_token,
                                &text->out_buf, &text->out_buf_len);
    -    if (ret != 0)
    +    if (ret != 0) {
             goto cleanup;
    +    }
     
         *clientout = text->out_buf;
         *clientoutlen = text->out_buf_len;
    @@ -799,9 +810,9 @@ static int gs2_client_mech_step(void *conn_context,
             goto cleanup;
         }
     
    -    if (text->client_name != GSS_C_NO_NAME)
    +    if (text->client_name != GSS_C_NO_NAME) {
             gss_release_name(&min_stat, &text->client_name);
    -
    +    }
         maj_stat = gss_inquire_context(&min_stat,
                                        text->gss_ctx,
                                        &text->client_name,
    @@ -811,11 +822,13 @@ static int gs2_client_mech_step(void *conn_context,
                                        &ret_flags, /* flags */
                                        NULL,
                                        NULL);
    -    if (GSS_ERROR(maj_stat))
    +    if (GSS_ERROR(maj_stat)) {
    +	ret = SASL_OK;
             goto cleanup;
    +    }
     
         if ((ret_flags & req_flags) != req_flags) {
    -        maj_stat = SASL_BADAUTH;
    +        ret = SASL_BADAUTH;
             goto cleanup;
         }
     
    @@ -823,8 +836,10 @@ static int gs2_client_mech_step(void *conn_context,
                                     text->client_name,
                                     &name_buf,
                                     NULL);
    -    if (GSS_ERROR(maj_stat))
    +    if (GSS_ERROR(maj_stat)) {
    +	ret = SASL_OK;
             goto cleanup;
    +    }
     
         oparams->gss_peer_name = text->server_name;
         oparams->gss_local_name = text->client_name;
    @@ -834,16 +849,20 @@ static int gs2_client_mech_step(void *conn_context,
         oparams->maxoutbuf = 0xFFFFFF;
         oparams->doneflag = 1;
     
    -cleanup:
    -    gss_release_buffer(&min_stat, &output_token);
    -    gss_release_buffer(&min_stat, &name_buf);
    +    ret = SASL_OK;
     
    +cleanup:
         if (ret == SASL_OK && maj_stat != GSS_S_COMPLETE) {
             sasl_gs2_seterror(text->utils, maj_stat, min_stat);
             ret = SASL_FAIL;
         }
    -    if (ret < SASL_OK)
    +
    +    gss_release_buffer(&min_stat, &output_token);
    +    gss_release_buffer(&min_stat, &name_buf);
    +
    +    if (ret < SASL_OK) {
             sasl_gs2_free_context_contents(text);
    +    }
     
         return ret;
     }
    
    From 61f9859eec2a6d96978dd109bbcd14f17b896686 Mon Sep 17 00:00:00 2001
    From: Ken Murchison 
    Date: Sat, 28 Jan 2012 21:21:21 -0500
    Subject: [PATCH 135/796] digestmd5: check client supplied credentials for
     correctness before denying (sending "stale" prevents client from
     (re)promtping for password)
    
    ---
     plugins/digestmd5.c | 130 +++++++++++++++++++++++---------------------
     1 file changed, 68 insertions(+), 62 deletions(-)
    
    diff --git a/plugins/digestmd5.c b/plugins/digestmd5.c
    index be1652c0..22b9cbac 100644
    --- a/plugins/digestmd5.c
    +++ b/plugins/digestmd5.c
    @@ -2118,7 +2118,7 @@ digestmd5_server_mech_step1(server_context_t *stext,
     	return SASL_FAIL;
         }
     
    -    if (text->http_mode && sparams->http_request->non_persist &&
    +    if (text->http_mode &&
     	sparams->utils->mutex_lock(text->reauth->mutex) == SASL_OK) { /* LOCK */
     
     	/* Create an initial cache entry for non-persistent HTTP connections */
    @@ -2434,7 +2434,24 @@ static int digestmd5_server_mech_step2(server_context_t *stext,
     	goto FreeAllMem;
         }
     
    -    if (text->state == 1) {
    +    if (realm == NULL) {
    +        /* From 2831bis:
    +           If the directive is missing, "realm-value" will set to
    +           the empty string when computing A1. */
    +	_plug_strdup(sparams->utils, "", &realm, NULL);
    +	sparams->utils->log(sparams->utils->conn, SASL_LOG_DEBUG,
    +			"The client didn't send a realm, assuming empty string.");
    +#if 0
    +        if (text->realm[0] != '\0') {
    +            SETERROR(sparams->utils,
    +		 "realm changed: authentication aborted");
    +            result = SASL_BADAUTH;
    +            goto FreeAllMem;
    +        }
    +#endif
    +    }
    +
    +    if (text->state == 1 || !text->nonce) {
     	unsigned val = hash((char *) nonce) % text->reauth->size;
     
     	/* reauth attempt or continuation of HTTP Digest on a
    @@ -2465,63 +2482,50 @@ static int digestmd5_server_mech_step2(server_context_t *stext,
     	    /* we don't have any reauth info, so bail */
     	    sparams->utils->log(sparams->utils->conn, SASL_LOG_DEBUG,
     				"No reauth info for '%s' found", nonce);
    -	    result = SASL_FAIL;
    -	    goto FreeAllMem;
     	}
         }
     
         /* Sanity check the parameters */
    -    if (realm == NULL) {
    -        /* From 2831bis:
    -           If the directive is missing, "realm-value" will set to
    -           the empty string when computing A1. */
    -	_plug_strdup(sparams->utils, "", &realm, NULL);
    -	sparams->utils->log(sparams->utils->conn, SASL_LOG_DEBUG,
    -			"The client didn't send a realm, assuming empty string.");
    -        if (text->realm[0] != '\0') {
    -            SETERROR(sparams->utils,
    -		 "realm changed: authentication aborted");
    -            result = SASL_BADAUTH;
    -            goto FreeAllMem;
    -        }
    +    if (text->nonce) {
    +	/* CLAIM: realm is not NULL below */
    +	if (text->realm == NULL) {
    +	    sparams->utils->log(sparams->utils->conn, SASL_LOG_DEBUG,
    +				"The client specifies a realm when the server hasn't provided one. Using client's realm.");
    +	    _plug_strdup(sparams->utils, realm, &text->realm, NULL);
    +	} else if ((strcmp(realm, text->realm) != 0) &&
    +		   /* XXX - Not sure why the check for text->realm not being empty is needed,
    +		      as it should always be non-empty */
    +		   (text->realm[0] != 0)) {
    +
    +	    client_ignores_realm = 1;
    +	    sparams->utils->log(sparams->utils->conn, SASL_LOG_DEBUG,
    +				"The client tries to override server provided realm");
    +	    if (text->realm) sparams->utils->free(text->realm);
    +	    _plug_strdup(sparams->utils, realm, &text->realm, NULL);
    +	}
     
    -    /* CLAIM: realm is not NULL below */
    -    } else if (text->realm == NULL) {
    -	sparams->utils->log(sparams->utils->conn, SASL_LOG_DEBUG,
    -			"The client specifies a realm when the server hasn't provided one. Using client's realm.");
    -	_plug_strdup(sparams->utils, realm, &text->realm, NULL);
    -    } else if ((strcmp(realm, text->realm) != 0) &&
    -	    /* XXX - Not sure why the check for text->realm not being empty is needed,
    -	       as it should always be non-empty */
    -	       (text->realm[0] != 0)) {
    -
    -	client_ignores_realm = 1;
    -	sparams->utils->log(sparams->utils->conn, SASL_LOG_DEBUG,
    -			"The client tries to override server provided realm");
    -	if (text->realm) sparams->utils->free(text->realm);
    -	_plug_strdup(sparams->utils, realm, &text->realm, NULL);
    -    }
    -    if (strcmp((char *) nonce, (char *) text->nonce) != 0) {
    -	SETERROR(sparams->utils,
    -		 "nonce changed: authentication aborted");
    -	result = SASL_BADAUTH;
    -	goto FreeAllMem;
    -    }
    -    if (noncecount != text->nonce_count) {
    -	SETERROR(sparams->utils,
    -		 "incorrect nonce-count: authentication aborted");
    -	result = SASL_BADAUTH;
    -	goto FreeAllMem;
    -    }
    -#if 0  /* XXX  Neither RFC 2617 nor RFC 2831 state that the cnonce
    -	  needs to remain constant for subsequent authentication to work */
    -    if (text->cnonce && strcmp((char *) cnonce, (char *) text->cnonce) != 0) {
    -	SETERROR(sparams->utils,
    -		 "cnonce changed: authentication aborted");
    -	result = SASL_BADAUTH;
    -	goto FreeAllMem;
    -    }
    +	if (strcmp((char *) nonce, (char *) text->nonce) != 0) {
    +	    SETERROR(sparams->utils,
    +		     "nonce changed: authentication aborted");
    +	    result = SASL_BADAUTH;
    +	    goto FreeAllMem;
    +	}
    +	if (noncecount != text->nonce_count) {
    +	    SETERROR(sparams->utils,
    +		     "incorrect nonce-count: authentication aborted");
    +	    result = SASL_BADAUTH;
    +	    goto FreeAllMem;
    +	}
    +#if 0	/* XXX  Neither RFC 2617 nor RFC 2831 state that the cnonce
    +	   needs to remain constant for subsequent authentication to work */
    +	if (text->cnonce && strcmp((char *) cnonce, (char *) text->cnonce) != 0) {
    +	    SETERROR(sparams->utils,
    +		     "cnonce changed: authentication aborted");
    +	    result = SASL_BADAUTH;
    +	    goto FreeAllMem;
    +	}
     #endif
    +    }
     	    
         result = sparams->utils->prop_request(sparams->propctx, password_request);
         if(result != SASL_OK) {
    @@ -2620,7 +2624,7 @@ static int digestmd5_server_mech_step2(server_context_t *stext,
     	    
     	    Try_8859_1 = DigestCalcSecret(sparams->utils,
     					  (unsigned char *) username,
    -					  (unsigned char *) text->realm,
    +					  (unsigned char *) realm,
     					  sec->data,
     					  sec->len,
     					  FALSE,
    @@ -2636,7 +2640,7 @@ static int digestmd5_server_mech_step2(server_context_t *stext,
     	    
     	    DigestCalcSecret(sparams->utils,
     			     (unsigned char *) username,
    -			     (unsigned char *) text->realm,
    +			     (unsigned char *) realm,
     			     sec->data,
     			     sec->len,
     			     TRUE,
    @@ -2729,8 +2733,8 @@ static int digestmd5_server_mech_step2(server_context_t *stext,
         
         serverresponse = create_response(text,
     				     sparams->utils,
    -				     text->nonce,
    -				     text->nonce_count,
    +				     nonce,
    +				     noncecount,
     				     cnonce,
     				     qop,
     				     request,
    @@ -2750,8 +2754,8 @@ static int digestmd5_server_mech_step2(server_context_t *stext,
     	    
     	    serverresponse = create_response(text,
     					     sparams->utils,
    -					     text->nonce,
    -					     text->nonce_count,
    +					     nonce,
    +					     noncecount,
     					     cnonce,
     					     qop,
     					     request,
    @@ -2784,9 +2788,11 @@ static int digestmd5_server_mech_step2(server_context_t *stext,
         }
     
         /* see if our nonce expired */
    -    if (text->reauth->timeout &&
    -	time(0) - stext->timestamp > text->reauth->timeout) {
    -	SETERROR(sparams->utils, "server nonce expired");
    +    if (!text->nonce ||
    +	(text->reauth->timeout &&
    +	 time(0) - stext->timestamp > text->reauth->timeout)) {
    +	if (!text->nonce) SETERROR(sparams->utils, "no cached server nonce");
    +	else SETERROR(sparams->utils, "server nonce expired");
     	stext->stale = 1;
     	result = SASL_BADAUTH;
     
    
    From 5dc97fbd4a2e1ad2853e738162abe65355c6eb7d Mon Sep 17 00:00:00 2001
    From: Ken Murchison 
    Date: Fri, 10 Feb 2012 11:28:27 -0500
    Subject: [PATCH 136/796] digestmd5: don't require HTTP request until step 2
     for server
    
    ---
     plugins/digestmd5.c | 12 ++++++------
     1 file changed, 6 insertions(+), 6 deletions(-)
    
    diff --git a/plugins/digestmd5.c b/plugins/digestmd5.c
    index 22b9cbac..77d3c203 100644
    --- a/plugins/digestmd5.c
    +++ b/plugins/digestmd5.c
    @@ -1899,12 +1899,6 @@ static int digestmd5_server_mech_new(void *glob_context,
     {
         context_t *text;
         
    -    if ((sparams->flags & SASL_NEED_HTTP) && !sparams->http_request) {
    -	SETERROR(sparams->utils,
    -		 "DIGEST-MD5 unavailable due to lack of HTTP request");
    -	return SASL_BADPARAM;
    -    }
    -
         /* holds state are in -- allocate server size */
         text = sparams->utils->malloc(sizeof(server_context_t));
         if (text == NULL)
    @@ -2213,6 +2207,12 @@ static int digestmd5_server_mech_step2(server_context_t *stext,
         if (text->http_mode) {
     	/* per RFC 2617 (HTTP Request as set by calling application) */
     	request = sparams->http_request;
    +	if (!request) {
    +	    SETERROR(sparams->utils,
    +		     "missing HTTP request in DIGEST-MD5, step 2");
    +	    result = SASL_BADPARAM;
    +	    goto FreeAllMem;
    +	}
         }
         else {
     	/* per RFC 2831 */
    
    From 2fd1a0a683019f8c82c8d8330cf12d02d69c05bc Mon Sep 17 00:00:00 2001
    From: Ken Murchison 
    Date: Fri, 10 Feb 2012 15:17:22 -0500
    Subject: [PATCH 137/796] digest-md5: better handling of HTTP reauth cases
    
    ---
     plugins/digestmd5.c | 19 ++++++++++++++++---
     1 file changed, 16 insertions(+), 3 deletions(-)
    
    diff --git a/plugins/digestmd5.c b/plugins/digestmd5.c
    index 77d3c203..bdd9c343 100644
    --- a/plugins/digestmd5.c
    +++ b/plugins/digestmd5.c
    @@ -2451,7 +2451,7 @@ static int digestmd5_server_mech_step2(server_context_t *stext,
     #endif
         }
     
    -    if (text->state == 1 || !text->nonce) {
    +    if (!text->nonce) {
     	unsigned val = hash((char *) nonce) % text->reauth->size;
     
     	/* reauth attempt or continuation of HTTP Digest on a
    @@ -2479,9 +2479,12 @@ static int digestmd5_server_mech_step2(server_context_t *stext,
     	}
     
     	if (!text->nonce) {
    -	    /* we don't have any reauth info, so bail */
    +	    /* we don't have any reauth info */
     	    sparams->utils->log(sparams->utils->conn, SASL_LOG_DEBUG,
     				"No reauth info for '%s' found", nonce);
    +
    +	    /* we will continue processing the response to determine
    +	       if the client knows the password and return stale accordingly */
     	}
         }
     
    @@ -2510,12 +2513,16 @@ static int digestmd5_server_mech_step2(server_context_t *stext,
     	    result = SASL_BADAUTH;
     	    goto FreeAllMem;
     	}
    +#if 0	/* XXX  Possible replay attack, but we will continue processing
    +	 * the response to determine if the client knows the password and
    +	 return stale accordingly */
     	if (noncecount != text->nonce_count) {
     	    SETERROR(sparams->utils,
     		     "incorrect nonce-count: authentication aborted");
     	    result = SASL_BADAUTH;
     	    goto FreeAllMem;
     	}
    +#endif
     #if 0	/* XXX  Neither RFC 2617 nor RFC 2831 state that the cnonce
     	   needs to remain constant for subsequent authentication to work */
     	if (text->cnonce && strcmp((char *) cnonce, (char *) text->cnonce) != 0) {
    @@ -2789,15 +2796,18 @@ static int digestmd5_server_mech_step2(server_context_t *stext,
     
         /* see if our nonce expired */
         if (!text->nonce ||
    +	(noncecount != text->nonce_count) ||
     	(text->reauth->timeout &&
     	 time(0) - stext->timestamp > text->reauth->timeout)) {
     	if (!text->nonce) SETERROR(sparams->utils, "no cached server nonce");
    +	else if (noncecount != text->nonce_count)
    +	    SETERROR(sparams->utils, "incorrect nonce-count");
     	else SETERROR(sparams->utils, "server nonce expired");
     	stext->stale = 1;
     	result = SASL_BADAUTH;
     
     	goto FreeAllMem;
    -     }
    +    }
     
         /*
          * nothing more to do; authenticated set oparams information
    @@ -3036,6 +3046,9 @@ static int digestmd5_server_mech_step(void *conn_context,
     
     	    /* re-initialize everything for a fresh start */
     	    memset(oparams, 0, sizeof(sasl_out_params_t));
    +	    if (text->nonce) sparams->utils->free(text->nonce);
    +	    if (text->realm) sparams->utils->free(text->realm);
    +	    text->nonce = text->realm = NULL;
     
     	    /* fall through and issue challenge */
     	}
    
    From 789e7faa095004c514a93a6ac81ffa2f789afe55 Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Thu, 19 Apr 2012 14:34:14 +0100
    Subject: [PATCH 138/796] Fixes several warning (64 bit related and others) on
     Windows.
    
    This patch fixes several warnings generated by Visual Studio 2003 compiler
    with /Wp64 (64bit compatibility) flag.
    ---
     plugins/plugin_common.c | 8 ++++----
     1 file changed, 4 insertions(+), 4 deletions(-)
    
    diff --git a/plugins/plugin_common.c b/plugins/plugin_common.c
    index 741c3d7b..3aa6f9ab 100644
    --- a/plugins/plugin_common.c
    +++ b/plugins/plugin_common.c
    @@ -152,7 +152,7 @@ int _plug_ipfromstring(const sasl_utils_t *utils, const char *addr,
     	return SASL_BADPARAM;
         }
     
    -    len = ai->ai_addrlen;
    +    len = (socklen_t) ai->ai_addrlen;
         memcpy(&ss, ai->ai_addr, len);
         freeaddrinfo(ai);
         sockaddr_unmapped((struct sockaddr *)&ss, &len);
    @@ -230,7 +230,7 @@ int _plug_buf_alloc(const sasl_utils_t *utils, char **rwbuf,
     	}
     	*curlen = newlen;
         } else if(*rwbuf && *curlen < newlen) {
    -	size_t needed = 2*(*curlen);
    +	unsigned needed = 2*(*curlen);
     
     	while(needed < newlen)
     	    needed *= 2;
    @@ -267,7 +267,7 @@ int _plug_strdup(const sasl_utils_t * utils, const char *in,
       strcpy((char *) *out, in);
     
       if (outlen)
    -      *outlen = len;
    +      *outlen = (int) len;
     
       return SASL_OK;
     }
    @@ -280,7 +280,7 @@ void _plug_free_string(const sasl_utils_t *utils, char **str)
     
       len = strlen(*str);
     
    -  utils->erasebuffer(*str, len);
    +  utils->erasebuffer(*str, (unsigned int) len);
       utils->free(*str);
     
       *str=NULL;
    
    From 32c3b03ef4918a457f2be41ba12f349f1de0f8fd Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Fri, 20 Apr 2012 20:50:10 +0100
    Subject: [PATCH 139/796] Make server and client side global callbacks private
     to server.c/client.c respectively
    
    ---
     lib/client.c  | 2 +-
     lib/saslint.h | 2 --
     lib/server.c  | 2 +-
     3 files changed, 2 insertions(+), 4 deletions(-)
    
    diff --git a/lib/client.c b/lib/client.c
    index a6cc7ab8..44ccb667 100644
    --- a/lib/client.c
    +++ b/lib/client.c
    @@ -60,7 +60,7 @@
     #include "saslint.h"
     
     static cmech_list_t *cmechlist; /* global var which holds the list */
    -sasl_global_callbacks_t global_callbacks_client; 
    +static sasl_global_callbacks_t global_callbacks_client;
     static int _sasl_client_active = 0;
     
     static int init_mechlist()
    diff --git a/lib/saslint.h b/lib/saslint.h
    index 7643e298..e2edb3db 100644
    --- a/lib/saslint.h
    +++ b/lib/saslint.h
    @@ -118,8 +118,6 @@ typedef struct {
       const char *appname;
     } sasl_global_callbacks_t;
     
    -extern sasl_global_callbacks_t global_callbacks;
    -
     typedef struct _sasl_external_properties 
     {
         sasl_ssf_t ssf;
    diff --git a/lib/server.c b/lib/server.c
    index 9858d7ea..4b89b39a 100644
    --- a/lib/server.c
    +++ b/lib/server.c
    @@ -90,7 +90,7 @@ static int _sasl_checkpass(sasl_conn_t *conn,
     
     static mech_list_t *mechlist = NULL; /* global var which holds the list */
     
    -sasl_global_callbacks_t global_callbacks;
    +static sasl_global_callbacks_t global_callbacks;
     
     /* set the password for a user
      *  conn        -- SASL connection
    
    From 417b32dfbed13bc0ede81c05671eedf7874c44d9 Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Mon, 28 May 2012 20:24:55 +0100
    Subject: [PATCH 140/796] Added support for BerkleyDB 5.X or later
    
    Patch by Howard Chu
    ---
     sasldb/db_berkeley.c  | 18 ++++++++----------
     utils/dbconverter-2.c | 17 +++++++----------
     2 files changed, 15 insertions(+), 20 deletions(-)
    
    diff --git a/sasldb/db_berkeley.c b/sasldb/db_berkeley.c
    index 8778312a..4104acdb 100644
    --- a/sasldb/db_berkeley.c
    +++ b/sasldb/db_berkeley.c
    @@ -53,6 +53,8 @@
     #include 
     #include "sasldb.h"
     
    +#define DB_VERSION_FULL ((DB_VERSION_MAJOR << 24) | (DB_VERSION_MINOR << 16) | DB_VERSION_PATCH)
    +
     static int db_ok = 0;
     #if defined(KEEP_DB_OPEN)
     static DB * g_db = NULL;
    @@ -95,13 +97,13 @@ static int berkeleydb_open(const sasl_utils_t *utils,
     #endif
     #endif
     
    -#if DB_VERSION_MAJOR < 3
    +#if DB_VERSION_FULL < 0x03000000
         ret = db_open(path, DB_HASH, flags, 0660, NULL, NULL, mbdb);
    -#else /* DB_VERSION_MAJOR < 3 */
    +#else /* DB_VERSION_FULL < 0x03000000 */
         ret = db_create(mbdb, NULL, 0);
         if (ret == 0 && *mbdb != NULL)
         {
    -#if DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1
    +#if DB_VERSION_FULL >= 0x04010000 
     	ret = (*mbdb)->open(*mbdb, NULL, path, NULL, DB_HASH, flags, 0660);
     #else
     	ret = (*mbdb)->open(*mbdb, path, NULL, DB_HASH, flags, 0660);
    @@ -112,7 +114,7 @@ static int berkeleydb_open(const sasl_utils_t *utils,
     	    *mbdb = NULL;
     	}
         }
    -#endif /* DB_VERSION_MAJOR < 3 */
    +#endif /* DB_VERSION_FULL < 0x03000000 */
     
         if (ret != 0) {
     	if (rdwr == 0 && ret == ENOENT) {
    @@ -464,15 +466,11 @@ int _sasldb_getnextkey(const sasl_utils_t *utils __attribute__((unused)),
     
         if(!dbh->cursor) {
             /* make cursor */
    -#if DB_VERSION_MAJOR < 3
    -#if DB_VERSION_MINOR < 6
    +#if DB_VERSION_FULL < 0x03060000
     	result = mbdb->cursor(mbdb, NULL,&dbh->cursor); 
     #else
     	result = mbdb->cursor(mbdb, NULL,&dbh->cursor, 0); 
    -#endif /* DB_VERSION_MINOR < 7 */
    -#else /* DB_VERSION_MAJOR < 3 */
    -	result = mbdb->cursor(mbdb, NULL,&dbh->cursor, 0); 
    -#endif /* DB_VERSION_MAJOR < 3 */
    +#endif /* DB_VERSION_FULL < 0x03000000 */
     
     	if (result!=0) {
     	    return SASL_FAIL;
    diff --git a/utils/dbconverter-2.c b/utils/dbconverter-2.c
    index d188e00c..04df2cba 100644
    --- a/utils/dbconverter-2.c
    +++ b/utils/dbconverter-2.c
    @@ -200,6 +200,7 @@ int listusers(const char *path, listcb_t *cb)
     
     #include 
     
    +#define DB_VERSION_FULL ((DB_VERSION_MAJOR << 24) | (DB_VERSION_MINOR << 16) | DB_VERSION_PATCH)
     /*
      * Open the database
      *
    @@ -208,13 +209,13 @@ static int berkeleydb_open(const char *path,DB **mbdb)
     {
         int ret;
     
    -#if DB_VERSION_MAJOR < 3
    +#if DB_VERSION_FULL < 0x03000000
         ret = db_open(path, DB_HASH, DB_CREATE, 0664, NULL, NULL, mbdb);
    -#else /* DB_VERSION_MAJOR < 3 */
    +#else /* DB_VERSION_FULL < 0x03000000 */
         ret = db_create(mbdb, NULL, 0);
         if (ret == 0 && *mbdb != NULL)
         {
    -#if DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1
    +#if DB_VERSION_FULL >= 0x04010000
     	ret = (*mbdb)->open(*mbdb, NULL, path, NULL, DB_HASH, DB_CREATE, 0664);
     #else
     	ret = (*mbdb)->open(*mbdb, path, NULL, DB_HASH, DB_CREATE, 0664);
    @@ -225,7 +226,7 @@ static int berkeleydb_open(const char *path,DB **mbdb)
     	    *mbdb = NULL;
     	}
         }
    -#endif /* DB_VERSION_MAJOR < 3 */
    +#endif /* DB_VERSION_FULL < 0x03000000 */
     
         if (ret != 0) {
     	fprintf(stderr,"Error opening password file %s\n", path);
    @@ -263,15 +264,11 @@ int listusers(const char *path, listcb_t *cb)
         if (result!=SASL_OK) goto cleanup;
     
         /* make cursor */
    -#if DB_VERSION_MAJOR < 3
    -#if DB_VERSION_MINOR < 6
    +#if DB_VERSION_FULL < 0x03060000
         result = mbdb->cursor(mbdb, NULL,&cursor); 
     #else
         result = mbdb->cursor(mbdb, NULL,&cursor, 0); 
    -#endif /* DB_VERSION_MINOR < 7 */
    -#else /* DB_VERSION_MAJOR < 3 */
    -    result = mbdb->cursor(mbdb, NULL,&cursor, 0); 
    -#endif /* DB_VERSION_MAJOR < 3 */
    +#endif /* DB_VERSION_FULL < 0x03060000 */
     
         if (result!=0) {
     	fprintf(stderr,"Making cursor failure: %s\n",db_strerror(result));
    
    From 69dc9c4a1bf363f03b0c54f49c9ec8ccf600c818 Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Tue, 8 May 2012 15:44:35 +0100
    Subject: [PATCH 141/796] SASL fix exporting of variables
    
    On Unix, global variables should have a .h like:
            extern int answer;
    
    and a .c like:
            int answer = 42;
    
    On Windows, the header should have when included from non-library source:
            extern __declspec(dllimport) int answer;
    and when included from library source:
            extern __declspec(dllexport) int answer;
    and in the source:
            int answer = 42;
    
    This patch fixes up the code to ensure this.
    
    Patch from Kurt Zeilenga.
    ---
     include/prop.h  | 13 ++++++-------
     lib/Makefile.am |  2 +-
     lib/common.c    |  2 +-
     3 files changed, 8 insertions(+), 9 deletions(-)
    
    diff --git a/include/prop.h b/include/prop.h
    index 7a65c85c..fed3fa77 100644
    --- a/include/prop.h
    +++ b/include/prop.h
    @@ -34,24 +34,23 @@
      * as extern.  (Technically, we don't even have to do that.) */
     #ifdef WIN32
     # ifdef LIBSASL_EXPORTS
    -#  define LIBSASL_API  __declspec(dllexport)
    +#  define LIBSASL_API  extern __declspec(dllexport)
     # else /* LIBSASL_EXPORTS */
    -#  define LIBSASL_API  __declspec(dllimport)
    +#  define LIBSASL_API  extern __declspec(dllimport)
     # endif /* LIBSASL_EXPORTS */
     #else /* WIN32 */
     # define LIBSASL_API extern
     #endif /* WIN32 */
     
    -/* Same as above, but used during a variable declaration. Only Unix definition
    - * is different, as we can't assign an initial value to an extern variable */ 
    +/* Same as above, but used during a variable declaration. */
     #ifdef WIN32
     # ifdef LIBSASL_EXPORTS
    -#  define LIBSASL_VAR  __declspec(dllexport)
    +#  define LIBSASL_VAR  extern __declspec(dllexport)
     # else /* LIBSASL_EXPORTS */
    -#  define LIBSASL_VAR  __declspec(dllimport)
    +#  define LIBSASL_VAR  extern __declspec(dllimport)
     # endif /* LIBSASL_EXPORTS */
     #else /* WIN32 */
    -# define LIBSASL_VAR
    +# define LIBSASL_VAR extern
     #endif /* WIN32 */
     
     /* the resulting structure for property values
    diff --git a/lib/Makefile.am b/lib/Makefile.am
    index 6e1b8c57..3beccf02 100644
    --- a/lib/Makefile.am
    +++ b/lib/Makefile.am
    @@ -43,7 +43,7 @@
     # Library version info - here at the top, for sanity
     sasl_version = 2:25:0
     
    -INCLUDES=-I$(top_srcdir)/include -I$(top_srcdir)/plugins -I$(top_builddir)/include -I$(top_srcdir)/sasldb
    +INCLUDES=-DLIBSASL_EXPORTS=1 -I$(top_srcdir)/include -I$(top_srcdir)/plugins -I$(top_builddir)/include -I$(top_srcdir)/sasldb
     
     EXTRA_DIST = windlopen.c staticopen.h NTMakefile
     EXTRA_LIBRARIES = libsasl2.a
    diff --git a/lib/common.c b/lib/common.c
    index 013e3bbd..e0f59ebc 100644
    --- a/lib/common.c
    +++ b/lib/common.c
    @@ -89,7 +89,7 @@ static char * _sasl_get_default_win_path(void *context __attribute__((unused)),
     static const char build_ident[] = "$Build: libsasl " PACKAGE "-" VERSION " $";
     
     /* It turns out to be convenient to have a shared sasl_utils_t */
    -LIBSASL_VAR const sasl_utils_t *sasl_global_utils = NULL;
    +const sasl_utils_t *sasl_global_utils = NULL;
     
     /* Should be a null-terminated array that lists the available mechanisms */
     static char **global_mech_list = NULL;
    
    From 8fc14fd702897e652a38384af2f55e51752e8c15 Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Tue, 29 May 2012 16:00:47 +0100
    Subject: [PATCH 142/796] get_fqhostname() function has broken logic when
     abort_if_no_fqdn is 0
    
    When abort_if_no_fqdn is 0, a getaddrinfo failure should be ignored,
    as long as gethostname() succeeded.
    
    Cyrus SASL Bug # 3589
    
    Patch by baggins@pld-linux.org
    ---
     lib/saslutil.c | 36 ++++++++++++++++++++++++------------
     1 file changed, 24 insertions(+), 12 deletions(-)
    
    diff --git a/lib/saslutil.c b/lib/saslutil.c
    index fc5b7741..61741246 100644
    --- a/lib/saslutil.c
    +++ b/lib/saslutil.c
    @@ -557,32 +557,44 @@ int get_fqhostname(
     		  NULL,		/* don't care abour service/port */
     		  &hints,
     		  &result) != 0) {
    -	/* errno on Unix, WSASetLastError on Windows are already done by the function */
    -	return (-1);
    +        if (abort_if_no_fqdn) {
    +	    /* errno on Unix, WSASetLastError on Windows are already done by the function */
    +	    return (-1);
    +	} else {
    +	    goto LOWERCASE;
    +	}
         }
     
    -    if (abort_if_no_fqdn && (result == NULL || result->ai_canonname == NULL)) {
    +    if (result == NULL || result->ai_canonname == NULL) {
     	freeaddrinfo (result);
    +        if (abort_if_no_fqdn) {
     #ifdef WIN32
    -	WSASetLastError (WSANO_DATA);
    +	    WSASetLastError (WSANO_DATA);
     #elif defined(ENODATA)
    -	errno = ENODATA;
    +	    errno = ENODATA;
     #elif defined(EADDRNOTAVAIL)
    -	errno = EADDRNOTAVAIL;
    +	    errno = EADDRNOTAVAIL;
     #endif
    -	return (-1);
    +	    return (-1);
    +	} else {
    +	    goto LOWERCASE;
    +	}
         }
     
    -    if (abort_if_no_fqdn && strchr (result->ai_canonname, '.') == NULL) {
    +    if (strchr (result->ai_canonname, '.') == NULL) {
     	freeaddrinfo (result);
    +        if (abort_if_no_fqdn) {
     #ifdef WIN32
    -	WSASetLastError (WSANO_DATA);
    +	    WSASetLastError (WSANO_DATA);
     #elif defined(ENODATA)
    -	errno = ENODATA;
    +	    errno = ENODATA;
     #elif defined(EADDRNOTAVAIL)
    -	errno = EADDRNOTAVAIL;
    +	    errno = EADDRNOTAVAIL;
     #endif
    -	return (-1);
    +	    return (-1);
    +	} else {
    +	    goto LOWERCASE;
    +	}
         }
     
     
    
    From b4744a25ebc11687def101ebbef8c82d3241d2a5 Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Tue, 8 May 2012 15:18:18 +0100
    Subject: [PATCH 143/796] Modernize SASL malloc/realloc callback prototypes
    
    This eliminates some warnings on Windows 64, among other things.
    ---
     include/sasl.h | 6 +++---
     1 file changed, 3 insertions(+), 3 deletions(-)
    
    diff --git a/include/sasl.h b/include/sasl.h
    index 5bbbbfbc..2ac53003 100755
    --- a/include/sasl.h
    +++ b/include/sasl.h
    @@ -225,9 +225,9 @@ extern "C" {
     
     /* memory allocation functions which may optionally be replaced:
      */
    -typedef void *sasl_malloc_t(unsigned long);
    -typedef void *sasl_calloc_t(unsigned long, unsigned long);
    -typedef void *sasl_realloc_t(void *, unsigned long);
    +typedef void *sasl_malloc_t(size_t);
    +typedef void *sasl_calloc_t(size_t, size_t);
    +typedef void *sasl_realloc_t(void *, size_t);
     typedef void sasl_free_t(void *);
     
     LIBSASL_API void sasl_set_alloc(sasl_malloc_t *,
    
    From 2d0e416946ee599e407fca9ab0858a1ebe27cd80 Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Tue, 29 May 2012 17:40:56 +0100
    Subject: [PATCH 144/796] bug in "saslauthd -a rimap" - not reading the whole
     IMAP greeting
    
    Cyrus SASL Bug # 3211
    
    Red Hat Bugzilla # 582540
    
    Patch from Lutz Mark (via Red Hat)
    ---
     saslauthd/auth_rimap.c | 49 ++++++++++++++++++++++++++++++++++++++++++
     1 file changed, 49 insertions(+)
    
    diff --git a/saslauthd/auth_rimap.c b/saslauthd/auth_rimap.c
    index 1bf2deb3..2c3870f0 100644
    --- a/saslauthd/auth_rimap.c
    +++ b/saslauthd/auth_rimap.c
    @@ -1,3 +1,4 @@
    +
     /* MODULE: auth_rimap */
     
     /* COPYRIGHT
    @@ -367,6 +368,30 @@ auth_rimap (
         alarm(NETWORK_IO_TIMEOUT);
         rc = read(s, rbuf, sizeof(rbuf));
         alarm(0);
    +    if ( rc>0 ) {
    +        /* check if there is more to read */
    +        fd_set         perm;
    +        int            fds, ret;
    +        struct timeval timeout;
    +
    +        FD_ZERO(&perm);
    +        FD_SET(s, &perm);
    +        fds = s +1;
    +
    +        timeout.tv_sec  = 1;
    +        timeout.tv_usec = 0;
    +        while( select (fds, &perm, NULL, NULL, &timeout ) >0 ) {
    +           if ( FD_ISSET(s, &perm) ) {
    +              ret = read(s, rbuf+rc, sizeof(rbuf)-rc);
    +              if ( ret<0 ) {
    +                 rc = ret;
    +                 break;
    +              } else {
    +                 rc += ret;
    +              }
    +           }
    +        }
    +    }
         if (rc == -1) {
     	syslog(LOG_WARNING, "auth_rimap: read (banner): %m");
     	(void) close(s);
    @@ -456,6 +481,30 @@ auth_rimap (
         alarm(NETWORK_IO_TIMEOUT);
         rc = read(s, rbuf, sizeof(rbuf));
         alarm(0);
    +    if ( rc>0 ) {
    +        /* check if there is more to read */
    +        fd_set         perm;
    +        int            fds, ret;
    +        struct timeval timeout;
    +
    +        FD_ZERO(&perm);
    +        FD_SET(s, &perm);
    +        fds = s +1;
    +
    +        timeout.tv_sec  = 1;
    +        timeout.tv_usec = 0;
    +        while( select (fds, &perm, NULL, NULL, &timeout ) >0 ) {
    +           if ( FD_ISSET(s, &perm) ) {
    +              ret = read(s, rbuf+rc, sizeof(rbuf)-rc);
    +              if ( ret<0 ) {
    +                 rc = ret;
    +                 break;
    +              } else {
    +                 rc += ret;
    +              }
    +           }
    +        }
    +    }
         (void) close(s);			/* we're done with the remote */
         if (rc == -1) {
     	syslog(LOG_WARNING, "auth_rimap: read (response): %m");
    
    From 023c5c94fe5ca268051e58e96dffd0897eb13e1e Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Tue, 29 May 2012 19:39:10 +0100
    Subject: [PATCH 145/796] GS2 plugin might fail to compiled with Heimdal
    
    gssapi/gssapi_ext.h is MIT specific, so including it with Heimdal
    can cause compilation problems.
    
    Cyrus SASL Bug # 3567
    
    Patch by Quanah Gibson-Mount.
    ---
     plugins/gs2.c       | 4 ++++
     plugins/gs2_token.h | 3 +++
     2 files changed, 7 insertions(+)
    
    diff --git a/plugins/gs2.c b/plugins/gs2.c
    index b35456bd..42d29c97 100644
    --- a/plugins/gs2.c
    +++ b/plugins/gs2.c
    @@ -72,9 +72,13 @@
     
     #include 
     #include 
    +
    +#ifndef KRB5_HEIMDAL
     #ifdef HAVE_GSSAPI_GSSAPI_EXT_H
     #include 
     #endif
    +#endif
    +
     #include 
     #include 
     #include 
    diff --git a/plugins/gs2_token.h b/plugins/gs2_token.h
    index 52cb3902..f7e2f745 100644
    --- a/plugins/gs2_token.h
    +++ b/plugins/gs2_token.h
    @@ -26,9 +26,12 @@
     #include 
     
     #include 
    +
    +#ifndef KRB5_HEIMDAL
     #ifdef HAVE_GSSAPI_GSSAPI_EXT_H
     #include 
     #endif
    +#endif
     
     #ifndef HAVE_GSS_DECAPSULATE_TOKEN
     OM_uint32
    
    From 9b598caa7d0e970df70b2b2ddf6c112946ec48ec Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Wed, 30 May 2012 23:47:37 +0100
    Subject: [PATCH 146/796] Fixed file descriptor leaks throughout the code
    
    Missing fclose on parsing errors for various file descriptors.
    
    Cyrus SASL Bug # 3702
    
    Slightly reformatted patch by Manfred Weichel.
    ---
     lib/config.c      | 17 ++++++++++++++---
     saslauthd/cfile.c |  4 ++++
     saslauthd/lak.c   |  8 ++++++--
     3 files changed, 24 insertions(+), 5 deletions(-)
    
    diff --git a/lib/config.c b/lib/config.c
    index c901bd83..7cae3020 100644
    --- a/lib/config.c
    +++ b/lib/config.c
    @@ -90,6 +90,7 @@ int sasl_config_init(const char *filename)
     	    p++;
     	}
     	if (*p != ':') {
    +	    fclose(infile);
     	    return SASL_FAIL;
     	}
     	*p++ = '\0';
    @@ -97,6 +98,7 @@ int sasl_config_init(const char *filename)
     	while (*p && isspace((int) *p)) p++;
     	
     	if (!*p) {
    +	    fclose(infile);
     	    return SASL_FAIL;
     	}
     
    @@ -111,17 +113,26 @@ int sasl_config_init(const char *filename)
     	    alloced += CONFIGLISTGROWSIZE;
     	    configlist=sasl_REALLOC((char *)configlist, 
     				    alloced * sizeof(struct configlist));
    -	    if (configlist==NULL) return SASL_NOMEM;
    +	    if (configlist == NULL) {
    +		fclose(infile);
    +		return SASL_NOMEM;
    +	    }
     	}
     
     	result = _sasl_strdup(key,
     			      &(configlist[nconfiglist].key),
     			      NULL);
    -	if (result!=SASL_OK) return result;
    +	if (result != SASL_OK) {
    +	    fclose(infile);
    +	    return result;
    +	}
     	result = _sasl_strdup(p,
     			      &(configlist[nconfiglist].value),
     			      NULL);
    -	if (result!=SASL_OK) return result;
    +	if (result != SASL_OK) {
    +	    fclose(infile);
    +	    return result;
    +	}
     
     	nconfiglist++;
         }
    diff --git a/saslauthd/cfile.c b/saslauthd/cfile.c
    index 6b72b0a1..5c87d022 100644
    --- a/saslauthd/cfile.c
    +++ b/saslauthd/cfile.c
    @@ -116,6 +116,7 @@ cfile cfile_read(const char *filename, char *complaint, int complaint_len)
     	  if (complaint)
     	    snprintf(complaint, complaint_len, "%s: line %d: no colon separator", filename, lineno);
     	  cfile_free(cf);
    +	  fclose(infile);
     	  return 0;
     	}
     	*p++ = '\0';
    @@ -126,6 +127,7 @@ cfile cfile_read(const char *filename, char *complaint, int complaint_len)
     	  if (complaint)
     	    snprintf(complaint, complaint_len, "%s: line %d: keyword %s: no value", filename, lineno, key);
     	  cfile_free(cf);
    +	  fclose(infile);
     	  return 0;
     	}
     
    @@ -137,6 +139,7 @@ cfile cfile_read(const char *filename, char *complaint, int complaint_len)
     	      if (complaint)
     	        snprintf(complaint, complaint_len, "cfile_read: no memory");
     	      cfile_free(cf);
    +	      fclose(infile);
     	      return 0;
     	    }
     	}
    @@ -147,6 +150,7 @@ cfile cfile_read(const char *filename, char *complaint, int complaint_len)
     	        snprintf(complaint, complaint_len, "cfile_read: no memory");
     	      cf->n_kv++; /* maybe one strdup() worked */
     	      cfile_free(cf);
    +	      fclose(infile);
     	      return 0;
     	}
     
    diff --git a/saslauthd/lak.c b/saslauthd/lak.c
    index 92c2116f..419a6584 100644
    --- a/saslauthd/lak.c
    +++ b/saslauthd/lak.c
    @@ -169,16 +169,20 @@ static int lak_config_read(
     				*p = tolower(*p);
     			p++;
     		}
    -		if (*p != ':')
    +		if (*p != ':') {
    +			fclose(infile);
     			return LAK_FAIL;
    +		}
     		
     		*p++ = '\0';
     
     		while (*p && isspace((int) *p)) 
     			p++;
     
    -		if (!*p)
    +		if (!*p) {
    +			fclose(infile);
     			return LAK_FAIL;
    +		}
     
     		if (!strcasecmp(key, "ldap_servers"))
     			strlcpy(conf->servers, p, LAK_URL_LEN);
    
    From 09348d4e94a49ad4f0891934e353d993226cc9fd Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Wed, 30 May 2012 23:24:16 +0100
    Subject: [PATCH 147/796] Encode the parameter values passed to auth_httpform,
     not the whole POST data
    
    Before this change the whole application/x-www-form-urlencoded form data
    was URL-%encoded. There was an exception made for "=" and "&" (as they
    are special delimiters in this format), which resulted in the following problem:
    any usernames/passwords/realm that contained "=" or "&" were not encoded
    correctly. This patch fixes that by encoding only username/password/realm
    values.
    
    Note that this patch changes the earlier behavior, as remaining form data
    is not encoded now.
    
    The following issue is known with this change (it was present in the
    original version of auth_httpform):
    
    1) Spaces need to be replaced with "+". This needs to be done in usernames,
    passwords and realms.
    
    Cyrus SASL Bug # 3508
    
    Based on patch by Jeroen van Meeuwen (Kolab Systems).
    ---
     saslauthd/auth_httpform.c | 56 ++++++++++++++++++++++++++-------------
     1 file changed, 37 insertions(+), 19 deletions(-)
    
    diff --git a/saslauthd/auth_httpform.c b/saslauthd/auth_httpform.c
    index 45fb0837..8dbf5518 100644
    --- a/saslauthd/auth_httpform.c
    +++ b/saslauthd/auth_httpform.c
    @@ -179,8 +179,7 @@ static char *url_escape(
             char in = string[inidx];
             if (!(in >= 'a' && in <= 'z') &&
                 !(in >= 'A' && in <= 'Z') &&
    -            !(in >= '0' && in <= '9') &&
    -            in != '&' && in != '=' && in != '-' && in != '_') {
    +            !(in >= '0' && in <= '9')) {
     
                 /* encode it */
                 if (outidx+3 > alloc) {
    @@ -242,12 +241,36 @@ static char *create_post_data(
         int biggest;
         size_t i;
         /* END VARIABLES */
    +
    +    user = url_escape(user);
    +    if (!user) {
    +        logger(LOG_ERR, "auth_httpform:create_post_data", "failed to allocate memory");
    +        return NULL;
    +    }
    +
    +    password = url_escape(password);
    +    if (!password) {
    +        memset(user, 0, strlen(user));
    +        free(user);
    +        logger(LOG_ERR, "auth_httpform:create_post_data", "failed to allocate memory");
    +        return NULL;
    +    }
    +
    +    realm = url_escape(realm);
    +    if (!realm) {
    +        memset(user, 0, strlen(user));
    +        free(user);
    +        memset(password, 0, strlen(password));
    +        free(password);
    +        logger(LOG_ERR, "auth_httpform:create_post_data", "failed to allocate memory");
    +        return NULL;
    +    }
         
         /* calculate memory needed for creating the complete query string. */
         ulen = strlen(user);
         plen = strlen(password);
         rlen = strlen(realm);
    -    
    +
         /* what if we have multiple %foo occurrences in the input query? */
         for (i = 0; i < strlen(formdata); i++) {
             if (formdata[i] == '%') {
    @@ -266,7 +289,7 @@ static char *create_post_data(
         
         if (!buf) {
             logger(LOG_ERR, "auth_httpform:create_post_data", "failed to allocate memory");
    -        return NULL;
    +        goto CLEANUP;
         }
         
         buf_ptr = buf;
    @@ -308,6 +331,14 @@ static char *create_post_data(
         /* don't forget the rest */    
         memcpy(buf_ptr, line_ptr, strlen(line_ptr)+1);
     
    +CLEANUP:
    +    memset(user, 0, strlen(user));
    +    memset(password, 0, strlen(password));
    +    memset(realm, 0, strlen(realm));
    +    free(user);
    +    free(password);
    +    free(realm);
    +
         return buf;
     }
     
    @@ -471,7 +502,6 @@ auth_httpform (
         int s=-1;                           /* socket to remote auth host   */
         struct addrinfo *r;                 /* remote socket address info   */
         char *req;                          /* request, with user and pw    */
    -    char *escreq;                       /* URL-escaped request          */
         char *c;                            /* scratch pointer              */
         int rc;                             /* return code scratch area     */
         char postbuf[RESP_LEN];             /* request buffer               */
    @@ -535,14 +565,6 @@ auth_httpform (
             syslog(LOG_WARNING, "auth_httpform: create_post_data == NULL");
             return strdup(RESP_IERROR);
         }
    -    escreq = url_escape(req);
    -    if (escreq == NULL) {
    -        memset(req, 0, strlen(req));
    -        free(req); 
    -        close(s);
    -        syslog(LOG_WARNING, "auth_httpform: url_escape == NULL");
    -        return strdup(RESP_IERROR);
    -    }
     
         postlen = snprintf(postbuf, RESP_LEN-1,
                   "POST %s HTTP/1.1" CRLF
    @@ -552,11 +574,11 @@ auth_httpform (
                   "Content-Type: application/x-www-form-urlencoded" CRLF
                   "Content-Length: %d" TWO_CRLF
                   "%s",
    -              r_uri, r_host, r_port, strlen(escreq), escreq);
    +              r_uri, r_host, r_port, strlen(req), req);
     
         if (flags & VERBOSE) {
             syslog(LOG_DEBUG, "auth_httpform: sending %s %s %s",
    -               r_host, r_uri, escreq);
    +               r_host, r_uri, req);
         }
         
         /* send it */
    @@ -568,8 +590,6 @@ auth_httpform (
             syslog(LOG_WARNING, "auth_httpform: failed to send request");
             memset(req, 0, strlen(req));
             free(req); 
    -        memset(escreq, 0, strlen(escreq));
    -        free(escreq);
             memset(postbuf, 0, postlen);
             close(s);
             return strdup(RESP_IERROR);
    @@ -578,8 +598,6 @@ auth_httpform (
         /* don't need these any longer */
         memset(req, 0, strlen(req));
         free(req); 
    -    memset(escreq, 0, strlen(escreq));
    -    free(escreq);
         memset(postbuf, 0, postlen);
     
         /* read and parse the response */
    
    From e6d893478d8370ad82e4774572c4619e306e42d5 Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Wed, 25 Apr 2012 15:34:28 +0100
    Subject: [PATCH 148/796] Removed some trailing whitespaces GIT complains about
    
    ---
     configure.in        | 12 ++++++------
     plugins/digestmd5.c |  2 +-
     2 files changed, 7 insertions(+), 7 deletions(-)
    
    diff --git a/configure.in b/configure.in
    index cc5750d1..d1725328 100644
    --- a/configure.in
    +++ b/configure.in
    @@ -277,8 +277,8 @@ if test "$with_pam" != no; then
       fi
       AC_CHECK_HEADERS(security/pam_appl.h pam/pam_appl.h)
       cmu_save_LIBS="$LIBS"
    -  AC_CHECK_FUNC(pam_start, :, 
    -	LIBS="-lpam $LIBS" 
    +  AC_CHECK_FUNC(pam_start, :,
    +	LIBS="-lpam $LIBS"
     	AC_TRY_LINK([[
     #include 
     #ifdef HAVE_PAM_PAM_APPL_H
    @@ -835,7 +835,7 @@ AC_ARG_WITH(sqlite,  [  --with-sqlite=PATH       use SQLite from PATH ],
       with_sqlite=$withval,
       with_sqlite=$sql)
     
    -# find location of library 
    +# find location of library
     # presuing if one given then correct
     if test "${with_sqlite}" = "yes"; then
       with_sqlite=notfound
    @@ -878,7 +878,7 @@ case "$with_sqlite" in
     	   [Do we have SQLite support?]),
                [AC_WARN([SQLite Library sqlite does not work])
     	    with_sqlite=no], $LIB_SQLITE_DIR);;
    -         
    +
     esac
     AC_SUBST(LIB_SQLITE)
     
    @@ -887,7 +887,7 @@ AC_ARG_WITH(sqlite3,  [  --with-sqlite3=PATH       use SQLite3 from PATH ],
       with_sqlite3=$withval,
       with_sqlite3=$sql)
     
    -# find location of library 
    +# find location of library
     # we assume that if one given then it is correct
     if test "${with_sqlite3}" = "yes"; then
       with_sqlite3=notfound
    @@ -930,7 +930,7 @@ case "$with_sqlite3" in
     	   [Do we have SQLite3 support?]),
                [AC_WARN([SQLite3 Library sqlite3 does not work])
     	    with_sqlite3=no], $LIB_SQLITE3_DIR);;
    -         
    +
     esac
     AC_SUBST(LIB_SQLITE3)
     
    diff --git a/plugins/digestmd5.c b/plugins/digestmd5.c
    index bdd9c343..2f7276a2 100644
    --- a/plugins/digestmd5.c
    +++ b/plugins/digestmd5.c
    @@ -198,7 +198,7 @@ typedef struct reauth_entry {
     
     	    /* for HTTP mode (RFC 2617) only */
     	    char *algorithm;
    -	    unsigned char *opaque;	
    +	    unsigned char *opaque;
     	} c; /* client stuff */
         } u;
     } reauth_entry_t;
    
    From e94ad003928a9f9990e781c6c2ced79144ae9766 Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Fri, 25 May 2012 17:33:38 +0100
    Subject: [PATCH 149/796] Removed calling of EVP_cleanup() on SRP/OTP plugin
     shutdown
    
    This change is made because calling EVP_cleanup() messes with a calling
    application code that initializes OpenSSL once before calling SASL functions
    and expect that OpenSSL will still be initialized (e.g. ciphers available)
    once sasl_client_done()/sasl_server_done() are called. Unfortunately
    EVP_cleanup() doesn't use reference counting internally, so shutting down
    OpenSSL should be left to the calling application.
    
    Cyrus SASL Bug # 3703
    
    Test-information:
    
     Discovered and fixed the issue while testing trunk imapd on Windows 7
     with OTP/SRP plugins installed.
    ---
     plugins/otp.c | 3 ++-
     plugins/srp.c | 3 ++-
     2 files changed, 4 insertions(+), 2 deletions(-)
    
    diff --git a/plugins/otp.c b/plugins/otp.c
    index 255a6bcf..dd730651 100644
    --- a/plugins/otp.c
    +++ b/plugins/otp.c
    @@ -278,7 +278,8 @@ static void
     otp_common_mech_free(void *global_context __attribute__((unused)),
     		     const sasl_utils_t *utils __attribute__((unused)))
     {
    -    EVP_cleanup();
    +    /* Don't call EVP_cleanup(); here, as this might confuse the calling
    +       application if it also uses OpenSSL */
     }
     
     /*****************************  Server Section  *****************************/
    diff --git a/plugins/srp.c b/plugins/srp.c
    index cc012d52..a07561c6 100644
    --- a/plugins/srp.c
    +++ b/plugins/srp.c
    @@ -1521,7 +1521,8 @@ static void
     srp_common_mech_free(void *global_context __attribute__((unused)),
     		     const sasl_utils_t *utils __attribute__((unused)))
     {
    -    EVP_cleanup();
    +    /* Don't call EVP_cleanup(); here, as this might confuse the calling
    +       application if it also uses OpenSSL */
     }
     
     
    
    From 03d38a3d2ba19a920e2a71363a9673f5469b9ea5 Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Fri, 1 Jun 2012 11:41:23 +0100
    Subject: [PATCH 150/796] saslauthd man page update
    
    From a patch by Greg A. Woods.
    ---
     saslauthd/saslauthd.mdoc | 13 +++++++++----
     1 file changed, 9 insertions(+), 4 deletions(-)
    
    diff --git a/saslauthd/saslauthd.mdoc b/saslauthd/saslauthd.mdoc
    index 34a3c1f6..50f7dbf2 100644
    --- a/saslauthd/saslauthd.mdoc
    +++ b/saslauthd/saslauthd.mdoc
    @@ -10,7 +10,7 @@
     .\" manpage in saslauthd.8 whenever you change this source
     .\" version. Only the pre-formatted manpage is installed.
     .\"
    -.Dd 10 24 2002
    +.Dd 12 12 2005
     .Dt SASLAUTHD 8
     .Os "CMU-SASL"
     .Sh NAME
    @@ -98,8 +98,13 @@ Enable caching of authentication credentials
     Disable the use of a lock file for controlling access to accept().
     .It Fl r
     Combine the realm with the login (with an '@' sign in between).  e.g.
    -login: "foo" realm: "bar" will get passed as login: "foo@bar".  Note that
    -the realm will still be passed, which may lead to unexpected behaviour.
    +login: "foo" realm: "bar" will get passed as login: "foo@bar".  Note
    +that the realm will still be passed, which may lead to unexpected
    +behavior for authentication mechanisms that make use of the realm,
    +however for mechanisms which don't, such as
    +.Ar getpwent ,
    +this is the only way to authenticate domain-specific users sharing the
    +same userid.
     .It Fl v
     Print the version number and available authentication
     mechanisms on standard error, then exit.
    @@ -119,7 +124,7 @@ supports one or more
     .Qq authentication mechanisms ,
     dependent upon the facilities provided by the underlying operating system.
     The mechanism is selected by the
    -.Fl aho
    +.Fl a
     flag from the following list of choices:
     .Bl -tag -width "kerberos4"
     .It Li dce
    
    From 240d8f0ad7b8564467c8ccb3123851d350835e27 Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Fri, 1 Jun 2012 11:52:44 +0100
    Subject: [PATCH 151/796] Corrected some spelling mistakes in configure.in
     messages
    
    ---
     configure.in | 26 +++++++++++++-------------
     1 file changed, 13 insertions(+), 13 deletions(-)
    
    diff --git a/configure.in b/configure.in
    index d1725328..af00a448 100644
    --- a/configure.in
    +++ b/configure.in
    @@ -124,7 +124,7 @@ AC_ARG_ENABLE(staticdlopen, [  --enable-staticdlopen   try dynamic plugins when
                     enable_staticdlopen=no)
     
     if test "$enable_staticdlopen" = yes; then
    -  AC_DEFINE(TRY_DLOPEN_WHEN_STATIC,[],[Should we try to dlopen() plugins while staticly compiled?])
    +  AC_DEFINE(TRY_DLOPEN_WHEN_STATIC,[],[Should we try to dlopen() plugins while statically compiled?])
     fi
     
     if test "$ac_cv_prog_gcc" = yes; then
    @@ -394,7 +394,7 @@ if test "$cram" != no; then
       if test "$enable_static" = yes; then
         SASL_STATIC_OBJS="$SASL_STATIC_OBJS cram.o"
         SASL_STATIC_SRCS="$SASL_STATIC_SRCS \$(top_srcdir)/plugins/cram.c"
    -    AC_DEFINE(STATIC_CRAMMD5, [], [Link CRAM-MD5 Staticly])
    +    AC_DEFINE(STATIC_CRAMMD5, [], [Link CRAM-MD5 Statically])
       fi
     else
       AC_MSG_RESULT(disabled)
    @@ -429,7 +429,7 @@ if test "$digest" != no; then
       if test "$enable_static" = yes; then
         SASL_STATIC_SRCS="$SASL_STATIC_SRCS \$(top_srcdir)/plugins/digestmd5.c"
         SASL_STATIC_OBJS="$SASL_STATIC_OBJS digestmd5.o"
    -    AC_DEFINE(STATIC_DIGESTMD5, [], [Link DIGEST-MD5 Staticly])
    +    AC_DEFINE(STATIC_DIGESTMD5, [], [Link DIGEST-MD5 Statically])
       fi
     else
       AC_MSG_RESULT(disabled)
    @@ -454,7 +454,7 @@ if test "$scram" != no; then
       if test "$enable_static" = yes; then
         SASL_STATIC_SRCS="$SASL_STATIC_SRCS \$(top_srcdir)/plugins/scram.c"
         SASL_STATIC_OBJS="$SASL_STATIC_OBJS scram.o"
    -    AC_DEFINE(STATIC_SCRAM, [], [Link SCRAM Staticly])
    +    AC_DEFINE(STATIC_SCRAM, [], [Link SCRAM Statically])
       fi
     
       AC_SUBST(SCRAM_LIBS)
    @@ -481,7 +481,7 @@ if test "$otp" != no; then
       if test "$enable_static" = yes; then
         SASL_STATIC_SRCS="$SASL_STATIC_SRCS \$(top_srcdir)/plugins/otp.c"
         SASL_STATIC_OBJS="$SASL_STATIC_OBJS otp.o"
    -    AC_DEFINE(STATIC_OTP, [], [Link OTP Staticly])
    +    AC_DEFINE(STATIC_OTP, [], [Link OTP Statically])
       fi
     
       dnl Test for OPIE
    @@ -538,7 +538,7 @@ if test "$srp" != no; then
       if test "$enable_static" = yes; then
         SASL_STATIC_SRCS="$SASL_STATIC_SRCS \$(top_srcdir)/plugins/srp.c"
         SASL_STATIC_OBJS="$SASL_STATIC_OBJS srp.o"
    -    AC_DEFINE(STATIC_SRP, [], [Link SRP Staticly])
    +    AC_DEFINE(STATIC_SRP, [], [Link SRP Statically])
       fi
     
     dnl srp_setpass support
    @@ -564,7 +564,7 @@ SASL_KERBEROS_V4_CHK
     SASL_GSSAPI_CHK
     
     if test "$gssapi" != "no"; then
    -  AC_DEFINE(STATIC_GSSAPIV2,[],[Link GSSAPI Staticly])
    +  AC_DEFINE(STATIC_GSSAPIV2,[],[Link GSSAPI Statically])
       mutex_default="no"
       if test "$gss_impl" = "mit"; then
          mutex_default="yes"
    @@ -594,7 +594,7 @@ if test "$anon" != no; then
       if test "$enable_static" = yes; then
         SASL_STATIC_OBJS="$SASL_STATIC_OBJS anonymous.o"
         SASL_STATIC_SRCS="$SASL_STATIC_SRCS \$(top_srcdir)/plugins/anonymous.c"
    -    AC_DEFINE(STATIC_ANONYMOUS, [], [Link ANONYMOUS Staticly])
    +    AC_DEFINE(STATIC_ANONYMOUS, [], [Link ANONYMOUS Statically])
       fi
     else
       AC_MSG_RESULT(disabled)
    @@ -612,7 +612,7 @@ if test "$login" != no; then
       if test "$enable_static" = yes; then
         SASL_STATIC_SRCS="$SASL_STATIC_SRCS \$(top_srcdir)/plugins/login.c"
         SASL_STATIC_OBJS="$SASL_STATIC_OBJS login.o"
    -    AC_DEFINE(STATIC_LOGIN,[],[Link LOGIN Staticly])
    +    AC_DEFINE(STATIC_LOGIN,[],[Link LOGIN Statically])
       fi
     else
       AC_MSG_RESULT(disabled)
    @@ -638,7 +638,7 @@ if test "$ntlm" != no; then
       if test "$enable_static" = yes; then
         SASL_STATIC_SRCS="$SASL_STATIC_SRCS \$(top_srcdir)/plugins/ntlm.c"
         SASL_STATIC_OBJS="$SASL_STATIC_OBJS ntlm.o"
    -    AC_DEFINE(STATIC_NTLM,[],[Link NTLM Staticly])
    +    AC_DEFINE(STATIC_NTLM,[],[Link NTLM Statically])
       fi
     else
       AC_MSG_RESULT(disabled)
    @@ -664,7 +664,7 @@ if test "$passdss" != no; then
       if test "$enable_static" = yes; then
         SASL_STATIC_OBJS="$SASL_STATIC_OBJS passdss.o"
         SASL_STATIC_SRCS="$SASL_STATIC_SRCS \$(top_srcdir)/plugins/passdss.c"
    -    AC_DEFINE(STATIC_PASSDSS,[],[Link PASSDSS Staticly])
    +    AC_DEFINE(STATIC_PASSDSS,[],[Link PASSDSS Statically])
       fi
     else
       AC_MSG_RESULT(disabled)
    @@ -695,7 +695,7 @@ if test "$sql" != no; then
       if test "$enable_static" = yes; then
         SASL_STATIC_SRCS="$SASL_STATIC_SRCS \$(top_srcdir)/plugins/sql.c"
         SASL_STATIC_OBJS="$SASL_STATIC_OBJS sql.o"
    -    AC_DEFINE(STATIC_SQL,[],[Link SQL plugin staticly])
    +    AC_DEFINE(STATIC_SQL,[],[Link SQL plugin statically])
       fi
     else
       AC_MSG_RESULT(disabled)
    @@ -987,7 +987,7 @@ if test "$ldapdb" != no; then
                 if test "$enable_static" = yes; then
                     SASL_STATIC_SRCS="$SASL_STATIC_SRCS \$(top_srcdir)/plugins/ldapdb.c"
                     SASL_STATIC_OBJS="$SASL_STATIC_OBJS ldapdb.o"
    -                AC_DEFINE(STATIC_LDAPDB,[],[Link ldapdb plugin Staticly])
    +                AC_DEFINE(STATIC_LDAPDB,[],[Link ldapdb plugin Statically])
                 fi
             fi
         fi
    
    From e5f679e80edb224793e4ee8331c3332114a621f5 Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Fri, 1 Jun 2012 18:21:49 +0100
    Subject: [PATCH 152/796] Updated the Cyrus SASL Bugzilla URL, removed a CVS
     revision tag
    
    ---
     README | 4 +---
     1 file changed, 1 insertion(+), 3 deletions(-)
    
    diff --git a/README b/README
    index 597cff61..b55280e0 100644
    --- a/README
    +++ b/README
    @@ -1,5 +1,3 @@
    -$Id: README,v 1.33 2008/01/25 01:57:40 murch Exp $
    -
     This is the Cyrus SASL API implentation. It can be used on the client
     or server side to provide authentication and authorization services.
     See RFC 4422 for more information.
    @@ -16,7 +14,7 @@ http://asg.web.cmu.edu/archive/mailbox.php3?mailbox=archive.cyrus-sasl.
     If you are looking to port SASLv1 applications to SASLv2, please see
     doc/appconvert.html
     
    -Bugs can be searched/reported at: http://bugzilla.andrew.cmu.edu
    +Bugs can be searched/reported at: http://bugzilla.cyrussasl.org
     
     DOCUMENTATION
     --------------
    
    From 7a964aefe4cdbe8aae7a0e2a81d7a6659fba616a Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Sat, 2 Jun 2012 20:40:15 +0100
    Subject: [PATCH 153/796] Improved error logging on failure to load plugins
    
    Patch by Greg A. Woods.
    ---
     lib/canonusr.c | 5 +++--
     lib/client.c   | 4 ++--
     lib/server.c   | 6 ++++--
     3 files changed, 9 insertions(+), 6 deletions(-)
    
    diff --git a/lib/canonusr.c b/lib/canonusr.c
    index ccbda6b5..0049d136 100644
    --- a/lib/canonusr.c
    +++ b/lib/canonusr.c
    @@ -316,14 +316,15 @@ int sasl_canonuser_add_plugin(const char *plugname,
     			   &out_version, &plug, plugname);
     
         if(result != SASL_OK) {
    -	_sasl_log(NULL, SASL_LOG_ERR, "canonuserfunc error %i\n",result);
    +	_sasl_log(NULL, SASL_LOG_ERR, "%s_canonuser_plug_init() failed in sasl_canonuser_add_plugin(): %z\n",
    +		  plugname, result);
     	return result;
         }
     
         if(!plug->canon_user_server && !plug->canon_user_client) {
     	/* We need at least one of these implemented */
     	_sasl_log(NULL, SASL_LOG_ERR,
    -		  "canonuser plugin without either client or server side");
    +		  "canonuser plugin '%s' without either client or server side", plugname);
     	return SASL_BADPROT;
         }
         
    diff --git a/lib/client.c b/lib/client.c
    index 44ccb667..dc76afff 100644
    --- a/lib/client.c
    +++ b/lib/client.c
    @@ -195,8 +195,8 @@ int sasl_client_add_plugin(const char *plugname,
         if (result != SASL_OK)
         {
     	_sasl_log(NULL, SASL_LOG_WARN,
    -	      "entry_point failed in sasl_client_add_plugin for %s",
    -	      plugname);
    +		  "sasl_client_add_plugin(): entry_point(): failed for plugname %s: %z",
    +		  plugname, result);
     	return result;
         }
     
    diff --git a/lib/server.c b/lib/server.c
    index 4b89b39a..490b6521 100644
    --- a/lib/server.c
    +++ b/lib/server.c
    @@ -440,7 +440,8 @@ int sasl_server_add_plugin(const char *plugname,
         if ((result != SASL_OK) && (result != SASL_NOUSER)
             && (result != SASL_CONTINUE)) {
     	_sasl_log(NULL, SASL_LOG_DEBUG,
    -		  "server add_plugin entry_point error %z\n", result);
    +		  "%s_client_plug_init() failed in sasl_server_add_plugin(): %z\n",
    +		  plugname, result);
     	return result;
         }
     
    @@ -449,7 +450,8 @@ int sasl_server_add_plugin(const char *plugname,
         {
     	_sasl_log(NULL,
     		  SASL_LOG_ERR,
    -		  "version mismatch on plugin: %d expected, but %d reported",
    +		  "version mismatch on  sasl_server_add_plugin for '%s': %d expected, but %d reported",
    +		  plugname,
     		  SASL_SERVER_PLUG_VERSION,
     		  version);
     	return SASL_BADVERS;
    
    From af21b5b787219dd50256652e0fd7966f1b058a7e Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Sat, 2 Jun 2012 21:12:02 +0100
    Subject: [PATCH 154/796] Corrected a variable type, improved comments in the
     client side mechanism selection code
    
    Based on a patch by Greg A. Woods.
    ---
     lib/client.c | 11 +++++++----
     1 file changed, 7 insertions(+), 4 deletions(-)
    
    diff --git a/lib/client.c b/lib/client.c
    index dc76afff..62dfb0bf 100644
    --- a/lib/client.c
    +++ b/lib/client.c
    @@ -752,7 +752,8 @@ int sasl_client_start(sasl_conn_t *conn,
     
     	/* for each mechanism in client's list */
     	for (m = c_conn->mech_list; m != NULL; m = m->next) {
    -	    int myflags, plus;
    +	    unsigned myflags;
    +	    int plus;
     
     	    if (!_sasl_is_equal_mech(name, m->m.plug->mech_name, name_len, &plus)) {
     		continue;
    @@ -766,15 +767,17 @@ int sasl_client_start(sasl_conn_t *conn,
     	    if (minssf > m->m.plug->max_ssf)
     		break;
     
    -	    /* Does it meet our security properties? */
     	    myflags = conn->props.security_flags;
    -	    
    -	    /* if there's an external layer this is no longer plaintext */
    +
    +	    /* if there's an external layer with a better SSF then this is no
    +	     * longer considered a plaintext mechanism
    +	     */
     	    if ((conn->props.min_ssf <= conn->external.ssf) && 
     		(conn->external.ssf > 1)) {
     		myflags &= ~SASL_SEC_NOPLAINTEXT;
     	    }
     
    +	    /* Does it meet our security properties? */
     	    if (((myflags ^ m->m.plug->security_flags) & myflags) != 0) {
     		break;
     	    }
    
    From e3c3d1c0f597a9792e288cf799646183b477e8d2 Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Sat, 2 Jun 2012 15:55:46 +0100
    Subject: [PATCH 155/796] Better error reporting from
     auth_getpwent.c/auth_shadow.c
    
    Cyrus SASL Bug # 3134
    
    Patch by Greg A. Woods with some additional fixes.
    ---
     saslauthd/auth_getpwent.c | 33 ++++++++++++++++--
     saslauthd/auth_shadow.c   | 72 +++++++++++++++++++++++++++------------
     saslauthd/configure.in    |  6 +++-
     saslauthd/utils.c         | 45 ++++++++++++++++++++++++
     4 files changed, 132 insertions(+), 24 deletions(-)
    
    diff --git a/saslauthd/auth_getpwent.c b/saslauthd/auth_getpwent.c
    index 78a865b9..fc8029d7 100644
    --- a/saslauthd/auth_getpwent.c
    +++ b/saslauthd/auth_getpwent.c
    @@ -40,6 +40,8 @@
     #include 
     #include 
     #include 
    +#include 
    +#include 
     
     #ifdef HAVE_CRYPT_H
     #include 
    @@ -55,6 +57,8 @@
     #   include 
     #  endif /* WITH_SSL_DES */
     # endif /* WITH_DES */
    +
    +# include "globals.h"
     /* END PUBLIC DEPENDENCIES */
     
     #define RETURN(x) return strdup(x)
    @@ -73,19 +77,44 @@ auth_getpwent (
     {
         /* VARIABLES */
         struct passwd *pw;			/* pointer to passwd file entry */
    +    int errnum;
         /* END VARIABLES */
       
    +    errno = 0;
         pw = getpwnam(login);
    +    errnum = errno;
         endpwent();
     
         if (pw == NULL) {
    -	RETURN("NO");
    +	if (errnum != 0) {
    +	    char *errstr;
    +
    +	    if (flags & VERBOSE) {
    +		syslog(LOG_DEBUG, "DEBUG: auth_getpwent: getpwnam(%s) failure: %m", login);
    +	    }
    +	    if (asprintf(&errstr, "NO Username lookup failure: %s", strerror(errno)) == -1) {
    +		/* XXX the hidden strdup() will likely fail and return NULL here.... */
    +		RETURN("NO Username lookup failure: unknown error (ENOMEM formatting strerror())");
    +	    }
    +	    return errstr;
    +	} else {
    +	    if (flags & VERBOSE) {
    +		syslog(LOG_DEBUG, "DEBUG: auth_getpwent: getpwnam(%s): invalid username", login);
    +	    }
    +	    RETURN("NO Invalid username");
    +	}
         }
     
         if (strcmp(pw->pw_passwd, (const char *)crypt(password, pw->pw_passwd))) {
    -	RETURN("NO");
    +	if (flags & VERBOSE) {
    +	    syslog(LOG_DEBUG, "DEBUG: auth_getpwent: %s: invalid password", login);
    +	}
    +	RETURN("NO Incorrect password");
         }
     
    +    if (flags & VERBOSE) {
    +	syslog(LOG_DEBUG, "DEBUG: auth_getpwent: OK: %s", login);
    +    }
         RETURN("OK");
     }
     
    diff --git a/saslauthd/auth_shadow.c b/saslauthd/auth_shadow.c
    index 714e1481..677131b7 100644
    --- a/saslauthd/auth_shadow.c
    +++ b/saslauthd/auth_shadow.c
    @@ -44,6 +44,7 @@
     # include 
     # include 
     # include 
    +# include 
     # include 
     
     #ifdef HAVE_CRYPT_H
    @@ -60,7 +61,8 @@
     #  endif /* WITH_SSL_DES */
     # endif /* WITH_DES */
     
    -#endif /* ! HAVE_GETSPNAM */
    +# endif /* ! HAVE_GETSPNAM */
    +
     # ifdef HAVE_GETUSERPW
     #  include 
     #  include 
    @@ -109,6 +111,7 @@ auth_shadow (
         char *cpw;				/* pointer to crypt() result */
         struct passwd	*pw;		/* return from getpwnam_r() */
         struct spwd   	*sp;		/* return from getspnam_r() */
    +    int errnum;
     #  ifdef _REENTRANT
         struct passwd pwbuf;
         char pwdata[PWBUFSZ];		/* pwbuf indirect data goes in here */
    @@ -121,11 +124,10 @@ auth_shadow (
     #  define RETURN(x) return strdup(x)
     
         /*
    -     * "Magic" password field entries for SunOS.
    +     * "Magic" password field entries for SunOS/SysV
          *
    -     * *LK* is hinted at in the shadow(4) man page, but the
    -     * only definition for it (that I could find) is in the passmgmt(1M)
    -     * man page.
    +     * "*LK*" is defined at in the shadow(4) man page, but of course any string
    +     * inserted in front of the password will prevent the strings from matching
          *
          * *NP* is documented in getspnam(3) and indicates the caller had
          * insufficient permission to read the shadow password database
    @@ -144,12 +146,27 @@ auth_shadow (
     #  else
         pw = getpwnam(login);
     #  endif /* _REENTRANT */
    +    errnum = errno;
         endpwent();
    +
         if (pw == NULL) {
    -	if (flags & VERBOSE) {
    -	    syslog(LOG_DEBUG, "DEBUG: auth_shadow: getpwnam(%s) returned NULL", login);
    +	if (errnum != 0) {
    +	    char *errstr;
    +
    +	    if (flags & VERBOSE) {
    +		syslog(LOG_DEBUG, "DEBUG: auth_shadow: getpwnam(%s) failure: %m", login);
    +	    }
    +	    if (asprintf(&errstr, "NO Username lookup failure: %s", strerror(errno)) == -1) {
    +		/* XXX the hidden strdup() will likely fail and return NULL here.... */
    +		RETURN("NO Username lookup failure: unknown error (ENOMEM formatting strerror())");
    +	    }
    +	    return errstr;
    +	} else {
    +	    if (flags & VERBOSE) {
    +		syslog(LOG_DEBUG, "DEBUG: auth_shadow: getpwnam(%s): invalid username", login);
    +	    }
    +	    RETURN("NO Invalid username");
     	}
    -	RETURN("NO");
         }
     
         today = (long)time(NULL)/(24L*60*60);
    @@ -163,13 +180,27 @@ auth_shadow (
     #  else
         sp = getspnam(login);
     #  endif /* _REENTRANT */
    +    errnum = errno;
         endspent();
     
         if (sp == NULL) {
    -	if (flags & VERBOSE) {
    -	    syslog(LOG_DEBUG, "DEBUG: auth_shadow: getspnam(%s) returned NULL", login);
    +	if (errnum != 0) {
    +	    char *errstr;
    +
    +	    if (flags & VERBOSE) {
    +		syslog(LOG_DEBUG, "DEBUG: auth_shadow: getspnam(%s) failure: %m", login);
    +	    }
    +	    if (asprintf(&errstr, "NO Username shadow lookup failure: %s", strerror(errno)) == -1) {
    +		/* XXX the hidden strdup() will likely fail and return NULL here.... */
    +		RETURN("NO Username shadow lookup failure: unknown error (ENOMEM formatting strerror())");
    +	    }
    +	    return errstr;
    +	} else {
    +	    if (flags & VERBOSE) {
    +		syslog(LOG_DEBUG, "DEBUG: auth_shadow: getspnam(%s): invalid shadow username", login);
    +	    }
    +	    RETURN("NO Invalid shadow username");
     	}
    -	RETURN("NO");
         }
     
         if (!strcmp(sp->sp_pwdp, SHADOW_PW_EPERM)) {
    @@ -179,20 +210,19 @@ auth_shadow (
     	RETURN("NO Insufficient permission to access NIS authentication database (saslauthd)");
         }
     
    -    /*
    -     * Note: no check for SHADOW_PW_LOCKED. Returning a "locked" notification
    -     * would allow login-id namespace probes, and violates our policy of
    -     * not returning any information about a login until we have validated
    -     * the password.
    -     */
         cpw = strdup((const char *)crypt(password, sp->sp_pwdp));
         if (strcmp(sp->sp_pwdp, cpw)) {
     	if (flags & VERBOSE) {
    +	    /*
    +	     * This _should_ reveal the SHADOW_PW_LOCKED prefix to an
    +	     * administrator trying to debug the situation, though maybe we
    +	     * should do the check here and be less obtuse about it....
    +	     */
     	    syslog(LOG_DEBUG, "DEBUG: auth_shadow: pw mismatch: '%s' != '%s'",
     		   sp->sp_pwdp, cpw);
     	}
     	free(cpw);
    -	RETURN("NO");
    +	RETURN("NO Incorrect password");
         }
         free(cpw);
     
    @@ -250,10 +280,10 @@ auth_shadow (
       
         if (upw == 0) {
     	if (flags & VERBOSE) {
    -	    syslog(LOG_DEBUG, "auth_shadow: getuserpw(%s) == 0",
    +	    syslog(LOG_DEBUG, "auth_shadow: getuserpw(%s) failed: %m",
     		   login);
     	}
    -	RETURN("NO");
    +	RETURN("NO Invalid username");
         }
       
         if (strcmp(upw->upw_passwd, crypt(password, upw->upw_passwd)) != 0) {
    @@ -261,7 +291,7 @@ auth_shadow (
     	    syslog(LOG_DEBUG, "auth_shadow: pw mismatch: %s != %s",
     		   password, upw->upw_passwd);
     	}
    -	RETURN("NO");
    +	RETURN("NO Incorrect password");
         }
     
         RETURN("OK");
    diff --git a/saslauthd/configure.in b/saslauthd/configure.in
    index f79d65d7..59d269db 100644
    --- a/saslauthd/configure.in
    +++ b/saslauthd/configure.in
    @@ -195,8 +195,9 @@ fi
     dnl Checks for library functions.
     AC_TYPE_SIGNAL
     AC_CHECK_FUNCS(gethostname mkdir socket strdup)
    +dnl Only look for one or the other
     AC_CHECK_FUNCS(getspnam getuserpw, break)
    -AC_CHECK_FUNCS(strlcat strlcpy)
    +AC_CHECK_FUNCS(asprintf strlcat strlcpy)
     
     if test $ac_cv_func_getspnam = yes; then
     	AC_MSG_CHECKING(if getpwnam_r/getspnam_r take 5 arguments)
    @@ -327,6 +328,9 @@ extern size_t saslauthd_strlcpy(char *dst, const char *src, size_t len);
     extern size_t saslauthd_strlcat(char *dst, const char *src, size_t len);
     #define strlcat(x,y,z) saslauthd_strlcat((x),(y),(z))
     #endif
    +#ifndef HAVE_ASPRINTF
    +extern int asprintf(char **str, const char *fmt, ...);
    +#endif
     
     #endif
     ])
    diff --git a/saslauthd/utils.c b/saslauthd/utils.c
    index df7162f3..bddbd15d 100644
    --- a/saslauthd/utils.c
    +++ b/saslauthd/utils.c
    @@ -227,6 +227,51 @@ int retry_writev(int fd, struct iovec *iov, int iovcnt) {
     	}
     }
     
    +#ifndef HAVE_ASPRINTF
    +
    +# include 
    +
    +/*
    + * asprintf -- work around lame systems that haven't added their own yet
    + *
    + * XXX relies on a valid working (SuSv3) vsnprintf(), OK on SunOS-5.10 BUT NOT BEFORE!
    + */
    +int
    +asprintf(char **str,
    +	 const char *fmt,
    +	 ...)
    +{
    +	va_list ap;
    +	char *newstr;
    +	size_t len;
    +	int ret;
    +
    +	*str = NULL;
    +
    +	va_start(ap, fmt);
    +	ret = vsnprintf((char *) NULL, (size_t) 0, fmt, ap);
    +	va_end(ap);
    +	if (ret < 0) {
    +		return ret;
    +	}
    +	len = (size_t) ret + 1;		/* allow for nul */
    +	if ((newstr = malloc(len)) == NULL) {
    +		return (-1);
    +	}
    +	va_start(ap, fmt);
    +	ret = vsnprintf(newstr, len, fmt, ap);
    +	va_end(ap);
    +	if (ret >= 0 && (size_t) ret < len) { /* XXX (ret == len-1) */
    +		*str = newstr;
    +	} else {
    +		free(newstr);
    +		return ret;
    +	}
    +
    +	return ret;
    +}
    +#endif /* HAVE_ASPRINTF */
    +
     #ifndef HAVE_STRLCPY
     /* strlcpy -- copy string smartly.
      *
    
    From 69495a26cacc2b7fde398ce4b3a5904b34f52888 Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Sun, 3 Jun 2012 22:18:50 +0100
    Subject: [PATCH 156/796] Updated libtool version for libsasl and its plugins
     due to ABI change
    
    Cyrus SASL Bug # 3692
    ---
     lib/Makefile.am     | 4 +++-
     plugins/Makefile.am | 3 ++-
     2 files changed, 5 insertions(+), 2 deletions(-)
    
    diff --git a/lib/Makefile.am b/lib/Makefile.am
    index 3beccf02..b8964a87 100644
    --- a/lib/Makefile.am
    +++ b/lib/Makefile.am
    @@ -41,7 +41,9 @@
     #
     
     # Library version info - here at the top, for sanity
    -sasl_version = 2:25:0
    +# See 
    +# CURRENT:REVISION:AGE
    +sasl_version = 3:0:0
     
     INCLUDES=-DLIBSASL_EXPORTS=1 -I$(top_srcdir)/include -I$(top_srcdir)/plugins -I$(top_builddir)/include -I$(top_srcdir)/sasldb
     
    diff --git a/plugins/Makefile.am b/plugins/Makefile.am
    index b00915fc..550098d5 100644
    --- a/plugins/Makefile.am
    +++ b/plugins/Makefile.am
    @@ -45,8 +45,9 @@
     ################################################################
     
     # Library version info - here at the top, for sanity
    +# See 
     # CURRENT:REVISION:AGE
    -plugin_version = 2:25:0
    +sasl_version = 3:0:0
     
     INCLUDES=-I$(top_srcdir)/include -I$(top_srcdir)/lib -I$(top_srcdir)/sasldb -I$(top_builddir)/include
     AM_LDFLAGS = -module -export-dynamic -rpath $(plugindir) -version-info $(plugin_version)
    
    From 2e37a9681c542cc1ca3c01953158f5c4c8459f70 Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Fri, 8 Jun 2012 19:25:11 +0100
    Subject: [PATCH 157/796] Added generation of pkg-config .pc file for Cyrus
     SASL
    
    This installs a file $(libdir)/pkgconfig/libsasl2.pc, which programs
    using Cyrus SASL can use to link with the library and to detect at
    ./configure time the installed version.
    
    Patch by Dilyan Palauzov.
    ---
     Makefile.am    | 6 +++++-
     configure.in   | 1 +
     libsasl2.pc.in | 7 +++++++
     3 files changed, 13 insertions(+), 1 deletion(-)
     create mode 100644 libsasl2.pc.in
    
    diff --git a/Makefile.am b/Makefile.am
    index b35164e7..2091dd10 100644
    --- a/Makefile.am
    +++ b/Makefile.am
    @@ -70,7 +70,11 @@ INSTALLOSX =
     endif
     
     SUBDIRS=include sasldb lib plugins utils doc man $(PWC) $(SAM) $(JAV) $(SAD)
    -EXTRA_DIST=config cmulocal win32 mac dlcompat-20010505 NTMakefile INSTALL.TXT
    +EXTRA_DIST=config cmulocal win32 mac dlcompat-20010505 NTMakefile INSTALL.TXT \
    +    libsasl2.pc.in
    +
    +pkgconfigdir = $(libdir)/pkgconfig
    +pkgconfig_DATA = libsasl2.pc
     
     dist-hook:
     	@find $(distdir) -exec chmod o+w {} ';'
    diff --git a/configure.in b/configure.in
    index af00a448..445a74cb 100644
    --- a/configure.in
    +++ b/configure.in
    @@ -1415,6 +1415,7 @@ inline static unsigned int sleep(unsigned int seconds) {
     AM_CONFIG_HEADER(config.h)
     
     AC_OUTPUT(Makefile
    +libsasl2.pc
     include/Makefile
     sasldb/Makefile
     plugins/Makefile
    diff --git a/libsasl2.pc.in b/libsasl2.pc.in
    new file mode 100644
    index 00000000..dbb4f248
    --- /dev/null
    +++ b/libsasl2.pc.in
    @@ -0,0 +1,7 @@
    +libdir = @libdir@
    +
    +Name: Cyrus SASL
    +Description: Cyrus SASL implementation
    +URL: http://www.cyrussasl.org/
    +Version: @VERSION@
    +Libs: -L${libdir} -lsasl2
    
    From d1b57852247641be30decc480b0719d322f0bc5c Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Thu, 19 Apr 2012 14:41:12 +0100
    Subject: [PATCH 158/796] Fixed PLAIN/LOGIN authentication failure when using
     saslauthd with no auxprop plugins
    
    PLAIN/LOGIN plugins should be able to work with no auxprop plugins configured,
    for example if they are using saslauthd. This patch fixes them to work
    in such configurations. In order to achieve this the following changes were
    made
    
     1) SASL_NOMECH should be handled the same way as SASL_NOUSER while looking
        up auxprop properties.
     2) SASL PLAIN/LOGIN should pass "this identity was verified externally"
        to auxprop lookup. This will prevent auxprop lookup from failing with
        SASL_NOMECH. Note that they verify user accounts using checkpass interface
        anyway.
    
    Cyrus SASL Bug # 3590
    
    Test-information:
     The following SASL plugins were tested:
      PLAIN, EXTERNAL, SCRAM-SHA-1, LOGIN (partially)
     They were tested with missing auxprop plugins and with a present one.
    ---
     include/sasl.h  | 4 +++-
     lib/canonusr.c  | 8 +++++---
     plugins/login.c | 6 ++++--
     plugins/plain.c | 2 +-
     4 files changed, 13 insertions(+), 7 deletions(-)
    
    diff --git a/include/sasl.h b/include/sasl.h
    index 2ac53003..ed271041 100755
    --- a/include/sasl.h
    +++ b/include/sasl.h
    @@ -633,8 +633,10 @@ typedef int sasl_server_userdb_setpass_t(sasl_conn_t *conn,
     /* One of the following two is required */
     #define SASL_CU_AUTHID  0x01
     #define SASL_CU_AUTHZID 0x02
    +
     /* Combine the following with SASL_CU_AUTHID, if you don't want
    -   to fail if auxprop returned SASL_NOUSER */
    +   to fail if auxprop returned SASL_NOUSER/SASL_NOMECH.
    +   This flag has no effect on SASL_CU_AUTHZID. */
     #define SASL_CU_EXTERNALLY_VERIFIED 0x04
     
     #define SASL_CU_OVERRIDE	    0x08    /* mapped to SASL_AUXPROP_OVERRIDE */
    diff --git a/lib/canonusr.c b/lib/canonusr.c
    index 0049d136..faee1038 100644
    --- a/lib/canonusr.c
    +++ b/lib/canonusr.c
    @@ -241,12 +241,14 @@ static int _sasl_auxprop_lookup_user_props (sasl_conn_t *conn,
     	    }
     	}
     
    -	if (result == SASL_NOUSER && (flags & SASL_CU_EXTERNALLY_VERIFIED)) {
    +	if ((flags & SASL_CU_EXTERNALLY_VERIFIED) && (result == SASL_NOUSER || result == SASL_NOMECH)) {
     	    /* The called has explicitly told us that the authentication identity
    -	       was already verified. So a failure to retrieve any associated properties
    +	       was already verified or will be verified independently.
    +	       So a failure to retrieve any associated properties
     	       is not an error. For example the caller is using Kerberos to verify user,
     	       but the LDAPDB/SASLDB auxprop plugin doesn't contain any auxprops for
    -	       the user. */
    +	       the user.
    +	       Another case is PLAIN/LOGIN not using auxprop to verify user passwords. */
     	    result = SASL_OK;
     	}	
         }
    diff --git a/plugins/login.c b/plugins/login.c
    index ee44be64..f2a05ac5 100644
    --- a/plugins/login.c
    +++ b/plugins/login.c
    @@ -179,9 +179,11 @@ static int login_server_mech_step(void *conn_context,
     
     	/* canonicalize username first, so that password verification is
     	 * done against the canonical id */
    -	result = params->canon_user(params->utils->conn, text->username,
    +	result = params->canon_user(params->utils->conn,
    +				    text->username,
     				    text->username_len,
    -				    SASL_CU_AUTHID | SASL_CU_AUTHZID, oparams);
    +				    SASL_CU_AUTHID | SASL_CU_AUTHZID | SASL_CU_EXTERNALLY_VERIFIED,
    +				    oparams);
     	if (result != SASL_OK) return result;
     	
     	/* verify_password - return sasl_ok on success */
    diff --git a/plugins/plain.c b/plugins/plain.c
    index ddbc1f89..e6180a1c 100644
    --- a/plugins/plain.c
    +++ b/plugins/plain.c
    @@ -159,7 +159,7 @@ static int plain_server_mech_step(void *conn_context __attribute__((unused)),
         result = params->canon_user(params->utils->conn,
     				authen,
     				0,
    -				SASL_CU_AUTHID | canon_flags,
    +				SASL_CU_AUTHID | canon_flags | SASL_CU_EXTERNALLY_VERIFIED,
     				oparams);
         if (result != SASL_OK) {
     	_plug_free_string(params->utils, &passcopy);
    
    From 4dec5426bba32ba21c11052bd1303e7c6868893c Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Sun, 10 Jun 2012 12:20:44 +0100
    Subject: [PATCH 159/796] Correctly fix the libtool version
    
    An earlier fix contained a cut & paste error. This should fix it properly.
    
    Cyrus SASL Bug # 3692
    Cyrus SASL Bug # 3704
    ---
     plugins/Makefile.am | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/plugins/Makefile.am b/plugins/Makefile.am
    index 550098d5..d570de1c 100644
    --- a/plugins/Makefile.am
    +++ b/plugins/Makefile.am
    @@ -47,7 +47,7 @@
     # Library version info - here at the top, for sanity
     # See 
     # CURRENT:REVISION:AGE
    -sasl_version = 3:0:0
    +plugin_version = 3:0:0
     
     INCLUDES=-I$(top_srcdir)/include -I$(top_srcdir)/lib -I$(top_srcdir)/sasldb -I$(top_builddir)/include
     AM_LDFLAGS = -module -export-dynamic -rpath $(plugindir) -version-info $(plugin_version)
    
    From a07afc4d4f263db1f938bc08a0a3504a85242a9c Mon Sep 17 00:00:00 2001
    From: Alexey Melnikov 
    Date: Fri, 15 Jun 2012 14:54:52 +0100
    Subject: [PATCH 160/796] Updated to reference GIT instead of CVS in
     documentation
    
    ---
     doc/install.html | 2 +-
     doc/macosx.html  | 4 ++--
     doc/windows.html | 6 +++---
     3 files changed, 6 insertions(+), 6 deletions(-)
    
    diff --git a/doc/install.html b/doc/install.html
    index 65c0f90f..fe99995e 100644
    --- a/doc/install.html
    +++ b/doc/install.html
    @@ -18,7 +18,7 @@ 

    Quick and Dirty

    ln -s /usr/local/lib/sasl2 /usr/lib/sasl2
    -

    If you're checking this directly out of CVS, you'll need to run "sh +

    If you're checking this directly out of GIT, you'll need to run "sh ./SMakefile" to build the configure script first.

    Read the System Administrator's Guide to diff --git a/doc/macosx.html b/doc/macosx.html index 6d87046d..07714ee4 100644 --- a/doc/macosx.html +++ b/doc/macosx.html @@ -71,7 +71,7 @@

    Compiling and Using the Unix library

    As of version 2.1.16, SASL uses and requires a recent version of GNU autotools (autoconf, automake, and libtool) to build its configuration scripts. -If you are building from CVS, you will need to have the autotools installed +If you are building from GIT, you will need to have the autotools installed on your system. The version included with all releases of the developer tools for OS X 10.2.x is too old for this; if you aren't using OS X 10.3 or later, you should upgrade to more recent patchlevels of these tools. The easiest way @@ -135,7 +135,7 @@

    Changes to the Mac OS 9 projects to support Carbon

  • Important! You must make sure that all files have their correct HFS filetype before starting to build this code! In particular, all source and text files must be of type 'TEXT', -which is not the default if you use the Mac OS X cvs client to check +which is not the default if you use the Mac OS X GIT client to check out the projects. If you run into this problem, you may want to use a utility such as FileTyper to recursively change the type on all files. CodeWarrior is less picky about the projects' filetypes, but diff --git a/doc/windows.html b/doc/windows.html index 48788c45..738bf431 100755 --- a/doc/windows.html +++ b/doc/windows.html @@ -23,7 +23,7 @@

    Prerequisites

  • SleepyCat include files and libraries are required to buil SASLDB plugin, saslpasswd2.exe and sasldblistusers2.exe. We have tested SleepyCat 4.1.X-4.4.X. -
  • If you are building directly from CVS, you'll need the If you are building directly from GIT, you'll need the Cygwin Unix-compatibility environment to create the _init.c files needed for dynamic loading. Cygwin is not required for building from our tar @@ -33,10 +33,10 @@

    Prerequisites

    Step by step

    -These directions assume that you've untarred the library or used CVS +These directions assume that you've untarred the library or used GIT and the sources are in C:\SASL. -

    preparing to build (cvs only!)

    +

    preparing to build (GIT only!)

    Start a cygwin shell and create the dynamic loading stubs: From 4cf19c9b33e70150a12d7c91609ca1ef09911012 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Fri, 22 Jun 2012 11:25:13 +0100 Subject: [PATCH 161/796] Added Libs.private to libsasl2.pc.in The value of Libs.private is used when linking statically with libsasl2.a. In this case -ldoos / -ldl would be added as linker flags, if configure determines so. The patch from Dilyan Palauzov. --- libsasl2.pc.in | 1 + 1 file changed, 1 insertion(+) diff --git a/libsasl2.pc.in b/libsasl2.pc.in index dbb4f248..40bea37c 100644 --- a/libsasl2.pc.in +++ b/libsasl2.pc.in @@ -5,3 +5,4 @@ Description: Cyrus SASL implementation URL: http://www.cyrussasl.org/ Version: @VERSION@ Libs: -L${libdir} -lsasl2 +Libs.private: @LIB_DOOR@ @SASL_DL_LIB@ @LIBS@ From e0f53705ecc739190990c5ad7190d6c6ac447649 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Tue, 3 Jul 2012 17:00:11 +0100 Subject: [PATCH 162/796] Fixed incorrect Darwin version matching in ltconfig In config/ltconfig and saslauthd/config/ltconfig, there's a switch with two cases for different darwin versions. The first one is pretty clearly meant to match old versions, i.e. rhapsody, darwin 1.x, and darwin 5.x; while the second case is meant to match all later versions. However, the first case also matches later darwin version that begin with 1, such as 10 and 11. The patch fixes this problem. Bugzilla # 3713 Patch by Joshua Root --- config/ltconfig | 2 +- saslauthd/config/ltconfig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/ltconfig b/config/ltconfig index a91118e9..e9ca47cd 100755 --- a/config/ltconfig +++ b/config/ltconfig @@ -1372,7 +1372,7 @@ else hardcode_shlibpath_var=no ;; - darwin[15]* | rhapsody*) + darwin[15].* | rhapsody*) allow_undefined_flag='-undefined error' archive_cmds='$CC $(test x$module = xyes && echo -bundle || echo -dynamiclib) $allow_undefined_flag -o $lib $libobjs $deplibs $linkopts $(test x$module != xyes && echo -install_name $rpath/$soname) $(test -n "$verstring" -a x$verstring != x0.0 && echo $verstring)' # We need to add '_' to the symbols in $export_symbols first diff --git a/saslauthd/config/ltconfig b/saslauthd/config/ltconfig index ba8bb1cd..888addc0 100755 --- a/saslauthd/config/ltconfig +++ b/saslauthd/config/ltconfig @@ -1372,7 +1372,7 @@ else hardcode_shlibpath_var=no ;; - darwin[15]* | rhapsody*) + darwin[15].* | rhapsody*) allow_undefined_flag='-undefined error' archive_cmds='$CC $(test x$module = xyes && echo -bundle || echo -dynamiclib) $allow_undefined_flag -o $lib $libobjs $deplibs $linkopts $(test x$module != xyes && echo -install_name $rpath/$soname) $(test -n "$verstring" -a x$verstring != x0.0 && echo $verstring)' # We need to add '_' to the symbols in $export_symbols first From 5cc32707b800c11a70df4f9ee014733359ea57db Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Thu, 5 Jul 2012 11:49:33 +0100 Subject: [PATCH 163/796] Fixed a memory leak in the client side DIGEST-MD5 code Cyrus SASL bug # 3716 Patch by michele@acksyn.org --- plugins/digestmd5.c | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/digestmd5.c b/plugins/digestmd5.c index 2f7276a2..4ab90dd2 100644 --- a/plugins/digestmd5.c +++ b/plugins/digestmd5.c @@ -3464,6 +3464,7 @@ static int make_client_response(context_t *text, resplen = 0; + if (text->out_buf) params->utils->free(text->out_buf); text->out_buf = NULL; text->out_buf_len = 0; if (add_to_challenge(params->utils, From cd4c0f70e1980f3cea439195bb6e01155755edf8 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Fri, 6 Jul 2012 12:08:00 +0100 Subject: [PATCH 164/796] Fixed a crash in the auth_krb5.c The buffer pointed to by "packet" won't be initialized if k5_retcode is not zero, so we shouldn't try to free it. Cyrus SASL Bug # 2706 Patch by Nalin Dahyabhai --- saslauthd/auth_krb5.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/saslauthd/auth_krb5.c b/saslauthd/auth_krb5.c index 8af42487..0648a291 100644 --- a/saslauthd/auth_krb5.c +++ b/saslauthd/auth_krb5.c @@ -338,7 +338,9 @@ static int k5support_verify_tgt(krb5_context context, /* all is good now */ result = 1; fini: - krb5_free_data_contents(context, &packet); + if (!k5_retcode) { + krb5_free_data_contents(context, &packet); + } krb5_free_principal(context, server); return result; From 74ebf6e58bbcc43a6c8719485c7121e2c16de6d7 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Thu, 20 Sep 2012 14:35:30 +0100 Subject: [PATCH 165/796] Updated some known email addresses for authors/contributors. Updated description of who did what. --- AUTHORS | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/AUTHORS b/AUTHORS index 0e472065..437a27e3 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,8 +1,9 @@ Rob Siemborski wrote and tested the conversion to the SASLv2 API. -Ken Murchison worked on the OTP, NTLM, SRP and SQL -plugins, as well as helping to track down bugs as they appear. +Ken Murchison worked on the OTP, NTLM, SRP and SQL +plugins, as well as helping to track down bugs as they appear. He also +added support for HTTP authentication. Rob Earhart wrote the build/installation procedure, wrote and tested some of the code, and provided general guidance and @@ -33,7 +34,7 @@ most of the SASLv1 code. Larry Greenfield complained. a lot. -Chris Newman wrote the initial version of the +Chris Newman wrote the initial version of the SASL API, as well as the version 2 SASL API (documented in sasl.h, saslutil.h, saslplug.h, and prop.h). From 37bf04b6f712645fd99d34d69d86a908e9781786 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Fri, 12 Oct 2012 10:09:15 +0100 Subject: [PATCH 166/796] Updated the release steps, partially due to migration to GIT. --- README.andrew | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.andrew b/README.andrew index 9da2a260..6591aad4 100644 --- a/README.andrew +++ b/README.andrew @@ -15,7 +15,7 @@ To release: - run testsuite successfully - compile successfully without kerberos or gssapi support - compile successfully on all andrew systypes -- increment version in configure.in +- increment version in configure.in and saslauthd/configure.in - synchronize version with include/sasl.h, win32/common.mak and win32/include/config.h - increment version in saslauthd/configure.in as needed @@ -24,7 +24,7 @@ To release: - add release notice to ChangeLog - add user visible changes to NEWS -- tag the CVS repository with sasl-Major_Minor_Revision +- tag the GIT repository with sasl-Major_Minor_Revision - check out the tag into a CLEAN repository - to make tarball: make distcheck (make sure you are on a machine that is not using GNU tar! Solaris tar seems to not get along with it well.) From 8c1a61580ced68194ba53f2bfcccf2af644393de Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Fri, 12 Oct 2012 11:11:12 +0100 Subject: [PATCH 167/796] Updated ChangeLog/NEWS as per recent 2.1.26 changes --- ChangeLog | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ NEWS | 39 +++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) diff --git a/ChangeLog b/ChangeLog index 42689e94..4b97e79c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,73 @@ +2012-10-12 Alexey Melnikov + * Getting ready for 2.1.25. + +2012-07-06 Alexey Melnikov + * saslauthd/auth_krb5.c: Fixed a crash in the auth_krb5.c + (bug # 2706). Patch by Nalin Dahyabhai. + +2012-07-03 Alexey Melnikov + * config/ltconfig: Fixed incorrect Darwin version matching in ltconfig + (bug # 3713). Patch by Joshua Root. + +2012-06-08 Alexey Melnikov + * Fixed PLAIN/LOGIN authentication failure when using saslauthd + with no auxprop plugins (bug # 3590). + +2012-06-08 Alexey Melnikov + * Added generation of pkg-config .pc file for Cyrus SASL. + Patch by Dilyan Palauzov. + +2012-06-03 Alexey Melnikov + * Correctly updated libtool version for libsasl and its plugins due + to ABI changes (bug # 3692). + +2012-06-02 Alexey Melnikov + * Better error reporting from auth_getpwent.c/auth_shadow.c + (bug # 3134). Based on a patch by Greg A. Woods. + +2012-06-02 Alexey Melnikov + * Improved error logging on failure to load plugins. + Patch by Greg A. Woods. + +2012-05-30 Alexey Melnikov + * plugins/otp.c, plugins/srp.c: Removed calling of EVP_cleanup() + on SRP/OTP plugin shutdown + +2012-05-30 Alexey Melnikov + * saslauthd/auth_httpform.c: Encode the parameter values passed to + auth_httpform, not the whole POST data. + +2012-05-30 Alexey Melnikov + * lib/config.c, saslauthd/cfile.c: Fixed file descriptor leaks + throughout the code (bug # 3702). Slightly reformatted patch + by Manfred Weichel. + +2012-05-29 Alexey Melnikov + * bug in "saslauthd -a rimap" - not reading the whole IMAP greeting + (bug # 3211). Patch from Lutz Mark (via Red Hat) + +2012-05-29 Alexey Melnikov + * Modernize SASL malloc/realloc callback prototypes + +2012-05-29 Alexey Melnikov + * lib/saslutil.c: Fixed broken logic in get_fqhostname() when + abort_if_no_fqdn is 0 (bug # 3589). Patch by baggins@pld-linux.org + +2012-05-28 Alexey Melnikov + * sasldb/db_berkeley.c, utils/dbconverter-2.c: Added support for + BerkleyDB 5.X or later (Patch by Howard Chu) + +2012-04-20 Alexey Melnikov + * lib/client.c, lib/server.c, lib/saslint.h: Make server and client + side global callbacks private to server.c/client.c respectively + +2012-02-10 Ken Murchison + * plugins/digestmd5.c: better handling of HTTP reauth cases. + +2012-01-28 Ken Murchison + * plugins/digestmd5.c: Correctly send "stale" directive to prevent + clients from (re)promtping for password + 2011-11-25 Alexey Melnikov * plugins/gs2.c: Updated GS2 plugin not to lose minor GSS-API status codes on errors (based on a patch from Ralf Haferkamp diff --git a/NEWS b/NEWS index b4eb0395..b9add573 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,42 @@ +New in 2.1.26 +------------- + +* Modernize SASL malloc/realloc callback prototypes +* Added sasl_config_done() to plug a memory leak when using an application + specific config file +* Fixed PLAIN/LOGIN authentication failure when using saslauthd + with no auxprop plugins (bug # 3590). +* unlock the mutex in sasl_dispose if the context was freed by another thread +* MINGW32 compatibility patches +* Fixed broken logic in get_fqhostname() when abort_if_no_fqdn is 0 +* Fixed some memory leaks in libsasl +* GSSAPI plugin: + - Fixed a segfault in gssapi.c introduced in 2.1.25. + - Code refactoring + - Added support for GSS-SPNEGO SASL mechanism (Unix only), which is also + HTTP capable +* GS2 plugin: + - Updated GS2 plugin not to lose minor GSS-API status codes on errors +* DIGEST-MD5 plugin: + - Correctly send "stale" directive to prevent clients from (re)promtping + for password + - Better handling of HTTP reauthentication cases + - fixed some memory leaks +* SASLDB plugin: + - Added support for BerkleyDB 5.X or later +* OTP plugin: + - Removed calling of EVP_cleanup() on plugin shutdown in order to prevent + TLS from failing in calling applications +* SRP plugin: + - Removed calling of EVP_cleanup() on plugin shutdown in order to prevent + TLS from failing in calling applications +* saslauthd: + - auth_rimap.c: qstring incorrectly appending the closing double quote, + which might be causing crashes + - auth_rimap.c: read the whole IMAP greeting + - better error reporting from some drivers + - fixed some memory leaks + New in 2.1.25 ------------- From 5c7a3af1cbe8818f401a6ad5daf6aae99044c62a Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Tue, 18 Sep 2012 08:46:20 +0100 Subject: [PATCH 168/796] Updated version numbers in preparation for 2.1.26 --- configure.in | 2 +- include/sasl.h | 2 +- saslauthd/configure.in | 2 +- win32/common.mak | 2 +- win32/include/config.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/configure.in b/configure.in index 445a74cb..465a3625 100644 --- a/configure.in +++ b/configure.in @@ -59,7 +59,7 @@ dnl dnl REMINDER: When changing the version number here, please also update dnl the values in win32/include/config.h and include/sasl.h as well. dnl -AM_INIT_AUTOMAKE(cyrus-sasl, 2.1.25) +AM_INIT_AUTOMAKE(cyrus-sasl, 2.1.26) CMU_INIT_AUTOMAKE # and include our config dir scripts diff --git a/include/sasl.h b/include/sasl.h index ed271041..fef4d510 100755 --- a/include/sasl.h +++ b/include/sasl.h @@ -124,7 +124,7 @@ /* Keep in sync with win32/common.mak */ #define SASL_VERSION_MAJOR 2 #define SASL_VERSION_MINOR 1 -#define SASL_VERSION_STEP 25 +#define SASL_VERSION_STEP 26 /* A convenience macro: same as was defined in the OpenLDAP LDAPDB */ #define SASL_VERSION_FULL ((SASL_VERSION_MAJOR << 16) |\ diff --git a/saslauthd/configure.in b/saslauthd/configure.in index 59d269db..0addcf41 100644 --- a/saslauthd/configure.in +++ b/saslauthd/configure.in @@ -15,7 +15,7 @@ AC_ARG_WITH(saslauthd, [ --with-saslauthd=DIR enable use of the saslauth dae AC_DEFINE_UNQUOTED(PATH_SASLAUTHD_RUNDIR, "$with_saslauthd",[Location of saslauthd socket]) AM_CONDITIONAL(SASLAUTHD, test "$with_saslauthd" != no) -AM_INIT_AUTOMAKE(saslauthd,2.1.25) +AM_INIT_AUTOMAKE(saslauthd,2.1.26) CMU_INIT_AUTOMAKE dnl Checks for programs. diff --git a/win32/common.mak b/win32/common.mak index ac30f2fd..c2a9338b 100644 --- a/win32/common.mak +++ b/win32/common.mak @@ -2,7 +2,7 @@ #Keep in sync with include/sasl.h and win32/include/config.h SASL_VERSION_MAJOR=2 SASL_VERSION_MINOR=1 -SASL_VERSION_STEP=25 +SASL_VERSION_STEP=26 !IF "$(STATIC)" == "" STATIC=yes diff --git a/win32/include/config.h b/win32/include/config.h index 5c35c98b..0ad9628f 100644 --- a/win32/include/config.h +++ b/win32/include/config.h @@ -55,7 +55,7 @@ #define PACKAGE "cyrus-sasl" /* Our version */ -#define VERSION "2.1.25" +#define VERSION "2.1.26" /* Visual Studio supports prototypes */ #define PROTOTYPES 1 From 5c7bcb07494c9bdc143e91727e710923744c4332 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Fri, 12 Oct 2012 12:23:44 +0100 Subject: [PATCH 169/796] Updated copyright years in the Windows resource files --- lib/NTMakefile | 2 +- plugins/NTMakefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/NTMakefile b/lib/NTMakefile index 80dfd6d4..61412ba3 100755 --- a/lib/NTMakefile +++ b/lib/NTMakefile @@ -99,7 +99,7 @@ BEGIN VALUE "FileDescription", "CMU SASL API v2\0" VALUE "FileVersion", "$(SASL_VERSION_MAJOR).$(SASL_VERSION_MINOR).$(SASL_VERSION_STEP).0\0" VALUE "InternalName", "libsasl\0" - VALUE "LegalCopyright", "Copyright (c) Carnegie Mellon University 2002-2011\0" + VALUE "LegalCopyright", "Copyright (c) Carnegie Mellon University 2002-2012\0" VALUE "OriginalFilename", "libsasl.dll\0" VALUE "ProductName", "Carnegie Mellon University SASL\0" VALUE "ProductVersion", "$(SASL_VERSION_MAJOR).$(SASL_VERSION_MINOR).$(SASL_VERSION_STEP)-0" diff --git a/plugins/NTMakefile b/plugins/NTMakefile index cc74bb12..ef249def 100755 --- a/plugins/NTMakefile +++ b/plugins/NTMakefile @@ -311,7 +311,7 @@ BEGIN VALUE "FileDescription", "CMU SASL $(@B) plugin\0" VALUE "FileVersion", "$(SASL_VERSION_MAJOR).$(SASL_VERSION_MINOR).$(SASL_VERSION_STEP).0\0" VALUE "InternalName", "$(@B)\0" - VALUE "LegalCopyright", "Copyright (c) Carnegie Mellon University 2002-2011\0" + VALUE "LegalCopyright", "Copyright (c) Carnegie Mellon University 2002-2012\0" VALUE "OriginalFilename", "$(@B).dll\0" VALUE "ProductName", "Carnegie Mellon University SASL\0" VALUE "ProductVersion", "$(SASL_VERSION_MAJOR).$(SASL_VERSION_MINOR).$(SASL_VERSION_STEP)-0" From fdad2e9cc554ac35bfc0dcfbbdb8653914f83cc8 Mon Sep 17 00:00:00 2001 From: Ken Murchison Date: Tue, 16 Oct 2012 09:10:50 -0400 Subject: [PATCH 170/796] sample/Makefile.in: include NTMakefile and http_digest_client.c in distro --- sample/Makefile.in | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sample/Makefile.in b/sample/Makefile.in index 2d56bf3c..29929a8f 100644 --- a/sample/Makefile.in +++ b/sample/Makefile.in @@ -81,8 +81,9 @@ host_triplet = @host@ target_triplet = @target@ noinst_PROGRAMS = client$(EXEEXT) server$(EXEEXT) EXTRA_PROGRAMS = sample-client$(EXEEXT) sample-server$(EXEEXT) +EXTRA_DIST = http_digest_client.c subdir = sample -DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in $(srcdir)/NTMakefile ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config/kerberos_v4.m4 \ $(top_srcdir)/config/libtool.m4 $(top_srcdir)/config/plain.m4 \ From 9a9907b557a9e74cb0f7f1afd1ce1396eee59503 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Thu, 18 Oct 2012 11:43:48 +0100 Subject: [PATCH 171/796] Changed afxres.h to windows.h to make resource files compile with Visual Studio 2010 --- lib/NTMakefile | 2 +- plugins/NTMakefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/NTMakefile b/lib/NTMakefile index 61412ba3..817f9a4b 100755 --- a/lib/NTMakefile +++ b/lib/NTMakefile @@ -76,7 +76,7 @@ CLEAN : $(libsasl_res): NTMakefile rc /fo"$(libsasl_res)" << -#include "afxres.h" +#include "windows.h" VS_VERSION_INFO VERSIONINFO FILEVERSION $(SASL_VERSION_MAJOR),$(SASL_VERSION_MINOR),$(SASL_VERSION_STEP),0 diff --git a/plugins/NTMakefile b/plugins/NTMakefile index ef249def..32dc58eb 100755 --- a/plugins/NTMakefile +++ b/plugins/NTMakefile @@ -288,7 +288,7 @@ CLEAN : $(generated_rc): copy < Date: Tue, 20 Nov 2012 09:52:51 +0000 Subject: [PATCH 172/796] Previous commit was the official 2.1.26 Also fixed a typo in ChangeLog (2.1.25 instead of 2.1.26). --- ChangeLog | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4b97e79c..c7be303c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,5 @@ -2012-10-12 Alexey Melnikov - * Getting ready for 2.1.25. +2012-11-19 Alexey Melnikov + * Final 2.1.26 tagged and released by Ken. 2012-07-06 Alexey Melnikov * saslauthd/auth_krb5.c: Fixed a crash in the auth_krb5.c From 645bad48214d56e55b196d81b5ea9128a8350347 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Fri, 12 Oct 2012 11:11:31 -0700 Subject: [PATCH 173/796] Add support for OpenLDAP MDB --- config/sasldb.m4 | 21 +- configure.in | 10 +- doc/options.html | 26 +++ sasldb/Makefile.am | 2 +- sasldb/db_mdb.c | 496 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 547 insertions(+), 8 deletions(-) create mode 100644 sasldb/db_mdb.c diff --git a/config/sasldb.m4 b/config/sasldb.m4 index b28b087f..e3c9016b 100644 --- a/config/sasldb.m4 +++ b/config/sasldb.m4 @@ -5,7 +5,9 @@ dnl Berkeley DB specific checks first.. dnl Figure out what database type we're using AC_DEFUN([SASL_DB_CHECK], [ cmu_save_LIBS="$LIBS" -AC_ARG_WITH(dblib, [ --with-dblib=DBLIB set the DB library to use [berkeley] ], +AC_ARG_WITH(dblib, + [AC_HELP_STRING([--with-dblib={berkeley|gdbm|mdb|ndbm|none|auto_detect}], + [set the DB library to use [[berkeley]]])], dblib=$withval, dblib=auto_detect) @@ -43,6 +45,11 @@ dnl named. arg. fi esac ;; + mdb) + AC_CHECK_HEADER(mdb.h, [ + AC_CHECK_LIB(mdb, mdb_env_create, SASL_DB_LIB="-lmdb"; enable_keep_db_open=yes, dblib="no")], + dblib="no") + ;; ndbm) dnl We want to attempt to use -lndbm if we can, just in case dnl there's some version of it installed and overriding libc @@ -54,6 +61,12 @@ dnl named. arg. auto_detect) dnl How about berkeley db? CYRUS_BERKELEY_DB_CHK() + if test "$dblib" = no; then + dnl How about OpenLDAP's mdb? + AC_CHECK_HEADER(mdb.h, [ + AC_CHECK_LIB(mdb, mdb_env_create, SASL_DB_LIB="-lmdb"; enable_keep_db_open=yes, dblib="no")], + dblib="no") + fi if test "$dblib" = no; then dnl How about ndbm? AC_CHECK_HEADER(ndbm.h, [ @@ -86,7 +99,7 @@ dnl named. arg. ;; *) AC_MSG_WARN([Bad DB library implementation specified;]) - AC_ERROR([Use either \"berkeley\", \"gdbm\", \"ndbm\" or \"none\"]) + AC_ERROR([Use either \"berkeley\", \"gdbm\", \"mdb\", \"ndbm\" or \"none\"]) dblib=no ;; esac @@ -106,6 +119,10 @@ case "$dblib" in SASL_MECHS="$SASL_MECHS libsasldb.la" AC_DEFINE(SASL_GDBM,[],[Use GDBM for SASLdb]) ;; + mdb) + SASL_MECHS="$SASL_MECHS libsasldb.la" + AC_DEFINE(SASL_MDB,[],[Use MDB for SASLdb]) + ;; ndbm) SASL_MECHS="$SASL_MECHS libsasldb.la" AC_DEFINE(SASL_NDBM,[],[Use NDBM for SASLdb]) diff --git a/configure.in b/configure.in index 465a3625..5f750641 100644 --- a/configure.in +++ b/configure.in @@ -200,19 +200,19 @@ SASL_DB_CHECK() # Do we not install the SASL DB man pages? AM_CONDITIONAL(NO_SASL_DB_MANS, test "x$SASL_DB_MANS" = "x") -AC_ARG_ENABLE(keep_db_open, [ --enable-keep-db-open keep handle to Berkeley DB open for improved performance [[no]] ], +AC_ARG_ENABLE(keep_db_open, [ --enable-keep-db-open keep handle to DB open for improved performance [[no]] ], keep_db_open=$enableval, keep_db_open=no) -# Disable if Berkeley DB is not used -if test "$dblib" != berkeley; then +# Disable if Berkeley DB and MDB are not used +if test "$dblib" != berkeley -a "$dblib" != mdb; then keep_db_open=no fi if test "$keep_db_open" = yes; then - AC_DEFINE(KEEP_DB_OPEN,[],[Should we keep handle to Berkeley DB open in SASLDB plugin?]) + AC_DEFINE(KEEP_DB_OPEN,[],[Should we keep handle to DB open in SASLDB plugin?]) fi -AC_MSG_CHECKING(if Berkeley DB handle is kept open in SASLDB) +AC_MSG_CHECKING(if DB handle is kept open in SASLDB) AC_MSG_RESULT($keep_db_open) AC_CHECK_LIB(dl, dlopen, SASL_DL_LIB="-ldl", SASL_DL_LIB="") diff --git a/doc/options.html b/doc/options.html index 4f195f7e..66db5f69 100644 --- a/doc/options.html +++ b/doc/options.html @@ -148,6 +148,20 @@

    Options for Cyrus SASL

    sasldb_pathsasldb plugin Path to sasldb file/etc/sasldb2 (system dependant) + + +sasldb_mapsizesasldb with MDB +Size of the memory map used by the DB. This is also the maximum possible +size of the database, so it must be set to a value large enough to contain +all the desired user records. +1048576 bytes + + +sasldb_maxreaderssasldb with MDB +Maximum number of threads (or processes) that may concurrently read the +database. +126 + sql_engineSQL plugin Name of SQL engine to use (possible values: 'mysql', 'pgsql', 'sqlite', 'sqlite3'). @@ -342,6 +356,18 @@

    Examples:

    +

    Notes on sasldb with MDB

    + +

    +

    + +

    The OpenLDAP MDB library is an extremely compact, extremely high performance +B+tree database. The code for it is available in the regular OpenLDAP source +distributions and it is distributed under the terms of the OpenLDAP Public License.

    + +

    Full documentation, plus papers and presentations are available on +the MDB page.

    +
    Back to the index diff --git a/sasldb/Makefile.am b/sasldb/Makefile.am index 067477cb..e1e3f568 100644 --- a/sasldb/Makefile.am +++ b/sasldb/Makefile.am @@ -46,7 +46,7 @@ sasl_version = 1:25:0 INCLUDES=-I$(top_srcdir)/include -I$(top_builddir)/include @SASL_DB_INC@ -extra_common_sources = db_none.c db_ndbm.c db_gdbm.c db_berkeley.c +extra_common_sources = db_none.c db_mdb.c db_ndbm.c db_gdbm.c db_berkeley.c EXTRA_DIST = NTMakefile diff --git a/sasldb/db_mdb.c b/sasldb/db_mdb.c new file mode 100644 index 00000000..2e2577f5 --- /dev/null +++ b/sasldb/db_mdb.c @@ -0,0 +1,496 @@ +/* db_mdb.c--SASL OpenLDAP MDB interface + * Howard Chu + * $Id$ + */ +/* + * Copyright (C) 2011-2012 Howard Chu, All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any other legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include + +#include +#include +#include +#include +#include "sasldb.h" + +static int db_ok = 0; +static MDB_env *db_env; +static MDB_dbi db_dbi; + +#define KILO 1024 + +/* + * Open the environment + */ +static int do_open(const sasl_utils_t *utils, + sasl_conn_t *conn, + int rdwr, MDB_txn **mtxn) +{ + const char *path = SASL_DB_PATH; + void *cntxt; + MDB_env *env; + MDB_txn *txn; + sasl_getopt_t *getopt; + size_t mapsize = 0; + int readers = 0; + int ret; + int flags; + + if (!db_env) { + + if (utils->getcallback(conn, SASL_CB_GETOPT, + (sasl_callback_ft *)&getopt, &cntxt) == SASL_OK) { + const char *p; + if (getopt(cntxt, NULL, "sasldb_path", &p, NULL) == SASL_OK + && p != NULL && *p != 0) { + path = p; + } + if (getopt(cntxt, NULL, "sasldb_maxreaders", &p, NULL) == SASL_OK + && p != NULL && *p != 0) { + readers = atoi(p); + } + if (getopt(cntxt, NULL, "sasldb_mapsize", &p, NULL) == SASL_OK + && p != NULL && *p != 0) { + mapsize = atoi(p); + mapsize *= KILO; + } + } + + ret = mdb_env_create(&env); + if (ret) { + utils->log(conn, SASL_LOG_ERR, + "unable to create MDB environment: %s", + mdb_strerror(ret)); + utils->seterror(conn, SASL_NOLOG, "Unable to create MDB environment"); + return SASL_FAIL; + } + + if (readers) { + ret = mdb_env_set_maxreaders(env, readers); + if (ret) { + utils->log(conn, SASL_LOG_ERR, + "unable to set MDB maxreaders: %s", + mdb_strerror(ret)); + utils->seterror(conn, SASL_NOLOG, "Unable to set MDB maxreaders"); + return SASL_FAIL; + } + } + + if (mapsize) { + ret = mdb_env_set_mapsize(env, mapsize); + if (ret) { + utils->log(conn, SASL_LOG_ERR, + "unable to set MDB mapsize: %s", + mdb_strerror(ret)); + utils->seterror(conn, SASL_NOLOG, "Unable to set MDB mapsize"); + return SASL_FAIL; + } + } + + flags = MDB_NOSUBDIR; + if (!rdwr) flags |= MDB_RDONLY; + ret = mdb_env_open(env, path, flags, 0660); + if (ret) { + mdb_env_close(env); + if (!rdwr && ret == ENOENT) { + /* File not found and we are only reading the data. + Treat as SASL_NOUSER. */ + return SASL_NOUSER; + } + utils->log(conn, SASL_LOG_ERR, + "unable to open MDB environment %s: %s", + path, mdb_strerror(ret)); + utils->seterror(conn, SASL_NOLOG, "Unable to open MDB environment"); + return SASL_FAIL; + } + } else { + env = db_env; + } + + ret = mdb_txn_begin(env, NULL, rdwr ? 0 : MDB_RDONLY, &txn); + if (ret) { + mdb_env_close(env); + utils->log(conn, SASL_LOG_ERR, + "unable to open MDB transaction: %s", + mdb_strerror(ret)); + utils->seterror(conn, SASL_NOLOG, "Unable to open MDB transaction"); + return SASL_FAIL; + } + + if (!db_dbi) { + ret = mdb_open(txn, NULL, 0, &db_dbi); + if (ret) { + mdb_txn_abort(txn); + mdb_env_close(env); + utils->log(conn, SASL_LOG_ERR, + "unable to open MDB database: %s", + mdb_strerror(ret)); + utils->seterror(conn, SASL_NOLOG, "Unable to open MDB database"); + return SASL_FAIL; + } + } + + if (!db_env) + db_env = env; + *mtxn = txn; + + return SASL_OK; +} + +/* + * Close the environment + */ +static void do_close() +{ + mdb_env_close(db_env); + db_env = NULL; +} + + +/* + * Retrieve the secret from the database. + * + * Return SASL_NOUSER if the entry doesn't exist, + * SASL_OK on success. + * + */ +int _sasldb_getdata(const sasl_utils_t *utils, + sasl_conn_t *context, + const char *auth_identity, + const char *realm, + const char *propName, + char *out, const size_t max_out, size_t *out_len) +{ + int result = SASL_OK; + char *key; + size_t key_len; + MDB_val dbkey, data; + MDB_txn *txn = NULL; + + if(!utils) return SASL_BADPARAM; + + /* check parameters */ + if (!auth_identity || !realm || !propName || !out || !max_out) { + utils->seterror(context, 0, + "Bad parameter in db_mdb.c: _sasldb_getdata"); + return SASL_BADPARAM; + } + + if (!db_ok) { + utils->seterror(context, 0, + "Database not checked"); + return SASL_FAIL; + } + + /* allocate a key */ + result = _sasldb_alloc_key(utils, auth_identity, realm, propName, + &key, &key_len); + if (result != SASL_OK) { + utils->seterror(context, 0, + "Could not allocate key in _sasldb_getdata"); + return result; + } + + /* open the db */ + result = do_open(utils, context, 0, &txn); + if (result != SASL_OK) goto cleanup; + + /* create the key to search for */ + dbkey.mv_data = key; + dbkey.mv_size = key_len; + + /* ask MDB for the entry */ + result = mdb_get(txn, db_dbi, &dbkey, &data); + + switch (result) { + case 0: + /* success */ + break; + + case MDB_NOTFOUND: + result = SASL_NOUSER; + utils->seterror(context, SASL_NOLOG, + "user: %s@%s property: %s not found in sasldb", + auth_identity,realm,propName); + goto cleanup; + break; + default: + utils->seterror(context, 0, + "error fetching from sasldb: %s", + mdb_strerror(result)); + result = SASL_FAIL; + goto cleanup; + break; + } + + if(data.mv_size > max_out + 1) + return SASL_BUFOVER; + + if(out_len) *out_len = data.mv_size; + memcpy(out, data.mv_data, data.mv_size); + out[data.mv_size] = '\0'; + + cleanup: + + mdb_txn_abort(txn); + utils->free(key); + + return result; +} + +/* + * Put or delete an entry + * + * + */ + +int _sasldb_putdata(const sasl_utils_t *utils, + sasl_conn_t *context, + const char *authid, + const char *realm, + const char *propName, + const char *data_in, size_t data_len) +{ + int result = SASL_OK; + char *key; + size_t key_len; + MDB_val dbkey; + MDB_txn *txn = NULL; + + if (!utils) return SASL_BADPARAM; + + if (!authid || !realm || !propName) { + utils->seterror(context, 0, + "Bad parameter in db_mdb.c: _sasldb_putdata"); + return SASL_BADPARAM; + } + + if (!db_ok) { + utils->seterror(context, 0, + "Database not checked"); + return SASL_FAIL; + } + + result = _sasldb_alloc_key(utils, authid, realm, propName, + &key, &key_len); + if (result != SASL_OK) { + utils->seterror(context, 0, + "Could not allocate key in _sasldb_putdata"); + return result; + } + + /* open the db */ + result=do_open(utils, context, 1, &txn); + if (result!=SASL_OK) goto cleanup; + + /* create the db key */ + dbkey.mv_data = key; + dbkey.mv_size = key_len; + + if (data_in) { /* putting secret */ + MDB_val data; + + data.mv_data = (char *)data_in; + if(!data_len) data_len = strlen(data_in); + data.mv_size = data_len; + + result = mdb_put(txn, db_dbi, &dbkey, &data, 0); + + if (result != 0) + { + utils->log(NULL, SASL_LOG_ERR, + "error updating sasldb: %s", mdb_strerror(result)); + utils->seterror(context, SASL_NOLOG, + "Couldn't update db"); + result = SASL_FAIL; + goto cleanup; + } + } else { /* removing secret */ + result=mdb_del(txn, db_dbi, &dbkey, NULL); + + if (result != 0) + { + utils->log(NULL, SASL_LOG_ERR, + "error deleting entry from sasldb: %s", mdb_strerror(result)); + utils->seterror(context, SASL_NOLOG, + "Couldn't update db"); + if (result == MDB_NOTFOUND) + result = SASL_NOUSER; + else + result = SASL_FAIL; + goto cleanup; + } + } + result = mdb_txn_commit(txn); + if (result) { + utils->log(NULL, SASL_LOG_ERR, + "error committing to sasldb: %s", mdb_strerror(result)); + utils->seterror(context, SASL_NOLOG, + "Couldn't update db"); + result = SASL_FAIL; + } + txn = NULL; + + cleanup: + + mdb_txn_abort(txn); + utils->free(key); + + return result; +} + +int _sasl_check_db(const sasl_utils_t *utils, + sasl_conn_t *conn) +{ + const char *path = SASL_DB_PATH; + int ret; + void *cntxt; + sasl_getopt_t *getopt; + sasl_verifyfile_t *vf; + + if (!utils) return SASL_BADPARAM; + + if (utils->getcallback(conn, SASL_CB_GETOPT, + (sasl_callback_ft *)&getopt, &cntxt) == SASL_OK) { + const char *p; + if (getopt(cntxt, NULL, "sasldb_path", &p, NULL) == SASL_OK + && p != NULL && *p != 0) { + path = p; + } + } + + ret = utils->getcallback(conn, SASL_CB_VERIFYFILE, + (sasl_callback_ft *)&vf, &cntxt); + if (ret != SASL_OK) { + utils->seterror(conn, 0, "verifyfile failed"); + return ret; + } + + ret = vf(cntxt, path, SASL_VRFY_PASSWD); + + if (ret == SASL_OK) { + db_ok = 1; + } + + if (ret == SASL_OK || ret == SASL_CONTINUE) { + return SASL_OK; + } else { + return ret; + } +} + +void sasldb_auxprop_free (void *glob_context, + const sasl_utils_t *utils) +{ + do_close(); +} + +sasldb_handle _sasldb_getkeyhandle(const sasl_utils_t *utils, + sasl_conn_t *conn) +{ + int ret; + MDB_txn *txn; + MDB_cursor *mc; + + if(!utils || !conn) return NULL; + + if(!db_ok) { + utils->seterror(conn, 0, "Database not OK in _sasldb_getkeyhandle"); + return NULL; + } + + ret = do_open(utils, conn, 0, &txn); + + if (ret != SASL_OK) { + return NULL; + } + + ret = mdb_cursor_open(txn, db_dbi, &mc); + if (ret) { + utils->seterror(conn, 0, "cursor_open failed in _sasldb_gekeythandle"); + return NULL; + } + + return (sasldb_handle)mc; +} + +int _sasldb_getnextkey(const sasl_utils_t *utils __attribute__((unused)), + sasldb_handle handle, char *out, + const size_t max_out, size_t *out_len) +{ + int result; + MDB_cursor *mc = (MDB_cursor *)handle; + MDB_val key; + + if(!utils || !handle || !out || !max_out) + return SASL_BADPARAM; + + result = mdb_cursor_get(mc, &key, NULL, MDB_NEXT); + + if (result == MDB_NOTFOUND) return SASL_OK; + + if (result != 0) { + return SASL_FAIL; + } + + if (key.mv_size > max_out) { + return SASL_BUFOVER; + } + + memcpy(out, key.mv_data, key.mv_size); + if (out_len) *out_len = key.mv_size; + + return SASL_CONTINUE; +} + + +int _sasldb_releasekeyhandle(const sasl_utils_t *utils, + sasldb_handle handle) +{ + MDB_cursor *mc = (MDB_cursor *)handle; + + if (!utils || !handle) return SASL_BADPARAM; + + mdb_cursor_close(mc); + + return SASL_OK; +} From 836a2ec54a86ca618119a395161de5b97c304d9c Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Tue, 20 Nov 2012 10:03:11 +0000 Subject: [PATCH 174/796] Corrected a spelling error in a comment --- win32/include/config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/win32/include/config.h b/win32/include/config.h index 0ad9628f..34408378 100644 --- a/win32/include/config.h +++ b/win32/include/config.h @@ -91,7 +91,7 @@ typedef int intptr_t; /* #undef SASL_NDBM */ #define SASL_BERKELEYDB 1 -/* which mechs can we link staticly? */ +/* which mechs can we link statically? */ #define STATIC_ANONYMOUS 1 #define STATIC_CRAMMD5 1 #define STATIC_DIGESTMD5 1 From 67a188693796a14e3a76ac603104807fbbfddfc4 Mon Sep 17 00:00:00 2001 From: Ken Murchison Date: Thu, 20 Dec 2012 18:14:50 -0500 Subject: [PATCH 175/796] sasl.h: #include for size_t on NetBSD --- include/sasl.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/sasl.h b/include/sasl.h index fef4d510..8b8a63fb 100755 --- a/include/sasl.h +++ b/include/sasl.h @@ -121,6 +121,8 @@ #ifndef SASL_H #define SASL_H 1 +#include /* For size_t */ + /* Keep in sync with win32/common.mak */ #define SASL_VERSION_MAJOR 2 #define SASL_VERSION_MINOR 1 From 9e561a1117e6452dc586a883bb10964dd9f4833a Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Thu, 20 Sep 2012 14:37:06 +0100 Subject: [PATCH 176/796] Removed a CVS tag as it is no longer updated by GIT --- AUTHORS | 2 -- 1 file changed, 2 deletions(-) diff --git a/AUTHORS b/AUTHORS index 437a27e3..3e00420b 100644 --- a/AUTHORS +++ b/AUTHORS @@ -44,5 +44,3 @@ and both Larry Greenfield and Alexey Melnikov have done more work on it. getaddrinfo.c was written by Hajimu UMEMOTO which is based on the IPv6 code written by KIKUCHI Takahiro - -$Id: AUTHORS,v 1.18 2006/12/01 17:34:58 mel Exp $ From cf783d7ab486b8eaedfcf1edf23e9946fce643f9 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Fri, 21 Jun 2013 20:44:36 +0100 Subject: [PATCH 177/796] Improved some error messages in _plug_get_* functions This should make it easier to figure out which one is failing to retrieve prompt data. --- plugins/plugin_common.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/plugin_common.c b/plugins/plugin_common.c index 3aa6f9ab..1d633eea 100644 --- a/plugins/plugin_common.c +++ b/plugins/plugin_common.c @@ -334,7 +334,7 @@ int _plug_get_simple(const sasl_utils_t *utils, unsigned int id, int required, /* We prompted, and got.*/ if (required && !prompt->result) { - SETERROR(utils, "Unexpectedly missing a prompt result"); + SETERROR(utils, "Unexpectedly missing a prompt result in _plug_get_simple"); return SASL_BADPARAM; } @@ -382,7 +382,7 @@ int _plug_get_password(const sasl_utils_t *utils, sasl_secret_t **password, /* We prompted, and got.*/ if (!prompt->result) { - SETERROR(utils, "Unexpectedly missing a prompt result"); + SETERROR(utils, "Unexpectedly missing a prompt result in _plug_get_password"); return SASL_BADPARAM; } @@ -441,7 +441,7 @@ int _plug_challenge_prompt(const sasl_utils_t *utils, unsigned int id, /* We prompted, and got.*/ if (!prompt->result) { - SETERROR(utils, "Unexpectedly missing a prompt result"); + SETERROR(utils, "Unexpectedly missing a prompt result in _plug_challenge_prompt"); return SASL_BADPARAM; } @@ -487,7 +487,7 @@ int _plug_get_realm(const sasl_utils_t *utils, const char **availrealms, /* We prompted, and got.*/ if (!prompt->result) { - SETERROR(utils, "Unexpectedly missing a prompt result"); + SETERROR(utils, "Unexpectedly missing a prompt result in _plug_get_realm"); return SASL_BADPARAM; } From 281a8ad5faeb096036b12036b44c6af8fa62fd01 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Thu, 11 Jul 2013 10:08:07 +0100 Subject: [PATCH 178/796] Handle NULL returns from glibc 2.17+ crypt() Starting with glibc 2.17 (eglibc 2.17), crypt() fails with EINVAL (w/ NULL return) if the salt violates specifications. Additionally, on FIPS-140 enabled Linux systems, DES/MD5-encrypted passwords passed to crypt() fail with EPERM (w/ NULL return). When using glibc's crypt(), check return value to avoid a possible NULL pointer dereference. Original patch by mancha1@hush.com. --- pwcheck/pwcheck_getpwnam.c | 3 ++- pwcheck/pwcheck_getspnam.c | 4 +++- saslauthd/auth_getpwent.c | 4 +++- saslauthd/auth_shadow.c | 8 +++----- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/pwcheck/pwcheck_getpwnam.c b/pwcheck/pwcheck_getpwnam.c index 4b34222b..400289c4 100644 --- a/pwcheck/pwcheck_getpwnam.c +++ b/pwcheck/pwcheck_getpwnam.c @@ -32,6 +32,7 @@ char *userid; char *password; { char* r; + char* crpt_passwd; struct passwd *pwd; pwd = getpwnam(userid); @@ -41,7 +42,7 @@ char *password; else if (pwd->pw_passwd[0] == '*') { r = "Account disabled"; } - else if (strcmp(pwd->pw_passwd, crypt(password, pwd->pw_passwd)) != 0) { + else if (!(crpt_passwd = crypt(password, pwd->pw_passwd)) || strcmp(pwd->pw_passwd, (const char *)crpt_passwd) != 0) { r = "Incorrect password"; } else { diff --git a/pwcheck/pwcheck_getspnam.c b/pwcheck/pwcheck_getspnam.c index 2b112866..6d607bbd 100644 --- a/pwcheck/pwcheck_getspnam.c +++ b/pwcheck/pwcheck_getspnam.c @@ -32,13 +32,15 @@ char *userid; char *password; { struct spwd *pwd; + char *crpt_passwd; pwd = getspnam(userid); if (!pwd) { return "Userid not found"; } - if (strcmp(pwd->sp_pwdp, crypt(password, pwd->sp_pwdp)) != 0) { + crpt_passwd = crypt(password, pwd->sp_pwdp); + if (!crpt_passwd || strcmp(pwd->sp_pwdp, (const char *)crpt_passwd) != 0) { return "Incorrect password"; } else { diff --git a/saslauthd/auth_getpwent.c b/saslauthd/auth_getpwent.c index fc8029d7..d4ebe542 100644 --- a/saslauthd/auth_getpwent.c +++ b/saslauthd/auth_getpwent.c @@ -77,6 +77,7 @@ auth_getpwent ( { /* VARIABLES */ struct passwd *pw; /* pointer to passwd file entry */ + char *crpt_passwd; /* encrypted password */ int errnum; /* END VARIABLES */ @@ -105,7 +106,8 @@ auth_getpwent ( } } - if (strcmp(pw->pw_passwd, (const char *)crypt(password, pw->pw_passwd))) { + crpt_passwd = crypt(password, pw->pw_passwd); + if (!crpt_passwd || strcmp(pw->pw_passwd, (const char *)crpt_passwd)) { if (flags & VERBOSE) { syslog(LOG_DEBUG, "DEBUG: auth_getpwent: %s: invalid password", login); } diff --git a/saslauthd/auth_shadow.c b/saslauthd/auth_shadow.c index 677131b7..1988afdf 100644 --- a/saslauthd/auth_shadow.c +++ b/saslauthd/auth_shadow.c @@ -210,8 +210,8 @@ auth_shadow ( RETURN("NO Insufficient permission to access NIS authentication database (saslauthd)"); } - cpw = strdup((const char *)crypt(password, sp->sp_pwdp)); - if (strcmp(sp->sp_pwdp, cpw)) { + cpw = crypt(password, sp->sp_pwdp); + if (!cpw || strcmp(sp->sp_pwdp, (const char *)cpw)) { if (flags & VERBOSE) { /* * This _should_ reveal the SHADOW_PW_LOCKED prefix to an @@ -221,10 +221,8 @@ auth_shadow ( syslog(LOG_DEBUG, "DEBUG: auth_shadow: pw mismatch: '%s' != '%s'", sp->sp_pwdp, cpw); } - free(cpw); RETURN("NO Incorrect password"); } - free(cpw); /* * The following fields will be set to -1 if: @@ -286,7 +284,7 @@ auth_shadow ( RETURN("NO Invalid username"); } - if (strcmp(upw->upw_passwd, crypt(password, upw->upw_passwd)) != 0) { + if (!(cpw = crypt(password, upw->upw_passwd)) || (strcmp(upw->upw_passwd, (const char *)cpw) != 0)) { if (flags & VERBOSE) { syslog(LOG_DEBUG, "auth_shadow: pw mismatch: %s != %s", password, upw->upw_passwd); From dedad73e5e7a75d01a5f3d5a6702ab8ccd2ff40d Mon Sep 17 00:00:00 2001 From: mancha Date: Thu, 11 Jul 2013 10:08:07 +0100 Subject: [PATCH 179/796] Handle NULL returns from glibc 2.17+ crypt() Starting with glibc 2.17 (eglibc 2.17), crypt() fails with EINVAL (w/ NULL return) if the salt violates specifications. Additionally, on FIPS-140 enabled Linux systems, DES/MD5-encrypted passwords passed to crypt() fail with EPERM (w/ NULL return). When using glibc's crypt(), check return value to avoid a possible NULL pointer dereference. Patch by mancha1@hush.com. --- pwcheck/pwcheck_getpwnam.c | 3 ++- pwcheck/pwcheck_getspnam.c | 4 +++- saslauthd/auth_getpwent.c | 4 +++- saslauthd/auth_shadow.c | 8 +++----- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/pwcheck/pwcheck_getpwnam.c b/pwcheck/pwcheck_getpwnam.c index 4b34222b..400289c4 100644 --- a/pwcheck/pwcheck_getpwnam.c +++ b/pwcheck/pwcheck_getpwnam.c @@ -32,6 +32,7 @@ char *userid; char *password; { char* r; + char* crpt_passwd; struct passwd *pwd; pwd = getpwnam(userid); @@ -41,7 +42,7 @@ char *password; else if (pwd->pw_passwd[0] == '*') { r = "Account disabled"; } - else if (strcmp(pwd->pw_passwd, crypt(password, pwd->pw_passwd)) != 0) { + else if (!(crpt_passwd = crypt(password, pwd->pw_passwd)) || strcmp(pwd->pw_passwd, (const char *)crpt_passwd) != 0) { r = "Incorrect password"; } else { diff --git a/pwcheck/pwcheck_getspnam.c b/pwcheck/pwcheck_getspnam.c index 2b112866..6d607bbd 100644 --- a/pwcheck/pwcheck_getspnam.c +++ b/pwcheck/pwcheck_getspnam.c @@ -32,13 +32,15 @@ char *userid; char *password; { struct spwd *pwd; + char *crpt_passwd; pwd = getspnam(userid); if (!pwd) { return "Userid not found"; } - if (strcmp(pwd->sp_pwdp, crypt(password, pwd->sp_pwdp)) != 0) { + crpt_passwd = crypt(password, pwd->sp_pwdp); + if (!crpt_passwd || strcmp(pwd->sp_pwdp, (const char *)crpt_passwd) != 0) { return "Incorrect password"; } else { diff --git a/saslauthd/auth_getpwent.c b/saslauthd/auth_getpwent.c index fc8029d7..d4ebe542 100644 --- a/saslauthd/auth_getpwent.c +++ b/saslauthd/auth_getpwent.c @@ -77,6 +77,7 @@ auth_getpwent ( { /* VARIABLES */ struct passwd *pw; /* pointer to passwd file entry */ + char *crpt_passwd; /* encrypted password */ int errnum; /* END VARIABLES */ @@ -105,7 +106,8 @@ auth_getpwent ( } } - if (strcmp(pw->pw_passwd, (const char *)crypt(password, pw->pw_passwd))) { + crpt_passwd = crypt(password, pw->pw_passwd); + if (!crpt_passwd || strcmp(pw->pw_passwd, (const char *)crpt_passwd)) { if (flags & VERBOSE) { syslog(LOG_DEBUG, "DEBUG: auth_getpwent: %s: invalid password", login); } diff --git a/saslauthd/auth_shadow.c b/saslauthd/auth_shadow.c index 677131b7..1988afdf 100644 --- a/saslauthd/auth_shadow.c +++ b/saslauthd/auth_shadow.c @@ -210,8 +210,8 @@ auth_shadow ( RETURN("NO Insufficient permission to access NIS authentication database (saslauthd)"); } - cpw = strdup((const char *)crypt(password, sp->sp_pwdp)); - if (strcmp(sp->sp_pwdp, cpw)) { + cpw = crypt(password, sp->sp_pwdp); + if (!cpw || strcmp(sp->sp_pwdp, (const char *)cpw)) { if (flags & VERBOSE) { /* * This _should_ reveal the SHADOW_PW_LOCKED prefix to an @@ -221,10 +221,8 @@ auth_shadow ( syslog(LOG_DEBUG, "DEBUG: auth_shadow: pw mismatch: '%s' != '%s'", sp->sp_pwdp, cpw); } - free(cpw); RETURN("NO Incorrect password"); } - free(cpw); /* * The following fields will be set to -1 if: @@ -286,7 +284,7 @@ auth_shadow ( RETURN("NO Invalid username"); } - if (strcmp(upw->upw_passwd, crypt(password, upw->upw_passwd)) != 0) { + if (!(cpw = crypt(password, upw->upw_passwd)) || (strcmp(upw->upw_passwd, (const char *)cpw) != 0)) { if (flags & VERBOSE) { syslog(LOG_DEBUG, "auth_shadow: pw mismatch: %s != %s", password, upw->upw_passwd); From 26dcfb2d7176b78e70757aa5d01951a28ca217c7 Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Fri, 5 Jul 2013 16:37:59 +0100 Subject: [PATCH 180/796] Treat SCRAM-SHA-1/DIGEST-MD5 as more secure than PLAIN when selecting the best client side SASL mechanism Both SCRAM-SHA-1 & DIGEST-MD5 are lacking SASL_SEC_PASS_CREDENTIALS security flag, which prevented them from being chosen over PLAIN when PLAIN is selected as the best mechanism first. For example the problem can be observed when the server advertises "PLAIN DIGEST-MD5 SCRAM-SHA-1" (PLAIN just has to be returned before SCRAM/DIGEST.) Cyrus SASL bug # 3793 --- lib/client.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/lib/client.c b/lib/client.c index 62dfb0bf..31fe3462 100644 --- a/lib/client.c +++ b/lib/client.c @@ -658,6 +658,20 @@ _sasl_cbinding_disp(sasl_client_params_t *cparams, return SASL_OK; } +static int +_sasl_are_current_security_flags_worse_then_best(unsigned best_security_flags, + unsigned current_security_flags) +{ + /* We don't qualify SASL_SEC_PASS_CREDENTIALS as "secure" flag */ + best_security_flags &= ~SASL_SEC_PASS_CREDENTIALS; + + if ((current_security_flags ^ best_security_flags) & best_security_flags) { + return 1; + } else { + return 0; + } +} + /* select a mechanism for a connection * mechlist -- mechanisms server has available (punctuation ignored) * secret -- optional secret from previous session @@ -823,8 +837,9 @@ int sasl_client_start(sasl_conn_t *conn, */ if (bestm && - ((m->m.plug->security_flags ^ bestm->m.plug->security_flags) & - bestm->m.plug->security_flags)) { + _sasl_are_current_security_flags_worse_then_best( + bestm->m.plug->security_flags, + m->m.plug->security_flags)) { break; } From f2e77ab1ac01f611d71ae56ff7635a46b930ef8e Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Tue, 27 Aug 2013 14:19:50 +0100 Subject: [PATCH 181/796] Added missing include files for struct timeval As reported by Julien ELIE --- saslauthd/auth_rimap.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/saslauthd/auth_rimap.c b/saslauthd/auth_rimap.c index 2c3870f0..24ed3e93 100644 --- a/saslauthd/auth_rimap.c +++ b/saslauthd/auth_rimap.c @@ -75,6 +75,16 @@ #include #include #include +#if TIME_WITH_SYS_TIME +# include +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif #include "auth_rimap.h" #include "utils.h" From 76ce885a44e7cb511ba54ceae46349036abb9cc8 Mon Sep 17 00:00:00 2001 From: Ken Murchison Date: Fri, 30 Aug 2013 16:57:14 -0400 Subject: [PATCH 182/796] digestmd5.c: don't try to locate a reauth cache entry if reauth isn't enabled on the server-side (NULL timeout == NULL hash table size) --- plugins/digestmd5.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/digestmd5.c b/plugins/digestmd5.c index 4ab90dd2..5061a100 100644 --- a/plugins/digestmd5.c +++ b/plugins/digestmd5.c @@ -2112,7 +2112,7 @@ digestmd5_server_mech_step1(server_context_t *stext, return SASL_FAIL; } - if (text->http_mode && + if (text->http_mode && text->reauth->timeout && sparams->utils->mutex_lock(text->reauth->mutex) == SASL_OK) { /* LOCK */ /* Create an initial cache entry for non-persistent HTTP connections */ @@ -2451,7 +2451,7 @@ static int digestmd5_server_mech_step2(server_context_t *stext, #endif } - if (!text->nonce) { + if (!text->nonce && text->reauth->timeout) { unsigned val = hash((char *) nonce) % text->reauth->size; /* reauth attempt or continuation of HTTP Digest on a From 12b7be1a53bff3143d08af6e70176f89119f72b4 Mon Sep 17 00:00:00 2001 From: Mili Verma Date: Wed, 11 Sep 2013 14:47:02 +0100 Subject: [PATCH 183/796] Memory leaks in DIGEST-MD5 on authentication failure This patch fixes it Test-information: Verified with Valgrind. No leak after patch. --- plugins/digestmd5.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/digestmd5.c b/plugins/digestmd5.c index 5061a100..af443f83 100644 --- a/plugins/digestmd5.c +++ b/plugins/digestmd5.c @@ -2758,7 +2758,7 @@ static int digestmd5_server_mech_step2(server_context_t *stext, /* if ok verified */ if (strcmp(serverresponse, response) != 0) { if (Try_8859_1) { - + sparams->utils->free(serverresponse); serverresponse = create_response(text, sparams->utils, nonce, From 7739268e775e6ed91509727b014cc1d367ad386d Mon Sep 17 00:00:00 2001 From: Alexey Melnikov Date: Sun, 30 Mar 2014 15:13:34 +0100 Subject: [PATCH 184/796] When processing a list of mechanism names, we shouldn't allow a short prefix match the whole mechanism name "A", "AN", etc where matching "ANONYMOUS". This patch fixes that. As reported by plautrba@redhat.com --- lib/common.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/common.c b/lib/common.c index e0f59ebc..672fe2ff 100644 --- a/lib/common.c +++ b/lib/common.c @@ -2428,6 +2428,11 @@ int _sasl_is_equal_mech(const char *req_mech, *plus = 0; } + if (n < strlen(plug_mech)) { + /* Don't allow arbitrary prefix match */ + return 0; + } + return (strncasecmp(req_mech, plug_mech, n) == 0); } From e87843e5cfe5d97c8c00c67a9ebaa8cf1387b356 Mon Sep 17 00:00:00 2001 From: Ken Murchison Date: Mon, 17 Nov 2014 17:52:57 -0500 Subject: [PATCH 185/796] digestmd5.c: prevent going from step 3 back to step 2 --- plugins/digestmd5.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/plugins/digestmd5.c b/plugins/digestmd5.c index af443f83..9e22e69c 100644 --- a/plugins/digestmd5.c +++ b/plugins/digestmd5.c @@ -4299,7 +4299,7 @@ digestmd5_client_mech_step1(client_context_t *ctext, *clientoutlen = (unsigned) strlen(text->out_buf); *clientout = text->out_buf; - text->state = 3; + /* check for next state (2 or 3) is done in digestmd5_client_mech_step() */ return SASL_CONTINUE; } @@ -4525,16 +4525,10 @@ static int digestmd5_client_mech_step(void *conn_context, return SASL_CONTINUE; } } - - /* fall through and respond to challenge */ - - case 3: - if (serverin && !strncasecmp(serverin, "rspauth=", 8)) { - return digestmd5_client_mech_step3(ctext, params, - serverin, serverinlen, - prompt_need, - clientout, clientoutlen, - oparams); + else if (!strncasecmp(serverin, "rspauth=", 8)) { + /* server accepted fast reauth */ + text->state = 3; + goto step3; } /* fall through and respond to challenge */ @@ -4561,6 +4555,14 @@ static int digestmd5_client_mech_step(void *conn_context, clientout, clientoutlen, oparams); + case 3: + step3: + return digestmd5_client_mech_step3(ctext, params, + serverin, serverinlen, + prompt_need, + clientout, clientoutlen, + oparams); + default: params->utils->log(NULL, SASL_LOG_ERR, "Invalid DIGEST-MD5 client step %d\n", text->state); From 163df64da5557d1f4156665bbbd3cc38d718e782 Mon Sep 17 00:00:00 2001 From: Ken Murchison Date: Mon, 17 Nov 2014 18:27:23 -0500 Subject: [PATCH 186/796] digestmd5.c: squash potential memory leaks --- plugins/digestmd5.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/digestmd5.c b/plugins/digestmd5.c index 9e22e69c..2fb05508 100644 --- a/plugins/digestmd5.c +++ b/plugins/digestmd5.c @@ -4583,6 +4583,8 @@ static void digestmd5_client_mech_dispose(void *conn_context, "DIGEST-MD5 client mech dispose"); if (ctext->free_password) _plug_free_secret(utils, &ctext->password); + if (ctext->algorithm) utils->free(ctext->algorithm); + if (ctext->opaque) utils->free(ctext->opaque); digestmd5_common_mech_dispose(conn_context, utils); } From 1f81574ab879002d5625d298f2f5dfb5d7d69deb Mon Sep 17 00:00:00 2001 From: Ken Murchison Date: Thu, 28 May 2015 13:33:46 -0400 Subject: [PATCH 187/796] configure.in, cmulocal/: replace the *.m4 pieces required to compile cyrus-sasl --- Makefile.am | 1 + SMakefile | 2 + cmulocal/berkdb.m4 | 288 ++ cmulocal/bsd_sockets.m4 | 38 + cmulocal/c-attribute.m4 | 26 + cmulocal/common.m4 | 59 + cmulocal/cyrus.m4 | 44 + cmulocal/init_automake.m4 | 7 + cmulocal/ipv6.m4 | 111 + {config => cmulocal}/kerberos_v4.m4 | 8 +- cmulocal/openldap.m4 | 35 + cmulocal/openssl.m4 | 47 + {config => cmulocal}/plain.m4 | 0 cmulocal/sasl2.m4 | 519 ++++ {config => cmulocal}/sasldb.m4 | 0 config/config.guess | 1516 ---------- config/config.sub | 1764 ------------ config/depcomp | 423 --- config/install-sh | 276 -- config/libtool.m4 | 430 --- config/ltconfig | 3150 --------------------- config/ltmain.sh | 4059 --------------------------- config/missing | 336 --- config/mkinstalldirs | 111 - configure.in | 1 + sample/Makefile.in | 607 ---- saslauthd/Makefile.am | 2 +- saslauthd/config/config.guess | 1516 ---------- saslauthd/config/config.sub | 1764 ------------ saslauthd/config/depcomp | 423 --- saslauthd/config/install-sh | 276 -- saslauthd/config/ltconfig | 3150 --------------------- saslauthd/config/ltmain.sh | 4053 -------------------------- saslauthd/config/missing | 336 --- saslauthd/config/mkinstalldirs | 111 - saslauthd/configure.in | 30 +- 36 files changed, 1198 insertions(+), 24321 deletions(-) create mode 100644 cmulocal/berkdb.m4 create mode 100644 cmulocal/bsd_sockets.m4 create mode 100644 cmulocal/c-attribute.m4 create mode 100644 cmulocal/common.m4 create mode 100644 cmulocal/cyrus.m4 create mode 100644 cmulocal/init_automake.m4 create mode 100644 cmulocal/ipv6.m4 rename {config => cmulocal}/kerberos_v4.m4 (95%) create mode 100644 cmulocal/openldap.m4 create mode 100644 cmulocal/openssl.m4 rename {config => cmulocal}/plain.m4 (100%) create mode 100644 cmulocal/sasl2.m4 rename {config => cmulocal}/sasldb.m4 (100%) delete mode 100755 config/config.guess delete mode 100755 config/config.sub delete mode 100755 config/depcomp delete mode 100755 config/install-sh delete mode 100644 config/libtool.m4 delete mode 100755 config/ltconfig delete mode 100644 config/ltmain.sh delete mode 100755 config/missing delete mode 100755 config/mkinstalldirs delete mode 100644 sample/Makefile.in delete mode 100755 saslauthd/config/config.guess delete mode 100755 saslauthd/config/config.sub delete mode 100755 saslauthd/config/depcomp delete mode 100755 saslauthd/config/install-sh delete mode 100755 saslauthd/config/ltconfig delete mode 100644 saslauthd/config/ltmain.sh delete mode 100755 saslauthd/config/missing delete mode 100755 saslauthd/config/mkinstalldirs diff --git a/Makefile.am b/Makefile.am index 2091dd10..bd12837a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,5 @@ AUTOMAKE_OPTIONS = 1.7 +ACLOCAL_AMFLAGS = -I config # Top-level Makefile.am for SASL # Rob Earhart # diff --git a/SMakefile b/SMakefile index 75e566f1..87038a94 100644 --- a/SMakefile +++ b/SMakefile @@ -2,6 +2,8 @@ NEW_AUTOTOOLS=yes export NEW_AUTOTOOLS if test ! -x configure; then + echo libtoolize + libtoolize echo aclocal -I cmulocal -I config aclocal -I cmulocal -I config echo autoheader diff --git a/cmulocal/berkdb.m4 b/cmulocal/berkdb.m4 new file mode 100644 index 00000000..98e8cb62 --- /dev/null +++ b/cmulocal/berkdb.m4 @@ -0,0 +1,288 @@ +dnl $Id: berkdb.m4,v 1.24 2010/01/06 17:01:27 murch Exp $ + +AC_DEFUN([CMU_DB_INC_WHERE1], [ +saved_CPPFLAGS=$CPPFLAGS +CPPFLAGS="$saved_CPPFLAGS -I$1" +AC_TRY_COMPILE([#include ], +[DB *db; +db_create(&db, NULL, 0); +db->open(db, "foo.db", NULL, DB_UNKNOWN, DB_RDONLY, 0644);], +ac_cv_found_db_inc=yes, +ac_cv_found_db_inc=no) +CPPFLAGS=$saved_CPPFLAGS +]) + +AC_DEFUN([CMU_DB_INC_WHERE], [ + for i in $1; do + AC_MSG_CHECKING(for db headers in $i) + CMU_DB_INC_WHERE1($i) + CMU_TEST_INCPATH($i, db) + if test "$ac_cv_found_db_inc" = "yes"; then + ac_cv_db_where_inc=$i + AC_MSG_RESULT(found) + break + else + AC_MSG_RESULT(not found) + fi + done +]) + +# +# Test for lib files +# + +AC_DEFUN([CMU_DB3_LIB_WHERE1], [ +AC_REQUIRE([CMU_AFS]) +AC_REQUIRE([CMU_KRB4]) +saved_LIBS=$LIBS + LIBS="$saved_LIBS -L$1 -ldb-3" +AC_TRY_LINK([#include ], +[db_env_create(NULL, 0);], +[ac_cv_found_db_3_lib=yes], +ac_cv_found_db_3_lib=no) +LIBS=$saved_LIBS +]) +AC_DEFUN([CMU_DB4_LIB_WHERE1], [ +AC_REQUIRE([CMU_AFS]) +AC_REQUIRE([CMU_KRB4]) +saved_LIBS=$LIBS +LIBS="$saved_LIBS -L$1 -ldb-4" +AC_TRY_LINK([#include ], +[db_env_create(NULL, 0);], +[ac_cv_found_db_4_lib=yes], +ac_cv_found_db_4_lib=no) +LIBS=$saved_LIBS +]) + +AC_DEFUN([CMU_DB_LIB_WHERE], [ + for i in $1; do + AC_MSG_CHECKING(for db libraries in $i) +if test "$enable_db4" = "yes"; then + CMU_DB4_LIB_WHERE1($i) + CMU_TEST_LIBPATH($i, [db-4]) + ac_cv_found_db_lib=$ac_cv_found_db_4_lib +else + CMU_DB3_LIB_WHERE1($i) + CMU_TEST_LIBPATH($i, [db-3]) + ac_cv_found_db_lib=$ac_cv_found_db_3_lib +fi + if test "$ac_cv_found_db_lib" = "yes" ; then + ac_cv_db_where_lib=$i + AC_MSG_RESULT(found) + break + else + AC_MSG_RESULT(not found) + fi + done +]) + +AC_DEFUN([CMU_USE_DB], [ +AC_REQUIRE([CMU_FIND_LIB_SUBDIR]) +AC_ARG_WITH(db, + [ --with-db=PREFIX Compile with db support], + [if test "X$with_db" = "X"; then + with_db=yes + fi]) +AC_ARG_WITH(db-lib, + [ --with-db-lib=dir use db libraries in dir], + [if test "$withval" = "yes" -o "$withval" = "no"; then + AC_MSG_ERROR([No argument for --with-db-lib]) + fi]) +AC_ARG_WITH(db-include, + [ --with-db-include=dir use db headers in dir], + [if test "$withval" = "yes" -o "$withval" = "no"; then + AC_MSG_ERROR([No argument for --with-db-include]) + fi]) +AC_ARG_ENABLE(db4, + [ --enable-db4 use db 4.x libraries]) + + if test "X$with_db" != "X"; then + if test "$with_db" != "yes"; then + ac_cv_db_where_lib=$with_db/$CMU_LIB_SUBDIR + ac_cv_db_where_inc=$with_db/include + fi + fi + + if test "X$with_db_lib" != "X"; then + ac_cv_db_where_lib=$with_db_lib + fi + if test "X$ac_cv_db_where_lib" = "X"; then + CMU_DB_LIB_WHERE(/usr/athena/$CMU_LIB_SUBDIR /usr/$CMU_LIB_SUBDIR /usr/local/$CMU_LIB_SUBDIR) + fi + + if test "X$with_db_include" != "X"; then + ac_cv_db_where_inc=$with_db_include + fi + if test "X$ac_cv_db_where_inc" = "X"; then + CMU_DB_INC_WHERE(/usr/athena/include /usr/local/include) + fi + + AC_MSG_CHECKING(whether to include db) + if test "X$ac_cv_db_where_lib" = "X" -o "X$ac_cv_db_where_inc" = "X"; then + ac_cv_found_db=no + AC_MSG_RESULT(no) + else + ac_cv_found_db=yes + AC_MSG_RESULT(yes) + DB_INC_DIR=$ac_cv_db_where_inc + DB_LIB_DIR=$ac_cv_db_where_lib + DB_INC_FLAGS="-I${DB_INC_DIR}" + if test "$enable_db4" = "yes"; then + DB_LIB_FLAGS="-L${DB_LIB_DIR} -ldb-4" + else + DB_LIB_FLAGS="-L${DB_LIB_DIR} -ldb-3" + fi + dnl Do not force configure.in to put these in CFLAGS and LIBS unconditionally + dnl Allow makefile substitutions.... + AC_SUBST(DB_INC_FLAGS) + AC_SUBST(DB_LIB_FLAGS) + if test "X$RPATH" = "X"; then + RPATH="" + fi + case "${host}" in + *-*-linux*) + if test "X$RPATH" = "X"; then + RPATH="-Wl,-rpath,${DB_LIB_DIR}" + else + RPATH="${RPATH}:${DB_LIB_DIR}" + fi + ;; + *-*-hpux*) + if test "X$RPATH" = "X"; then + RPATH="-Wl,+b${DB_LIB_DIR}" + else + RPATH="${RPATH}:${DB_LIB_DIR}" + fi + ;; + *-*-irix*) + if test "X$RPATH" = "X"; then + RPATH="-Wl,-rpath,${DB_LIB_DIR}" + else + RPATH="${RPATH}:${DB_LIB_DIR}" + fi + ;; + *-*-solaris2*) + if test "$ac_cv_prog_gcc" = yes; then + if test "X$RPATH" = "X"; then + RPATH="-Wl,-R${DB_LIB_DIR}" + else + RPATH="${RPATH}:${DB_LIB_DIR}" + fi + else + RPATH="${RPATH} -R${DB_LIB_DIR}" + fi + ;; + esac + AC_SUBST(RPATH) + fi + ]) + + + +dnl ---- CUT HERE --- + +dnl These are the Cyrus Berkeley DB macros. In an ideal world these would be +dnl identical to the above. + +dnl They are here so that they can be shared between Cyrus IMAPd +dnl and Cyrus SASL with relative ease. + +dnl The big difference between this and the ones above is that we don't assume +dnl that we know the name of the library, and we try a lot of permutations +dnl instead. We also assume that DB4 is acceptable. + +dnl When we're done, there will be a BDB_LIBADD and a BDB_INCADD which should +dnl be used when necessary. We should probably be smarter about our RPATH +dnl handling. + +dnl Call these with BERKELEY_DB_CHK. + +dnl We will also set $dblib to "berkeley" if we are successful, "no" otherwise. + +dnl this is unbelievably painful due to confusion over what db-3 should be +dnl named and where the db-3 header file is located. arg. +AC_DEFUN([CYRUS_BERKELEY_DB_CHK_LIB], +[ + BDB_SAVE_LDFLAGS=$LDFLAGS + + if test -d $with_bdb_lib; then + CMU_ADD_LIBPATH_TO($with_bdb_lib, LDFLAGS) + CMU_ADD_LIBPATH_TO($with_bdb_lib, BDB_LIBADD) + else + BDB_LIBADD="" + fi + + saved_LIBS=$LIBS + for dbname in ${with_bdb} \ + db-5.2 db5.2 db52 \ + db-5.1 db5.2 db51 \ + db-5.0 db5.2 db50 \ + db-4.8 db4.8 db48 \ + db-4.7 db4.7 db47 \ + db-4.6 db4.6 db46 \ + db-4.5 db4.5 db45 \ + db-4.4 db4.4 db44 \ + db-4.3 db4.3 db43 \ + db-4.2 db4.2 db42 \ + db-4.1 db4.1 db41 \ + db-4.0 db4.0 db40 db-4 db4 \ + db-3.3 db3.3 db33 \ + db-3.2 db3.2 db32 \ + db-3.1 db3.1 db31 \ + db-3.0 db3.0 db30 db-3 db3 \ + db + do + LIBS="$saved_LIBS -l$dbname" + AC_TRY_LINK([#include +#include ], + [db_create(NULL, NULL, 0);], + BDB_LIBADD="$BDB_LIBADD -l$dbname"; dblib="berkeley"; dbname=db, + dblib="no") + if test "$dblib" = "berkeley"; then break; fi + done + if test "$dblib" = "no"; then + LIBS="$saved_LIBS -ldb" + AC_TRY_LINK([#include +#include ], + [db_open(NULL, 0, 0, 0, NULL, NULL, NULL);], + BDB_LIBADD="$BDB_LIBADD -ldb"; dblib="berkeley"; dbname=db, + dblib="no") + fi + LIBS=$saved_LIBS + + LDFLAGS=$BDB_SAVE_LDFLAGS +]) + +AC_DEFUN([CYRUS_BERKELEY_DB_OPTS], +[ +AC_ARG_WITH(bdb-libdir, + [ --with-bdb-libdir=DIR Berkeley DB lib files are in DIR], + with_bdb_lib=$withval, + [ test "${with_bdb_lib+set}" = set || with_bdb_lib=none]) +AC_ARG_WITH(bdb-incdir, + [ --with-bdb-incdir=DIR Berkeley DB include files are in DIR], + with_bdb_inc=$withval, + [ test "${with_bdb_inc+set}" = set || with_bdb_inc=none ]) +]) + +AC_DEFUN([CYRUS_BERKELEY_DB_CHK], +[ + AC_REQUIRE([CYRUS_BERKELEY_DB_OPTS]) + + cmu_save_CPPFLAGS=$CPPFLAGS + + if test -d $with_bdb_inc; then + CPPFLAGS="$CPPFLAGS -I$with_bdb_inc" + BDB_INCADD="-I$with_bdb_inc" + else + BDB_INCADD="" + fi + + dnl Note that FreeBSD puts it in a wierd place + dnl (but they should use with-bdb-incdir) + AC_CHECK_HEADER(db.h, + [CYRUS_BERKELEY_DB_CHK_LIB()], + dblib="no") + + CPPFLAGS=$cmu_save_CPPFLAGS +]) diff --git a/cmulocal/bsd_sockets.m4 b/cmulocal/bsd_sockets.m4 new file mode 100644 index 00000000..42b3c7fa --- /dev/null +++ b/cmulocal/bsd_sockets.m4 @@ -0,0 +1,38 @@ +dnl bsd_sockets.m4--which socket libraries do we need? +dnl Derrick Brashear +dnl from Zephyr + +dnl Hacked on by Rob Earhart to not just toss stuff in LIBS +dnl It now puts everything required for sockets into LIB_SOCKET + +AC_DEFUN([CMU_SOCKETS], [ + save_LIBS="$LIBS" + LIB_SOCKET="" + AC_CHECK_FUNC(connect, :, + [AC_CHECK_LIB(nsl, gethostbyname, + LIB_SOCKET="-lnsl $LIB_SOCKET") + AC_CHECK_LIB(socket, connect, + LIB_SOCKET="-lsocket $LIB_SOCKET")] + ) + LIBS="$LIB_SOCKET $save_LIBS" + AC_CHECK_FUNC(res_search, :, + [LIBS="-lresolv $LIB_SOCKET $save_LIBS" + AC_TRY_LINK([[ +#include +#include +#include +#ifdef HAVE_ARPA_NAMESER_COMPAT_H +#include +#endif +#include ]],[[ +const char host[12]="openafs.org"; +u_char ans[1024]; +res_search( host, C_IN, T_MX, (u_char *)&ans, sizeof(ans)); +return 0; +]], LIB_SOCKET="-lresolv $LIB_SOCKET") + ]) + LIBS="$LIB_SOCKET $save_LIBS" + AC_CHECK_FUNCS(dn_expand dns_lookup) + LIBS="$save_LIBS" + AC_SUBST(LIB_SOCKET) + ]) diff --git a/cmulocal/c-attribute.m4 b/cmulocal/c-attribute.m4 new file mode 100644 index 00000000..30a4049c --- /dev/null +++ b/cmulocal/c-attribute.m4 @@ -0,0 +1,26 @@ +dnl +dnl Test for __attribute__ +dnl + +AC_DEFUN([CMU_C___ATTRIBUTE__], [ +AC_MSG_CHECKING(for __attribute__) +AC_CACHE_VAL(ac_cv___attribute__, [ +AC_TRY_COMPILE([ +#include +static void foo(void) __attribute__ ((noreturn)); + +static void +foo(void) +{ +exit(1); +} +], +[ +], +ac_cv___attribute__=yes, +ac_cv___attribute__=no)]) +if test "$ac_cv___attribute__" = "yes"; then +AC_DEFINE(HAVE___ATTRIBUTE__, 1, [define if your compiler has __attribute__]) +fi +AC_MSG_RESULT($ac_cv___attribute__) +]) diff --git a/cmulocal/common.m4 b/cmulocal/common.m4 new file mode 100644 index 00000000..51cdcd80 --- /dev/null +++ b/cmulocal/common.m4 @@ -0,0 +1,59 @@ +AC_DEFUN([CMU_TEST_LIBPATH], [ +changequote(<<, >>) +define(<>, translit(ac_cv_found_$2_lib, <<- *>>, <<__p>>)) +changequote([, ]) +if test "$CMU_AC_CV_FOUND" = "yes"; then + if test \! -r "$1/lib$2.a" -a \! -r "$1/lib$2.so" -a \! -r "$1/lib$2.sl" -a \! -r "$1/lib$2.dylib"; then + CMU_AC_CV_FOUND=no + fi +fi +]) + +AC_DEFUN([CMU_TEST_INCPATH], [ +changequote(<<, >>) +define(<>, translit(ac_cv_found_$2_inc, [ *], [_p])) +changequote([, ]) +if test "$CMU_AC_CV_FOUND" = "yes"; then + if test \! -r "$1/$2.h"; then + CMU_AC_CV_FOUND=no + fi +fi +]) + +dnl CMU_CHECK_HEADER_NOCACHE(HEADER-FILE, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +AC_DEFUN([CMU_CHECK_HEADER_NOCACHE], +[dnl Do the transliteration at runtime so arg 1 can be a shell variable. +ac_safe=`echo "$1" | sed 'y%./+-%__p_%'` +AC_MSG_CHECKING([for $1]) +AC_TRY_CPP([#include <$1>], eval "ac_cv_header_$ac_safe=yes", + eval "ac_cv_header_$ac_safe=no") +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) +else + AC_MSG_RESULT(no) +ifelse([$3], , , [$3 +])dnl +fi +]) + +AC_DEFUN([CMU_FIND_LIB_SUBDIR], +[dnl +AC_ARG_WITH([lib-subdir], AC_HELP_STRING([--with-lib-subdir=DIR],[Find libraries in DIR instead of lib])) +AC_CHECK_SIZEOF(long) +AC_CACHE_CHECK([what directory libraries are found in], [ac_cv_cmu_lib_subdir], +[test "X$with_lib_subdir" = "Xyes" && with_lib_subdir= +test "X$with_lib_subdir" = "Xno" && with_lib_subdir= +if test "X$with_lib_subdir" = "X" ; then + ac_cv_cmu_lib_subdir=lib + if test $ac_cv_sizeof_long -eq 4 ; then + test -d /usr/lib32 && ac_cv_cmu_lib_subdir=lib32 + fi + if test $ac_cv_sizeof_long -eq 8 ; then + test -d /usr/lib64 && ac_cv_cmu_lib_subdir=lib64 + fi +else + ac_cv_cmu_lib_subdir=$with_lib_subdir +fi]) +AC_SUBST(CMU_LIB_SUBDIR, $ac_cv_cmu_lib_subdir) +]) diff --git a/cmulocal/cyrus.m4 b/cmulocal/cyrus.m4 new file mode 100644 index 00000000..0f9ac483 --- /dev/null +++ b/cmulocal/cyrus.m4 @@ -0,0 +1,44 @@ +dnl +dnl Additional macros for configure.in packaged up for easier theft. +dnl tjs@andrew.cmu.edu 6-may-1998 +dnl + +dnl It would be good if ANDREW_ADD_LIBPATH could detect if something was +dnl already there and not redundantly add it if it is. + +dnl add -L(arg), and possibly (runpath switch)(arg), to LDFLAGS +dnl (so the runpath for shared libraries is set). +AC_DEFUN([CMU_ADD_LIBPATH], [ + # this is CMU ADD LIBPATH + if test "$andrew_cv_runpath_switch" = "none" ; then + LDFLAGS="-L$1 ${LDFLAGS}" + else + LDFLAGS="-L$1 $andrew_cv_runpath_switch$1 ${LDFLAGS}" + fi +]) + +dnl add -L(1st arg), and possibly (runpath switch)(1st arg), to (2nd arg) +dnl (so the runpath for shared libraries is set). +AC_DEFUN([CMU_ADD_LIBPATH_TO], [ + # this is CMU ADD LIBPATH TO + if test "$andrew_cv_runpath_switch" = "none" ; then + $2="-L$1 ${$2}" + else + $2="-L$1 ${$2} $andrew_cv_runpath_switch$1" + fi +]) + +dnl runpath initialization +AC_DEFUN([CMU_GUESS_RUNPATH_SWITCH], [ + # CMU GUESS RUNPATH SWITCH + AC_CACHE_CHECK(for runpath switch, andrew_cv_runpath_switch, [ + # first, try -R + SAVE_LDFLAGS="${LDFLAGS}" + LDFLAGS="-R /usr/lib" + AC_TRY_LINK([],[],[andrew_cv_runpath_switch="-R"], [ + LDFLAGS="-Wl,-rpath,/usr/lib" + AC_TRY_LINK([],[],[andrew_cv_runpath_switch="-Wl,-rpath,"], + [andrew_cv_runpath_switch="none"]) + ]) + LDFLAGS="${SAVE_LDFLAGS}" + ])]) diff --git a/cmulocal/init_automake.m4 b/cmulocal/init_automake.m4 new file mode 100644 index 00000000..fb2aff15 --- /dev/null +++ b/cmulocal/init_automake.m4 @@ -0,0 +1,7 @@ +dnl init_automake.m4--cmulocal automake setup macro +dnl Rob Earhart + +AC_DEFUN([CMU_INIT_AUTOMAKE], [ + AC_REQUIRE([AM_INIT_AUTOMAKE]) + ACLOCAL="$ACLOCAL -I \$(top_srcdir)/cmulocal" + ]) diff --git a/cmulocal/ipv6.m4 b/cmulocal/ipv6.m4 new file mode 100644 index 00000000..7e50c961 --- /dev/null +++ b/cmulocal/ipv6.m4 @@ -0,0 +1,111 @@ +dnl See whether we can use IPv6 related functions +dnl contributed by Hajimu UMEMOTO + +AC_DEFUN([IPv6_CHECK_FUNC], [ +AC_CHECK_FUNC($1, [dnl + ac_cv_lib_socket_$1=no + ac_cv_lib_inet6_$1=no +], [dnl + AC_CHECK_LIB(socket, $1, [dnl + LIBS="$LIBS -lsocket" + ac_cv_lib_inet6_$1=no + ], [dnl + AC_MSG_CHECKING([whether your system has IPv6 directory]) + AC_CACHE_VAL(ipv6_cv_dir, [dnl + for ipv6_cv_dir in /usr/local/v6 /usr/inet6 no; do + if test $ipv6_cv_dir = no -o -d $ipv6_cv_dir; then + break + fi + done])dnl + AC_MSG_RESULT($ipv6_cv_dir) + if test $ipv6_cv_dir = no; then + ac_cv_lib_inet6_$1=no + else + if test x$ipv6_libinet6 = x; then + ipv6_libinet6=no + SAVELDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -L$ipv6_cv_dir/lib" + fi + AC_CHECK_LIB(inet6, $1, [dnl + if test $ipv6_libinet6 = no; then + ipv6_libinet6=yes + LIBS="$LIBS -linet6" + fi],)dnl + if test $ipv6_libinet6 = no; then + LDFLAGS="$SAVELDFLAGS" + fi + fi])dnl +])dnl +ipv6_cv_$1=no +if test $ac_cv_func_$1 = yes -o $ac_cv_lib_socket_$1 = yes \ + -o $ac_cv_lib_inet6_$1 = yes +then + ipv6_cv_$1=yes +fi +if test $ipv6_cv_$1 = no; then + if test $1 = getaddrinfo; then + for ipv6_cv_pfx in o n; do + AC_EGREP_HEADER(${ipv6_cv_pfx}$1, netdb.h, + [AC_CHECK_FUNC(${ipv6_cv_pfx}$1)]) + if eval test X\$ac_cv_func_${ipv6_cv_pfx}$1 = Xyes; then + AC_DEFINE(HAVE_GETADDRINFO,[],[Do we have a getaddrinfo?]) + ipv6_cv_$1=yes + break + fi + done + fi +fi +if test $ipv6_cv_$1 = yes; then + ifelse([$2], , :, [$2]) +else + ifelse([$3], , :, [$3]) +fi]) + + +dnl See whether we have ss_family in sockaddr_storage +AC_DEFUN([IPv6_CHECK_SS_FAMILY], [ +AC_MSG_CHECKING([whether you have ss_family in struct sockaddr_storage]) +AC_CACHE_VAL(ipv6_cv_ss_family, [dnl +AC_TRY_COMPILE([#include +#include ], + [struct sockaddr_storage ss; int i = ss.ss_family;], + [ipv6_cv_ss_family=yes], [ipv6_cv_ss_family=no])])dnl +if test $ipv6_cv_ss_family = yes; then + ifelse([$1], , AC_DEFINE(HAVE_SS_FAMILY,[],[Is there an ss_family in sockaddr_storage?]), [$1]) +else + ifelse([$2], , :, [$2]) +fi +AC_MSG_RESULT($ipv6_cv_ss_family)]) + + +dnl whether you have sa_len in struct sockaddr +AC_DEFUN([IPv6_CHECK_SA_LEN], [ +AC_MSG_CHECKING([whether you have sa_len in struct sockaddr]) +AC_CACHE_VAL(ipv6_cv_sa_len, [dnl +AC_TRY_COMPILE([#include +#include ], + [struct sockaddr sa; int i = sa.sa_len;], + [ipv6_cv_sa_len=yes], [ipv6_cv_sa_len=no])])dnl +if test $ipv6_cv_sa_len = yes; then + ifelse([$1], , AC_DEFINE(HAVE_SOCKADDR_SA_LEN,[],[Does sockaddr have an sa_len?]), [$1]) +else + ifelse([$2], , :, [$2]) +fi +AC_MSG_RESULT($ipv6_cv_sa_len)]) + + +dnl See whether sys/socket.h has socklen_t +AC_DEFUN([IPv6_CHECK_SOCKLEN_T], [ +AC_MSG_CHECKING(for socklen_t) +AC_CACHE_VAL(ipv6_cv_socklen_t, [dnl +AC_TRY_LINK([#include +#include ], + [socklen_t len = 0;], + [ipv6_cv_socklen_t=yes], [ipv6_cv_socklen_t=no])])dnl +if test $ipv6_cv_socklen_t = yes; then + ifelse([$1], , AC_DEFINE(HAVE_SOCKLEN_T,[],[Do we have a socklen_t?]), [$1]) +else + ifelse([$2], , :, [$2]) +fi +AC_MSG_RESULT($ipv6_cv_socklen_t)]) + diff --git a/config/kerberos_v4.m4 b/cmulocal/kerberos_v4.m4 similarity index 95% rename from config/kerberos_v4.m4 rename to cmulocal/kerberos_v4.m4 index 78847439..0e9b58c5 100644 --- a/config/kerberos_v4.m4 +++ b/cmulocal/kerberos_v4.m4 @@ -89,18 +89,18 @@ AC_DEFUN([SASL_KERBEROS_V4_CHK], [ dnl if we were ambitious, we would look more aggressively for the dnl krb4 install if test -d ${krb4}; then - AC_CACHE_CHECK(for Kerberos includes, cyrus_krbinclude, [ + AC_CACHE_CHECK(for Kerberos includes, cyrus_cv_krbinclude, [ for krbhloc in include/kerberosIV include/kerberos include do if test -f ${krb4}/${krbhloc}/krb.h ; then - cyrus_krbinclude=${krb4}/${krbhloc} + cyrus_cv_krbinclude=${krb4}/${krbhloc} break fi done ]) - if test -n "${cyrus_krbinclude}"; then - CPPFLAGS="$CPPFLAGS -I${cyrus_krbinclude}" + if test -n "${cyrus_cv_krbinclude}"; then + CPPFLAGS="$CPPFLAGS -I${cyrus_cv_krbinclude}" fi LDFLAGS="$LDFLAGS -L$krb4/lib" fi diff --git a/cmulocal/openldap.m4 b/cmulocal/openldap.m4 new file mode 100644 index 00000000..5d0578f0 --- /dev/null +++ b/cmulocal/openldap.m4 @@ -0,0 +1,35 @@ +dnl +dnl macros for configure.in to detect openldap +dnl + +dnl +dnl Check for OpenLDAP version compatility +AC_DEFUN([CMU_OPENLDAP_API], +[AC_CACHE_CHECK([OpenLDAP api], [cmu_cv_openldap_api],[ + AC_EGREP_CPP(__openldap_api,[ +#include + +#ifdef LDAP_API_FEATURE_X_OPENLDAP +char *__openldap_api = LDAP_API_FEATURE_X_OPENLDAP; +#endif +], [cmu_cv_openldap_api=yes], [cmu_cv_openldap_api=no])]) +]) + +dnl +dnl Check for OpenLDAP version compatility +AC_DEFUN([CMU_OPENLDAP_COMPAT], +[AC_CACHE_CHECK([OpenLDAP version], [cmu_cv_openldap_compat],[ + AC_EGREP_CPP(__openldap_compat,[ +#include + +/* Require 2.1.27+ and 2.2.6+ */ +#if LDAP_VENDOR_VERSION_MAJOR == 2 && LDAP_VENDOR_VERSION_MINOR == 1 && LDAP_VENDOR_VERSION_PATCH > 26 +char *__openldap_compat = "2.1.27 or better okay"; +#elif LDAP_VENDOR_VERSION_MAJOR == 2 && LDAP_VENDOR_VERSION_MINOR == 2 && LDAP_VENDOR_VERSION_PATCH > 5 +char *__openldap_compat = "2.2.6 or better okay"; +#elif LDAP_VENDOR_VERSION_MAJOR == 2 && LDAP_VENDOR_VERSION_MINOR > 2 +char *__openldap_compat = "2.3 or better okay" +#endif +], [cmu_cv_openldap_compat=yes], [cmu_cv_openldap_compat=no])]) +]) + diff --git a/cmulocal/openssl.m4 b/cmulocal/openssl.m4 new file mode 100644 index 00000000..b1d7857a --- /dev/null +++ b/cmulocal/openssl.m4 @@ -0,0 +1,47 @@ +dnl +dnl macros for configure.in to detect openssl +dnl + +AC_DEFUN([CMU_HAVE_OPENSSL], [ +AC_REQUIRE([CMU_FIND_LIB_SUBDIR]) +AC_ARG_WITH(openssl, + [AS_HELP_STRING([--with-openssl=DIR], [use OpenSSL from DIR])], + with_openssl=$withval, with_openssl="yes") + + save_CPPFLAGS=$CPPFLAGS + save_LDFLAGS=$LDFLAGS + + if test -d $with_openssl; then + CPPFLAGS="${CPPFLAGS} -I${with_openssl}/include" + CMU_ADD_LIBPATH(${with_openssl}/$CMU_LIB_SUBDIR) + fi + +case "$with_openssl" in + no) + with_openssl="no";; + *) + dnl if openssl has been compiled with the rsaref2 libraries, + dnl we need to include the rsaref libraries in the crypto check + LIB_RSAREF="" + AC_CHECK_LIB(rsaref, RSAPublicEncrypt, + cmu_have_rsaref=yes; + [AC_CHECK_LIB(RSAglue, RSAPublicEncrypt, + LIB_RSAREF="-lRSAglue -lrsaref", + LIB_RSAREF="-lrsaref")], + cmu_have_rsaref=no) + + AC_CHECK_HEADER(openssl/evp.h, [ + AC_CHECK_LIB(crypto, EVP_DigestInit, + with_openssl="yes", + with_openssl="no", $LIB_RSAREF)], + with_openssl=no) + ;; +esac + + if test "$with_openssl" != "no"; then + AC_DEFINE(HAVE_OPENSSL,[],[Do we have OpenSSL?]) + else + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + fi +]) diff --git a/config/plain.m4 b/cmulocal/plain.m4 similarity index 100% rename from config/plain.m4 rename to cmulocal/plain.m4 diff --git a/cmulocal/sasl2.m4 b/cmulocal/sasl2.m4 new file mode 100644 index 00000000..795d347b --- /dev/null +++ b/cmulocal/sasl2.m4 @@ -0,0 +1,519 @@ +# sasl2.m4--sasl2 libraries and includes +# Rob Siemborski + +# SASL2_CRYPT_CHK +# --------------- +AC_DEFUN([SASL_GSSAPI_CHK], +[AC_REQUIRE([SASL2_CRYPT_CHK]) +AC_REQUIRE([CMU_SOCKETS]) +AC_ARG_ENABLE([gssapi], + [AC_HELP_STRING([--enable-gssapi=], + [enable GSSAPI authentication [yes]])], + [gssapi=$enableval], + [gssapi=yes]) +AC_ARG_WITH([gss_impl], + [AC_HELP_STRING([--with-gss_impl={heimdal|mit|cybersafe|seam|auto}], + [choose specific GSSAPI implementation [[auto]]])], + [gss_impl=$withval], + [gss_impl=auto]) + +if test "$gssapi" != no; then + platform= + case "${host}" in + *-*-linux*) + platform=__linux + ;; + *-*-hpux*) + platform=__hpux + ;; + *-*-irix*) + platform=__irix + ;; + *-*-solaris2*) +# When should we use __sunos? + platform=__solaris + ;; + *-*-aix*) +###_AIX + platform=__aix + ;; + *) + AC_WARN([The system type is not recognized. If you believe that CyberSafe GSSAPI works on this platform, please update the configure script]) + if test "$gss_impl" = "cybersafe"; then + AC_MSG_ERROR([CyberSafe was forced, cannot continue as platform is not supported]) + fi + ;; + esac + + cmu_saved_CPPFLAGS=$CPPFLAGS + + if test -d ${gssapi}; then + CPPFLAGS="$CPPFLAGS -I$gssapi/include" +# We want to keep -I in our CPPFLAGS, but only if we succeed + cmu_saved_CPPFLAGS=$CPPFLAGS +### I am not sure how useful is this (and whether this is required at all +### especially when we have to provide two -L flags for new CyberSafe + LDFLAGS="$LDFLAGS -L$gssapi/lib" + + if test -n "$platform"; then + if test "$gss_impl" = "auto" -o "$gss_impl" = "cybersafe"; then + CPPFLAGS="$CPPFLAGS -D$platform" + if test -d "${gssapi}/appsec-sdk/include"; then + CPPFLAGS="$CPPFLAGS -I${gssapi}/appsec-sdk/include" + fi + fi + fi + fi + AC_CHECK_HEADER([gssapi.h],, + [AC_CHECK_HEADER([gssapi/gssapi.h],, [gssapi=no])]) + AC_CHECK_HEADERS(gssapi/gssapi_ext.h) + CPPFLAGS=$cmu_saved_CPPFLAGS + +fi + +if test "$gssapi" != no; then + if test "$ac_cv_header_gssapi_h" = "yes" -o "$ac_cv_header_gssapi_gssapi_h" = "yes"; then + AC_DEFINE(HAVE_GSSAPI_H,,[Define if you have the gssapi.h header file]) + fi + + # We need to find out which gssapi implementation we are + # using. Supported alternatives are: MIT Kerberos 5, + # Heimdal Kerberos 5 (http://www.pdc.kth.se/heimdal), + # CyberSafe Kerberos 5 (http://www.cybersafe.com/) + # and Sun SEAM (http://wwws.sun.com/software/security/kerberos/) + # + # The choice is reflected in GSSAPIBASE_LIBS + + AC_CHECK_LIB(resolv,res_search) + if test -d ${gssapi}; then + gssapi_dir="${gssapi}/lib" + GSSAPIBASE_LIBS="-L$gssapi_dir" + GSSAPIBASE_STATIC_LIBS="-L$gssapi_dir" + else + # FIXME: This is only used for building cyrus, and then only as + # a real hack. it needs to be fixed. + gssapi_dir="/usr/local/lib" + fi + + # Check a full link against the Heimdal libraries. + # If this fails, check a full link against the MIT libraries. + # If this fails, check a full link against the CyberSafe libraries. + # If this fails, check a full link against the Solaris 8 and up libgss. + + if test "$gss_impl" = "auto" -o "$gss_impl" = "heimdal"; then + gss_failed=0 + AC_CHECK_LIB(gssapi,gss_unwrap,gss_impl="heimdal",gss_failed=1, + ${GSSAPIBASE_LIBS} -lgssapi -lkrb5 -lasn1 -lroken ${LIB_CRYPT} ${LIB_DES} -lcom_err ${LIB_SOCKET}) + if test "$gss_impl" != "auto" -a "$gss_failed" = "1"; then + gss_impl="failed" + fi + fi + + if test "$gss_impl" = "auto" -o "$gss_impl" = "mit"; then + # check for libkrb5support first + AC_CHECK_LIB(krb5support,krb5int_getspecific,K5SUP=-lkrb5support K5SUPSTATIC=$gssapi_dir/libkrb5support.a,,${LIB_SOCKET}) + + gss_failed=0 + AC_CHECK_LIB(gssapi_krb5,gss_unwrap,gss_impl="mit",gss_failed=1, + ${GSSAPIBASE_LIBS} -lgssapi_krb5 -lkrb5 -lk5crypto -lcom_err ${K5SUP} ${LIB_SOCKET}) + if test "$gss_impl" != "auto" -a "$gss_failed" = "1"; then + gss_impl="failed" + fi + fi + + # For Cybersafe one has to set a platform define in order to make compilation work + if test "$gss_impl" = "auto" -o "$gss_impl" = "cybersafe"; then + + cmu_saved_CPPFLAGS=$CPPFLAGS + cmu_saved_GSSAPIBASE_LIBS=$GSSAPIBASE_LIBS +# FIXME - Note that the libraries are in .../lib64 for 64bit kernels + if test -d "${gssapi}/appsec-rt/lib"; then + GSSAPIBASE_LIBS="$GSSAPIBASE_LIBS -L${gssapi}/appsec-rt/lib" + fi + CPPFLAGS="$CPPFLAGS -D$platform" + if test -d "${gssapi}/appsec-sdk/include"; then + CPPFLAGS="$CPPFLAGS -I${gssapi}/appsec-sdk/include" + fi + + gss_failed=0 + +# Check for CyberSafe with two libraries first, than fall back to a single +# library (older CyberSafe) + + unset ac_cv_lib_gss_csf_gss_acq_user + AC_CHECK_LIB(gss,csf_gss_acq_user,gss_impl="cybersafe03", + [unset ac_cv_lib_gss_csf_gss_acq_user; + AC_CHECK_LIB(gss,csf_gss_acq_user,gss_impl="cybersafe", + gss_failed=1,$GSSAPIBASE_LIBS -lgss)], + [${GSSAPIBASE_LIBS} -lgss -lcstbk5]) + + if test "$gss_failed" = "1"; then +# Restore variables + GSSAPIBASE_LIBS=$cmu_saved_GSSAPIBASE_LIBS + CPPFLAGS=$cmu_saved_CPPFLAGS + + if test "$gss_impl" != "auto"; then + gss_impl="failed" + fi + fi + fi + + if test "$gss_impl" = "auto" -o "$gss_impl" = "seam"; then + gss_failed=0 + AC_CHECK_LIB(gss,gss_unwrap,gss_impl="seam",gss_failed=1,-lgss) + if test "$gss_impl" != "auto" -a "$gss_failed" = "1"; then + gss_impl="failed" + fi + fi + + if test "$gss_impl" = "mit"; then + GSSAPIBASE_LIBS="$GSSAPIBASE_LIBS -lgssapi_krb5 -lkrb5 -lk5crypto -lcom_err ${K5SUP}" + GSSAPIBASE_STATIC_LIBS="$GSSAPIBASE_LIBS $gssapi_dir/libgssapi_krb5.a $gssapi_dir/libkrb5.a $gssapi_dir/libk5crypto.a $gssapi_dir/libcom_err.a ${K5SUPSTATIC}" + elif test "$gss_impl" = "heimdal"; then + CPPFLAGS="$CPPFLAGS -DKRB5_HEIMDAL" + GSSAPIBASE_LIBS="$GSSAPIBASE_LIBS -lgssapi -lkrb5 -lasn1 -lroken ${LIB_CRYPT} ${LIB_DES} -lcom_err" + GSSAPIBASE_STATIC_LIBS="$GSSAPIBASE_STATIC_LIBS $gssapi_dir/libgssapi.a $gssapi_dir/libkrb5.a $gssapi_dir/libasn1.a $gssapi_dir/libroken.a $gssapi_dir/libcom_err.a ${LIB_CRYPT}" + elif test "$gss_impl" = "cybersafe03"; then +# Version of CyberSafe with two libraries + CPPFLAGS="$CPPFLAGS -D$platform -I${gssapi}/appsec-sdk/include" + GSSAPIBASE_LIBS="$GSSAPIBASE_LIBS -lgss -lcstbk5" + # there is no static libgss for CyberSafe + GSSAPIBASE_STATIC_LIBS=none + elif test "$gss_impl" = "cybersafe"; then + CPPFLAGS="$CPPFLAGS -D$platform -I${gssapi}/appsec-sdk/include" + GSSAPIBASE_LIBS="$GSSAPIBASE_LIBS -lgss" + # there is no static libgss for CyberSafe + GSSAPIBASE_STATIC_LIBS=none + elif test "$gss_impl" = "seam"; then + GSSAPIBASE_LIBS=-lgss + # there is no static libgss on Solaris 8 and up + GSSAPIBASE_STATIC_LIBS=none + elif test "$gss_impl" = "failed"; then + gssapi="no" + GSSAPIBASE_LIBS= + GSSAPIBASE_STATIC_LIBS= + AC_WARN([Disabling GSSAPI - specified library not found]) + else + gssapi="no" + GSSAPIBASE_LIBS= + GSSAPIBASE_STATIC_LIBS= + AC_WARN([Disabling GSSAPI - no library]) + fi +fi + +# +# Cybersafe defines both GSS_C_NT_HOSTBASED_SERVICE and GSS_C_NT_USER_NAME +# in gssapi\rfckrb5.h +# +if test "$gssapi" != "no"; then + if test "$gss_impl" = "cybersafe" -o "$gss_impl" = "cybersafe03"; then + AC_EGREP_CPP(hostbased_service_gss_nt_yes, + [#include + #ifdef GSS_C_NT_HOSTBASED_SERVICE + hostbased_service_gss_nt_yes + #endif], + [AC_DEFINE(HAVE_GSS_C_NT_HOSTBASED_SERVICE,, + [Define if your GSSAPI implementation defines GSS_C_NT_HOSTBASED_SERVICE])], + [AC_WARN([Cybersafe define not found])]) + + elif test "$ac_cv_header_gssapi_h" = "yes"; then + AC_EGREP_HEADER(GSS_C_NT_HOSTBASED_SERVICE, gssapi.h, + [AC_DEFINE(HAVE_GSS_C_NT_HOSTBASED_SERVICE,, + [Define if your GSSAPI implementation defines GSS_C_NT_HOSTBASED_SERVICE])]) + elif test "$ac_cv_header_gssapi_gssapi_h"; then + AC_EGREP_HEADER(GSS_C_NT_HOSTBASED_SERVICE, gssapi/gssapi.h, + [AC_DEFINE(HAVE_GSS_C_NT_HOSTBASED_SERVICE,, + [Define if your GSSAPI implementation defines GSS_C_NT_HOSTBASED_SERVICE])]) + fi + + if test "$gss_impl" = "cybersafe" -o "$gss_impl" = "cybersafe03"; then + AC_EGREP_CPP(user_name_yes_gss_nt, + [#include + #ifdef GSS_C_NT_USER_NAME + user_name_yes_gss_nt + #endif], + [AC_DEFINE(HAVE_GSS_C_NT_USER_NAME,, + [Define if your GSSAPI implementation defines GSS_C_NT_USER_NAME])], + [AC_WARN([Cybersafe define not found])]) + elif test "$ac_cv_header_gssapi_h" = "yes"; then + AC_EGREP_HEADER(GSS_C_NT_USER_NAME, gssapi.h, + [AC_DEFINE(HAVE_GSS_C_NT_USER_NAME,, + [Define if your GSSAPI implementation defines GSS_C_NT_USER_NAME])]) + AC_EGREP_HEADER(gss_inquire_attrs_for_mech, gssapi.h, rfc5587=yes) + AC_EGREP_HEADER(gss_inquire_mech_for_saslname, gssapi.h, rfc5801=yes) + elif test "$ac_cv_header_gssapi_gssapi_h"; then + AC_EGREP_HEADER(GSS_C_NT_USER_NAME, gssapi/gssapi.h, + [AC_DEFINE(HAVE_GSS_C_NT_USER_NAME,, + [Define if your GSSAPI implementation defines GSS_C_NT_USER_NAME])]) + AC_EGREP_HEADER(gss_inquire_attrs_for_mech, gssapi/gssapi.h, rfc5587=yes) + AC_EGREP_HEADER(gss_inquire_mech_for_saslname, gssapi.h, rfc5801=yes) + fi +fi + +AC_MSG_CHECKING([GSSAPI]) +if test "$gssapi" != no; then + AC_MSG_RESULT([with implementation ${gss_impl}]) + AC_CHECK_LIB(resolv,res_search,GSSAPIBASE_LIBS="$GSSAPIBASE_LIBS -lresolv") + SASL_MECHS="$SASL_MECHS libgssapiv2.la" + SASL_STATIC_OBJS="$SASL_STATIC_OBJS gssapi.o" + SASL_STATIC_SRCS="$SASL_STATIC_SRCS \$(top_srcdir)/plugins/gssapi.c" + if test "$rfc5587" = "yes" -a "$rfc5801" = "yes"; then + SASL_MECHS="$SASL_MECHS libgs2.la" + SASL_STATIC_OBJS="$SASL_STATIC_OBJS gs2.o" + SASL_STATIC_SRCS="$SASL_STATIC_SRCS \$(top_srcdir)/plugins/gs2.c" + fi + + cmu_save_LIBS="$LIBS" + LIBS="$LIBS $GSSAPIBASE_LIBS" + AC_CHECK_FUNCS(gsskrb5_register_acceptor_identity) + AC_CHECK_FUNCS(gss_decapsulate_token) + AC_CHECK_FUNCS(gss_encapsulate_token) + AC_CHECK_FUNCS(gss_oid_equal) + LIBS="$cmu_save_LIBS" + + cmu_save_LIBS="$LIBS" + LIBS="$LIBS $GSSAPIBASE_LIBS" + AC_CHECK_FUNCS(gss_get_name_attribute) + LIBS="$cmu_save_LIBS" + + cmu_save_LIBS="$LIBS" + LIBS="$LIBS $GSSAPIBASE_LIBS" + AC_MSG_CHECKING([for SPNEGO support in GSSAPI libraries]) + AC_TRY_RUN([ +#ifdef HAVE_GSSAPI_H +#include +#else +#include +#endif + +int main(void) +{ + gss_OID_desc spnego_oid = { 6, (void *) "\x2b\x06\x01\x05\x05\x02" }; + gss_OID_set mech_set; + OM_uint32 min_stat; + int have_spnego = 0; + + if (gss_indicate_mechs(&min_stat, &mech_set) == GSS_S_COMPLETE) { + gss_test_oid_set_member(&min_stat, &spnego_oid, mech_set, &have_spnego); + gss_release_oid_set(&min_stat, &mech_set); + } + + return (!have_spnego); // 0 = success, 1 = failure +} +], + [ AC_DEFINE(HAVE_GSS_SPNEGO,,[Define if your GSSAPI implementation supports SPNEGO]) + AC_MSG_RESULT(yes) ], + AC_MSG_RESULT(no)) + LIBS="$cmu_save_LIBS" + +else + AC_MSG_RESULT([disabled]) +fi +AC_SUBST(GSSAPIBASE_LIBS) +])# SASL_GSSAPI_CHK + + +# SASL_SET_GSSAPI_LIBS +# -------------------- +AC_DEFUN([SASL_SET_GSSAPI_LIBS], +[SASL_GSSAPI_LIBS_SET="yes" +]) + + +# CMU_SASL2 +# --------- +# What we want to do here is setup LIB_SASL with what one would +# generally want to have (e.g. if static is requested, make it that, +# otherwise make it dynamic. +# +# We also want to create LIB_DYN_SASL and DYNSASLFLAGS. +# +# Also sets using_static_sasl to "no" "static" or "staticonly" +# +AC_DEFUN([CMU_SASL2], +[AC_REQUIRE([SASL_GSSAPI_CHK]) + +AC_ARG_WITH(sasl, + [AC_HELP_STRING([--with-sasl=DIR],[Compile with libsasl2 in ])], + with_sasl="$withval", + with_sasl="yes") + +AC_ARG_WITH(staticsasl, + [AC_HELP_STRING([--with-staticsasl=DIR], + [Compile with staticly linked libsasl2 in ])], + [with_staticsasl="$withval"; + if test $with_staticsasl != "no"; then + using_static_sasl="static" + fi], + [with_staticsasl="no"; using_static_sasl="no"]) + +SASLFLAGS="" +LIB_SASL="" + +cmu_saved_CPPFLAGS=$CPPFLAGS +cmu_saved_LDFLAGS=$LDFLAGS +cmu_saved_LIBS=$LIBS + +if test ${with_staticsasl} != "no"; then + if test -d ${with_staticsasl}; then + if test -d ${with_staticsasl}/lib64 ; then + ac_cv_sasl_where_lib=${with_staticsasl}/lib64 + else + ac_cv_sasl_where_lib=${with_staticsasl}/lib + fi + ac_cv_sasl_where_lib=${with_staticsasl}/lib + ac_cv_sasl_where_inc=${with_staticsasl}/include + + SASLFLAGS="-I$ac_cv_sasl_where_inc" + LIB_SASL="-L$ac_cv_sasl_where_lib" + CPPFLAGS="${cmu_saved_CPPFLAGS} -I${ac_cv_sasl_where_inc}" + LDFLAGS="${cmu_saved_LDFLAGS} -L${ac_cv_sasl_where_lib}" + else + with_staticsasl="/usr" + fi + + AC_CHECK_HEADER(sasl/sasl.h, + [AC_CHECK_HEADER(sasl/saslutil.h, + [for i42 in lib64 lib; do + if test -r ${with_staticsasl}/$i42/libsasl2.a; then + ac_cv_found_sasl=yes + AC_MSG_CHECKING([for static libsasl]) + LIB_SASL="$LIB_SASL ${with_staticsasl}/$i42/libsasl2.a" + fi + done + AC_CHECK_FUNC(dlopen,,[AC_CHECK_LIB(dl, dlopen, [LIB_SASL+="$LIB_SASL -ldl"])]) + if test ! "$ac_cv_found_sasl" = "yes"; then + AC_MSG_CHECKING([for static libsasl]) + AC_MSG_ERROR([Could not find ${with_staticsasl}/lib*/libsasl2.a]) + fi])]) + + AC_MSG_RESULT([found]) + + if test "x$SASL_GSSAPI_LIBS_SET" = "x"; then + LIB_SASL="$LIB_SASL $GSSAPIBASE_STATIC_LIBS" + else + SASL_GSSAPI_LIBS_SET="" + cmu_saved_LIBS="$GSSAPIBASE_STATIC_LIBS $cmu_saved_LIBS" + fi +fi + +if test -d ${with_sasl}; then + ac_cv_sasl_where_lib=${with_sasl}/lib + ac_cv_sasl_where_inc=${with_sasl}/include + + DYNSASLFLAGS="-I$ac_cv_sasl_where_inc" + if test "$ac_cv_sasl_where_lib" != ""; then + CMU_ADD_LIBPATH_TO($ac_cv_sasl_where_lib, LIB_DYN_SASL) + fi + LIB_DYN_SASL="$LIB_DYN_SASL -lsasl2" + CPPFLAGS="${cmu_saved_CPPFLAGS} -I${ac_cv_sasl_where_inc}" + LDFLAGS="${cmu_saved_LDFLAGS} -L${ac_cv_sasl_where_lib}" +fi + +# be sure to check for a SASLv2 specific function +AC_CHECK_HEADER(sasl/sasl.h, + [AC_CHECK_HEADER(sasl/saslutil.h, + [AC_CHECK_LIB(sasl2, prop_get, + ac_cv_found_sasl=yes, + ac_cv_found_sasl=no)], + ac_cv_found_sasl=no)], + ac_cv_found_sasl=no) + +if test "$ac_cv_found_sasl" = "yes"; then + if test "$ac_cv_sasl_where_lib" != ""; then + CMU_ADD_LIBPATH_TO($ac_cv_sasl_where_lib, DYNLIB_SASL) + fi + DYNLIB_SASL="$DYNLIB_SASL -lsasl2" + if test "$using_static_sasl" != "static"; then + LIB_SASL=$DYNLIB_SASL + SASLFLAGS=$DYNSASLFLAGS + fi +else + DYNLIB_SASL="" + DYNSASLFLAGS="" + using_static_sasl="staticonly" +fi + +if test "x$SASL_GSSAPI_LIBS_SET" != "x"; then + SASL_GSSAPI_LIBS_SET="" + cmu_saved_LIBS="$GSSAPIBASE_LIBS $cmu_saved_LIBS" +fi + +LIBS="$cmu_saved_LIBS" +LDFLAGS="$cmu_saved_LDFLAGS" +CPPFLAGS="$cmu_saved_CPPFLAGS" + +AC_SUBST(LIB_DYN_SASL) +AC_SUBST(DYNSASLFLAGS) +AC_SUBST(LIB_SASL) +AC_SUBST(SASLFLAGS) +])# CMU_SASL2 + + +# CMU_SASL2_REQUIRED +# ------------------ +AC_DEFUN([CMU_SASL2_REQUIRED], +[AC_REQUIRE([CMU_SASL2]) +if test "$ac_cv_found_sasl" != "yes"; then + AC_MSG_ERROR([Cannot continue without libsasl2. +Get it from ftp://ftp.andrew.cmu.edu/pub/cyrus-mail/.]) +fi]) + + +# CMU_SASL2_REQUIRE_VER +# --------------------- +AC_DEFUN([CMU_SASL2_REQUIRE_VER], +[AC_REQUIRE([CMU_SASL2_REQUIRED]) + +cmu_saved_CPPFLAGS=$CPPFLAGS +CPPFLAGS="$CPPFLAGS $SASLFLAGS" + +AC_TRY_CPP([ +#include + +#ifndef SASL_VERSION_MAJOR +#error SASL_VERSION_MAJOR not defined +#endif +#ifndef SASL_VERSION_MINOR +#error SASL_VERSION_MINOR not defined +#endif +#ifndef SASL_VERSION_STEP +#error SASL_VERSION_STEP not defined +#endif + +#if SASL_VERSION_MAJOR < $1 || SASL_VERSION_MINOR < $2 || SASL_VERSION_STEP < $3 +#error SASL version is less than $1.$2.$3 +#endif +],, + [AC_MSG_ERROR([Incorrect SASL headers found. This package requires SASL $1.$2.$3 or newer.])]) + +CPPFLAGS=$cmu_saved_CPPFLAGS +])# CMU_SASL2_REQUIRE_VER + + +# CMU_SASL2_CHECKAPOP_REQUIRED +# ---------------------------- +AC_DEFUN([CMU_SASL2_CHECKAPOP_REQUIRED], +[AC_REQUIRE([CMU_SASL2_REQUIRED]) + +cmu_saved_LDFLAGS=$LDFLAGS + +LDFLAGS="$LDFLAGS $LIB_SASL" + +AC_CHECK_LIB(sasl2, sasl_checkapop, + [AC_DEFINE(HAVE_APOP,[],[Does SASL support APOP?])], + [AC_MSG_ERROR([libsasl2 without working sasl_checkapop. Cannot continue.])]) + +LDFLAGS=$cmu_saved_LDFLAGS +])# CMU_SASL2_CHECKAPOP_REQUIRED + + +# SASL2_CRYPT_CHK +# --------------- +AC_DEFUN([SASL2_CRYPT_CHK], +[AC_CHECK_FUNC(crypt, cmu_have_crypt=yes, + [AC_CHECK_LIB(crypt, crypt, + LIB_CRYPT="-lcrypt"; cmu_have_crypt=yes, + cmu_have_crypt=no)]) +AC_SUBST(LIB_CRYPT) +])# SASL2_CRYPT_CHK diff --git a/config/sasldb.m4 b/cmulocal/sasldb.m4 similarity index 100% rename from config/sasldb.m4 rename to cmulocal/sasldb.m4 diff --git a/config/config.guess b/config/config.guess deleted file mode 100755 index f7dd69ec..00000000 --- a/config/config.guess +++ /dev/null @@ -1,1516 +0,0 @@ -#! /bin/sh -# Attempt to guess a canonical system name. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, -# 2011 Free Software Foundation, Inc. - -timestamp='2011-08-20' - -# This file 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 2 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, write to the Free Software -# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA -# 02110-1301, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - - -# Originally written by Per Bothner. Please send patches (context -# diff format) to and include a ChangeLog -# entry. -# -# This script attempts to guess a canonical system name similar to -# config.sub. If it succeeds, it prints the system name on stdout, and -# exits with 0. Otherwise, it exits with 1. -# -# You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] - -Output the configuration name of the system \`$me' is run on. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.guess ($timestamp) - -Originally written by Per Bothner. -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, -2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free -Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" >&2 - exit 1 ;; - * ) - break ;; - esac -done - -if test $# != 0; then - echo "$me: too many arguments$help" >&2 - exit 1 -fi - -trap 'exit 1' 1 2 15 - -# CC_FOR_BUILD -- compiler used by this script. Note that the use of a -# compiler to aid in system detection is discouraged as it requires -# temporary files to be created and, as you can see below, it is a -# headache to deal with in a portable fashion. - -# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still -# use `HOST_CC' if defined, but it is deprecated. - -# Portable tmp directory creation inspired by the Autoconf team. - -set_cc_for_build=' -trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; -trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; -: ${TMPDIR=/tmp} ; - { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || - { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || - { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || - { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; -dummy=$tmp/dummy ; -tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; -case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int x;" > $dummy.c ; - for c in cc gcc c89 c99 ; do - if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then - CC_FOR_BUILD="$c"; break ; - fi ; - done ; - if test x"$CC_FOR_BUILD" = x ; then - CC_FOR_BUILD=no_compiler_found ; - fi - ;; - ,,*) CC_FOR_BUILD=$CC ;; - ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac ; set_cc_for_build= ;' - -# This is needed to find uname on a Pyramid OSx when run in the BSD universe. -# (ghazi@noc.rutgers.edu 1994-08-24) -if (test -f /.attbin/uname) >/dev/null 2>&1 ; then - PATH=$PATH:/.attbin ; export PATH -fi - -UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown -UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown -UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown -UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown - -# Note: order is significant - the case branches are not exclusive. - -case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in - *:NetBSD:*:*) - # NetBSD (nbsd) targets should (where applicable) match one or - # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, - # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently - # switched to ELF, *-*-netbsd* would select the old - # object file format. This provides both forward - # compatibility and a consistent mechanism for selecting the - # object file format. - # - # Note: NetBSD doesn't particularly care about the vendor - # portion of the name. We always set it to "unknown". - sysctl="sysctl -n hw.machine_arch" - UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ - /usr/sbin/$sysctl 2>/dev/null || echo unknown)` - case "${UNAME_MACHINE_ARCH}" in - armeb) machine=armeb-unknown ;; - arm*) machine=arm-unknown ;; - sh3el) machine=shl-unknown ;; - sh3eb) machine=sh-unknown ;; - sh5el) machine=sh5le-unknown ;; - *) machine=${UNAME_MACHINE_ARCH}-unknown ;; - esac - # The Operating System including object format, if it has switched - # to ELF recently, or will in the future. - case "${UNAME_MACHINE_ARCH}" in - arm*|i386|m68k|ns32k|sh3*|sparc|vax) - eval $set_cc_for_build - if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ELF__ - then - # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). - # Return netbsd for either. FIX? - os=netbsd - else - os=netbsdelf - fi - ;; - *) - os=netbsd - ;; - esac - # The OS release - # Debian GNU/NetBSD machines have a different userland, and - # thus, need a distinct triplet. However, they do not need - # kernel version information, so it can be replaced with a - # suitable tag, in the style of linux-gnu. - case "${UNAME_VERSION}" in - Debian*) - release='-gnu' - ;; - *) - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` - ;; - esac - # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: - # contains redundant information, the shorter form: - # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}" - exit ;; - *:OpenBSD:*:*) - UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} - exit ;; - *:ekkoBSD:*:*) - echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} - exit ;; - *:SolidBSD:*:*) - echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} - exit ;; - macppc:MirBSD:*:*) - echo powerpc-unknown-mirbsd${UNAME_RELEASE} - exit ;; - *:MirBSD:*:*) - echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} - exit ;; - alpha:OSF1:*:*) - case $UNAME_RELEASE in - *4.0) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` - ;; - *5.*) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` - ;; - esac - # According to Compaq, /usr/sbin/psrinfo has been available on - # OSF/1 and Tru64 systems produced since 1995. I hope that - # covers most systems running today. This code pipes the CPU - # types through head -n 1, so we only detect the type of CPU 0. - ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` - case "$ALPHA_CPU_TYPE" in - "EV4 (21064)") - UNAME_MACHINE="alpha" ;; - "EV4.5 (21064)") - UNAME_MACHINE="alpha" ;; - "LCA4 (21066/21068)") - UNAME_MACHINE="alpha" ;; - "EV5 (21164)") - UNAME_MACHINE="alphaev5" ;; - "EV5.6 (21164A)") - UNAME_MACHINE="alphaev56" ;; - "EV5.6 (21164PC)") - UNAME_MACHINE="alphapca56" ;; - "EV5.7 (21164PC)") - UNAME_MACHINE="alphapca57" ;; - "EV6 (21264)") - UNAME_MACHINE="alphaev6" ;; - "EV6.7 (21264A)") - UNAME_MACHINE="alphaev67" ;; - "EV6.8CB (21264C)") - UNAME_MACHINE="alphaev68" ;; - "EV6.8AL (21264B)") - UNAME_MACHINE="alphaev68" ;; - "EV6.8CX (21264D)") - UNAME_MACHINE="alphaev68" ;; - "EV6.9A (21264/EV69A)") - UNAME_MACHINE="alphaev69" ;; - "EV7 (21364)") - UNAME_MACHINE="alphaev7" ;; - "EV7.9 (21364A)") - UNAME_MACHINE="alphaev79" ;; - esac - # A Pn.n version is a patched version. - # A Vn.n version is a released version. - # A Tn.n version is a released field test version. - # A Xn.n version is an unreleased experimental baselevel. - # 1.2 uses "1.2" for uname -r. - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - # Reset EXIT trap before exiting to avoid spurious non-zero exit code. - exitcode=$? - trap '' 0 - exit $exitcode ;; - Alpha\ *:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # Should we change UNAME_MACHINE based on the output of uname instead - # of the specific Alpha model? - echo alpha-pc-interix - exit ;; - 21064:Windows_NT:50:3) - echo alpha-dec-winnt3.5 - exit ;; - Amiga*:UNIX_System_V:4.0:*) - echo m68k-unknown-sysv4 - exit ;; - *:[Aa]miga[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-amigaos - exit ;; - *:[Mm]orph[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-morphos - exit ;; - *:OS/390:*:*) - echo i370-ibm-openedition - exit ;; - *:z/VM:*:*) - echo s390-ibm-zvmoe - exit ;; - *:OS400:*:*) - echo powerpc-ibm-os400 - exit ;; - arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix${UNAME_RELEASE} - exit ;; - arm:riscos:*:*|arm:RISCOS:*:*) - echo arm-unknown-riscos - exit ;; - SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) - echo hppa1.1-hitachi-hiuxmpp - exit ;; - Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) - # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. - if test "`(/bin/universe) 2>/dev/null`" = att ; then - echo pyramid-pyramid-sysv3 - else - echo pyramid-pyramid-bsd - fi - exit ;; - NILE*:*:*:dcosx) - echo pyramid-pyramid-svr4 - exit ;; - DRS?6000:unix:4.0:6*) - echo sparc-icl-nx6 - exit ;; - DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) - case `/usr/bin/uname -p` in - sparc) echo sparc-icl-nx7; exit ;; - esac ;; - s390x:SunOS:*:*) - echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) - echo i386-pc-auroraux${UNAME_RELEASE} - exit ;; - i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) - eval $set_cc_for_build - SUN_ARCH="i386" - # If there is a compiler, see if it is configured for 64-bit objects. - # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. - # This test works for both compilers. - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then - if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - SUN_ARCH="x86_64" - fi - fi - echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:6*:*) - # According to config.sub, this is the proper way to canonicalize - # SunOS6. Hard to guess exactly what SunOS6 will be like, but - # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:*:*) - case "`/usr/bin/arch -k`" in - Series*|S4*) - UNAME_RELEASE=`uname -v` - ;; - esac - # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` - exit ;; - sun3*:SunOS:*:*) - echo m68k-sun-sunos${UNAME_RELEASE} - exit ;; - sun*:*:4.2BSD:*) - UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 - case "`/bin/arch`" in - sun3) - echo m68k-sun-sunos${UNAME_RELEASE} - ;; - sun4) - echo sparc-sun-sunos${UNAME_RELEASE} - ;; - esac - exit ;; - aushp:SunOS:*:*) - echo sparc-auspex-sunos${UNAME_RELEASE} - exit ;; - # The situation for MiNT is a little confusing. The machine name - # can be virtually everything (everything which is not - # "atarist" or "atariste" at least should have a processor - # > m68000). The system name ranges from "MiNT" over "FreeMiNT" - # to the lowercase version "mint" (or "freemint"). Finally - # the system name "TOS" denotes a system which is actually not - # MiNT. But MiNT is downward compatible to TOS, so this should - # be no problem. - atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} - exit ;; - hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} - exit ;; - *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} - exit ;; - m68k:machten:*:*) - echo m68k-apple-machten${UNAME_RELEASE} - exit ;; - powerpc:machten:*:*) - echo powerpc-apple-machten${UNAME_RELEASE} - exit ;; - RISC*:Mach:*:*) - echo mips-dec-mach_bsd4.3 - exit ;; - RISC*:ULTRIX:*:*) - echo mips-dec-ultrix${UNAME_RELEASE} - exit ;; - VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix${UNAME_RELEASE} - exit ;; - 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix${UNAME_RELEASE} - exit ;; - mips:*:*:UMIPS | mips:*:*:RISCos) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c -#ifdef __cplusplus -#include /* for printf() prototype */ - int main (int argc, char *argv[]) { -#else - int main (argc, argv) int argc; char *argv[]; { -#endif - #if defined (host_mips) && defined (MIPSEB) - #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_SVR4) - printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) - printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); - #endif - #endif - exit (-1); - } -EOF - $CC_FOR_BUILD -o $dummy $dummy.c && - dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && - SYSTEM_NAME=`$dummy $dummyarg` && - { echo "$SYSTEM_NAME"; exit; } - echo mips-mips-riscos${UNAME_RELEASE} - exit ;; - Motorola:PowerMAX_OS:*:*) - echo powerpc-motorola-powermax - exit ;; - Motorola:*:4.3:PL8-*) - echo powerpc-harris-powermax - exit ;; - Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) - echo powerpc-harris-powermax - exit ;; - Night_Hawk:Power_UNIX:*:*) - echo powerpc-harris-powerunix - exit ;; - m88k:CX/UX:7*:*) - echo m88k-harris-cxux7 - exit ;; - m88k:*:4*:R4*) - echo m88k-motorola-sysv4 - exit ;; - m88k:*:3*:R3*) - echo m88k-motorola-sysv3 - exit ;; - AViiON:dgux:*:*) - # DG/UX returns AViiON for all architectures - UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] - then - if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ - [ ${TARGET_BINARY_INTERFACE}x = x ] - then - echo m88k-dg-dgux${UNAME_RELEASE} - else - echo m88k-dg-dguxbcs${UNAME_RELEASE} - fi - else - echo i586-dg-dgux${UNAME_RELEASE} - fi - exit ;; - M88*:DolphinOS:*:*) # DolphinOS (SVR3) - echo m88k-dolphin-sysv3 - exit ;; - M88*:*:R3*:*) - # Delta 88k system running SVR3 - echo m88k-motorola-sysv3 - exit ;; - XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) - echo m88k-tektronix-sysv3 - exit ;; - Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) - echo m68k-tektronix-bsd - exit ;; - *:IRIX*:*:*) - echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` - exit ;; - ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. - echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id - exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' - i*86:AIX:*:*) - echo i386-ibm-aix - exit ;; - ia64:AIX:*:*) - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} - exit ;; - *:AIX:2:3) - if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - - main() - { - if (!__power_pc()) - exit(1); - puts("powerpc-ibm-aix3.2.5"); - exit(0); - } -EOF - if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` - then - echo "$SYSTEM_NAME" - else - echo rs6000-ibm-aix3.2.5 - fi - elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then - echo rs6000-ibm-aix3.2.4 - else - echo rs6000-ibm-aix3.2 - fi - exit ;; - *:AIX:*:[4567]) - IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` - if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then - IBM_ARCH=rs6000 - else - IBM_ARCH=powerpc - fi - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${IBM_ARCH}-ibm-aix${IBM_REV} - exit ;; - *:AIX:*:*) - echo rs6000-ibm-aix - exit ;; - ibmrt:4.4BSD:*|romp-ibm:BSD:*) - echo romp-ibm-bsd4.4 - exit ;; - ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to - exit ;; # report: romp-ibm BSD 4.3 - *:BOSX:*:*) - echo rs6000-bull-bosx - exit ;; - DPX/2?00:B.O.S.:*:*) - echo m68k-bull-sysv3 - exit ;; - 9000/[34]??:4.3bsd:1.*:*) - echo m68k-hp-bsd - exit ;; - hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) - echo m68k-hp-bsd4.4 - exit ;; - 9000/[34678]??:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - case "${UNAME_MACHINE}" in - 9000/31? ) HP_ARCH=m68000 ;; - 9000/[34]?? ) HP_ARCH=m68k ;; - 9000/[678][0-9][0-9]) - if [ -x /usr/bin/getconf ]; then - sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` - sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in - 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 - 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 - 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in - 32) HP_ARCH="hppa2.0n" ;; - 64) HP_ARCH="hppa2.0w" ;; - '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 - esac ;; - esac - fi - if [ "${HP_ARCH}" = "" ]; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - - #define _HPUX_SOURCE - #include - #include - - int main () - { - #if defined(_SC_KERNEL_BITS) - long bits = sysconf(_SC_KERNEL_BITS); - #endif - long cpu = sysconf (_SC_CPU_VERSION); - - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1"); break; - case CPU_PA_RISC2_0: - #if defined(_SC_KERNEL_BITS) - switch (bits) - { - case 64: puts ("hppa2.0w"); break; - case 32: puts ("hppa2.0n"); break; - default: puts ("hppa2.0"); break; - } break; - #else /* !defined(_SC_KERNEL_BITS) */ - puts ("hppa2.0"); break; - #endif - default: puts ("hppa1.0"); break; - } - exit (0); - } -EOF - (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` - test -z "$HP_ARCH" && HP_ARCH=hppa - fi ;; - esac - if [ ${HP_ARCH} = "hppa2.0w" ] - then - eval $set_cc_for_build - - # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating - # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler - # generating 64-bit code. GNU and HP use different nomenclature: - # - # $ CC_FOR_BUILD=cc ./config.guess - # => hppa2.0w-hp-hpux11.23 - # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess - # => hppa64-hp-hpux11.23 - - if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | - grep -q __LP64__ - then - HP_ARCH="hppa2.0w" - else - HP_ARCH="hppa64" - fi - fi - echo ${HP_ARCH}-hp-hpux${HPUX_REV} - exit ;; - ia64:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - echo ia64-hp-hpux${HPUX_REV} - exit ;; - 3050*:HI-UX:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - int - main () - { - long cpu = sysconf (_SC_CPU_VERSION); - /* The order matters, because CPU_IS_HP_MC68K erroneously returns - true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct - results, however. */ - if (CPU_IS_PA_RISC (cpu)) - { - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; - case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; - default: puts ("hppa-hitachi-hiuxwe2"); break; - } - } - else if (CPU_IS_HP_MC68K (cpu)) - puts ("m68k-hitachi-hiuxwe2"); - else puts ("unknown-hitachi-hiuxwe2"); - exit (0); - } -EOF - $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && - { echo "$SYSTEM_NAME"; exit; } - echo unknown-hitachi-hiuxwe2 - exit ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) - echo hppa1.1-hp-bsd - exit ;; - 9000/8??:4.3bsd:*:*) - echo hppa1.0-hp-bsd - exit ;; - *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) - echo hppa1.0-hp-mpeix - exit ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) - echo hppa1.1-hp-osf - exit ;; - hp8??:OSF1:*:*) - echo hppa1.0-hp-osf - exit ;; - i*86:OSF1:*:*) - if [ -x /usr/sbin/sysversion ] ; then - echo ${UNAME_MACHINE}-unknown-osf1mk - else - echo ${UNAME_MACHINE}-unknown-osf1 - fi - exit ;; - parisc*:Lites*:*:*) - echo hppa1.1-hp-lites - exit ;; - C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) - echo c1-convex-bsd - exit ;; - C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) - echo c34-convex-bsd - exit ;; - C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) - echo c38-convex-bsd - exit ;; - C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) - echo c4-convex-bsd - exit ;; - CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*[A-Z]90:*:*:*) - echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ - | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ - -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ - -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*TS:*:*:*) - echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*SV1:*:*:*) - echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - *:UNICOS/mp:*:*) - echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` - echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; - 5000:UNIX_System_V:4.*:*) - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` - echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; - i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} - exit ;; - sparc*:BSD/OS:*:*) - echo sparc-unknown-bsdi${UNAME_RELEASE} - exit ;; - *:BSD/OS:*:*) - echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} - exit ;; - *:FreeBSD:*:*) - UNAME_PROCESSOR=`/usr/bin/uname -p` - case ${UNAME_PROCESSOR} in - amd64) - echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - *) - echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - esac - exit ;; - i*:CYGWIN*:*) - echo ${UNAME_MACHINE}-pc-cygwin - exit ;; - *:MINGW*:*) - echo ${UNAME_MACHINE}-pc-mingw32 - exit ;; - i*:windows32*:*) - # uname -m includes "-pc" on this system. - echo ${UNAME_MACHINE}-mingw32 - exit ;; - i*:PW*:*) - echo ${UNAME_MACHINE}-pc-pw32 - exit ;; - *:Interix*:*) - case ${UNAME_MACHINE} in - x86) - echo i586-pc-interix${UNAME_RELEASE} - exit ;; - authenticamd | genuineintel | EM64T) - echo x86_64-unknown-interix${UNAME_RELEASE} - exit ;; - IA64) - echo ia64-unknown-interix${UNAME_RELEASE} - exit ;; - esac ;; - [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) - echo i${UNAME_MACHINE}-pc-mks - exit ;; - 8664:Windows_NT:*) - echo x86_64-pc-mks - exit ;; - i*:Windows_NT*:* | Pentium*:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we - # UNAME_MACHINE based on the output of uname instead of i386? - echo i586-pc-interix - exit ;; - i*:UWIN*:*) - echo ${UNAME_MACHINE}-pc-uwin - exit ;; - amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) - echo x86_64-unknown-cygwin - exit ;; - p*:CYGWIN*:*) - echo powerpcle-unknown-cygwin - exit ;; - prep*:SunOS:5.*:*) - echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - *:GNU:*:*) - # the GNU system - echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` - exit ;; - *:GNU/*:*:*) - # other systems with GNU libc and userland - echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu - exit ;; - i*86:Minix:*:*) - echo ${UNAME_MACHINE}-pc-minix - exit ;; - alpha:Linux:*:*) - case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in - EV5) UNAME_MACHINE=alphaev5 ;; - EV56) UNAME_MACHINE=alphaev56 ;; - PCA56) UNAME_MACHINE=alphapca56 ;; - PCA57) UNAME_MACHINE=alphapca56 ;; - EV6) UNAME_MACHINE=alphaev6 ;; - EV67) UNAME_MACHINE=alphaev67 ;; - EV68*) UNAME_MACHINE=alphaev68 ;; - esac - objdump --private-headers /bin/sh | grep -q ld.so.1 - if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi - echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} - exit ;; - arm*:Linux:*:*) - eval $set_cc_for_build - if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_EABI__ - then - echo ${UNAME_MACHINE}-unknown-linux-gnu - else - if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_PCS_VFP - then - echo ${UNAME_MACHINE}-unknown-linux-gnueabi - else - echo ${UNAME_MACHINE}-unknown-linux-gnueabihf - fi - fi - exit ;; - avr32*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - cris:Linux:*:*) - echo cris-axis-linux-gnu - exit ;; - crisv32:Linux:*:*) - echo crisv32-axis-linux-gnu - exit ;; - frv:Linux:*:*) - echo frv-unknown-linux-gnu - exit ;; - i*86:Linux:*:*) - LIBC=gnu - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #ifdef __dietlibc__ - LIBC=dietlibc - #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` - echo "${UNAME_MACHINE}-pc-linux-${LIBC}" - exit ;; - ia64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - m32r*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - m68*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - mips:Linux:*:* | mips64:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #undef CPU - #undef ${UNAME_MACHINE} - #undef ${UNAME_MACHINE}el - #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=${UNAME_MACHINE}el - #else - #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=${UNAME_MACHINE} - #else - CPU= - #endif - #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` - test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } - ;; - or32:Linux:*:*) - echo or32-unknown-linux-gnu - exit ;; - padre:Linux:*:*) - echo sparc-unknown-linux-gnu - exit ;; - parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-gnu - exit ;; - parisc:Linux:*:* | hppa:Linux:*:*) - # Look for CPU level - case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-unknown-linux-gnu ;; - PA8*) echo hppa2.0-unknown-linux-gnu ;; - *) echo hppa-unknown-linux-gnu ;; - esac - exit ;; - ppc64:Linux:*:*) - echo powerpc64-unknown-linux-gnu - exit ;; - ppc:Linux:*:*) - echo powerpc-unknown-linux-gnu - exit ;; - s390:Linux:*:* | s390x:Linux:*:*) - echo ${UNAME_MACHINE}-ibm-linux - exit ;; - sh64*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - sh*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - sparc:Linux:*:* | sparc64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - tile*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - vax:Linux:*:*) - echo ${UNAME_MACHINE}-dec-linux-gnu - exit ;; - x86_64:Linux:*:*) - echo x86_64-unknown-linux-gnu - exit ;; - xtensa*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - i*86:DYNIX/ptx:4*:*) - # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. - # earlier versions are messed up and put the nodename in both - # sysname and nodename. - echo i386-sequent-sysv4 - exit ;; - i*86:UNIX_SV:4.2MP:2.*) - # Unixware is an offshoot of SVR4, but it has its own version - # number series starting with 2... - # I am not positive that other SVR4 systems won't match this, - # I just have to hope. -- rms. - # Use sysv4.2uw... so that sysv4* matches it. - echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} - exit ;; - i*86:OS/2:*:*) - # If we were able to find `uname', then EMX Unix compatibility - # is probably installed. - echo ${UNAME_MACHINE}-pc-os2-emx - exit ;; - i*86:XTS-300:*:STOP) - echo ${UNAME_MACHINE}-unknown-stop - exit ;; - i*86:atheos:*:*) - echo ${UNAME_MACHINE}-unknown-atheos - exit ;; - i*86:syllable:*:*) - echo ${UNAME_MACHINE}-pc-syllable - exit ;; - i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) - echo i386-unknown-lynxos${UNAME_RELEASE} - exit ;; - i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp - exit ;; - i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) - UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` - if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} - else - echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} - fi - exit ;; - i*86:*:5:[678]*) - # UnixWare 7.x, OpenUNIX and OpenServer 6. - case `/bin/uname -X | grep "^Machine"` in - *486*) UNAME_MACHINE=i486 ;; - *Pentium) UNAME_MACHINE=i586 ;; - *Pent*|*Celeron) UNAME_MACHINE=i686 ;; - esac - echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} - exit ;; - i*86:*:3.2:*) - if test -f /usr/options/cb.name; then - UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then - UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` - (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 - (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ - && UNAME_MACHINE=i586 - (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ - && UNAME_MACHINE=i686 - (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ - && UNAME_MACHINE=i686 - echo ${UNAME_MACHINE}-pc-sco$UNAME_REL - else - echo ${UNAME_MACHINE}-pc-sysv32 - fi - exit ;; - pc:*:*:*) - # Left here for compatibility: - # uname -m prints for DJGPP always 'pc', but it prints nothing about - # the processor, so we play safe by assuming i586. - # Note: whatever this is, it MUST be the same as what config.sub - # prints for the "djgpp" host, or else GDB configury will decide that - # this is a cross-build. - echo i586-pc-msdosdjgpp - exit ;; - Intel:Mach:3*:*) - echo i386-pc-mach3 - exit ;; - paragon:*:*:*) - echo i860-intel-osf1 - exit ;; - i860:*:4.*:*) # i860-SVR4 - if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 - else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 - fi - exit ;; - mini*:CTIX:SYS*5:*) - # "miniframe" - echo m68010-convergent-sysv - exit ;; - mc68k:UNIX:SYSTEM5:3.51m) - echo m68k-convergent-sysv - exit ;; - M680?0:D-NIX:5.3:*) - echo m68k-diab-dnix - exit ;; - M68*:*:R3V[5678]*:*) - test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; - 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) - OS_REL='' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; - 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4; exit; } ;; - NCR*:*:4.2:* | MPRAS*:*:4.2:*) - OS_REL='.3' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; - m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - echo m68k-unknown-lynxos${UNAME_RELEASE} - exit ;; - mc68030:UNIX_System_V:4.*:*) - echo m68k-atari-sysv4 - exit ;; - TSUNAMI:LynxOS:2.*:*) - echo sparc-unknown-lynxos${UNAME_RELEASE} - exit ;; - rs6000:LynxOS:2.*:*) - echo rs6000-unknown-lynxos${UNAME_RELEASE} - exit ;; - PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) - echo powerpc-unknown-lynxos${UNAME_RELEASE} - exit ;; - SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv${UNAME_RELEASE} - exit ;; - RM*:ReliantUNIX-*:*:*) - echo mips-sni-sysv4 - exit ;; - RM*:SINIX-*:*:*) - echo mips-sni-sysv4 - exit ;; - *:SINIX-*:*:*) - if uname -p 2>/dev/null >/dev/null ; then - UNAME_MACHINE=`(uname -p) 2>/dev/null` - echo ${UNAME_MACHINE}-sni-sysv4 - else - echo ns32k-sni-sysv - fi - exit ;; - PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort - # says - echo i586-unisys-sysv4 - exit ;; - *:UNIX_System_V:4*:FTX*) - # From Gerald Hewes . - # How about differentiating between stratus architectures? -djm - echo hppa1.1-stratus-sysv4 - exit ;; - *:*:*:FTX*) - # From seanf@swdc.stratus.com. - echo i860-stratus-sysv4 - exit ;; - i*86:VOS:*:*) - # From Paul.Green@stratus.com. - echo ${UNAME_MACHINE}-stratus-vos - exit ;; - *:VOS:*:*) - # From Paul.Green@stratus.com. - echo hppa1.1-stratus-vos - exit ;; - mc68*:A/UX:*:*) - echo m68k-apple-aux${UNAME_RELEASE} - exit ;; - news*:NEWS-OS:6*:*) - echo mips-sony-newsos6 - exit ;; - R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) - if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} - else - echo mips-unknown-sysv${UNAME_RELEASE} - fi - exit ;; - BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. - echo powerpc-be-beos - exit ;; - BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. - echo powerpc-apple-beos - exit ;; - BePC:BeOS:*:*) # BeOS running on Intel PC compatible. - echo i586-pc-beos - exit ;; - BePC:Haiku:*:*) # Haiku running on Intel PC compatible. - echo i586-pc-haiku - exit ;; - SX-4:SUPER-UX:*:*) - echo sx4-nec-superux${UNAME_RELEASE} - exit ;; - SX-5:SUPER-UX:*:*) - echo sx5-nec-superux${UNAME_RELEASE} - exit ;; - SX-6:SUPER-UX:*:*) - echo sx6-nec-superux${UNAME_RELEASE} - exit ;; - SX-7:SUPER-UX:*:*) - echo sx7-nec-superux${UNAME_RELEASE} - exit ;; - SX-8:SUPER-UX:*:*) - echo sx8-nec-superux${UNAME_RELEASE} - exit ;; - SX-8R:SUPER-UX:*:*) - echo sx8r-nec-superux${UNAME_RELEASE} - exit ;; - Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody${UNAME_RELEASE} - exit ;; - *:Rhapsody:*:*) - echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} - exit ;; - *:Darwin:*:*) - UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown - case $UNAME_PROCESSOR in - i386) - eval $set_cc_for_build - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then - if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - UNAME_PROCESSOR="x86_64" - fi - fi ;; - unknown) UNAME_PROCESSOR=powerpc ;; - esac - echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} - exit ;; - *:procnto*:*:* | *:QNX:[0123456789]*:*) - UNAME_PROCESSOR=`uname -p` - if test "$UNAME_PROCESSOR" = "x86"; then - UNAME_PROCESSOR=i386 - UNAME_MACHINE=pc - fi - echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} - exit ;; - *:QNX:*:4*) - echo i386-pc-qnx - exit ;; - NEO-?:NONSTOP_KERNEL:*:*) - echo neo-tandem-nsk${UNAME_RELEASE} - exit ;; - NSE-?:NONSTOP_KERNEL:*:*) - echo nse-tandem-nsk${UNAME_RELEASE} - exit ;; - NSR-?:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk${UNAME_RELEASE} - exit ;; - *:NonStop-UX:*:*) - echo mips-compaq-nonstopux - exit ;; - BS2000:POSIX*:*:*) - echo bs2000-siemens-sysv - exit ;; - DS/*:UNIX_System_V:*:*) - echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} - exit ;; - *:Plan9:*:*) - # "uname -m" is not consistent, so use $cputype instead. 386 - # is converted to i386 for consistency with other x86 - # operating systems. - if test "$cputype" = "386"; then - UNAME_MACHINE=i386 - else - UNAME_MACHINE="$cputype" - fi - echo ${UNAME_MACHINE}-unknown-plan9 - exit ;; - *:TOPS-10:*:*) - echo pdp10-unknown-tops10 - exit ;; - *:TENEX:*:*) - echo pdp10-unknown-tenex - exit ;; - KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) - echo pdp10-dec-tops20 - exit ;; - XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) - echo pdp10-xkl-tops20 - exit ;; - *:TOPS-20:*:*) - echo pdp10-unknown-tops20 - exit ;; - *:ITS:*:*) - echo pdp10-unknown-its - exit ;; - SEI:*:*:SEIUX) - echo mips-sei-seiux${UNAME_RELEASE} - exit ;; - *:DragonFly:*:*) - echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` - exit ;; - *:*VMS:*:*) - UNAME_MACHINE=`(uname -p) 2>/dev/null` - case "${UNAME_MACHINE}" in - A*) echo alpha-dec-vms ; exit ;; - I*) echo ia64-dec-vms ; exit ;; - V*) echo vax-dec-vms ; exit ;; - esac ;; - *:XENIX:*:SysV) - echo i386-pc-xenix - exit ;; - i*86:skyos:*:*) - echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' - exit ;; - i*86:rdos:*:*) - echo ${UNAME_MACHINE}-pc-rdos - exit ;; - i*86:AROS:*:*) - echo ${UNAME_MACHINE}-pc-aros - exit ;; -esac - -#echo '(No uname command or uname output not recognized.)' 1>&2 -#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 - -eval $set_cc_for_build -cat >$dummy.c < -# include -#endif -main () -{ -#if defined (sony) -#if defined (MIPSEB) - /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, - I don't know.... */ - printf ("mips-sony-bsd\n"); exit (0); -#else -#include - printf ("m68k-sony-newsos%s\n", -#ifdef NEWSOS4 - "4" -#else - "" -#endif - ); exit (0); -#endif -#endif - -#if defined (__arm) && defined (__acorn) && defined (__unix) - printf ("arm-acorn-riscix\n"); exit (0); -#endif - -#if defined (hp300) && !defined (hpux) - printf ("m68k-hp-bsd\n"); exit (0); -#endif - -#if defined (NeXT) -#if !defined (__ARCHITECTURE__) -#define __ARCHITECTURE__ "m68k" -#endif - int version; - version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; - if (version < 4) - printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); - else - printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); - exit (0); -#endif - -#if defined (MULTIMAX) || defined (n16) -#if defined (UMAXV) - printf ("ns32k-encore-sysv\n"); exit (0); -#else -#if defined (CMU) - printf ("ns32k-encore-mach\n"); exit (0); -#else - printf ("ns32k-encore-bsd\n"); exit (0); -#endif -#endif -#endif - -#if defined (__386BSD__) - printf ("i386-pc-bsd\n"); exit (0); -#endif - -#if defined (sequent) -#if defined (i386) - printf ("i386-sequent-dynix\n"); exit (0); -#endif -#if defined (ns32000) - printf ("ns32k-sequent-dynix\n"); exit (0); -#endif -#endif - -#if defined (_SEQUENT_) - struct utsname un; - - uname(&un); - - if (strncmp(un.version, "V2", 2) == 0) { - printf ("i386-sequent-ptx2\n"); exit (0); - } - if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ - printf ("i386-sequent-ptx1\n"); exit (0); - } - printf ("i386-sequent-ptx\n"); exit (0); - -#endif - -#if defined (vax) -# if !defined (ultrix) -# include -# if defined (BSD) -# if BSD == 43 - printf ("vax-dec-bsd4.3\n"); exit (0); -# else -# if BSD == 199006 - printf ("vax-dec-bsd4.3reno\n"); exit (0); -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# endif -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# else - printf ("vax-dec-ultrix\n"); exit (0); -# endif -#endif - -#if defined (alliant) && defined (i860) - printf ("i860-alliant-bsd\n"); exit (0); -#endif - - exit (1); -} -EOF - -$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && - { echo "$SYSTEM_NAME"; exit; } - -# Apollos put the system type in the environment. - -test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } - -# Convex versions that predate uname can use getsysinfo(1) - -if [ -x /usr/convex/getsysinfo ] -then - case `getsysinfo -f cpu_type` in - c1*) - echo c1-convex-bsd - exit ;; - c2*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - c34*) - echo c34-convex-bsd - exit ;; - c38*) - echo c38-convex-bsd - exit ;; - c4*) - echo c4-convex-bsd - exit ;; - esac -fi - -cat >&2 < in order to provide the needed -information to handle your system. - -config.guess timestamp = $timestamp - -uname -m = `(uname -m) 2>/dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null` - -hostinfo = `(hostinfo) 2>/dev/null` -/bin/universe = `(/bin/universe) 2>/dev/null` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` -/bin/arch = `(/bin/arch) 2>/dev/null` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` - -UNAME_MACHINE = ${UNAME_MACHINE} -UNAME_RELEASE = ${UNAME_RELEASE} -UNAME_SYSTEM = ${UNAME_SYSTEM} -UNAME_VERSION = ${UNAME_VERSION} -EOF - -exit 1 - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/config/config.sub b/config/config.sub deleted file mode 100755 index da19a880..00000000 --- a/config/config.sub +++ /dev/null @@ -1,1764 +0,0 @@ -#! /bin/sh -# Configuration validation subroutine script. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, -# 2011 Free Software Foundation, Inc. - -timestamp='2011-08-23' - -# This file is (in principle) common to ALL GNU software. -# The presence of a machine in this file suggests that SOME GNU software -# can handle that machine. It does not imply ALL GNU software can. -# -# This file 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 2 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, write to the Free Software -# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA -# 02110-1301, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - - -# Please send patches to . Submit a context -# diff and a properly formatted GNU ChangeLog entry. -# -# Configuration subroutine to validate and canonicalize a configuration type. -# Supply the specified configuration type as an argument. -# If it is invalid, we print an error message on stderr and exit with code 1. -# Otherwise, we print the canonical config type on stdout and succeed. - -# You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD - -# This file is supposed to be the same for all GNU packages -# and recognize all the CPU types, system types and aliases -# that are meaningful with *any* GNU software. -# Each package is responsible for reporting which valid configurations -# it does not support. The user should be able to distinguish -# a failure to support a valid configuration from a meaningless -# configuration. - -# The goal of this file is to map all the various variations of a given -# machine specification into a single specification in the form: -# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM -# or in some cases, the newer four-part form: -# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM -# It is wrong to echo any other type of specification. - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS - $0 [OPTION] ALIAS - -Canonicalize a configuration name. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.sub ($timestamp) - -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, -2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free -Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" - exit 1 ;; - - *local*) - # First pass through any local machine types. - echo $1 - exit ;; - - * ) - break ;; - esac -done - -case $# in - 0) echo "$me: missing argument$help" >&2 - exit 1;; - 1) ;; - *) echo "$me: too many arguments$help" >&2 - exit 1;; -esac - -# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). -# Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` -case $maybe_os in - nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ - linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ - knetbsd*-gnu* | netbsd*-gnu* | \ - kopensolaris*-gnu* | \ - storm-chaos* | os2-emx* | rtmk-nova*) - os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` - ;; - *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] - then os=`echo $1 | sed 's/.*-/-/'` - else os=; fi - ;; -esac - -### Let's recognize common machines as not being operating systems so -### that things like config.sub decstation-3100 work. We also -### recognize some manufacturers as not being operating systems, so we -### can provide default operating systems below. -case $os in - -sun*os*) - # Prevent following clause from handling this invalid input. - ;; - -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ - -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ - -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ - -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ - -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ - -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis | -knuth | -cray | -microblaze) - os= - basic_machine=$1 - ;; - -bluegene*) - os=-cnk - ;; - -sim | -cisco | -oki | -wec | -winbond) - os= - basic_machine=$1 - ;; - -scout) - ;; - -wrs) - os=-vxworks - basic_machine=$1 - ;; - -chorusos*) - os=-chorusos - basic_machine=$1 - ;; - -chorusrdb) - os=-chorusrdb - basic_machine=$1 - ;; - -hiux*) - os=-hiuxwe2 - ;; - -sco6) - os=-sco5v6 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5) - os=-sco3.2v5 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco4) - os=-sco3.2v4 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2.[4-9]*) - os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2v[4-9]*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5v6*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco*) - os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -udk*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -isc) - os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -clix*) - basic_machine=clipper-intergraph - ;; - -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -lynx*) - os=-lynxos - ;; - -ptx*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` - ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` - ;; - -psos*) - os=-psos - ;; - -mint | -mint[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; -esac - -# Decode aliases for certain CPU-COMPANY combinations. -case $basic_machine in - # Recognize the basic CPU types without company name. - # Some are omitted here because they have special meanings below. - 1750a | 580 \ - | a29k \ - | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ - | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ - | am33_2.0 \ - | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ - | be32 | be64 \ - | bfin \ - | c4x | clipper \ - | d10v | d30v | dlx | dsp16xx \ - | fido | fr30 | frv \ - | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ - | i370 | i860 | i960 | ia64 \ - | ip2k | iq2000 \ - | le32 | le64 \ - | lm32 \ - | m32c | m32r | m32rle | m68000 | m68k | m88k \ - | maxq | mb | microblaze | mcore | mep | metag \ - | mips | mipsbe | mipseb | mipsel | mipsle \ - | mips16 \ - | mips64 | mips64el \ - | mips64octeon | mips64octeonel \ - | mips64orion | mips64orionel \ - | mips64r5900 | mips64r5900el \ - | mips64vr | mips64vrel \ - | mips64vr4100 | mips64vr4100el \ - | mips64vr4300 | mips64vr4300el \ - | mips64vr5000 | mips64vr5000el \ - | mips64vr5900 | mips64vr5900el \ - | mipsisa32 | mipsisa32el \ - | mipsisa32r2 | mipsisa32r2el \ - | mipsisa64 | mipsisa64el \ - | mipsisa64r2 | mipsisa64r2el \ - | mipsisa64sb1 | mipsisa64sb1el \ - | mipsisa64sr71k | mipsisa64sr71kel \ - | mipstx39 | mipstx39el \ - | mn10200 | mn10300 \ - | moxie \ - | mt \ - | msp430 \ - | nds32 | nds32le | nds32be \ - | nios | nios2 \ - | ns16k | ns32k \ - | open8 \ - | or32 \ - | pdp10 | pdp11 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle \ - | pyramid \ - | rx \ - | score \ - | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ - | sh64 | sh64le \ - | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ - | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ - | spu \ - | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ - | ubicom32 \ - | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ - | we32k \ - | x86 | xc16x | xstormy16 | xtensa \ - | z8k | z80) - basic_machine=$basic_machine-unknown - ;; - c54x) - basic_machine=tic54x-unknown - ;; - c55x) - basic_machine=tic55x-unknown - ;; - c6x) - basic_machine=tic6x-unknown - ;; - m6811 | m68hc11 | m6812 | m68hc12 | picochip) - # Motorola 68HC11/12. - basic_machine=$basic_machine-unknown - os=-none - ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) - ;; - ms1) - basic_machine=mt-unknown - ;; - - strongarm | thumb | xscale) - basic_machine=arm-unknown - ;; - - xscaleeb) - basic_machine=armeb-unknown - ;; - - xscaleel) - basic_machine=armel-unknown - ;; - - # We use `pc' rather than `unknown' - # because (1) that's what they normally are, and - # (2) the word "unknown" tends to confuse beginning users. - i*86 | x86_64) - basic_machine=$basic_machine-pc - ;; - # Object if more than one company name word. - *-*-*) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; - # Recognize the basic CPU types with company name. - 580-* \ - | a29k-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ - | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ - | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ - | avr-* | avr32-* \ - | be32-* | be64-* \ - | bfin-* | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* \ - | clipper-* | craynv-* | cydra-* \ - | d10v-* | d30v-* | dlx-* \ - | elxsi-* \ - | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ - | h8300-* | h8500-* \ - | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ - | i*86-* | i860-* | i960-* | ia64-* \ - | ip2k-* | iq2000-* \ - | le32-* | le64-* \ - | lm32-* \ - | m32c-* | m32r-* | m32rle-* \ - | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ - | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ - | mips16-* \ - | mips64-* | mips64el-* \ - | mips64octeon-* | mips64octeonel-* \ - | mips64orion-* | mips64orionel-* \ - | mips64r5900-* | mips64r5900el-* \ - | mips64vr-* | mips64vrel-* \ - | mips64vr4100-* | mips64vr4100el-* \ - | mips64vr4300-* | mips64vr4300el-* \ - | mips64vr5000-* | mips64vr5000el-* \ - | mips64vr5900-* | mips64vr5900el-* \ - | mipsisa32-* | mipsisa32el-* \ - | mipsisa32r2-* | mipsisa32r2el-* \ - | mipsisa64-* | mipsisa64el-* \ - | mipsisa64r2-* | mipsisa64r2el-* \ - | mipsisa64sb1-* | mipsisa64sb1el-* \ - | mipsisa64sr71k-* | mipsisa64sr71kel-* \ - | mipstx39-* | mipstx39el-* \ - | mmix-* \ - | mt-* \ - | msp430-* \ - | nds32-* | nds32le-* | nds32be-* \ - | nios-* | nios2-* \ - | none-* | np1-* | ns16k-* | ns32k-* \ - | open8-* \ - | orion-* \ - | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ - | pyramid-* \ - | romp-* | rs6000-* | rx-* \ - | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ - | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ - | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ - | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ - | tahoe-* \ - | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ - | tile*-* \ - | tron-* \ - | ubicom32-* \ - | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ - | vax-* \ - | we32k-* \ - | x86-* | x86_64-* | xc16x-* | xps100-* \ - | xstormy16-* | xtensa*-* \ - | ymp-* \ - | z8k-* | z80-*) - ;; - # Recognize the basic CPU types without company name, with glob match. - xtensa*) - basic_machine=$basic_machine-unknown - ;; - # Recognize the various machine names and aliases which stand - # for a CPU type and a company and sometimes even an OS. - 386bsd) - basic_machine=i386-unknown - os=-bsd - ;; - 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) - basic_machine=m68000-att - ;; - 3b*) - basic_machine=we32k-att - ;; - a29khif) - basic_machine=a29k-amd - os=-udi - ;; - abacus) - basic_machine=abacus-unknown - ;; - adobe68k) - basic_machine=m68010-adobe - os=-scout - ;; - alliant | fx80) - basic_machine=fx80-alliant - ;; - altos | altos3068) - basic_machine=m68k-altos - ;; - am29k) - basic_machine=a29k-none - os=-bsd - ;; - amd64) - basic_machine=x86_64-pc - ;; - amd64-*) - basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - amdahl) - basic_machine=580-amdahl - os=-sysv - ;; - amiga | amiga-*) - basic_machine=m68k-unknown - ;; - amigaos | amigados) - basic_machine=m68k-unknown - os=-amigaos - ;; - amigaunix | amix) - basic_machine=m68k-unknown - os=-sysv4 - ;; - apollo68) - basic_machine=m68k-apollo - os=-sysv - ;; - apollo68bsd) - basic_machine=m68k-apollo - os=-bsd - ;; - aros) - basic_machine=i386-pc - os=-aros - ;; - aux) - basic_machine=m68k-apple - os=-aux - ;; - balance) - basic_machine=ns32k-sequent - os=-dynix - ;; - blackfin) - basic_machine=bfin-unknown - os=-linux - ;; - blackfin-*) - basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - bluegene*) - basic_machine=powerpc-ibm - os=-cnk - ;; - c54x-*) - basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c55x-*) - basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c6x-*) - basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c90) - basic_machine=c90-cray - os=-unicos - ;; - cegcc) - basic_machine=arm-unknown - os=-cegcc - ;; - convex-c1) - basic_machine=c1-convex - os=-bsd - ;; - convex-c2) - basic_machine=c2-convex - os=-bsd - ;; - convex-c32) - basic_machine=c32-convex - os=-bsd - ;; - convex-c34) - basic_machine=c34-convex - os=-bsd - ;; - convex-c38) - basic_machine=c38-convex - os=-bsd - ;; - cray | j90) - basic_machine=j90-cray - os=-unicos - ;; - craynv) - basic_machine=craynv-cray - os=-unicosmp - ;; - cr16 | cr16-*) - basic_machine=cr16-unknown - os=-elf - ;; - crds | unos) - basic_machine=m68k-crds - ;; - crisv32 | crisv32-* | etraxfs*) - basic_machine=crisv32-axis - ;; - cris | cris-* | etrax*) - basic_machine=cris-axis - ;; - crx) - basic_machine=crx-unknown - os=-elf - ;; - da30 | da30-*) - basic_machine=m68k-da30 - ;; - decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) - basic_machine=mips-dec - ;; - decsystem10* | dec10*) - basic_machine=pdp10-dec - os=-tops10 - ;; - decsystem20* | dec20*) - basic_machine=pdp10-dec - os=-tops20 - ;; - delta | 3300 | motorola-3300 | motorola-delta \ - | 3300-motorola | delta-motorola) - basic_machine=m68k-motorola - ;; - delta88) - basic_machine=m88k-motorola - os=-sysv3 - ;; - dicos) - basic_machine=i686-pc - os=-dicos - ;; - djgpp) - basic_machine=i586-pc - os=-msdosdjgpp - ;; - dpx20 | dpx20-*) - basic_machine=rs6000-bull - os=-bosx - ;; - dpx2* | dpx2*-bull) - basic_machine=m68k-bull - os=-sysv3 - ;; - ebmon29k) - basic_machine=a29k-amd - os=-ebmon - ;; - elxsi) - basic_machine=elxsi-elxsi - os=-bsd - ;; - encore | umax | mmax) - basic_machine=ns32k-encore - ;; - es1800 | OSE68k | ose68k | ose | OSE) - basic_machine=m68k-ericsson - os=-ose - ;; - fx2800) - basic_machine=i860-alliant - ;; - genix) - basic_machine=ns32k-ns - ;; - gmicro) - basic_machine=tron-gmicro - os=-sysv - ;; - go32) - basic_machine=i386-pc - os=-go32 - ;; - h3050r* | hiux*) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - h8300hms) - basic_machine=h8300-hitachi - os=-hms - ;; - h8300xray) - basic_machine=h8300-hitachi - os=-xray - ;; - h8500hms) - basic_machine=h8500-hitachi - os=-hms - ;; - harris) - basic_machine=m88k-harris - os=-sysv3 - ;; - hp300-*) - basic_machine=m68k-hp - ;; - hp300bsd) - basic_machine=m68k-hp - os=-bsd - ;; - hp300hpux) - basic_machine=m68k-hp - os=-hpux - ;; - hp3k9[0-9][0-9] | hp9[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k2[0-9][0-9] | hp9k31[0-9]) - basic_machine=m68000-hp - ;; - hp9k3[2-9][0-9]) - basic_machine=m68k-hp - ;; - hp9k6[0-9][0-9] | hp6[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k7[0-79][0-9] | hp7[0-79][0-9]) - basic_machine=hppa1.1-hp - ;; - hp9k78[0-9] | hp78[0-9]) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][13679] | hp8[0-9][13679]) - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][0-9] | hp8[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hppa-next) - os=-nextstep3 - ;; - hppaosf) - basic_machine=hppa1.1-hp - os=-osf - ;; - hppro) - basic_machine=hppa1.1-hp - os=-proelf - ;; - i370-ibm* | ibm*) - basic_machine=i370-ibm - ;; -# I'm not sure what "Sysv32" means. Should this be sysv3.2? - i*86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv32 - ;; - i*86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv4 - ;; - i*86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv - ;; - i*86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-solaris2 - ;; - i386mach) - basic_machine=i386-mach - os=-mach - ;; - i386-vsta | vsta) - basic_machine=i386-unknown - os=-vsta - ;; - iris | iris4d) - basic_machine=mips-sgi - case $os in - -irix*) - ;; - *) - os=-irix4 - ;; - esac - ;; - isi68 | isi) - basic_machine=m68k-isi - os=-sysv - ;; - m68knommu) - basic_machine=m68k-unknown - os=-linux - ;; - m68knommu-*) - basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - m88k-omron*) - basic_machine=m88k-omron - ;; - magnum | m3230) - basic_machine=mips-mips - os=-sysv - ;; - merlin) - basic_machine=ns32k-utek - os=-sysv - ;; - microblaze) - basic_machine=microblaze-xilinx - ;; - mingw32) - basic_machine=i386-pc - os=-mingw32 - ;; - mingw32ce) - basic_machine=arm-unknown - os=-mingw32ce - ;; - miniframe) - basic_machine=m68000-convergent - ;; - *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; - mips3*-*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` - ;; - mips3*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown - ;; - monitor) - basic_machine=m68k-rom68k - os=-coff - ;; - morphos) - basic_machine=powerpc-unknown - os=-morphos - ;; - msdos) - basic_machine=i386-pc - os=-msdos - ;; - ms1-*) - basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` - ;; - mvs) - basic_machine=i370-ibm - os=-mvs - ;; - nacl) - basic_machine=le32-unknown - os=-nacl - ;; - ncr3000) - basic_machine=i486-ncr - os=-sysv4 - ;; - netbsd386) - basic_machine=i386-unknown - os=-netbsd - ;; - netwinder) - basic_machine=armv4l-rebel - os=-linux - ;; - news | news700 | news800 | news900) - basic_machine=m68k-sony - os=-newsos - ;; - news1000) - basic_machine=m68030-sony - os=-newsos - ;; - news-3600 | risc-news) - basic_machine=mips-sony - os=-newsos - ;; - necv70) - basic_machine=v70-nec - os=-sysv - ;; - next | m*-next ) - basic_machine=m68k-next - case $os in - -nextstep* ) - ;; - -ns2*) - os=-nextstep2 - ;; - *) - os=-nextstep3 - ;; - esac - ;; - nh3000) - basic_machine=m68k-harris - os=-cxux - ;; - nh[45]000) - basic_machine=m88k-harris - os=-cxux - ;; - nindy960) - basic_machine=i960-intel - os=-nindy - ;; - mon960) - basic_machine=i960-intel - os=-mon960 - ;; - nonstopux) - basic_machine=mips-compaq - os=-nonstopux - ;; - np1) - basic_machine=np1-gould - ;; - neo-tandem) - basic_machine=neo-tandem - ;; - nse-tandem) - basic_machine=nse-tandem - ;; - nsr-tandem) - basic_machine=nsr-tandem - ;; - op50n-* | op60c-*) - basic_machine=hppa1.1-oki - os=-proelf - ;; - openrisc | openrisc-*) - basic_machine=or32-unknown - ;; - os400) - basic_machine=powerpc-ibm - os=-os400 - ;; - OSE68000 | ose68000) - basic_machine=m68000-ericsson - os=-ose - ;; - os68k) - basic_machine=m68k-none - os=-os68k - ;; - pa-hitachi) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - paragon) - basic_machine=i860-intel - os=-osf - ;; - parisc) - basic_machine=hppa-unknown - os=-linux - ;; - parisc-*) - basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - pbd) - basic_machine=sparc-tti - ;; - pbb) - basic_machine=m68k-tti - ;; - pc532 | pc532-*) - basic_machine=ns32k-pc532 - ;; - pc98) - basic_machine=i386-pc - ;; - pc98-*) - basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium | p5 | k5 | k6 | nexgen | viac3) - basic_machine=i586-pc - ;; - pentiumpro | p6 | 6x86 | athlon | athlon_*) - basic_machine=i686-pc - ;; - pentiumii | pentium2 | pentiumiii | pentium3) - basic_machine=i686-pc - ;; - pentium4) - basic_machine=i786-pc - ;; - pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium4-*) - basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pn) - basic_machine=pn-gould - ;; - power) basic_machine=power-ibm - ;; - ppc | ppcbe) basic_machine=powerpc-unknown - ;; - ppc-* | ppcbe-*) - basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppcle | powerpclittle | ppc-le | powerpc-little) - basic_machine=powerpcle-unknown - ;; - ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64) basic_machine=powerpc64-unknown - ;; - ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64le | powerpc64little | ppc64-le | powerpc64-little) - basic_machine=powerpc64le-unknown - ;; - ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ps2) - basic_machine=i386-ibm - ;; - pw32) - basic_machine=i586-unknown - os=-pw32 - ;; - rdos) - basic_machine=i386-pc - os=-rdos - ;; - rom68k) - basic_machine=m68k-rom68k - os=-coff - ;; - rm[46]00) - basic_machine=mips-siemens - ;; - rtpc | rtpc-*) - basic_machine=romp-ibm - ;; - s390 | s390-*) - basic_machine=s390-ibm - ;; - s390x | s390x-*) - basic_machine=s390x-ibm - ;; - sa29200) - basic_machine=a29k-amd - os=-udi - ;; - sb1) - basic_machine=mipsisa64sb1-unknown - ;; - sb1el) - basic_machine=mipsisa64sb1el-unknown - ;; - sde) - basic_machine=mipsisa32-sde - os=-elf - ;; - sei) - basic_machine=mips-sei - os=-seiux - ;; - sequent) - basic_machine=i386-sequent - ;; - sh) - basic_machine=sh-hitachi - os=-hms - ;; - sh5el) - basic_machine=sh5le-unknown - ;; - sh64) - basic_machine=sh64-unknown - ;; - sparclite-wrs | simso-wrs) - basic_machine=sparclite-wrs - os=-vxworks - ;; - sps7) - basic_machine=m68k-bull - os=-sysv2 - ;; - spur) - basic_machine=spur-unknown - ;; - st2000) - basic_machine=m68k-tandem - ;; - stratus) - basic_machine=i860-stratus - os=-sysv4 - ;; - strongarm-* | thumb-*) - basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - sun2) - basic_machine=m68000-sun - ;; - sun2os3) - basic_machine=m68000-sun - os=-sunos3 - ;; - sun2os4) - basic_machine=m68000-sun - os=-sunos4 - ;; - sun3os3) - basic_machine=m68k-sun - os=-sunos3 - ;; - sun3os4) - basic_machine=m68k-sun - os=-sunos4 - ;; - sun4os3) - basic_machine=sparc-sun - os=-sunos3 - ;; - sun4os4) - basic_machine=sparc-sun - os=-sunos4 - ;; - sun4sol2) - basic_machine=sparc-sun - os=-solaris2 - ;; - sun3 | sun3-*) - basic_machine=m68k-sun - ;; - sun4) - basic_machine=sparc-sun - ;; - sun386 | sun386i | roadrunner) - basic_machine=i386-sun - ;; - sv1) - basic_machine=sv1-cray - os=-unicos - ;; - symmetry) - basic_machine=i386-sequent - os=-dynix - ;; - t3e) - basic_machine=alphaev5-cray - os=-unicos - ;; - t90) - basic_machine=t90-cray - os=-unicos - ;; - tile*) - basic_machine=$basic_machine-unknown - os=-linux-gnu - ;; - tx39) - basic_machine=mipstx39-unknown - ;; - tx39el) - basic_machine=mipstx39el-unknown - ;; - toad1) - basic_machine=pdp10-xkl - os=-tops20 - ;; - tower | tower-32) - basic_machine=m68k-ncr - ;; - tpf) - basic_machine=s390x-ibm - os=-tpf - ;; - udi29k) - basic_machine=a29k-amd - os=-udi - ;; - ultra3) - basic_machine=a29k-nyu - os=-sym1 - ;; - v810 | necv810) - basic_machine=v810-nec - os=-none - ;; - vaxv) - basic_machine=vax-dec - os=-sysv - ;; - vms) - basic_machine=vax-dec - os=-vms - ;; - vpp*|vx|vx-*) - basic_machine=f301-fujitsu - ;; - vxworks960) - basic_machine=i960-wrs - os=-vxworks - ;; - vxworks68) - basic_machine=m68k-wrs - os=-vxworks - ;; - vxworks29k) - basic_machine=a29k-wrs - os=-vxworks - ;; - w65*) - basic_machine=w65-wdc - os=-none - ;; - w89k-*) - basic_machine=hppa1.1-winbond - os=-proelf - ;; - xbox) - basic_machine=i686-pc - os=-mingw32 - ;; - xps | xps100) - basic_machine=xps100-honeywell - ;; - xscale-* | xscalee[bl]-*) - basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` - ;; - ymp) - basic_machine=ymp-cray - os=-unicos - ;; - z8k-*-coff) - basic_machine=z8k-unknown - os=-sim - ;; - z80-*-coff) - basic_machine=z80-unknown - os=-sim - ;; - none) - basic_machine=none-none - os=-none - ;; - -# Here we handle the default manufacturer of certain CPU types. It is in -# some cases the only manufacturer, in others, it is the most popular. - w89k) - basic_machine=hppa1.1-winbond - ;; - op50n) - basic_machine=hppa1.1-oki - ;; - op60c) - basic_machine=hppa1.1-oki - ;; - romp) - basic_machine=romp-ibm - ;; - mmix) - basic_machine=mmix-knuth - ;; - rs6000) - basic_machine=rs6000-ibm - ;; - vax) - basic_machine=vax-dec - ;; - pdp10) - # there are many clones, so DEC is not a safe bet - basic_machine=pdp10-unknown - ;; - pdp11) - basic_machine=pdp11-dec - ;; - we32k) - basic_machine=we32k-att - ;; - sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) - basic_machine=sh-unknown - ;; - sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) - basic_machine=sparc-sun - ;; - cydra) - basic_machine=cydra-cydrome - ;; - orion) - basic_machine=orion-highlevel - ;; - orion105) - basic_machine=clipper-highlevel - ;; - mac | mpw | mac-mpw) - basic_machine=m68k-apple - ;; - pmac | pmac-mpw) - basic_machine=powerpc-apple - ;; - *-unknown) - # Make sure to match an already-canonicalized machine name. - ;; - *) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; -esac - -# Here we canonicalize certain aliases for manufacturers. -case $basic_machine in - *-digital*) - basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` - ;; - *-commodore*) - basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` - ;; - *) - ;; -esac - -# Decode manufacturer-specific aliases for certain operating systems. - -if [ x"$os" != x"" ] -then -case $os in - # First match some system type aliases - # that might get confused with valid system types. - # -solaris* is a basic system type, with this one exception. - -auroraux) - os=-auroraux - ;; - -solaris1 | -solaris1.*) - os=`echo $os | sed -e 's|solaris1|sunos4|'` - ;; - -solaris) - os=-solaris2 - ;; - -svr4*) - os=-sysv4 - ;; - -unixware*) - os=-sysv4.2uw - ;; - -gnu/linux*) - os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` - ;; - # First accept the basic system types. - # The portable systems comes first. - # Each alternative MUST END IN A *, to match a version number. - # -sysv* is not here because it comes later, after sysvr4. - -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ - | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ - | -sym* | -kopensolaris* \ - | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* | -aros* \ - | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ - | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ - | -openbsd* | -solidbsd* \ - | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ - | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ - | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ - | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* | -cegcc* \ - | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -linux-gnu* | -linux-android* \ - | -linux-newlib* | -linux-uclibc* \ - | -uxpv* | -beos* | -mpeix* | -udk* \ - | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ - | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ - | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ - | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ - | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) - # Remember, each alternative MUST END IN *, to match a version number. - ;; - -qnx*) - case $basic_machine in - x86-* | i*86-*) - ;; - *) - os=-nto$os - ;; - esac - ;; - -nto-qnx*) - ;; - -nto*) - os=`echo $os | sed -e 's|nto|nto-qnx|'` - ;; - -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ - | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) - ;; - -mac*) - os=`echo $os | sed -e 's|mac|macos|'` - ;; - -linux-dietlibc) - os=-linux-dietlibc - ;; - -linux*) - os=`echo $os | sed -e 's|linux|linux-gnu|'` - ;; - -sunos5*) - os=`echo $os | sed -e 's|sunos5|solaris2|'` - ;; - -sunos6*) - os=`echo $os | sed -e 's|sunos6|solaris3|'` - ;; - -opened*) - os=-openedition - ;; - -os400*) - os=-os400 - ;; - -wince*) - os=-wince - ;; - -osfrose*) - os=-osfrose - ;; - -osf*) - os=-osf - ;; - -utek*) - os=-bsd - ;; - -dynix*) - os=-bsd - ;; - -acis*) - os=-aos - ;; - -atheos*) - os=-atheos - ;; - -syllable*) - os=-syllable - ;; - -386bsd) - os=-bsd - ;; - -ctix* | -uts*) - os=-sysv - ;; - -nova*) - os=-rtmk-nova - ;; - -ns2 ) - os=-nextstep2 - ;; - -nsk*) - os=-nsk - ;; - # Preserve the version number of sinix5. - -sinix5.*) - os=`echo $os | sed -e 's|sinix|sysv|'` - ;; - -sinix*) - os=-sysv4 - ;; - -tpf*) - os=-tpf - ;; - -triton*) - os=-sysv3 - ;; - -oss*) - os=-sysv3 - ;; - -svr4) - os=-sysv4 - ;; - -svr3) - os=-sysv3 - ;; - -sysvr4) - os=-sysv4 - ;; - # This must come after -sysvr4. - -sysv*) - ;; - -ose*) - os=-ose - ;; - -es1800*) - os=-ose - ;; - -xenix) - os=-xenix - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - os=-mint - ;; - -aros*) - os=-aros - ;; - -kaos*) - os=-kaos - ;; - -zvmoe) - os=-zvmoe - ;; - -dicos*) - os=-dicos - ;; - -nacl*) - ;; - -none) - ;; - *) - # Get rid of the `-' at the beginning of $os. - os=`echo $os | sed 's/[^-]*-//'` - echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 - exit 1 - ;; -esac -else - -# Here we handle the default operating systems that come with various machines. -# The value should be what the vendor currently ships out the door with their -# machine or put another way, the most popular os provided with the machine. - -# Note that if you're going to try to match "-MANUFACTURER" here (say, -# "-sun"), then you have to tell the case statement up towards the top -# that MANUFACTURER isn't an operating system. Otherwise, code above -# will signal an error saying that MANUFACTURER isn't an operating -# system, and we'll never get to this point. - -case $basic_machine in - score-*) - os=-elf - ;; - spu-*) - os=-elf - ;; - *-acorn) - os=-riscix1.2 - ;; - arm*-rebel) - os=-linux - ;; - arm*-semi) - os=-aout - ;; - c4x-* | tic4x-*) - os=-coff - ;; - tic54x-*) - os=-coff - ;; - tic55x-*) - os=-coff - ;; - tic6x-*) - os=-coff - ;; - # This must come before the *-dec entry. - pdp10-*) - os=-tops20 - ;; - pdp11-*) - os=-none - ;; - *-dec | vax-*) - os=-ultrix4.2 - ;; - m68*-apollo) - os=-domain - ;; - i386-sun) - os=-sunos4.0.2 - ;; - m68000-sun) - os=-sunos3 - # This also exists in the configure program, but was not the - # default. - # os=-sunos4 - ;; - m68*-cisco) - os=-aout - ;; - mep-*) - os=-elf - ;; - mips*-cisco) - os=-elf - ;; - mips*-*) - os=-elf - ;; - or32-*) - os=-coff - ;; - *-tti) # must be before sparc entry or we get the wrong os. - os=-sysv3 - ;; - sparc-* | *-sun) - os=-sunos4.1.1 - ;; - *-be) - os=-beos - ;; - *-haiku) - os=-haiku - ;; - *-ibm) - os=-aix - ;; - *-knuth) - os=-mmixware - ;; - *-wec) - os=-proelf - ;; - *-winbond) - os=-proelf - ;; - *-oki) - os=-proelf - ;; - *-hp) - os=-hpux - ;; - *-hitachi) - os=-hiux - ;; - i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) - os=-sysv - ;; - *-cbm) - os=-amigaos - ;; - *-dg) - os=-dgux - ;; - *-dolphin) - os=-sysv3 - ;; - m68k-ccur) - os=-rtu - ;; - m88k-omron*) - os=-luna - ;; - *-next ) - os=-nextstep - ;; - *-sequent) - os=-ptx - ;; - *-crds) - os=-unos - ;; - *-ns) - os=-genix - ;; - i370-*) - os=-mvs - ;; - *-next) - os=-nextstep3 - ;; - *-gould) - os=-sysv - ;; - *-highlevel) - os=-bsd - ;; - *-encore) - os=-bsd - ;; - *-sgi) - os=-irix - ;; - *-siemens) - os=-sysv4 - ;; - *-masscomp) - os=-rtu - ;; - f30[01]-fujitsu | f700-fujitsu) - os=-uxpv - ;; - *-rom68k) - os=-coff - ;; - *-*bug) - os=-coff - ;; - *-apple) - os=-macos - ;; - *-atari*) - os=-mint - ;; - *) - os=-none - ;; -esac -fi - -# Here we handle the case where we know the os, and the CPU type, but not the -# manufacturer. We pick the logical manufacturer. -vendor=unknown -case $basic_machine in - *-unknown) - case $os in - -riscix*) - vendor=acorn - ;; - -sunos*) - vendor=sun - ;; - -cnk*|-aix*) - vendor=ibm - ;; - -beos*) - vendor=be - ;; - -hpux*) - vendor=hp - ;; - -mpeix*) - vendor=hp - ;; - -hiux*) - vendor=hitachi - ;; - -unos*) - vendor=crds - ;; - -dgux*) - vendor=dg - ;; - -luna*) - vendor=omron - ;; - -genix*) - vendor=ns - ;; - -mvs* | -opened*) - vendor=ibm - ;; - -os400*) - vendor=ibm - ;; - -ptx*) - vendor=sequent - ;; - -tpf*) - vendor=ibm - ;; - -vxsim* | -vxworks* | -windiss*) - vendor=wrs - ;; - -aux*) - vendor=apple - ;; - -hms*) - vendor=hitachi - ;; - -mpw* | -macos*) - vendor=apple - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - vendor=atari - ;; - -vos*) - vendor=stratus - ;; - esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` - ;; -esac - -echo $basic_machine$os -exit - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/config/depcomp b/config/depcomp deleted file mode 100755 index 807b991f..00000000 --- a/config/depcomp +++ /dev/null @@ -1,423 +0,0 @@ -#! /bin/sh - -# depcomp - compile a program generating dependencies as side-effects -# Copyright 1999, 2000 Free Software Foundation, Inc. - -# 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 2, 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# Originally written by Alexandre Oliva . - -if test -z "$depmode" || test -z "$source" || test -z "$object"; then - echo "depcomp: Variables source, object and depmode must be set" 1>&2 - exit 1 -fi -# `libtool' can also be set to `yes' or `no'. - -if test -z "$depfile"; then - base=`echo "$object" | sed -e 's,^.*/,,' -e 's,\.\([^.]*\)$,.P\1,'` - dir=`echo "$object" | sed 's,/.*$,/,'` - if test "$dir" = "$object"; then - dir= - fi - # FIXME: should be _deps on DOS. - depfile="$dir.deps/$base" -fi - -tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} - -rm -f "$tmpdepfile" - -# Some modes work just like other modes, but use different flags. We -# parameterize here, but still list the modes in the big case below, -# to make depend.m4 easier to write. Note that we *cannot* use a case -# here, because this file can only contain one case statement. -if test "$depmode" = hp; then - # HP compiler uses -M and no extra arg. - gccflag=-M - depmode=gcc -fi - -if test "$depmode" = dashXmstdout; then - # This is just like dashmstdout with a different argument. - dashmflag=-xM - depmode=dashmstdout -fi - -case "$depmode" in -gcc3) -## gcc 3 implements dependency tracking that does exactly what -## we want. Yay! Note: for some reason libtool 1.4 doesn't like -## it if -MD -MP comes after the -MF stuff. Hmm. - "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile" - exit $stat - fi - mv "$tmpdepfile" "$depfile" - ;; - -gcc) -## There are various ways to get dependency output from gcc. Here's -## why we pick this rather obscure method: -## - Don't want to use -MD because we'd like the dependencies to end -## up in a subdir. Having to rename by hand is ugly. -## (We might end up doing this anyway to support other compilers.) -## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like -## -MM, not -M (despite what the docs say). -## - Using -M directly means running the compiler twice (even worse -## than renaming). - if test -z "$gccflag"; then - gccflag=-MD, - fi - "$@" -Wp,"$gccflag$tmpdepfile" - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - echo "$object : \\" > "$depfile" - alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz -## The second -e expression handles DOS-style file names with drive letters. - sed -e 's/^[^:]*: / /' \ - -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" -## This next piece of magic avoids the `deleted header file' problem. -## The problem is that when a header file which appears in a .P file -## is deleted, the dependency causes make to die (because there is -## typically no way to rebuild the header). We avoid this by adding -## dummy dependencies for each header file. Too bad gcc doesn't do -## this for us directly. - tr ' ' ' -' < "$tmpdepfile" | -## Some versions of gcc put a space before the `:'. On the theory -## that the space means something, we add a space to the output as -## well. -## Some versions of the HPUX 10.20 sed can't process this invocation -## correctly. Breaking it into two sed invocations is a workaround. - sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -hp) - # This case exists only to let depend.m4 do its work. It works by - # looking at the text of this script. This case will never be run, - # since it is checked for above. - exit 1 - ;; - -sgi) - if test "$libtool" = yes; then - "$@" "-Wp,-MDupdate,$tmpdepfile" - else - "$@" -MDupdate "$tmpdepfile" - fi - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - - if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files - echo "$object : \\" > "$depfile" - - # Clip off the initial element (the dependent). Don't try to be - # clever and replace this with sed code, as IRIX sed won't handle - # lines with more than a fixed number of characters (4096 in - # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; - # the IRIX cc adds comments like `#:fec' to the end of the - # dependency line. - tr ' ' ' -' < "$tmpdepfile" \ - | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ - tr ' -' ' ' >> $depfile - echo >> $depfile - - # The second pass generates a dummy entry for each header file. - tr ' ' ' -' < "$tmpdepfile" \ - | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ - >> $depfile - else - # The sourcefile does not contain any dependencies, so just - # store a dummy comment line, to avoid errors with the Makefile - # "include basename.Plo" scheme. - echo "#dummy" > "$depfile" - fi - rm -f "$tmpdepfile" - ;; - -aix) - # The C for AIX Compiler uses -M and outputs the dependencies - # in a .u file. This file always lives in the current directory. - # Also, the AIX compiler puts `$object:' at the start of each line; - # $object doesn't have directory information. - stripped=`echo "$object" | sed -e 's,^.*/,,' -e 's/\(.*\)\..*$/\1/'` - tmpdepfile="$stripped.u" - outname="$stripped.o" - if test "$libtool" = yes; then - "$@" -Wc,-M - else - "$@" -M - fi - - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile" - exit $stat - fi - - if test -f "$tmpdepfile"; then - # Each line is of the form `foo.o: dependent.h'. - # Do two passes, one to just change these to - # `$object: dependent.h' and one to simply `dependent.h:'. - sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" - sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" - else - # The sourcefile does not contain any dependencies, so just - # store a dummy comment line, to avoid errors with the Makefile - # "include basename.Plo" scheme. - echo "#dummy" > "$depfile" - fi - rm -f "$tmpdepfile" - ;; - -tru64) - # The Tru64 compiler uses -MD to generate dependencies as a side - # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. - # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put - # dependencies in `foo.d' instead, so we check for that too. - # Subdirectories are respected. - dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` - test "x$dir" = "x$object" && dir= - base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` - - if test "$libtool" = yes; then - tmpdepfile1="$dir.libs/$base.lo.d" - tmpdepfile2="$dir.libs/$base.d" - "$@" -Wc,-MD - else - tmpdepfile1="$dir$base.o.d" - tmpdepfile2="$dir$base.d" - "$@" -MD - fi - - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile1" "$tmpdepfile2" - exit $stat - fi - - if test -f "$tmpdepfile1"; then - tmpdepfile="$tmpdepfile1" - else - tmpdepfile="$tmpdepfile2" - fi - if test -f "$tmpdepfile"; then - sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" - # That's a space and a tab in the []. - sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" - else - echo "#dummy" > "$depfile" - fi - rm -f "$tmpdepfile" - ;; - -#nosideeffect) - # This comment above is used by automake to tell side-effect - # dependency tracking mechanisms from slower ones. - -dashmstdout) - # Important note: in order to support this mode, a compiler *must* - # always write the proprocessed file to stdout, regardless of -o. - "$@" || exit $? - - # Remove the call to Libtool. - if test "$libtool" = yes; then - while test $1 != '--mode=compile'; do - shift - done - shift - fi - - # Remove `-o $object'. We will use -o /dev/null later, - # however we can't do the remplacement now because - # `-o $object' might simply not be used - IFS=" " - for arg - do - case $arg in - -o) - shift - ;; - $object) - shift - ;; - *) - set fnord "$@" "$arg" - shift # fnord - shift # $arg - ;; - esac - done - - test -z "$dashmflag" && dashmflag=-M - "$@" -o /dev/null $dashmflag | sed 's:^[^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" - rm -f "$depfile" - cat < "$tmpdepfile" > "$depfile" - tr ' ' ' -' < "$tmpdepfile" | \ -## Some versions of the HPUX 10.20 sed can't process this invocation -## correctly. Breaking it into two sed invocations is a workaround. - sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -dashXmstdout) - # This case only exists to satisfy depend.m4. It is never actually - # run, as this mode is specially recognized in the preamble. - exit 1 - ;; - -makedepend) - "$@" || exit $? - # X makedepend - shift - cleared=no - for arg in "$@"; do - case $cleared in - no) - set ""; shift - cleared=yes ;; - esac - case "$arg" in - -D*|-I*) - set fnord "$@" "$arg"; shift ;; - -*) - ;; - *) - set fnord "$@" "$arg"; shift ;; - esac - done - obj_suffix="`echo $object | sed 's/^.*\././'`" - touch "$tmpdepfile" - ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" - rm -f "$depfile" - cat < "$tmpdepfile" > "$depfile" - sed '1,2d' "$tmpdepfile" | tr ' ' ' -' | \ -## Some versions of the HPUX 10.20 sed can't process this invocation -## correctly. Breaking it into two sed invocations is a workaround. - sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" "$tmpdepfile".bak - ;; - -cpp) - # Important note: in order to support this mode, a compiler *must* - # always write the proprocessed file to stdout. - "$@" || exit $? - - # Remove the call to Libtool. - if test "$libtool" = yes; then - while test $1 != '--mode=compile'; do - shift - done - shift - fi - - # Remove `-o $object'. - IFS=" " - for arg - do - case $arg in - -o) - shift - ;; - $object) - shift - ;; - *) - set fnord "$@" "$arg" - shift # fnord - shift # $arg - ;; - esac - done - - "$@" -E | - sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | - sed '$ s: \\$::' > "$tmpdepfile" - rm -f "$depfile" - echo "$object : \\" > "$depfile" - cat < "$tmpdepfile" >> "$depfile" - sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -msvisualcpp) - # Important note: in order to support this mode, a compiler *must* - # always write the proprocessed file to stdout, regardless of -o, - # because we must use -o when running libtool. - "$@" || exit $? - IFS=" " - for arg - do - case "$arg" in - "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") - set fnord "$@" - shift - shift - ;; - *) - set fnord "$@" "$arg" - shift - shift - ;; - esac - done - "$@" -E | - sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" - rm -f "$depfile" - echo "$object : \\" > "$depfile" - . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" - echo " " >> "$depfile" - . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -none) - exec "$@" - ;; - -*) - echo "Unknown depmode $depmode" 1>&2 - exit 1 - ;; -esac - -exit 0 diff --git a/config/install-sh b/config/install-sh deleted file mode 100755 index 36f96f3e..00000000 --- a/config/install-sh +++ /dev/null @@ -1,276 +0,0 @@ -#!/bin/sh -# -# install - install a program, script, or datafile -# This comes from X11R5 (mit/util/scripts/install.sh). -# -# Copyright 1991 by the Massachusetts Institute of Technology -# -# Permission to use, copy, modify, distribute, and sell this software and its -# documentation for any purpose is hereby granted without fee, provided that -# the above copyright notice appear in all copies and that both that -# copyright notice and this permission notice appear in supporting -# documentation, and that the name of M.I.T. not be used in advertising or -# publicity pertaining to distribution of the software without specific, -# written prior permission. M.I.T. makes no representations about the -# suitability of this software for any purpose. It is provided "as is" -# without express or implied warranty. -# -# Calling this script install-sh is preferred over install.sh, to prevent -# `make' implicit rules from creating a file called install from it -# when there is no Makefile. -# -# This script is compatible with the BSD install script, but was written -# from scratch. It can only install one file at a time, a restriction -# shared with many OS's install programs. - - -# set DOITPROG to echo to test this script - -# Don't use :- since 4.3BSD and earlier shells don't like it. -doit="${DOITPROG-}" - - -# put in absolute paths if you don't have them in your path; or use env. vars. - -mvprog="${MVPROG-mv}" -cpprog="${CPPROG-cp}" -chmodprog="${CHMODPROG-chmod}" -chownprog="${CHOWNPROG-chown}" -chgrpprog="${CHGRPPROG-chgrp}" -stripprog="${STRIPPROG-strip}" -rmprog="${RMPROG-rm}" -mkdirprog="${MKDIRPROG-mkdir}" - -transformbasename="" -transform_arg="" -instcmd="$mvprog" -chmodcmd="$chmodprog 0755" -chowncmd="" -chgrpcmd="" -stripcmd="" -rmcmd="$rmprog -f" -mvcmd="$mvprog" -src="" -dst="" -dir_arg="" - -while [ x"$1" != x ]; do - case $1 in - -c) instcmd=$cpprog - shift - continue;; - - -d) dir_arg=true - shift - continue;; - - -m) chmodcmd="$chmodprog $2" - shift - shift - continue;; - - -o) chowncmd="$chownprog $2" - shift - shift - continue;; - - -g) chgrpcmd="$chgrpprog $2" - shift - shift - continue;; - - -s) stripcmd=$stripprog - shift - continue;; - - -t=*) transformarg=`echo $1 | sed 's/-t=//'` - shift - continue;; - - -b=*) transformbasename=`echo $1 | sed 's/-b=//'` - shift - continue;; - - *) if [ x"$src" = x ] - then - src=$1 - else - # this colon is to work around a 386BSD /bin/sh bug - : - dst=$1 - fi - shift - continue;; - esac -done - -if [ x"$src" = x ] -then - echo "$0: no input file specified" >&2 - exit 1 -else - : -fi - -if [ x"$dir_arg" != x ]; then - dst=$src - src="" - - if [ -d "$dst" ]; then - instcmd=: - chmodcmd="" - else - instcmd=$mkdirprog - fi -else - -# Waiting for this to be detected by the "$instcmd $src $dsttmp" command -# might cause directories to be created, which would be especially bad -# if $src (and thus $dsttmp) contains '*'. - - if [ -f "$src" ] || [ -d "$src" ] - then - : - else - echo "$0: $src does not exist" >&2 - exit 1 - fi - - if [ x"$dst" = x ] - then - echo "$0: no destination specified" >&2 - exit 1 - else - : - fi - -# If destination is a directory, append the input filename; if your system -# does not like double slashes in filenames, you may need to add some logic - - if [ -d "$dst" ] - then - dst=$dst/`basename "$src"` - else - : - fi -fi - -## this sed command emulates the dirname command -dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` - -# Make sure that the destination directory exists. -# this part is taken from Noah Friedman's mkinstalldirs script - -# Skip lots of stat calls in the usual case. -if [ ! -d "$dstdir" ]; then -defaultIFS=' - ' -IFS="${IFS-$defaultIFS}" - -oIFS=$IFS -# Some sh's can't handle IFS=/ for some reason. -IFS='%' -set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` -IFS=$oIFS - -pathcomp='' - -while [ $# -ne 0 ] ; do - pathcomp=$pathcomp$1 - shift - - if [ ! -d "$pathcomp" ] ; - then - $mkdirprog "$pathcomp" - else - : - fi - - pathcomp=$pathcomp/ -done -fi - -if [ x"$dir_arg" != x ] -then - $doit $instcmd "$dst" && - - if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi && - if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi && - if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi && - if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi -else - -# If we're going to rename the final executable, determine the name now. - - if [ x"$transformarg" = x ] - then - dstfile=`basename "$dst"` - else - dstfile=`basename "$dst" $transformbasename | - sed $transformarg`$transformbasename - fi - -# don't allow the sed command to completely eliminate the filename - - if [ x"$dstfile" = x ] - then - dstfile=`basename "$dst"` - else - : - fi - -# Make a couple of temp file names in the proper directory. - - dsttmp=$dstdir/#inst.$$# - rmtmp=$dstdir/#rm.$$# - -# Trap to clean up temp files at exit. - - trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0 - trap '(exit $?); exit' 1 2 13 15 - -# Move or copy the file name to the temp name - - $doit $instcmd "$src" "$dsttmp" && - -# and set any options; do chmod last to preserve setuid bits - -# If any of these fail, we abort the whole thing. If we want to -# ignore errors from any of these, just make sure not to ignore -# errors from the above "$doit $instcmd $src $dsttmp" command. - - if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi && - if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi && - if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi && - if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi && - -# Now remove or move aside any old file at destination location. We try this -# two ways since rm can't unlink itself on some systems and the destination -# file might be busy for other reasons. In this case, the final cleanup -# might fail but the new file should still install successfully. - -{ - if [ -f "$dstdir/$dstfile" ] - then - $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null || - $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null || - { - echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 - (exit 1); exit - } - else - : - fi -} && - -# Now rename the file to the real destination. - - $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" - -fi && - -# The final little trick to "correctly" pass the exit status to the exit trap. - -{ - (exit 0); exit -} diff --git a/config/libtool.m4 b/config/libtool.m4 deleted file mode 100644 index f134d1d2..00000000 --- a/config/libtool.m4 +++ /dev/null @@ -1,430 +0,0 @@ -## libtool.m4 - Configure libtool for the target system. -*-Shell-script-*- -## Copyright (C) 1996-1999 Free Software Foundation, Inc. -## Originally by Gordon Matzigkeit , 1996 -## -## 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 2 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, write to the Free Software -## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -## -## As a special exception to the GNU General Public License, if you -## distribute this file as part of a program that contains a -## configuration script generated by Autoconf, you may include it under -## the same distribution terms that you use for the rest of that program. - -# serial 40 AC_PROG_LIBTOOL -AC_DEFUN([AC_PROG_LIBTOOL], -[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl - -# Save cache, so that ltconfig can load it -AC_CACHE_SAVE - -# Actually configure libtool. ac_aux_dir is where install-sh is found. -CC="$CC" CFLAGS="$CFLAGS" CPPFLAGS="$CPPFLAGS" \ -LD="$LD" LDFLAGS="$LDFLAGS" LIBS="$LIBS" \ -LN_S="$LN_S" NM="$NM" RANLIB="$RANLIB" \ -DLLTOOL="$DLLTOOL" AS="$AS" OBJDUMP="$OBJDUMP" \ -${CONFIG_SHELL-/bin/sh} $ac_aux_dir/ltconfig --no-reexec \ -$libtool_flags --no-verify $ac_aux_dir/ltmain.sh $lt_target \ -|| AC_MSG_ERROR([libtool configure failed]) - -# Reload cache, that may have been modified by ltconfig -AC_CACHE_LOAD - -# This can be used to rebuild libtool when needed -LIBTOOL_DEPS="$ac_aux_dir/ltconfig $ac_aux_dir/ltmain.sh" - -# Always use our own libtool. -LIBTOOL='$(SHELL) $(top_builddir)/libtool' -AC_SUBST(LIBTOOL)dnl - -# Redirect the config.log output again, so that the ltconfig log is not -# clobbered by the next message. -exec 5>>./config.log -]) - -AC_DEFUN([AC_LIBTOOL_SETUP], -[AC_PREREQ(2.13)dnl -AC_REQUIRE([AC_ENABLE_SHARED])dnl -AC_REQUIRE([AC_ENABLE_STATIC])dnl -AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl -AC_REQUIRE([AC_CANONICAL_HOST])dnl -AC_REQUIRE([AC_CANONICAL_BUILD])dnl -AC_REQUIRE([AC_PROG_RANLIB])dnl -AC_REQUIRE([AC_PROG_CC])dnl -AC_REQUIRE([AC_PROG_LD])dnl -AC_REQUIRE([AC_PROG_NM])dnl -AC_REQUIRE([AC_PROG_LN_S])dnl -dnl - -case "$target" in -NONE) lt_target="$host" ;; -*) lt_target="$target" ;; -esac - -# Check for any special flags to pass to ltconfig. -libtool_flags="--cache-file=$cache_file" -test "$enable_shared" = no && libtool_flags="$libtool_flags --disable-shared" -test "$enable_static" = no && libtool_flags="$libtool_flags --disable-static" -test "$enable_fast_install" = no && libtool_flags="$libtool_flags --disable-fast-install" -test "$ac_cv_prog_gcc" = yes && libtool_flags="$libtool_flags --with-gcc" -test "$ac_cv_prog_gnu_ld" = yes && libtool_flags="$libtool_flags --with-gnu-ld" -ifdef([AC_PROVIDE_AC_LIBTOOL_DLOPEN], -[libtool_flags="$libtool_flags --enable-dlopen"]) -ifdef([AC_PROVIDE_AC_LIBTOOL_WIN32_DLL], -[libtool_flags="$libtool_flags --enable-win32-dll"]) -AC_ARG_ENABLE(libtool-lock, - [ --disable-libtool-lock avoid locking (might break parallel builds)]) -test "x$enable_libtool_lock" = xno && libtool_flags="$libtool_flags --disable-lock" -test x"$silent" = xyes && libtool_flags="$libtool_flags --silent" - -# Some flags need to be propagated to the compiler or linker for good -# libtool support. -case "$lt_target" in -*-*-irix6*) - # Find out which ABI we are using. - echo '[#]line __oline__ "configure"' > conftest.$ac_ext - if AC_TRY_EVAL(ac_compile); then - case "`/usr/bin/file conftest.o`" in - *32-bit*) - LD="${LD-ld} -32" - ;; - *N32*) - LD="${LD-ld} -n32" - ;; - *64-bit*) - LD="${LD-ld} -64" - ;; - esac - fi - rm -rf conftest* - ;; - -*-*-sco3.2v5*) - # On SCO OpenServer 5, we need -belf to get full-featured binaries. - SAVE_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS -belf" - AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, - [AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])]) - if test x"$lt_cv_cc_needs_belf" != x"yes"; then - # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf - CFLAGS="$SAVE_CFLAGS" - fi - ;; - -ifdef([AC_PROVIDE_AC_LIBTOOL_WIN32_DLL], -[*-*-cygwin* | *-*-mingw*) - AC_CHECK_TOOL(DLLTOOL, dlltool, false) - AC_CHECK_TOOL(AS, as, false) - AC_CHECK_TOOL(OBJDUMP, objdump, false) - ;; -]) -esac -]) - -# AC_LIBTOOL_DLOPEN - enable checks for dlopen support -AC_DEFUN([AC_LIBTOOL_DLOPEN], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])]) - -# AC_LIBTOOL_WIN32_DLL - declare package support for building win32 dll's -AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_BEFORE([$0], [AC_LIBTOOL_SETUP])]) - -# AC_ENABLE_SHARED - implement the --enable-shared flag -# Usage: AC_ENABLE_SHARED[(DEFAULT)] -# Where DEFAULT is either `yes' or `no'. If omitted, it defaults to -# `yes'. -AC_DEFUN([AC_ENABLE_SHARED], [dnl -define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl -AC_ARG_ENABLE(shared, -changequote(<<, >>)dnl -<< --enable-shared[=PKGS] build shared libraries [default=>>AC_ENABLE_SHARED_DEFAULT], -changequote([, ])dnl -[p=${PACKAGE-default} -case "$enableval" in -yes) enable_shared=yes ;; -no) enable_shared=no ;; -*) - enable_shared=no - # Look at the argument we got. We use all the common list separators. - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," - for pkg in $enableval; do - if test "X$pkg" = "X$p"; then - enable_shared=yes - fi - done - IFS="$ac_save_ifs" - ;; -esac], -enable_shared=AC_ENABLE_SHARED_DEFAULT)dnl -]) - -# AC_DISABLE_SHARED - set the default shared flag to --disable-shared -AC_DEFUN([AC_DISABLE_SHARED], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl -AC_ENABLE_SHARED(no)]) - -# AC_ENABLE_STATIC - implement the --enable-static flag -# Usage: AC_ENABLE_STATIC[(DEFAULT)] -# Where DEFAULT is either `yes' or `no'. If omitted, it defaults to -# `yes'. -AC_DEFUN([AC_ENABLE_STATIC], [dnl -define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl -AC_ARG_ENABLE(static, -changequote(<<, >>)dnl -<< --enable-static[=PKGS] build static libraries [default=>>AC_ENABLE_STATIC_DEFAULT], -changequote([, ])dnl -[p=${PACKAGE-default} -case "$enableval" in -yes) enable_static=yes ;; -no) enable_static=no ;; -*) - enable_static=no - # Look at the argument we got. We use all the common list separators. - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," - for pkg in $enableval; do - if test "X$pkg" = "X$p"; then - enable_static=yes - fi - done - IFS="$ac_save_ifs" - ;; -esac], -enable_static=AC_ENABLE_STATIC_DEFAULT)dnl -]) - -# AC_DISABLE_STATIC - set the default static flag to --disable-static -AC_DEFUN([AC_DISABLE_STATIC], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl -AC_ENABLE_STATIC(no)]) - - -# AC_ENABLE_FAST_INSTALL - implement the --enable-fast-install flag -# Usage: AC_ENABLE_FAST_INSTALL[(DEFAULT)] -# Where DEFAULT is either `yes' or `no'. If omitted, it defaults to -# `yes'. -AC_DEFUN([AC_ENABLE_FAST_INSTALL], [dnl -define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl -AC_ARG_ENABLE(fast-install, -changequote(<<, >>)dnl -<< --enable-fast-install[=PKGS] optimize for fast installation [default=>>AC_ENABLE_FAST_INSTALL_DEFAULT], -changequote([, ])dnl -[p=${PACKAGE-default} -case "$enableval" in -yes) enable_fast_install=yes ;; -no) enable_fast_install=no ;; -*) - enable_fast_install=no - # Look at the argument we got. We use all the common list separators. - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," - for pkg in $enableval; do - if test "X$pkg" = "X$p"; then - enable_fast_install=yes - fi - done - IFS="$ac_save_ifs" - ;; -esac], -enable_fast_install=AC_ENABLE_FAST_INSTALL_DEFAULT)dnl -]) - -# AC_ENABLE_FAST_INSTALL - set the default to --disable-fast-install -AC_DEFUN([AC_DISABLE_FAST_INSTALL], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl -AC_ENABLE_FAST_INSTALL(no)]) - -# AC_PROG_LD - find the path to the GNU or non-GNU linker -AC_DEFUN([AC_PROG_LD], -[AC_ARG_WITH(gnu-ld, -[ --with-gnu-ld assume the C compiler uses GNU ld [default=no]], -test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no) -AC_REQUIRE([AC_PROG_CC])dnl -AC_REQUIRE([AC_CANONICAL_HOST])dnl -AC_REQUIRE([AC_CANONICAL_BUILD])dnl -ac_prog=ld -if test "$ac_cv_prog_gcc" = yes; then - # Check if gcc -print-prog-name=ld gives a path. - AC_MSG_CHECKING([for ld used by GCC]) - ac_prog=`($CC -print-prog-name=ld) 2>&5` - case "$ac_prog" in - # Accept absolute paths. -changequote(,)dnl - [\\/]* | [A-Za-z]:[\\/]*) - re_direlt='/[^/][^/]*/\.\./' -changequote([,])dnl - # Canonicalize the path of ld - ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` - while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do - ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` - done - test -z "$LD" && LD="$ac_prog" - ;; - "") - # If it fails, then pretend we aren't using GCC. - ac_prog=ld - ;; - *) - # If it is relative, then search for the first ld in PATH. - with_gnu_ld=unknown - ;; - esac -elif test "$with_gnu_ld" = yes; then - AC_MSG_CHECKING([for GNU ld]) -else - AC_MSG_CHECKING([for non-GNU ld]) -fi -AC_CACHE_VAL(ac_cv_path_LD, -[if test -z "$LD"; then - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" - for ac_dir in $PATH; do - test -z "$ac_dir" && ac_dir=. - if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then - ac_cv_path_LD="$ac_dir/$ac_prog" - # Check to see if the program is GNU ld. I'd rather use --version, - # but apparently some GNU ld's only accept -v. - # Break only if it was the GNU/non-GNU ld that we prefer. - if "$ac_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then - test "$with_gnu_ld" != no && break - else - test "$with_gnu_ld" != yes && break - fi - fi - done - IFS="$ac_save_ifs" -else - ac_cv_path_LD="$LD" # Let the user override the test with a path. -fi]) -LD="$ac_cv_path_LD" -if test -n "$LD"; then - AC_MSG_RESULT($LD) -else - AC_MSG_RESULT(no) -fi -test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH]) -AC_PROG_LD_GNU -]) - -AC_DEFUN([AC_PROG_LD_GNU], -[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], ac_cv_prog_gnu_ld, -[# I'd rather use --version here, but apparently some GNU ld's only accept -v. -if $LD -v 2>&1 &5; then - ac_cv_prog_gnu_ld=yes -else - ac_cv_prog_gnu_ld=no -fi]) -]) - -# AC_PROG_NM - find the path to a BSD-compatible name lister -AC_DEFUN([AC_PROG_NM], -[AC_MSG_CHECKING([for BSD-compatible nm]) -AC_CACHE_VAL(ac_cv_path_NM, -[if test -n "$NM"; then - # Let the user override the test. - ac_cv_path_NM="$NM" -else - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" - for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/nm || test -f $ac_dir/nm$ac_exeext ; then - # Check to see if the nm accepts a BSD-compat flag. - # Adding the `sed 1q' prevents false positives on HP-UX, which says: - # nm: unknown option "B" ignored - if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then - ac_cv_path_NM="$ac_dir/nm -B" - break - elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then - ac_cv_path_NM="$ac_dir/nm -p" - break - else - ac_cv_path_NM=${ac_cv_path_NM="$ac_dir/nm"} # keep the first match, but - continue # so that we can try to find one that supports BSD flags - fi - fi - done - IFS="$ac_save_ifs" - test -z "$ac_cv_path_NM" && ac_cv_path_NM=nm -fi]) -NM="$ac_cv_path_NM" -AC_MSG_RESULT([$NM]) -]) - -# AC_CHECK_LIBM - check for math library -AC_DEFUN([AC_CHECK_LIBM], -[AC_REQUIRE([AC_CANONICAL_HOST])dnl -LIBM= -case "$lt_target" in -*-*-beos* | *-*-cygwin*) - # These system don't have libm - ;; -*-ncr-sysv4.3*) - AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") - AC_CHECK_LIB(m, main, LIBM="$LIBM -lm") - ;; -*) - AC_CHECK_LIB(m, main, LIBM="-lm") - ;; -esac -]) - -# AC_LIBLTDL_CONVENIENCE[(dir)] - sets LIBLTDL to the link flags for -# the libltdl convenience library, adds --enable-ltdl-convenience to -# the configure arguments. Note that LIBLTDL is not AC_SUBSTed, nor -# is AC_CONFIG_SUBDIRS called. If DIR is not provided, it is assumed -# to be `${top_builddir}/libltdl'. Make sure you start DIR with -# '${top_builddir}/' (note the single quotes!) if your package is not -# flat, and, if you're not using automake, define top_builddir as -# appropriate in the Makefiles. -AC_DEFUN([AC_LIBLTDL_CONVENIENCE], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl - case "$enable_ltdl_convenience" in - no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;; - "") enable_ltdl_convenience=yes - ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;; - esac - LIBLTDL=ifelse($#,1,$1,['${top_builddir}/libltdl'])/libltdlc.la - INCLTDL=ifelse($#,1,-I$1,['-I${top_builddir}/libltdl']) -]) - -# AC_LIBLTDL_INSTALLABLE[(dir)] - sets LIBLTDL to the link flags for -# the libltdl installable library, and adds --enable-ltdl-install to -# the configure arguments. Note that LIBLTDL is not AC_SUBSTed, nor -# is AC_CONFIG_SUBDIRS called. If DIR is not provided, it is assumed -# to be `${top_builddir}/libltdl'. Make sure you start DIR with -# '${top_builddir}/' (note the single quotes!) if your package is not -# flat, and, if you're not using automake, define top_builddir as -# appropriate in the Makefiles. -# In the future, this macro may have to be called after AC_PROG_LIBTOOL. -AC_DEFUN([AC_LIBLTDL_INSTALLABLE], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl - AC_CHECK_LIB(ltdl, main, - [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no], - [if test x"$enable_ltdl_install" = xno; then - AC_MSG_WARN([libltdl not installed, but installation disabled]) - else - enable_ltdl_install=yes - fi - ]) - if test x"$enable_ltdl_install" = x"yes"; then - ac_configure_args="$ac_configure_args --enable-ltdl-install" - LIBLTDL=ifelse($#,1,$1,['${top_builddir}/libltdl'])/libltdl.la - INCLTDL=ifelse($#,1,-I$1,['-I${top_builddir}/libltdl']) - else - ac_configure_args="$ac_configure_args --enable-ltdl-install=no" - LIBLTDL="-lltdl" - INCLTDL= - fi -]) - -dnl old names -AC_DEFUN([AM_PROG_LIBTOOL], [indir([AC_PROG_LIBTOOL])])dnl -AC_DEFUN([AM_ENABLE_SHARED], [indir([AC_ENABLE_SHARED], $@)])dnl -AC_DEFUN([AM_ENABLE_STATIC], [indir([AC_ENABLE_STATIC], $@)])dnl -AC_DEFUN([AM_DISABLE_SHARED], [indir([AC_DISABLE_SHARED], $@)])dnl -AC_DEFUN([AM_DISABLE_STATIC], [indir([AC_DISABLE_STATIC], $@)])dnl -AC_DEFUN([AM_PROG_LD], [indir([AC_PROG_LD])])dnl -AC_DEFUN([AM_PROG_NM], [indir([AC_PROG_NM])])dnl - -dnl This is just to silence aclocal about the macro not being used -ifelse([AC_DISABLE_FAST_INSTALL])dnl diff --git a/config/ltconfig b/config/ltconfig deleted file mode 100755 index e9ca47cd..00000000 --- a/config/ltconfig +++ /dev/null @@ -1,3150 +0,0 @@ -#! /bin/sh - -# ltconfig - Create a system-specific libtool. -# Copyright (C) 1996-1999 Free Software Foundation, Inc. -# Originally by Gordon Matzigkeit , 1996 -# -# This file 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 2 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# A lot of this script is taken from autoconf-2.10. - -# Check that we are running under the correct shell. -SHELL=${CONFIG_SHELL-/bin/sh} -echo=echo -if test "X$1" = X--no-reexec; then - # Discard the --no-reexec flag, and continue. - shift -elif test "X$1" = X--fallback-echo; then - # Avoid inline document here, it may be left over - : -elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then - # Yippee, $echo works! - : -else - # Restart under the correct shell. - exec "$SHELL" "$0" --no-reexec ${1+"$@"} -fi - -if test "X$1" = X--fallback-echo; then - # used as fallback echo - shift - cat </dev/null`} - case X$UNAME in - *-DOS) PATH_SEPARATOR=';' ;; - *) PATH_SEPARATOR=':' ;; - esac -fi - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -if test "X${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi - -if test "X${echo_test_string+set}" != Xset; then - # find a string as large as possible, as long as the shell can cope with it - for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do - # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... - if (echo_test_string="`eval $cmd`") 2>/dev/null && - echo_test_string="`eval $cmd`" && - (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null; then - break - fi - done -fi - -if test "X`($echo '\t') 2>/dev/null`" != 'X\t' || - test "X`($echo "$echo_test_string") 2>/dev/null`" != X"$echo_test_string"; then - # The Solaris, AIX, and Digital Unix default echo programs unquote - # backslashes. This makes it impossible to quote backslashes using - # echo "$something" | sed 's/\\/\\\\/g' - # - # So, first we look for a working echo in the user's PATH. - - IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" - for dir in $PATH /usr/ucb; do - if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && - test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && - test "X`($dir/echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then - echo="$dir/echo" - break - fi - done - IFS="$save_ifs" - - if test "X$echo" = Xecho; then - # We didn't find a better echo, so look for alternatives. - if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && - test "X`(print -r "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then - # This shell has a builtin print -r that does the trick. - echo='print -r' - elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && - test "X$CONFIG_SHELL" != X/bin/ksh; then - # If we have ksh, try running ltconfig again with it. - ORIGINAL_CONFIG_SHELL="${CONFIG_SHELL-/bin/sh}" - export ORIGINAL_CONFIG_SHELL - CONFIG_SHELL=/bin/ksh - export CONFIG_SHELL - exec "$CONFIG_SHELL" "$0" --no-reexec ${1+"$@"} - else - # Try using printf. - echo='printf "%s\n"' - if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && - test "X`($echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then - # Cool, printf works - : - elif test "X`("$ORIGINAL_CONFIG_SHELL" "$0" --fallback-echo '\t') 2>/dev/null`" = 'X\t' && - test "X`("$ORIGINAL_CONFIG_SHELL" "$0" --fallback-echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then - CONFIG_SHELL="$ORIGINAL_CONFIG_SHELL" - export CONFIG_SHELL - SHELL="$CONFIG_SHELL" - export SHELL - echo="$CONFIG_SHELL $0 --fallback-echo" - elif test "X`("$CONFIG_SHELL" "$0" --fallback-echo '\t') 2>/dev/null`" = 'X\t' && - test "X`("$CONFIG_SHELL" "$0" --fallback-echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then - echo="$CONFIG_SHELL $0 --fallback-echo" - else - # maybe with a smaller string... - prev=: - - for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do - if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null; then - break - fi - prev="$cmd" - done - - if test "$prev" != 'sed 50q "$0"'; then - echo_test_string=`eval $prev` - export echo_test_string - exec "${ORIGINAL_CONFIG_SHELL}" "$0" ${1+"$@"} - else - # Oops. We lost completely, so just stick with echo. - echo=echo - fi - fi - fi - fi -fi - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -Xsed='sed -e s/^X//' -sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g' - -# Same as above, but do not quote variable references. -double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g' - -# Sed substitution to delay expansion of an escaped shell variable in a -# double_quote_subst'ed string. -delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' - -# The name of this program. -progname=`$echo "X$0" | $Xsed -e 's%^.*/%%'` - -# Constants: -PROGRAM=ltconfig -PACKAGE=libtool -VERSION=1.3.5 -TIMESTAMP=" (1.385.2.206 2000/05/27 11:12:27)" -ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' -ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' -rm="rm -f" - -help="Try \`$progname --help' for more information." - -# Global variables: -default_ofile=libtool -can_build_shared=yes -enable_shared=yes -# All known linkers require a `.a' archive for static linking (except M$VC, -# which needs '.lib'). -enable_static=yes -enable_fast_install=yes -enable_dlopen=unknown -enable_win32_dll=no -ltmain= -silent= -srcdir= -ac_config_guess= -ac_config_sub= -host= -nonopt= -ofile="$default_ofile" -verify_host=yes -with_gcc=no -with_gnu_ld=no -need_locks=yes -ac_ext=c -objext=o -libext=a -exeext= -cache_file= - -old_AR="$AR" -old_CC="$CC" -old_CFLAGS="$CFLAGS" -old_CPPFLAGS="$CPPFLAGS" -old_LDFLAGS="$LDFLAGS" -old_LD="$LD" -old_LN_S="$LN_S" -old_LIBS="$LIBS" -old_NM="$NM" -old_RANLIB="$RANLIB" -old_DLLTOOL="$DLLTOOL" -old_OBJDUMP="$OBJDUMP" -old_AS="$AS" - -# Parse the command line options. -args= -prev= -for option -do - case "$option" in - -*=*) optarg=`echo "$option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; - *) optarg= ;; - esac - - # If the previous option needs an argument, assign it. - if test -n "$prev"; then - eval "$prev=\$option" - prev= - continue - fi - - case "$option" in - --help) cat <&2 - echo "$help" 1>&2 - exit 1 - ;; - - *) - if test -z "$ltmain"; then - ltmain="$option" - elif test -z "$host"; then -# This generates an unnecessary warning for sparc-sun-solaris4.1.3_U1 -# if test -n "`echo $option| sed 's/[-a-z0-9.]//g'`"; then -# echo "$progname: warning \`$option' is not a valid host type" 1>&2 -# fi - host="$option" - else - echo "$progname: too many arguments" 1>&2 - echo "$help" 1>&2 - exit 1 - fi ;; - esac -done - -if test -z "$ltmain"; then - echo "$progname: you must specify a LTMAIN file" 1>&2 - echo "$help" 1>&2 - exit 1 -fi - -if test ! -f "$ltmain"; then - echo "$progname: \`$ltmain' does not exist" 1>&2 - echo "$help" 1>&2 - exit 1 -fi - -# Quote any args containing shell metacharacters. -ltconfig_args= -for arg -do - case "$arg" in - *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) - ltconfig_args="$ltconfig_args '$arg'" ;; - *) ltconfig_args="$ltconfig_args $arg" ;; - esac -done - -# A relevant subset of AC_INIT. - -# File descriptor usage: -# 0 standard input -# 1 file creation -# 2 errors and warnings -# 3 some systems may open it to /dev/tty -# 4 used on the Kubota Titan -# 5 compiler messages saved in config.log -# 6 checking for... messages and results -if test "$silent" = yes; then - exec 6>/dev/null -else - exec 6>&1 -fi -exec 5>>./config.log - -# NLS nuisances. -# Only set LANG and LC_ALL to C if already set. -# These must not be set unconditionally because not all systems understand -# e.g. LANG=C (notably SCO). -if test "X${LC_ALL+set}" = Xset; then LC_ALL=C; export LC_ALL; fi -if test "X${LANG+set}" = Xset; then LANG=C; export LANG; fi - -if test -n "$cache_file" && test -r "$cache_file"; then - echo "loading cache $cache_file within ltconfig" - . $cache_file -fi - -if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then - # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. - if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then - ac_n= ac_c=' -' ac_t=' ' - else - ac_n=-n ac_c= ac_t= - fi -else - ac_n= ac_c='\c' ac_t= -fi - -if test -z "$srcdir"; then - # Assume the source directory is the same one as the path to LTMAIN. - srcdir=`$echo "X$ltmain" | $Xsed -e 's%/[^/]*$%%'` - test "$srcdir" = "$ltmain" && srcdir=. -fi - -trap "$rm conftest*; exit 1" 1 2 15 -if test "$verify_host" = yes; then - # Check for config.guess and config.sub. - ac_aux_dir= - for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do - if test -f $ac_dir/config.guess; then - ac_aux_dir=$ac_dir - break - fi - done - if test -z "$ac_aux_dir"; then - echo "$progname: cannot find config.guess in $srcdir $srcdir/.. $srcdir/../.." 1>&2 - echo "$help" 1>&2 - exit 1 - fi - ac_config_guess=$ac_aux_dir/config.guess - ac_config_sub=$ac_aux_dir/config.sub - - # Make sure we can run config.sub. - if $SHELL $ac_config_sub sun4 >/dev/null 2>&1; then : - else - echo "$progname: cannot run $ac_config_sub" 1>&2 - echo "$help" 1>&2 - exit 1 - fi - - echo $ac_n "checking host system type""... $ac_c" 1>&6 - - host_alias=$host - case "$host_alias" in - "") - if host_alias=`$SHELL $ac_config_guess`; then : - else - echo "$progname: cannot guess host type; you must specify one" 1>&2 - echo "$help" 1>&2 - exit 1 - fi ;; - esac - host=`$SHELL $ac_config_sub $host_alias` - echo "$ac_t$host" 1>&6 - - # Make sure the host verified. - test -z "$host" && exit 1 - -elif test -z "$host"; then - echo "$progname: you must specify a host type if you use \`--no-verify'" 1>&2 - echo "$help" 1>&2 - exit 1 -else - host_alias=$host -fi - -# Transform linux* to *-*-linux-gnu*, to support old configure scripts. -case "$host_os" in -linux-gnu*) ;; -linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'` -esac - -host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` -host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` -host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` - -case "$host_os" in -aix3*) - # AIX sometimes has problems with the GCC collect2 program. For some - # reason, if we set the COLLECT_NAMES environment variable, the problems - # vanish in a puff of smoke. - if test "X${COLLECT_NAMES+set}" != Xset; then - COLLECT_NAMES= - export COLLECT_NAMES - fi - ;; -esac - -# Determine commands to create old-style static archives. -old_archive_cmds='$AR cru $oldlib$oldobjs' -old_postinstall_cmds='chmod 644 $oldlib' -old_postuninstall_cmds= - -# Set a sane default for `AR'. -test -z "$AR" && AR=ar - -# Set a sane default for `OBJDUMP'. -test -z "$OBJDUMP" && OBJDUMP=objdump - -# If RANLIB is not set, then run the test. -if test "${RANLIB+set}" != "set"; then - result=no - - echo $ac_n "checking for ranlib... $ac_c" 1>&6 - IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" - for dir in $PATH; do - test -z "$dir" && dir=. - if test -f $dir/ranlib || test -f $dir/ranlib$ac_exeext; then - RANLIB="ranlib" - result="ranlib" - break - fi - done - IFS="$save_ifs" - - echo "$ac_t$result" 1>&6 -fi - -if test -n "$RANLIB"; then - old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" - old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds" -fi - -# Set sane defaults for `DLLTOOL', `OBJDUMP', and `AS', used on cygwin. -test -z "$DLLTOOL" && DLLTOOL=dlltool -test -z "$OBJDUMP" && OBJDUMP=objdump -test -z "$AS" && AS=as - -# Check to see if we are using GCC. -if test "$with_gcc" != yes || test -z "$CC"; then - # If CC is not set, then try to find GCC or a usable CC. - if test -z "$CC"; then - echo $ac_n "checking for gcc... $ac_c" 1>&6 - IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" - for dir in $PATH; do - test -z "$dir" && dir=. - if test -f $dir/gcc || test -f $dir/gcc$ac_exeext; then - CC="gcc" - break - fi - done - IFS="$save_ifs" - - if test -n "$CC"; then - echo "$ac_t$CC" 1>&6 - else - echo "$ac_t"no 1>&6 - fi - fi - - # Not "gcc", so try "cc", rejecting "/usr/ucb/cc". - if test -z "$CC"; then - echo $ac_n "checking for cc... $ac_c" 1>&6 - IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" - cc_rejected=no - for dir in $PATH; do - test -z "$dir" && dir=. - if test -f $dir/cc || test -f $dir/cc$ac_exeext; then - if test "$dir/cc" = "/usr/ucb/cc"; then - cc_rejected=yes - continue - fi - CC="cc" - break - fi - done - IFS="$save_ifs" - if test $cc_rejected = yes; then - # We found a bogon in the path, so make sure we never use it. - set dummy $CC - shift - if test $# -gt 0; then - # We chose a different compiler from the bogus one. - # However, it has the same name, so the bogon will be chosen - # first if we set CC to just the name; use the full file name. - shift - set dummy "$dir/cc" "$@" - shift - CC="$@" - fi - fi - - if test -n "$CC"; then - echo "$ac_t$CC" 1>&6 - else - echo "$ac_t"no 1>&6 - fi - - if test -z "$CC"; then - echo "$progname: error: no acceptable cc found in \$PATH" 1>&2 - exit 1 - fi - fi - - # Now see if the compiler is really GCC. - with_gcc=no - echo $ac_n "checking whether we are using GNU C... $ac_c" 1>&6 - echo "$progname:581: checking whether we are using GNU C" >&5 - - $rm conftest.c - cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then - with_gcc=yes - fi - $rm conftest.c - echo "$ac_t$with_gcc" 1>&6 -fi - -# Allow CC to be a program name with arguments. -set dummy $CC -compiler="$2" - -echo $ac_n "checking for object suffix... $ac_c" 1>&6 -$rm conftest* -echo 'int i = 1;' > conftest.c -echo "$progname:603: checking for object suffix" >& 5 -if { (eval echo $progname:604: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; }; then - # Append any warnings to the config.log. - cat conftest.err 1>&5 - - for ac_file in conftest.*; do - case $ac_file in - *.c) ;; - *) objext=`echo $ac_file | sed -e s/conftest.//` ;; - esac - done -else - cat conftest.err 1>&5 - echo "$progname: failed program was:" >&5 - cat conftest.c >&5 -fi -$rm conftest* -echo "$ac_t$objext" 1>&6 - -echo $ac_n "checking for executable suffix... $ac_c" 1>&6 -if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - ac_cv_exeext="no" - $rm conftest* - echo 'main () { return 0; }' > conftest.c - echo "$progname:629: checking for executable suffix" >& 5 - if { (eval echo $progname:630: \"$ac_link\") 1>&5; (eval $ac_link) 2>conftest.err; }; then - # Append any warnings to the config.log. - cat conftest.err 1>&5 - - for ac_file in conftest.*; do - case $ac_file in - *.c | *.err | *.$objext ) ;; - *) ac_cv_exeext=.`echo $ac_file | sed -e s/conftest.//` ;; - esac - done - else - cat conftest.err 1>&5 - echo "$progname: failed program was:" >&5 - cat conftest.c >&5 - fi - $rm conftest* -fi -if test "X$ac_cv_exeext" = Xno; then - exeext="" -else - exeext="$ac_cv_exeext" -fi -echo "$ac_t$ac_cv_exeext" 1>&6 - -echo $ac_n "checking for $compiler option to produce PIC... $ac_c" 1>&6 -pic_flag= -special_shlib_compile_flags= -wl= -link_static_flag= -no_builtin_flag= - -if test "$with_gcc" = yes; then - wl='-Wl,' - link_static_flag='-static' - - case "$host_os" in - beos* | irix5* | irix6* | osf3* | osf4* | osf5*) - # PIC is the default for these OSes. - ;; - aix*) - # Below there is a dirty hack to force normal static linking with -ldl - # The problem is because libdl dynamically linked with both libc and - # libC (AIX C++ library), which obviously doesn't included in libraries - # list by gcc. This cause undefined symbols with -static flags. - # This hack allows C programs to be linked with "-static -ldl", but - # we not sure about C++ programs. - link_static_flag="$link_static_flag ${wl}-lC" - ;; - cygwin* | mingw* | os2*) - # We can build DLLs from non-PIC. - ;; - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - pic_flag='-fno-common' - ;; - amigaos*) - # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. - pic_flag='-m68020 -resident32 -malways-restore-a4' - ;; - sysv4*MP*) - if test -d /usr/nec; then - pic_flag=-Kconform_pic - fi - ;; - *) - pic_flag='-fPIC' - ;; - esac -else - # PORTME Check for PIC flags for the system compiler. - case "$host_os" in - aix3* | aix4*) - # All AIX code is PIC. - link_static_flag='-bnso -bI:/lib/syscalls.exp' - ;; - - hpux9* | hpux10* | hpux11*) - # Is there a better link_static_flag that works with the bundled CC? - wl='-Wl,' - link_static_flag="${wl}-a ${wl}archive" - pic_flag='+Z' - ;; - - irix5* | irix6*) - wl='-Wl,' - link_static_flag='-non_shared' - # PIC (with -KPIC) is the default. - ;; - - cygwin* | mingw* | os2*) - # We can build DLLs from non-PIC. - ;; - - osf3* | osf4* | osf5*) - # All OSF/1 code is PIC. - wl='-Wl,' - link_static_flag='-non_shared' - ;; - - sco3.2v5*) - pic_flag='-Kpic' - link_static_flag='-dn' - special_shlib_compile_flags='-belf' - ;; - - solaris*) - pic_flag='-KPIC' - link_static_flag='-Bstatic' - wl='-Wl,' - ;; - - sunos4*) - pic_flag='-PIC' - link_static_flag='-Bstatic' - wl='-Qoption ld ' - ;; - - sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) - pic_flag='-KPIC' - link_static_flag='-Bstatic' - wl='-Wl,' - ;; - - uts4*) - pic_flag='-pic' - link_static_flag='-Bstatic' - ;; - sysv4*MP*) - if test -d /usr/nec ;then - pic_flag='-Kconform_pic' - link_static_flag='-Bstatic' - fi - ;; - *) - can_build_shared=no - ;; - esac -fi - -if test -n "$pic_flag"; then - echo "$ac_t$pic_flag" 1>&6 - - # Check to make sure the pic_flag actually works. - echo $ac_n "checking if $compiler PIC flag $pic_flag works... $ac_c" 1>&6 - $rm conftest* - echo "int some_variable = 0;" > conftest.c - save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $pic_flag -DPIC" - echo "$progname:781: checking if $compiler PIC flag $pic_flag works" >&5 - if { (eval echo $progname:782: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.$objext; then - # Append any warnings to the config.log. - cat conftest.err 1>&5 - - case "$host_os" in - hpux9* | hpux10* | hpux11*) - # On HP-UX, both CC and GCC only warn that PIC is supported... then they - # create non-PIC objects. So, if there were any warnings, we assume that - # PIC is not supported. - if test -s conftest.err; then - echo "$ac_t"no 1>&6 - can_build_shared=no - pic_flag= - else - echo "$ac_t"yes 1>&6 - pic_flag=" $pic_flag" - fi - ;; - *) - echo "$ac_t"yes 1>&6 - pic_flag=" $pic_flag" - ;; - esac - else - # Append any errors to the config.log. - cat conftest.err 1>&5 - can_build_shared=no - pic_flag= - echo "$ac_t"no 1>&6 - fi - CFLAGS="$save_CFLAGS" - $rm conftest* -else - echo "$ac_t"none 1>&6 -fi - -# Check to see if options -o and -c are simultaneously supported by compiler -echo $ac_n "checking if $compiler supports -c -o file.o... $ac_c" 1>&6 -$rm -r conftest 2>/dev/null -mkdir conftest -cd conftest -$rm conftest* -echo "int some_variable = 0;" > conftest.c -mkdir out -# According to Tom Tromey, Ian Lance Taylor reported there are C compilers -# that will create temporary files in the current directory regardless of -# the output directory. Thus, making CWD read-only will cause this test -# to fail, enabling locking or at least warning the user not to do parallel -# builds. -chmod -w . -save_CFLAGS="$CFLAGS" -CFLAGS="$CFLAGS -o out/conftest2.o" -echo "$progname:834: checking if $compiler supports -c -o file.o" >&5 -if { (eval echo $progname:835: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.o; then - - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - if test -s out/conftest.err; then - echo "$ac_t"no 1>&6 - compiler_c_o=no - else - echo "$ac_t"yes 1>&6 - compiler_c_o=yes - fi -else - # Append any errors to the config.log. - cat out/conftest.err 1>&5 - compiler_c_o=no - echo "$ac_t"no 1>&6 -fi -CFLAGS="$save_CFLAGS" -chmod u+w . -$rm conftest* out/* -rmdir out -cd .. -rmdir conftest -$rm -r conftest 2>/dev/null - -if test x"$compiler_c_o" = x"yes"; then - # Check to see if we can write to a .lo - echo $ac_n "checking if $compiler supports -c -o file.lo... $ac_c" 1>&6 - $rm conftest* - echo "int some_variable = 0;" > conftest.c - save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS -c -o conftest.lo" - echo "$progname:867: checking if $compiler supports -c -o file.lo" >&5 -if { (eval echo $progname:868: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.lo; then - - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - if test -s conftest.err; then - echo "$ac_t"no 1>&6 - compiler_o_lo=no - else - echo "$ac_t"yes 1>&6 - compiler_o_lo=yes - fi - else - # Append any errors to the config.log. - cat conftest.err 1>&5 - compiler_o_lo=no - echo "$ac_t"no 1>&6 - fi - CFLAGS="$save_CFLAGS" - $rm conftest* -else - compiler_o_lo=no -fi - -# Check to see if we can do hard links to lock some files if needed -hard_links="nottested" -if test "$compiler_c_o" = no && test "$need_locks" != no; then - # do not overwrite the value of need_locks provided by the user - echo $ac_n "checking if we can lock with hard links... $ac_c" 1>&6 - hard_links=yes - $rm conftest* - ln conftest.a conftest.b 2>/dev/null && hard_links=no - touch conftest.a - ln conftest.a conftest.b 2>&5 || hard_links=no - ln conftest.a conftest.b 2>/dev/null && hard_links=no - echo "$ac_t$hard_links" 1>&6 - $rm conftest* - if test "$hard_links" = no; then - echo "*** WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2 - need_locks=warn - fi -else - need_locks=no -fi - -if test "$with_gcc" = yes; then - # Check to see if options -fno-rtti -fno-exceptions are supported by compiler - echo $ac_n "checking if $compiler supports -fno-rtti -fno-exceptions ... $ac_c" 1>&6 - $rm conftest* - echo "int some_variable = 0;" > conftest.c - save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -c conftest.c" - echo "$progname:919: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 - if { (eval echo $progname:920: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.o; then - - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - if test -s conftest.err; then - echo "$ac_t"no 1>&6 - compiler_rtti_exceptions=no - else - echo "$ac_t"yes 1>&6 - compiler_rtti_exceptions=yes - fi - else - # Append any errors to the config.log. - cat conftest.err 1>&5 - compiler_rtti_exceptions=no - echo "$ac_t"no 1>&6 - fi - CFLAGS="$save_CFLAGS" - $rm conftest* - - if test "$compiler_rtti_exceptions" = "yes"; then - no_builtin_flag=' -fno-builtin -fno-rtti -fno-exceptions' - else - no_builtin_flag=' -fno-builtin' - fi - -fi - -# Check for any special shared library compilation flags. -if test -n "$special_shlib_compile_flags"; then - echo "$progname: warning: \`$CC' requires \`$special_shlib_compile_flags' to build shared libraries" 1>&2 - if echo "$old_CC $old_CFLAGS " | egrep -e "[ ]$special_shlib_compile_flags[ ]" >/dev/null; then : - else - echo "$progname: add \`$special_shlib_compile_flags' to the CC or CFLAGS env variable and reconfigure" 1>&2 - can_build_shared=no - fi -fi - -echo $ac_n "checking if $compiler static flag $link_static_flag works... $ac_c" 1>&6 -$rm conftest* -echo 'main(){return(0);}' > conftest.c -save_LDFLAGS="$LDFLAGS" -LDFLAGS="$LDFLAGS $link_static_flag" -echo "$progname:963: checking if $compiler static flag $link_static_flag works" >&5 -if { (eval echo $progname:964: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then - echo "$ac_t$link_static_flag" 1>&6 -else - echo "$ac_t"none 1>&6 - link_static_flag= -fi -LDFLAGS="$save_LDFLAGS" -$rm conftest* - -if test -z "$LN_S"; then - # Check to see if we can use ln -s, or we need hard links. - echo $ac_n "checking whether ln -s works... $ac_c" 1>&6 - $rm conftest.dat - if ln -s X conftest.dat 2>/dev/null; then - $rm conftest.dat - LN_S="ln -s" - else - LN_S=ln - fi - if test "$LN_S" = "ln -s"; then - echo "$ac_t"yes 1>&6 - else - echo "$ac_t"no 1>&6 - fi -fi - -# Make sure LD is an absolute path. -if test -z "$LD"; then - ac_prog=ld - if test "$with_gcc" = yes; then - # Check if gcc -print-prog-name=ld gives a path. - echo $ac_n "checking for ld used by GCC... $ac_c" 1>&6 - echo "$progname:996: checking for ld used by GCC" >&5 - ac_prog=`($CC -print-prog-name=ld) 2>&5` - case "$ac_prog" in - # Accept absolute paths. - [\\/]* | [A-Za-z]:[\\/]*) - re_direlt='/[^/][^/]*/\.\./' - # Canonicalize the path of ld - ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` - while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do - ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` - done - test -z "$LD" && LD="$ac_prog" - ;; - "") - # If it fails, then pretend we are not using GCC. - ac_prog=ld - ;; - *) - # If it is relative, then search for the first ld in PATH. - with_gnu_ld=unknown - ;; - esac - elif test "$with_gnu_ld" = yes; then - echo $ac_n "checking for GNU ld... $ac_c" 1>&6 - echo "$progname:1020: checking for GNU ld" >&5 - else - echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6 - echo "$progname:1023: checking for non-GNU ld" >&5 - fi - - if test -z "$LD"; then - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" - for ac_dir in $PATH; do - test -z "$ac_dir" && ac_dir=. - if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then - LD="$ac_dir/$ac_prog" - # Check to see if the program is GNU ld. I'd rather use --version, - # but apparently some GNU ld's only accept -v. - # Break only if it was the GNU/non-GNU ld that we prefer. - if "$LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then - test "$with_gnu_ld" != no && break - else - test "$with_gnu_ld" != yes && break - fi - fi - done - IFS="$ac_save_ifs" - fi - - if test -n "$LD"; then - echo "$ac_t$LD" 1>&6 - else - echo "$ac_t"no 1>&6 - fi - - if test -z "$LD"; then - echo "$progname: error: no acceptable ld found in \$PATH" 1>&2 - exit 1 - fi -fi - -# Check to see if it really is or is not GNU ld. -echo $ac_n "checking if the linker ($LD) is GNU ld... $ac_c" 1>&6 -# I'd rather use --version here, but apparently some GNU ld's only accept -v. -if $LD -v 2>&1 &5; then - with_gnu_ld=yes -else - with_gnu_ld=no -fi -echo "$ac_t$with_gnu_ld" 1>&6 - -# See if the linker supports building shared libraries. -echo $ac_n "checking whether the linker ($LD) supports shared libraries... $ac_c" 1>&6 - -allow_undefined_flag= -no_undefined_flag= -need_lib_prefix=unknown -need_version=unknown -# when you set need_version to no, make sure it does not cause -set_version -# flags to be left without arguments -archive_cmds= -archive_expsym_cmds= -old_archive_from_new_cmds= -export_dynamic_flag_spec= -whole_archive_flag_spec= -thread_safe_flag_spec= -hardcode_libdir_flag_spec= -hardcode_libdir_separator= -hardcode_direct=no -hardcode_minus_L=no -hardcode_shlibpath_var=unsupported -runpath_var= -always_export_symbols=no -export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | sed '\''s/.* //'\'' | sort | uniq > $export_symbols' -# include_expsyms should be a list of space-separated symbols to be *always* -# included in the symbol list -include_expsyms= -# exclude_expsyms can be an egrep regular expression of symbols to exclude -# it will be wrapped by ` (' and `)$', so one must not match beginning or -# end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', -# as well as any symbol that contains `d'. -exclude_expsyms="_GLOBAL_OFFSET_TABLE_" -# Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out -# platforms (ab)use it in PIC code, but their linkers get confused if -# the symbol is explicitly referenced. Since portable code cannot -# rely on this symbol name, it's probably fine to never include it in -# preloaded symbol tables. - -case "$host_os" in -cygwin* | mingw*) - # FIXME: the MSVC++ port hasn't been tested in a loooong time - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - if test "$with_gcc" != yes; then - with_gnu_ld=no - fi - ;; - -esac - -ld_shlibs=yes -if test "$with_gnu_ld" = yes; then - # If archive_cmds runs LD, not CC, wlarc should be empty - wlarc='${wl}' - - # See if GNU ld supports shared libraries. - case "$host_os" in - aix3* | aix4*) - # On AIX, the GNU linker is very broken - ld_shlibs=no - cat <&2 - -*** Warning: the GNU linker, at least up to release 2.9.1, is reported -*** to be unable to reliably create shared libraries on AIX. -*** Therefore, libtool is disabling shared libraries support. If you -*** really care for shared libraries, you may want to modify your PATH -*** so that a non-GNU linker is found, and then restart. - -EOF - ;; - - amigaos*) - archive_cmds='$rm $objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $objdir/a2ixlibrary.data~$AR cru $lib $libobjs~$RANLIB $lib~(cd $objdir && a2ixlibrary -32)' - hardcode_libdir_flag_spec='-L$libdir' - hardcode_minus_L=yes - - # Samuel A. Falvo II reports - # that the semantics of dynamic libraries on AmigaOS, at least up - # to version 4, is to share data among multiple programs linked - # with the same dynamic library. Since this doesn't match the - # behavior of shared libraries on other platforms, we can use - # them. - ld_shlibs=no - ;; - - beos*) - if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then - allow_undefined_flag=unsupported - # Joseph Beckenbach says some releases of gcc - # support --undefined. This deserves some investigation. FIXME - archive_cmds='$CC -nostart $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib' - else - ld_shlibs=no - fi - ;; - - cygwin* | mingw*) - # hardcode_libdir_flag_spec is actually meaningless, as there is - # no search path for DLLs. - hardcode_libdir_flag_spec='-L$libdir' - allow_undefined_flag=unsupported - always_export_symbols=yes - - # Extract the symbol export list from an `--export-all' def file, - # then regenerate the def file from the symbol export list, so that - # the compiled dll only exports the symbol export list. - # Be careful not to strip the DATA tag left by newer dlltools. - export_symbols_cmds='test -f $objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $0 > $objdir/$soname-ltdll.c~ - test -f $objdir/$soname-ltdll.$objext || (cd $objdir && $CC -c $soname-ltdll.c)~ - $DLLTOOL --export-all --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --output-def $objdir/$soname-def $objdir/$soname-ltdll.$objext $libobjs $convenience~ - sed -e "1,/EXPORTS/d" -e "s/ @ [0-9]*//" -e "s/ *;.*$//" < $objdir/$soname-def > $export_symbols' - - # If DATA tags from a recent dlltool are present, honour them! - archive_expsym_cmds='echo EXPORTS > $objdir/$soname-def~ - _lt_hint=1; - cat $export_symbols | while read symbol; do - set dummy \$symbol; - case \$# in - 2) echo " \$2 @ \$_lt_hint ; " >> $objdir/$soname-def;; - *) echo " \$2 @ \$_lt_hint \$3 ; " >> $objdir/$soname-def;; - esac; - _lt_hint=`expr 1 + \$_lt_hint`; - done~ - test -f $objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $0 > $objdir/$soname-ltdll.c~ - test -f $objdir/$soname-ltdll.$objext || (cd $objdir && $CC -c $soname-ltdll.c)~ - $CC -Wl,--base-file,$objdir/$soname-base -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts~ - $DLLTOOL --as=$AS --dllname $soname --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --def $objdir/$soname-def --base-file $objdir/$soname-base --output-exp $objdir/$soname-exp~ - $CC -Wl,--base-file,$objdir/$soname-base $objdir/$soname-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts~ - $DLLTOOL --as=$AS --dllname $soname --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --def $objdir/$soname-def --base-file $objdir/$soname-base --output-exp $objdir/$soname-exp~ - $CC $objdir/$soname-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts' - - old_archive_from_new_cmds='$DLLTOOL --as=$AS --dllname $soname --def $objdir/$soname-def --output-lib $objdir/$libname.a' - ;; - - netbsd*) - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - archive_cmds='$LD -Bshareable $libobjs $deplibs $linkopts -o $lib' - # can we support soname and/or expsyms with a.out? -oliva - fi - ;; - - solaris* | sysv5*) - if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then - ld_shlibs=no - cat <&2 - -*** Warning: The releases 2.8.* of the GNU linker cannot reliably -*** create shared libraries on Solaris systems. Therefore, libtool -*** is disabling shared libraries support. We urge you to upgrade GNU -*** binutils to release 2.9.1 or newer. Another option is to modify -*** your PATH or compiler configuration so that the native linker is -*** used, and then restart. - -EOF - elif $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then - archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - ld_shlibs=no - fi - ;; - - sunos4*) - archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linkopts' - wlarc= - hardcode_direct=yes - hardcode_shlibpath_var=no - ;; - - *) - if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then - archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - ld_shlibs=no - fi - ;; - esac - - if test "$ld_shlibs" = yes; then - runpath_var=LD_RUN_PATH - hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir' - export_dynamic_flag_spec='${wl}--export-dynamic' - case $host_os in - cygwin* | mingw*) - # dlltool doesn't understand --whole-archive et. al. - whole_archive_flag_spec= - ;; - *) - # ancient GNU ld didn't support --whole-archive et. al. - if $LD --help 2>&1 | egrep 'no-whole-archive' > /dev/null; then - whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - else - whole_archive_flag_spec= - fi - ;; - esac - fi -else - # PORTME fill in a description of your system's linker (not GNU ld) - case "$host_os" in - aix3*) - allow_undefined_flag=unsupported - always_export_symbols=yes - archive_expsym_cmds='$LD -o $objdir/$soname $libobjs $deplibs $linkopts -bE:$export_symbols -T512 -H512 -bM:SRE~$AR cru $lib $objdir/$soname' - # Note: this linker hardcodes the directories in LIBPATH if there - # are no directories specified by -L. - hardcode_minus_L=yes - if test "$with_gcc" = yes && test -z "$link_static_flag"; then - # Neither direct hardcoding nor static linking is supported with a - # broken collect2. - hardcode_direct=unsupported - fi - ;; - - aix4*) - hardcode_libdir_flag_spec='${wl}-b ${wl}nolibpath ${wl}-b ${wl}libpath:$libdir:/usr/lib:/lib' - hardcode_libdir_separator=':' - if test "$with_gcc" = yes; then - collect2name=`${CC} -print-prog-name=collect2` - if test -f "$collect2name" && \ - strings "$collect2name" | grep resolve_lib_name >/dev/null - then - # We have reworked collect2 - hardcode_direct=yes - else - # We have old collect2 - hardcode_direct=unsupported - # It fails to find uninstalled libraries when the uninstalled - # path is not listed in the libpath. Setting hardcode_minus_L - # to unsupported forces relinking - hardcode_minus_L=yes - hardcode_libdir_flag_spec='-L$libdir' - hardcode_libdir_separator= - fi - shared_flag='-shared' - else - shared_flag='${wl}-bM:SRE' - hardcode_direct=yes - fi - allow_undefined_flag=' ${wl}-berok' - archive_cmds="\$CC $shared_flag"' -o $objdir/$soname $libobjs $deplibs $linkopts ${wl}-bexpall ${wl}-bnoentry${allow_undefined_flag}' - archive_expsym_cmds="\$CC $shared_flag"' -o $objdir/$soname $libobjs $deplibs $linkopts ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}' - case "$host_os" in aix4.[01]|aix4.[01].*) - # According to Greg Wooledge, -bexpall is only supported from AIX 4.2 on - always_export_symbols=yes ;; - esac - ;; - - amigaos*) - archive_cmds='$rm $objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $objdir/a2ixlibrary.data~$AR cru $lib $libobjs~$RANLIB $lib~(cd $objdir && a2ixlibrary -32)' - hardcode_libdir_flag_spec='-L$libdir' - hardcode_minus_L=yes - # see comment about different semantics on the GNU ld section - ld_shlibs=no - ;; - - cygwin* | mingw*) - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - # hardcode_libdir_flag_spec is actually meaningless, as there is - # no search path for DLLs. - hardcode_libdir_flag_spec=' ' - allow_undefined_flag=unsupported - # Tell ltmain to make .lib files, not .a files. - libext=lib - # FIXME: Setting linknames here is a bad hack. - archive_cmds='$CC -o $lib $libobjs $linkopts `echo "$deplibs" | sed -e '\''s/ -lc$//'\''` -link -dll~linknames=' - # The linker will automatically build a .lib file if we build a DLL. - old_archive_from_new_cmds='true' - # FIXME: Should let the user specify the lib program. - old_archive_cmds='lib /OUT:$oldlib$oldobjs' - fix_srcfile_path='`cygpath -w $srcfile`' - ;; - - freebsd1*) - ld_shlibs=no - ;; - - # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor - # support. Future versions do this automatically, but an explicit c++rt0.o - # does not break anything, and helps significantly (at the cost of a little - # extra space). - freebsd2.2*) - archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts /usr/lib/c++rt0.o' - hardcode_libdir_flag_spec='-R$libdir' - hardcode_direct=yes - hardcode_shlibpath_var=no - ;; - - # Unfortunately, older versions of FreeBSD 2 do not have this feature. - freebsd2*) - archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts' - hardcode_direct=yes - hardcode_minus_L=yes - hardcode_shlibpath_var=no - ;; - - # FreeBSD 3 and greater uses gcc -shared to do shared libraries. - freebsd*) - archive_cmds='$CC -shared -o $lib $libobjs $deplibs $linkopts' - hardcode_libdir_flag_spec='-R$libdir' - hardcode_direct=yes - hardcode_shlibpath_var=no - ;; - - darwin[15].* | rhapsody*) - allow_undefined_flag='-undefined error' - archive_cmds='$CC $(test x$module = xyes && echo -bundle || echo -dynamiclib) $allow_undefined_flag -o $lib $libobjs $deplibs $linkopts $(test x$module != xyes && echo -install_name $rpath/$soname) $(test -n "$verstring" -a x$verstring != x0.0 && echo $verstring)' - # We need to add '_' to the symbols in $export_symbols first - #archive_expsym_cmds="$archive_cmds"' && strip -s $export_symbols $lib' - hardcode_direct=yes - hardcode_shlibpath_var=no - whole_archive_flag_spec='-all_load $convenience' - ;; - - # Mac OS X v10.2 uses bash for /bin/sh instead of zsh, and the quoting syntax is incompatible - darwin*) - allow_undefined_flag='-undefined error' - archive_cmds='$CC $(test x$module = xyes && echo -bundle || echo -dynamiclib) $allow_undefined_flag -o $lib $libobjs $deplibs $linkopts $(test x$module != xyes && echo -install_name $LD_RUN_PATH/$soname $tmp_verstring)' - # We need to add '_' to the symbols in $export_symbols first - #archive_expsym_cmds="$archive_cmds"' && strip -s $export_symbols $lib' - hardcode_direct=yes - hardcode_shlibpath_var=no - whole_archive_flag_spec='-all_load $convenience' - ;; - - hpux9* | hpux10* | hpux11*) - case "$host_os" in - hpux9*) archive_cmds='$rm $objdir/$soname~$LD -b +b $install_libdir -o $objdir/$soname $libobjs $deplibs $linkopts~test $objdir/$soname = $lib || mv $objdir/$soname $lib' ;; - *) archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linkopts' ;; - esac - hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' - hardcode_libdir_separator=: - hardcode_direct=yes - hardcode_minus_L=yes # Not in the search PATH, but as the default - # location of the library. - export_dynamic_flag_spec='${wl}-E' - ;; - - irix5* | irix6*) - if test "$with_gcc" = yes; then - archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' - else - archive_cmds='$LD -shared $libobjs $deplibs $linkopts -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' - fi - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator=: - ;; - - netbsd*) - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts' # a.out - else - archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linkopts' # ELF - fi - hardcode_libdir_flag_spec='${wl}-R$libdir' - hardcode_direct=yes - hardcode_shlibpath_var=no - ;; - - openbsd*) - archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts' - hardcode_libdir_flag_spec='-R$libdir' - hardcode_direct=yes - hardcode_shlibpath_var=no - ;; - - os2*) - hardcode_libdir_flag_spec='-L$libdir' - hardcode_minus_L=yes - allow_undefined_flag=unsupported - archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $objdir/$libname.def~$echo DATA >> $objdir/$libname.def~$echo " SINGLE NONSHARED" >> $objdir/$libname.def~$echo EXPORTS >> $objdir/$libname.def~emxexp $libobjs >> $objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $linkopts $objdir/$libname.def' - old_archive_from_new_cmds='emximp -o $objdir/$libname.a $objdir/$libname.def' - ;; - - osf3*) - if test "$with_gcc" = yes; then - allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $linkopts ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' - else - allow_undefined_flag=' -expect_unresolved \*' - archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linkopts -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' - fi - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator=: - ;; - - osf4* | osf5*) # As osf3* with the addition of the -msym flag - if test "$with_gcc" = yes; then - allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $linkopts ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' - else - allow_undefined_flag=' -expect_unresolved \*' - archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linkopts -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' - fi - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator=: - ;; - - sco3.2v5*) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' - hardcode_shlibpath_var=no - runpath_var=LD_RUN_PATH - hardcode_runpath_var=yes - ;; - - solaris*) - no_undefined_flag=' -z text' - # $CC -shared without GNU ld will not create a library from C++ - # object files and a static libstdc++, better avoid it by now - archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linkopts' - archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linkopts~$rm $lib.exp' - hardcode_libdir_flag_spec='-R$libdir' - hardcode_shlibpath_var=no - case "$host_os" in - solaris2.[0-5] | solaris2.[0-5].*) ;; - *) # Supported since Solaris 2.6 (maybe 2.5.1?) - whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;; - esac - ;; - - sunos4*) - archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linkopts' - hardcode_libdir_flag_spec='-L$libdir' - hardcode_direct=yes - hardcode_minus_L=yes - hardcode_shlibpath_var=no - ;; - - sysv4) - if test "x$host_vendor" = xsequent; then - # Use $CC to link under sequent, because it throws in some extra .o - # files that make .init and .fini sections work. - archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $linkopts' - else - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' - fi - runpath_var='LD_RUN_PATH' - hardcode_shlibpath_var=no - hardcode_direct=no #Motorola manual says yes, but my tests say they lie - ;; - - sysv4.3*) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' - hardcode_shlibpath_var=no - export_dynamic_flag_spec='-Bexport' - ;; - - sysv5*) - no_undefined_flag=' -z text' - # $CC -shared without GNU ld will not create a library from C++ - # object files and a static libstdc++, better avoid it by now - archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linkopts' - archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linkopts~$rm $lib.exp' - hardcode_libdir_flag_spec= - hardcode_shlibpath_var=no - runpath_var='LD_RUN_PATH' - ;; - - uts4*) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' - hardcode_libdir_flag_spec='-L$libdir' - hardcode_shlibpath_var=no - ;; - - dgux*) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' - hardcode_libdir_flag_spec='-L$libdir' - hardcode_shlibpath_var=no - ;; - - sysv4*MP*) - if test -d /usr/nec; then - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' - hardcode_shlibpath_var=no - runpath_var=LD_RUN_PATH - hardcode_runpath_var=yes - ld_shlibs=yes - fi - ;; - - sysv4.2uw2*) - archive_cmds='$LD -G -o $lib $libobjs $deplibs $linkopts' - hardcode_direct=yes - hardcode_minus_L=no - hardcode_shlibpath_var=no - hardcode_runpath_var=yes - runpath_var=LD_RUN_PATH - ;; - - unixware7*) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' - runpath_var='LD_RUN_PATH' - hardcode_shlibpath_var=no - ;; - - *) - ld_shlibs=no - ;; - esac -fi -echo "$ac_t$ld_shlibs" 1>&6 -test "$ld_shlibs" = no && can_build_shared=no - -if test -z "$NM"; then - echo $ac_n "checking for BSD-compatible nm... $ac_c" 1>&6 - case "$NM" in - [\\/]* | [A-Za-z]:[\\/]*) ;; # Let the user override the test with a path. - *) - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" - for ac_dir in $PATH /usr/ucb /usr/ccs/bin /bin; do - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/nm || test -f $ac_dir/nm$ac_exeext; then - # Check to see if the nm accepts a BSD-compat flag. - # Adding the `sed 1q' prevents false positives on HP-UX, which says: - # nm: unknown option "B" ignored - if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then - NM="$ac_dir/nm -B" - break - elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then - NM="$ac_dir/nm -p" - break - else - NM=${NM="$ac_dir/nm"} # keep the first match, but - continue # so that we can try to find one that supports BSD flags - fi - fi - done - IFS="$ac_save_ifs" - test -z "$NM" && NM=nm - ;; - esac - echo "$ac_t$NM" 1>&6 -fi - -# Check for command to grab the raw symbol name followed by C symbol from nm. -echo $ac_n "checking command to parse $NM output... $ac_c" 1>&6 - -# These are sane defaults that work on at least a few old systems. -# [They come from Ultrix. What could be older than Ultrix?!! ;)] - -# Character class describing NM global symbol codes. -symcode='[BCDEGRST]' - -# Regexp to match symbols that can be accessed directly from C. -sympat='\([_A-Za-z][_A-Za-z0-9]*\)' - -# Transform the above into a raw symbol and a C symbol. -symxfrm='\1 \2\3 \3' - -# Transform an extracted symbol line into a proper C declaration -global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'" - -# Define system-specific variables. -case "$host_os" in -aix*) - symcode='[BCDT]' - ;; -cygwin* | mingw*) - symcode='[ABCDGISTW]' - ;; -hpux*) # Its linker distinguishes data from code symbols - global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^. .* \(.*\)$/extern char \1;/p'" - ;; -irix*) - symcode='[BCDEGRST]' - ;; -solaris*) - symcode='[BDT]' - ;; -sysv4) - symcode='[DFNSTU]' - ;; -esac - -# If we're using GNU nm, then use its standard symbol codes. -if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then - symcode='[ABCDGISTW]' -fi - -# Try without a prefix undercore, then with it. -for ac_symprfx in "" "_"; do - - # Write the raw and C identifiers. - global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode\)[ ][ ]*\($ac_symprfx\)$sympat$/$symxfrm/p'" - - # Check to see that the pipe works correctly. - pipe_works=no - $rm conftest* - cat > conftest.c <&5 - if { (eval echo $progname:1663: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; } && test -s conftest.$objext; then - # Now try to grab the symbols. - nlist=conftest.nm - if { echo "$progname:1666: eval \"$NM conftest.$objext | $global_symbol_pipe > $nlist\"" >&5; eval "$NM conftest.$objext | $global_symbol_pipe > $nlist 2>&5"; } && test -s "$nlist"; then - - # Try sorting and uniquifying the output. - if sort "$nlist" | uniq > "$nlist"T; then - mv -f "$nlist"T "$nlist" - else - rm -f "$nlist"T - fi - - # Make sure that we snagged all the symbols we need. - if egrep ' nm_test_var$' "$nlist" >/dev/null; then - if egrep ' nm_test_func$' "$nlist" >/dev/null; then - cat < conftest.c -#ifdef __cplusplus -extern "C" { -#endif - -EOF - # Now generate the symbol file. - eval "$global_symbol_to_cdecl"' < "$nlist" >> conftest.c' - - cat <> conftest.c -#if defined (__STDC__) && __STDC__ -# define lt_ptr_t void * -#else -# define lt_ptr_t char * -# define const -#endif - -/* The mapping between symbol names and symbols. */ -const struct { - const char *name; - lt_ptr_t address; -} -lt_preloaded_symbols[] = -{ -EOF - sed 's/^. \(.*\) \(.*\)$/ {"\2", (lt_ptr_t) \&\2},/' < "$nlist" >> conftest.c - cat <<\EOF >> conftest.c - {0, (lt_ptr_t) 0} -}; - -#ifdef __cplusplus -} -#endif -EOF - # Now try linking the two files. - mv conftest.$objext conftstm.$objext - save_LIBS="$LIBS" - save_CFLAGS="$CFLAGS" - LIBS="conftstm.$objext" - CFLAGS="$CFLAGS$no_builtin_flag" - if { (eval echo $progname:1718: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then - pipe_works=yes - else - echo "$progname: failed program was:" >&5 - cat conftest.c >&5 - fi - LIBS="$save_LIBS" - else - echo "cannot find nm_test_func in $nlist" >&5 - fi - else - echo "cannot find nm_test_var in $nlist" >&5 - fi - else - echo "cannot run $global_symbol_pipe" >&5 - fi - else - echo "$progname: failed program was:" >&5 - cat conftest.c >&5 - fi - $rm conftest* conftst* - - # Do not use the global_symbol_pipe unless it works. - if test "$pipe_works" = yes; then - break - else - global_symbol_pipe= - fi -done -if test "$pipe_works" = yes; then - echo "${ac_t}ok" 1>&6 -else - echo "${ac_t}failed" 1>&6 -fi - -if test -z "$global_symbol_pipe"; then - global_symbol_to_cdecl= -fi - -# Check hardcoding attributes. -echo $ac_n "checking how to hardcode library paths into programs... $ac_c" 1>&6 -hardcode_action= -if test -n "$hardcode_libdir_flag_spec" || \ - test -n "$runpath_var"; then - - # We can hardcode non-existant directories. - if test "$hardcode_direct" != no && - # If the only mechanism to avoid hardcoding is shlibpath_var, we - # have to relink, otherwise we might link with an installed library - # when we should be linking with a yet-to-be-installed one - ## test "$hardcode_shlibpath_var" != no && - test "$hardcode_minus_L" != no; then - # Linking always hardcodes the temporary library directory. - hardcode_action=relink - else - # We can link without hardcoding, and we can hardcode nonexisting dirs. - hardcode_action=immediate - fi -else - # We cannot hardcode anything, or else we can only hardcode existing - # directories. - hardcode_action=unsupported -fi -echo "$ac_t$hardcode_action" 1>&6 - - -reload_flag= -reload_cmds='$LD$reload_flag -o $output$reload_objs' -echo $ac_n "checking for $LD option to reload object files... $ac_c" 1>&6 -# PORTME Some linkers may need a different reload flag. -reload_flag='-r' -echo "$ac_t$reload_flag" 1>&6 -test -n "$reload_flag" && reload_flag=" $reload_flag" - -# PORTME Fill in your ld.so characteristics -library_names_spec= -libname_spec='lib$name' -soname_spec= -postinstall_cmds= -postuninstall_cmds= -finish_cmds= -finish_eval= -shlibpath_var= -shlibpath_overrides_runpath=unknown -version_type=none -dynamic_linker="$host_os ld.so" -sys_lib_dlsearch_path_spec="/lib /usr/lib" -sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" -file_magic_cmd= -file_magic_test_file= -deplibs_check_method='unknown' -# Need to set the preceding variable on all platforms that support -# interlibrary dependencies. -# 'none' -- dependencies not supported. -# `unknown' -- same as none, but documents that we really don't know. -# 'pass_all' -- all dependencies passed with no checks. -# 'test_compile' -- check by making test program. -# 'file_magic [regex]' -- check by looking for files in library path -# which responds to the $file_magic_cmd with a given egrep regex. -# If you have `file' or equivalent on your system and you're not sure -# whether `pass_all' will *always* work, you probably want this one. -echo $ac_n "checking dynamic linker characteristics... $ac_c" 1>&6 -case "$host_os" in -aix3*) - version_type=linux - library_names_spec='${libname}${release}.so$versuffix $libname.a' - shlibpath_var=LIBPATH - - # AIX has no versioning support, so we append a major version to the name. - soname_spec='${libname}${release}.so$major' - ;; - -aix4*) - version_type=linux - # AIX has no versioning support, so currently we can not hardcode correct - # soname into executable. Probably we can add versioning support to - # collect2, so additional links can be useful in future. - # We preserve .a as extension for shared libraries though AIX4.2 - # and later linker supports .so - library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.a' - shlibpath_var=LIBPATH - deplibs_check_method=pass_all - ;; - -amigaos*) - library_names_spec='$libname.ixlibrary $libname.a' - # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done' - ;; - -beos*) - library_names_spec='${libname}.so' - dynamic_linker="$host_os ld.so" - shlibpath_var=LIBRARY_PATH - deplibs_check_method=pass_all - lt_cv_dlopen="load_add_on" - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - ;; - -bsdi4*) - version_type=linux - need_version=no - library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' - soname_spec='${libname}${release}.so$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' - file_magic_cmd=/usr/bin/file - file_magic_test_file=/shlib/libc.so - sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" - sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" - export_dynamic_flag_spec=-rdynamic - # the default ld.so.conf also contains /usr/contrib/lib and - # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow - # libtool to hard-code these into programs - ;; - -cygwin* | mingw*) - version_type=windows - need_version=no - need_lib_prefix=no - if test "$with_gcc" = yes; then - library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.a' - else - library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.lib' - fi - dynamic_linker='Win32 ld.exe' - deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' - file_magic_cmd='${OBJDUMP} -f' - # FIXME: first we should search . and the directory the executable is in - shlibpath_var=PATH - lt_cv_dlopen="LoadLibrary" - lt_cv_dlopen_libs= - ;; - -freebsd1*) - dynamic_linker=no - ;; - -freebsd*) - objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` - version_type=freebsd-$objformat - case "$version_type" in - freebsd-elf*) - deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB shared object' - file_magic_cmd=/usr/bin/file - file_magic_test_file=`echo /usr/lib/libc.so*` - library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so' - need_version=no - need_lib_prefix=no - ;; - freebsd-*) - deplibs_check_method=unknown - library_names_spec='${libname}${release}.so$versuffix $libname.so$versuffix' - need_version=yes - ;; - esac - shlibpath_var=LD_LIBRARY_PATH - case "$host_os" in - freebsd2* | freebsd3.[01]* | freebsdelf3.[01]*) - shlibpath_overrides_runpath=yes - ;; - *) # from 3.2 on - shlibpath_overrides_runpath=no - ;; - esac - ;; - -darwin* | rhapsody*) - dynamic_linker="$host_os dyld" - version_type=darwin - need_lib_prefix=no - need_version=no - deplibs_check_method='file_magic Mach-O (64-bit )?dynamically linked shared library' - file_magic_cmd='/usr/bin/file -L' - case "$host_os" in - rhapsody* | darwin1.[012]) - file_magic_test_file='/System/Library/Frameworks/System.framework/System' - ;; - *) # Darwin 1.3 on - file_magic_test_file='/usr/lib/libSystem.dylib' - ;; - esac - library_names_spec='${libname}.$(test x$module = xyes && echo plugin || echo dylib)' - soname_spec='${libname}.$(test x$module = xyes && echo plugin || echo dylib)' - shlibpath_overrides_runpath=yes - shlibpath_var=DYLD_LIBRARY_PATH - ;; - -gnu*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so${major} ${libname}.so' - soname_spec='${libname}${release}.so$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -hpux9* | hpux10* | hpux11*) - # Give a soname corresponding to the major version so that dld.sl refuses to - # link against other versions. - dynamic_linker="$host_os dld.sl" - version_type=sunos - need_lib_prefix=no - need_version=no - shlibpath_var=SHLIB_PATH - shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH - library_names_spec='${libname}${release}.sl$versuffix ${libname}${release}.sl$major $libname.sl' - soname_spec='${libname}${release}.sl$major' - # HP-UX runs *really* slowly unless shared libraries are mode 555. - postinstall_cmds='chmod 555 $lib' - case "$host_os" in - hpux10.20*) - # TODO: Does this work for hpux-11 too? - deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library' - file_magic_cmd=/usr/bin/file - file_magic_test_file=/usr/lib/libc.sl - ;; - esac - ;; - -irix5* | irix6*) - version_type=irix - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}.so.$major' - library_names_spec='${libname}${release}.so.$versuffix ${libname}${release}.so.$major ${libname}${release}.so $libname.so' - case "$host_os" in - irix5*) - libsuff= shlibsuff= - # this will be overridden with pass_all, but let us keep it just in case - deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1" - ;; - *) - case "$LD" in # libtool.m4 will add one of these switches to LD - *-32|*"-32 ") libsuff= shlibsuff= libmagic=32-bit;; - *-n32|*"-n32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; - *-64|*"-64 ") libsuff=64 shlibsuff=64 libmagic=64-bit;; - *) libsuff= shlibsuff= libmagic=never-match;; - esac - ;; - esac - shlibpath_var=LD_LIBRARY${shlibsuff}_PATH - shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" - sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" - file_magic_cmd=/usr/bin/file - file_magic_test_file=`echo /lib${libsuff}/libc.so*` - deplibs_check_method='pass_all' - ;; - -# No shared lib support for Linux oldld, aout, or coff. -linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*) - dynamic_linker=no - ;; - -# This must be Linux ELF. -linux-gnu*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' - soname_spec='${libname}${release}.so$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - deplibs_check_method=pass_all - - if test -f /lib/ld.so.1; then - dynamic_linker='GNU ld.so' - else - # Only the GNU ld.so supports shared libraries on MkLinux. - case "$host_cpu" in - powerpc*) dynamic_linker=no ;; - *) dynamic_linker='Linux ld.so' ;; - esac - fi - ;; - -netbsd*) - version_type=sunos - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - dynamic_linker='NetBSD (a.out) ld.so' - else - library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so ${libname}.so' - soname_spec='${libname}${release}.so$major' - dynamic_linker='NetBSD ld.elf_so' - fi - shlibpath_var=LD_LIBRARY_PATH - ;; - -openbsd*) - version_type=sunos - if test "$with_gnu_ld" = yes; then - need_lib_prefix=no - need_version=no - fi - library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - shlibpath_var=LD_LIBRARY_PATH - ;; - -os2*) - libname_spec='$name' - need_lib_prefix=no - library_names_spec='$libname.dll $libname.a' - dynamic_linker='OS/2 ld.exe' - shlibpath_var=LIBPATH - ;; - -osf3* | osf4* | osf5*) - version_type=osf - need_version=no - soname_spec='${libname}${release}.so' - library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so' - shlibpath_var=LD_LIBRARY_PATH - # this will be overridden with pass_all, but let us keep it just in case - deplibs_check_method='file_magic COFF format alpha shared library' - file_magic_cmd=/usr/bin/file - file_magic_test_file=/shlib/libc.so - deplibs_check_method='pass_all' - sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" - sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" - ;; - -sco3.2v5*) - version_type=osf - soname_spec='${libname}${release}.so$major' - library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' - shlibpath_var=LD_LIBRARY_PATH - ;; - -solaris*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' - soname_spec='${libname}${release}.so$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - # ldd complains unless libraries are executable - postinstall_cmds='chmod +x $lib' - deplibs_check_method="file_magic ELF [0-9][0-9]-bit [LM]SB dynamic lib" - file_magic_cmd=/usr/bin/file - file_magic_test_file=/lib/libc.so - ;; - -sunos4*) - version_type=sunos - library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' - finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - if test "$with_gnu_ld" = yes; then - need_lib_prefix=no - fi - need_version=yes - ;; - -sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) - version_type=linux - library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' - soname_spec='${libname}${release}.so$major' - shlibpath_var=LD_LIBRARY_PATH - case "$host_vendor" in - sequent) - file_magic_cmd='/bin/file' - deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' - ;; - ncr) - deplibs_check_method='pass_all' - ;; - motorola) - need_lib_prefix=no - need_version=no - shlibpath_overrides_runpath=no - sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' - deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' - file_magic_cmd=/usr/bin/file - file_magic_test_file=`echo /usr/lib/libc.so*` - ;; - esac - ;; - -uts4*) - version_type=linux - library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' - soname_spec='${libname}${release}.so$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -dgux*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' - soname_spec='${libname}${release}.so$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -sysv4*MP*) - if test -d /usr/nec ;then - version_type=linux - library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so' - soname_spec='$libname.so.$major' - shlibpath_var=LD_LIBRARY_PATH - fi - ;; - -*) - dynamic_linker=no - ;; -esac -echo "$ac_t$dynamic_linker" 1>&6 -test "$dynamic_linker" = no && can_build_shared=no - -# Report the final consequences. -echo "checking if libtool supports shared libraries... $can_build_shared" 1>&6 - -# Only try to build win32 dlls if AC_LIBTOOL_WIN32_DLL was used in -# configure.in, otherwise build static only libraries. -case "$host_os" in -cygwin* | mingw* | os2*) - if test x$can_build_shared = xyes; then - test x$enable_win32_dll = xno && can_build_shared=no - echo "checking if package supports dlls... $can_build_shared" 1>&6 - fi -;; -esac - -if test -n "$file_magic_test_file" && test -n "$file_magic_cmd"; then - case "$deplibs_check_method" in - "file_magic "*) - file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`" - if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | - egrep "$file_magic_regex" > /dev/null; then - : - else - cat <&2 - -*** Warning: the command libtool uses to detect shared libraries, -*** $file_magic_cmd, produces output that libtool cannot recognize. -*** The result is that libtool may fail to recognize shared libraries -*** as such. This will affect the creation of libtool libraries that -*** depend on shared libraries, but programs linked with such libtool -*** libraries will work regardless of this problem. Nevertheless, you -*** may want to report the problem to your system manager and/or to -*** bug-libtool@gnu.org - -EOF - fi ;; - esac -fi - -echo $ac_n "checking whether to build shared libraries... $ac_c" 1>&6 -test "$can_build_shared" = "no" && enable_shared=no - -# On AIX, shared libraries and static libraries use the same namespace, and -# are all built from PIC. -case "$host_os" in -aix3*) - test "$enable_shared" = yes && enable_static=no - if test -n "$RANLIB"; then - archive_cmds="$archive_cmds~\$RANLIB \$lib" - postinstall_cmds='$RANLIB $lib' - fi - ;; - -aix4*) - test "$enable_shared" = yes && enable_static=no - ;; -esac - -echo "$ac_t$enable_shared" 1>&6 - -# Make sure either enable_shared or enable_static is yes. -test "$enable_shared" = yes || enable_static=yes - -# Propagate what we've learned... -ac_cv_can_build_shared="$can_build_shared" - -echo "checking whether to build static libraries... $enable_static" 1>&6 - -if test "$hardcode_action" = relink; then - # Fast installation is not supported - enable_fast_install=no -elif test "$shlibpath_overrides_runpath" = yes || - test "$enable_shared" = no; then - # Fast installation is not necessary - enable_fast_install=needless -fi - -echo $ac_n "checking for objdir... $ac_c" 1>&6 -rm -f .libs 2>/dev/null -mkdir .libs 2>/dev/null -if test -d .libs; then - objdir=.libs -else - # MS-DOS does not allow filenames that begin with a dot. - objdir=_libs -fi -rmdir .libs 2>/dev/null -echo "$ac_t$objdir" 1>&6 - -if test "x$enable_dlopen" != xyes; then - enable_dlopen=unknown - enable_dlopen_self=unknown - enable_dlopen_self_static=unknown -else -if eval "test \"`echo '$''{'lt_cv_dlopen'+set}'`\" != set"; then - lt_cv_dlopen=no lt_cv_dlopen_libs= -echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6 -echo "$progname:2270: checking for dlopen in -ldl" >&5 -ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'` -if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - ac_save_LIBS="$LIBS" -LIBS="-ldl $LIBS" -cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=yes" -else - echo "$progname: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=no" -fi -rm -f conftest* -LIBS="$ac_save_LIBS" - -fi -if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then - echo "$ac_t""yes" 1>&6 - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" -else - echo "$ac_t""no" 1>&6 -echo $ac_n "checking for dlopen""... $ac_c" 1>&6 -echo "$progname:2310: checking for dlopen" >&5 -if eval "test \"`echo '$''{'ac_cv_func_dlopen'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext < -/* Override any gcc2 internal prototype to avoid an error. */ -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char dlopen(); - -int main() { - -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_dlopen) || defined (__stub___dlopen) -choke me -#else -dlopen(); -#endif - -; return 0; } -EOF -if { (eval echo $progname:2340: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - eval "ac_cv_func_dlopen=yes" -else - echo "$progname: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_func_dlopen=no" -fi -rm -f conftest* -fi -if eval "test \"`echo '$ac_cv_func_'dlopen`\" = yes"; then - echo "$ac_t""yes" 1>&6 - lt_cv_dlopen="dlopen" -else - echo "$ac_t""no" 1>&6 -echo $ac_n "checking for dld_link in -ldld""... $ac_c" 1>&6 -echo "$progname:2357: checking for dld_link in -ldld" >&5 -ac_lib_var=`echo dld'_'dld_link | sed 'y%./+-%__p_%'` -if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - ac_save_LIBS="$LIBS" -LIBS="-ldld $LIBS" -cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=yes" -else - echo "$progname: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=no" -fi -rm -f conftest* -LIBS="$ac_save_LIBS" - -fi -if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then - echo "$ac_t""yes" 1>&6 - lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" -else - echo "$ac_t""no" 1>&6 -echo $ac_n "checking for shl_load""... $ac_c" 1>&6 -echo "$progname:2397: checking for shl_load" >&5 -if eval "test \"`echo '$''{'ac_cv_func_shl_load'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext < -/* Override any gcc2 internal prototype to avoid an error. */ -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char shl_load(); - -int main() { - -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_shl_load) || defined (__stub___shl_load) -choke me -#else -shl_load(); -#endif - -; return 0; } -EOF -if { (eval echo $progname:2427: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - eval "ac_cv_func_shl_load=yes" -else - echo "$progname: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_func_shl_load=no" -fi -rm -f conftest* -fi - -if eval "test \"`echo '$ac_cv_func_'shl_load`\" = yes"; then - echo "$ac_t""yes" 1>&6 - lt_cv_dlopen="shl_load" -else - echo "$ac_t""no" 1>&6 -echo $ac_n "checking for shl_load in -ldld""... $ac_c" 1>&6 -echo "$progname:2445: checking for shl_load in -ldld" >&5 -ac_lib_var=`echo dld'_'shl_load | sed 'y%./+-%__p_%'` -if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - ac_save_LIBS="$LIBS" -LIBS="-ldld $LIBS" -cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=yes" -else - echo "$progname: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=no" -fi -rm -f conftest* -LIBS="$ac_save_LIBS" - -fi -if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then - echo "$ac_t""yes" 1>&6 - lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" -else - echo "$ac_t""no" 1>&6 -fi - - -fi - - -fi - - -fi - - -fi - -fi - - if test "x$lt_cv_dlopen" != xno; then - enable_dlopen=yes - fi - - case "$lt_cv_dlopen" in - dlopen) -for ac_hdr in dlfcn.h; do -ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` -echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "$progname:2510: checking for $ac_hdr" >&5 -if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext < -int fnord = 0; -EOF -ac_try="$ac_compile >/dev/null 2>conftest.out" -{ (eval echo $progname:2520: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } -ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` -if test -z "$ac_err"; then - rm -rf conftest* - eval "ac_cv_header_$ac_safe=yes" -else - echo "$ac_err" >&5 - echo "$progname: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_header_$ac_safe=no" -fi -rm -f conftest* -fi -if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then - echo "$ac_t""yes" 1>&6 -else - echo "$ac_t""no" 1>&6 -fi -done - - if test "x$ac_cv_header_dlfcn_h" = xyes; then - CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" - fi - eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" - LIBS="$lt_cv_dlopen_libs $LIBS" - - echo $ac_n "checking whether a program can dlopen itself""... $ac_c" 1>&6 -echo "$progname:2548: checking whether a program can dlopen itself" >&5 -if test "${lt_cv_dlopen_self+set}" = set; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test "$cross_compiling" = yes; then - lt_cv_dlopen_self=cross - else - cat > conftest.c < -#endif - -#include - -#ifdef RTLD_GLOBAL -# define LTDL_GLOBAL RTLD_GLOBAL -#else -# ifdef DL_GLOBAL -# define LTDL_GLOBAL DL_GLOBAL -# else -# define LTDL_GLOBAL 0 -# endif -#endif - -/* We may have to define LTDL_LAZY_OR_NOW in the command line if we - find out it does not work in some platform. */ -#ifndef LTDL_LAZY_OR_NOW -# ifdef RTLD_LAZY -# define LTDL_LAZY_OR_NOW RTLD_LAZY -# else -# ifdef DL_LAZY -# define LTDL_LAZY_OR_NOW DL_LAZY -# else -# ifdef RTLD_NOW -# define LTDL_LAZY_OR_NOW RTLD_NOW -# else -# ifdef DL_NOW -# define LTDL_LAZY_OR_NOW DL_NOW -# else -# define LTDL_LAZY_OR_NOW 0 -# endif -# endif -# endif -# endif -#endif - -fnord() { int i=42;} -main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW); - if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord"); - if(ptr1 || ptr2) { dlclose(self); exit(0); } } exit(1); } - -EOF -if { (eval echo $progname:2602: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null -then - lt_cv_dlopen_self=yes -else - echo "$progname: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -fr conftest* - lt_cv_dlopen_self=no -fi -rm -fr conftest* -fi - -fi - -echo "$ac_t""$lt_cv_dlopen_self" 1>&6 - - if test "$lt_cv_dlopen_self" = yes; then - LDFLAGS="$LDFLAGS $link_static_flag" - echo $ac_n "checking whether a statically linked program can dlopen itself""... $ac_c" 1>&6 -echo "$progname:2621: checking whether a statically linked program can dlopen itself" >&5 -if test "${lt_cv_dlopen_self_static+set}" = set; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test "$cross_compiling" = yes; then - lt_cv_dlopen_self_static=cross - else - cat > conftest.c < -#endif - -#include - -#ifdef RTLD_GLOBAL -# define LTDL_GLOBAL RTLD_GLOBAL -#else -# ifdef DL_GLOBAL -# define LTDL_GLOBAL DL_GLOBAL -# else -# define LTDL_GLOBAL 0 -# endif -#endif - -/* We may have to define LTDL_LAZY_OR_NOW in the command line if we - find out it does not work in some platform. */ -#ifndef LTDL_LAZY_OR_NOW -# ifdef RTLD_LAZY -# define LTDL_LAZY_OR_NOW RTLD_LAZY -# else -# ifdef DL_LAZY -# define LTDL_LAZY_OR_NOW DL_LAZY -# else -# ifdef RTLD_NOW -# define LTDL_LAZY_OR_NOW RTLD_NOW -# else -# ifdef DL_NOW -# define LTDL_LAZY_OR_NOW DL_NOW -# else -# define LTDL_LAZY_OR_NOW 0 -# endif -# endif -# endif -# endif -#endif - -fnord() { int i=42;} -main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW); - if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord"); - if(ptr1 || ptr2) { dlclose(self); exit(0); } } exit(1); } - -EOF -if { (eval echo $progname:2675: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null -then - lt_cv_dlopen_self_static=yes -else - echo "$progname: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -fr conftest* - lt_cv_dlopen_self_static=no -fi -rm -fr conftest* -fi - -fi - -echo "$ac_t""$lt_cv_dlopen_self_static" 1>&6 -fi - ;; - esac - - case "$lt_cv_dlopen_self" in - yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; - *) enable_dlopen_self=unknown ;; - esac - - case "$lt_cv_dlopen_self_static" in - yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; - *) enable_dlopen_self_static=unknown ;; - esac -fi - -# Copy echo and quote the copy, instead of the original, because it is -# used later. -ltecho="$echo" -if test "X$ltecho" = "X$CONFIG_SHELL $0 --fallback-echo"; then - ltecho="$CONFIG_SHELL \$0 --fallback-echo" -fi -LTSHELL="$SHELL" - -LTCONFIG_VERSION="$VERSION" - -# Only quote variables if we're using ltmain.sh. -case "$ltmain" in -*.sh) - # Now quote all the things that may contain metacharacters. - for var in ltecho old_CC old_CFLAGS old_CPPFLAGS \ - old_LD old_LDFLAGS old_LIBS \ - old_NM old_RANLIB old_LN_S old_DLLTOOL old_OBJDUMP old_AS \ - AR CC LD LN_S NM LTSHELL LTCONFIG_VERSION \ - reload_flag reload_cmds wl \ - pic_flag link_static_flag no_builtin_flag export_dynamic_flag_spec \ - thread_safe_flag_spec whole_archive_flag_spec libname_spec \ - library_names_spec soname_spec \ - RANLIB old_archive_cmds old_archive_from_new_cmds old_postinstall_cmds \ - old_postuninstall_cmds archive_cmds archive_expsym_cmds postinstall_cmds postuninstall_cmds \ - file_magic_cmd export_symbols_cmds deplibs_check_method allow_undefined_flag no_undefined_flag \ - finish_cmds finish_eval global_symbol_pipe global_symbol_to_cdecl \ - hardcode_libdir_flag_spec hardcode_libdir_separator \ - sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ - compiler_c_o compiler_o_lo need_locks exclude_expsyms include_expsyms; do - - case "$var" in - reload_cmds | old_archive_cmds | old_archive_from_new_cmds | \ - old_postinstall_cmds | old_postuninstall_cmds | \ - export_symbols_cmds | archive_cmds | archive_expsym_cmds | \ - postinstall_cmds | postuninstall_cmds | \ - finish_cmds | sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) - # Double-quote double-evaled strings. - eval "$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" - ;; - *) - eval "$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" - ;; - esac - done - - case "$ltecho" in - *'\$0 --fallback-echo"') - ltecho=`$echo "X$ltecho" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` - ;; - esac - - trap "$rm \"$ofile\"; exit 1" 1 2 15 - echo "creating $ofile" - $rm "$ofile" - cat < "$ofile" -#! $SHELL - -# `$echo "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. -# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) -# NOTE: Changes made to this file will be lost: look at ltconfig or ltmain.sh. -# -# Copyright (C) 1996-1999 Free Software Foundation, Inc. -# Originally by Gordon Matzigkeit , 1996 -# -# 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 2 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# Sed that helps us avoid accidentally triggering echo(1) options like -n. -Xsed="sed -e s/^X//" - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi - -### BEGIN LIBTOOL CONFIG -EOF - cfgfile="$ofile" - ;; - -*) - # Double-quote the variables that need it (for aesthetics). - for var in old_CC old_CFLAGS old_CPPFLAGS \ - old_LD old_LDFLAGS old_LIBS \ - old_NM old_RANLIB old_LN_S old_DLLTOOL old_OBJDUMP old_AS; do - eval "$var=\\\"\$var\\\"" - done - - # Just create a config file. - cfgfile="$ofile.cfg" - trap "$rm \"$cfgfile\"; exit 1" 1 2 15 - echo "creating $cfgfile" - $rm "$cfgfile" - cat < "$cfgfile" -# `$echo "$cfgfile" | sed 's%^.*/%%'` - Libtool configuration file. -# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) -EOF - ;; -esac - -cat <> "$cfgfile" -# Libtool was configured as follows, on host `(hostname || uname -n) 2>/dev/null | sed 1q`: -# -# CC=$old_CC CFLAGS=$old_CFLAGS CPPFLAGS=$old_CPPFLAGS \\ -# LD=$old_LD LDFLAGS=$old_LDFLAGS LIBS=$old_LIBS \\ -# NM=$old_NM RANLIB=$old_RANLIB LN_S=$old_LN_S \\ -# DLLTOOL=$old_DLLTOOL OBJDUMP=$old_OBJDUMP AS=$old_AS \\ -# $0$ltconfig_args -# -# Compiler and other test output produced by $progname, useful for -# debugging $progname, is in ./config.log if it exists. - -# The version of $progname that generated this script. -LTCONFIG_VERSION=$LTCONFIG_VERSION - -# Shell to use when invoking shell scripts. -SHELL=$LTSHELL - -# Whether or not to build shared libraries. -build_libtool_libs=$enable_shared - -# Whether or not to build static libraries. -build_old_libs=$enable_static - -# Whether or not to optimize for fast installation. -fast_install=$enable_fast_install - -# The host system. -host_alias=$host_alias -host=$host - -# An echo program that does not interpret backslashes. -echo=$ltecho - -# The archiver. -AR=$AR - -# The default C compiler. -CC=$CC - -# The linker used to build libraries. -LD=$LD - -# Whether we need hard or soft links. -LN_S=$LN_S - -# A BSD-compatible nm program. -NM=$NM - -# Used on cygwin: DLL creation program. -DLLTOOL="$DLLTOOL" - -# Used on cygwin: object dumper. -OBJDUMP="$OBJDUMP" - -# Used on cygwin: assembler. -AS="$AS" - -# The name of the directory that contains temporary libtool files. -objdir=$objdir - -# How to create reloadable object files. -reload_flag=$reload_flag -reload_cmds=$reload_cmds - -# How to pass a linker flag through the compiler. -wl=$wl - -# Object file suffix (normally "o"). -objext="$objext" - -# Old archive suffix (normally "a"). -libext="$libext" - -# Executable file suffix (normally ""). -exeext="$exeext" - -# Additional compiler flags for building library objects. -pic_flag=$pic_flag - -# Does compiler simultaneously support -c and -o options? -compiler_c_o=$compiler_c_o - -# Can we write directly to a .lo ? -compiler_o_lo=$compiler_o_lo - -# Must we lock files when doing compilation ? -need_locks=$need_locks - -# Do we need the lib prefix for modules? -need_lib_prefix=$need_lib_prefix - -# Do we need a version for libraries? -need_version=$need_version - -# Whether dlopen is supported. -dlopen=$enable_dlopen - -# Whether dlopen of programs is supported. -dlopen_self=$enable_dlopen_self - -# Whether dlopen of statically linked programs is supported. -dlopen_self_static=$enable_dlopen_self_static - -# Compiler flag to prevent dynamic linking. -link_static_flag=$link_static_flag - -# Compiler flag to turn off builtin functions. -no_builtin_flag=$no_builtin_flag - -# Compiler flag to allow reflexive dlopens. -export_dynamic_flag_spec=$export_dynamic_flag_spec - -# Compiler flag to generate shared objects directly from archives. -whole_archive_flag_spec=$whole_archive_flag_spec - -# Compiler flag to generate thread-safe objects. -thread_safe_flag_spec=$thread_safe_flag_spec - -# Library versioning type. -version_type=$version_type - -# Format of library name prefix. -libname_spec=$libname_spec - -# List of archive names. First name is the real one, the rest are links. -# The last name is the one that the linker finds with -lNAME. -library_names_spec=$library_names_spec - -# The coded name of the library, if different from the real name. -soname_spec=$soname_spec - -# Commands used to build and install an old-style archive. -RANLIB=$RANLIB -old_archive_cmds=$old_archive_cmds -old_postinstall_cmds=$old_postinstall_cmds -old_postuninstall_cmds=$old_postuninstall_cmds - -# Create an old-style archive from a shared archive. -old_archive_from_new_cmds=$old_archive_from_new_cmds - -# Commands used to build and install a shared archive. -archive_cmds=$archive_cmds -archive_expsym_cmds=$archive_expsym_cmds -postinstall_cmds=$postinstall_cmds -postuninstall_cmds=$postuninstall_cmds - -# Method to check whether dependent libraries are shared objects. -deplibs_check_method=$deplibs_check_method - -# Command to use when deplibs_check_method == file_magic. -file_magic_cmd=$file_magic_cmd - -# Flag that allows shared libraries with undefined symbols to be built. -allow_undefined_flag=$allow_undefined_flag - -# Flag that forces no undefined symbols. -no_undefined_flag=$no_undefined_flag - -# Commands used to finish a libtool library installation in a directory. -finish_cmds=$finish_cmds - -# Same as above, but a single script fragment to be evaled but not shown. -finish_eval=$finish_eval - -# Take the output of nm and produce a listing of raw symbols and C names. -global_symbol_pipe=$global_symbol_pipe - -# Transform the output of nm in a proper C declaration -global_symbol_to_cdecl=$global_symbol_to_cdecl - -# This is the shared library runtime path variable. -runpath_var=$runpath_var - -# This is the shared library path variable. -shlibpath_var=$shlibpath_var - -# Is shlibpath searched before the hard-coded library search path? -shlibpath_overrides_runpath=$shlibpath_overrides_runpath - -# How to hardcode a shared library path into an executable. -hardcode_action=$hardcode_action - -# Flag to hardcode \$libdir into a binary during linking. -# This must work even if \$libdir does not exist. -hardcode_libdir_flag_spec=$hardcode_libdir_flag_spec - -# Whether we need a single -rpath flag with a separated argument. -hardcode_libdir_separator=$hardcode_libdir_separator - -# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the -# resulting binary. -hardcode_direct=$hardcode_direct - -# Set to yes if using the -LDIR flag during linking hardcodes DIR into the -# resulting binary. -hardcode_minus_L=$hardcode_minus_L - -# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into -# the resulting binary. -hardcode_shlibpath_var=$hardcode_shlibpath_var - -# Compile-time system search path for libraries -sys_lib_search_path_spec=$sys_lib_search_path_spec - -# Run-time system search path for libraries -sys_lib_dlsearch_path_spec=$sys_lib_dlsearch_path_spec - -# Fix the shell variable \$srcfile for the compiler. -fix_srcfile_path="$fix_srcfile_path" - -# Set to yes if exported symbols are required. -always_export_symbols=$always_export_symbols - -# The commands to list exported symbols. -export_symbols_cmds=$export_symbols_cmds - -# Symbols that should not be listed in the preloaded symbols. -exclude_expsyms=$exclude_expsyms - -# Symbols that must always be exported. -include_expsyms=$include_expsyms - -EOF - -case "$ltmain" in -*.sh) - echo '### END LIBTOOL CONFIG' >> "$ofile" - echo >> "$ofile" - case "$host_os" in - aix3*) - cat <<\EOF >> "$ofile" - -# AIX sometimes has problems with the GCC collect2 program. For some -# reason, if we set the COLLECT_NAMES environment variable, the problems -# vanish in a puff of smoke. -if test "X${COLLECT_NAMES+set}" != Xset; then - COLLECT_NAMES= - export COLLECT_NAMES -fi -EOF - ;; - esac - - # Append the ltmain.sh script. - sed '$q' "$ltmain" >> "$ofile" || (rm -f "$ofile"; exit 1) - # We use sed instead of cat because bash on DJGPP gets confused if - # if finds mixed CR/LF and LF-only lines. Since sed operates in - # text mode, it properly converts lines to CR/LF. This bash problem - # is reportedly fixed, but why not run on old versions too? - - chmod +x "$ofile" - ;; - -*) - # Compile the libtool program. - echo "FIXME: would compile $ltmain" - ;; -esac - -test -n "$cache_file" || exit 0 - -# AC_CACHE_SAVE -trap '' 1 2 15 -cat > confcache <<\EOF -# This file is a shell script that caches the results of configure -# tests run on this system so they can be shared between configure -# scripts and configure runs. It is not useful on other systems. -# If it contains results you don't want to keep, you may remove or edit it. -# -# By default, configure uses ./config.cache as the cache file, -# creating it if it does not exist already. You can give configure -# the --cache-file=FILE option to use a different cache file; that is -# what configure does when it calls configure scripts in -# subdirectories, so they share the cache. -# Giving --cache-file=/dev/null disables caching, for debugging configure. -# config.status only pays attention to the cache file if you give it the -# --recheck option to rerun configure. -# -EOF -# The following way of writing the cache mishandles newlines in values, -# but we know of no workaround that is simple, portable, and efficient. -# So, don't put newlines in cache variables' values. -# Ultrix sh set writes to stderr and can't be redirected directly, -# and sets the high bit in the cache file unless we assign to the vars. -(set) 2>&1 | - case `(ac_space=' '; set | grep ac_space) 2>&1` in - *ac_space=\ *) - # `set' does not quote correctly, so add quotes (double-quote substitution - # turns \\\\ into \\, and sed turns \\ into \). - sed -n \ - -e "s/'/'\\\\''/g" \ - -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" - ;; - *) - # `set' quotes correctly as required by POSIX, so do not add quotes. - sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' - ;; - esac >> confcache -if cmp -s $cache_file confcache; then - : -else - if test -w $cache_file; then - echo "updating cache $cache_file" - cat confcache > $cache_file - else - echo "not updating unwritable cache $cache_file" - fi -fi -rm -f confcache - -exit 0 - -# Local Variables: -# mode:shell-script -# sh-indentation:2 -# End: diff --git a/config/ltmain.sh b/config/ltmain.sh deleted file mode 100644 index 76124818..00000000 --- a/config/ltmain.sh +++ /dev/null @@ -1,4059 +0,0 @@ -# ltmain.sh - Provide generalized library-building support services. -# NOTE: Changing this file will not affect anything until you rerun ltconfig. -# -# Copyright (C) 1996-1999 Free Software Foundation, Inc. -# Originally by Gordon Matzigkeit , 1996 -# -# 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 2 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# Check that we have a working $echo. -if test "X$1" = X--no-reexec; then - # Discard the --no-reexec flag, and continue. - shift -elif test "X$1" = X--fallback-echo; then - # Avoid inline document here, it may be left over - : -elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then - # Yippee, $echo works! - : -else - # Restart under the correct shell, and then maybe $echo will work. - exec $SHELL "$0" --no-reexec ${1+"$@"} -fi - -if test "X$1" = X--fallback-echo; then - # used as fallback echo - shift - cat <&2 - echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 - exit 1 -fi - -if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then - echo "$modename: not configured to build any kind of library" 1>&2 - echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 - exit 1 -fi - -# Global variables. -mode=$default_mode -nonopt= -prev= -prevopt= -run= -show="$echo" -show_help= -execute_dlfiles= -lo2o="s/\\.lo\$/.${objext}/" -o2lo="s/\\.${objext}\$/.lo/" - -# Parse our command line options once, thoroughly. -while test $# -gt 0 -do - arg="$1" - shift - - case "$arg" in - -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;; - *) optarg= ;; - esac - - # If the previous option needs an argument, assign it. - if test -n "$prev"; then - case "$prev" in - execute_dlfiles) - eval "$prev=\"\$$prev \$arg\"" - ;; - *) - eval "$prev=\$arg" - ;; - esac - - prev= - prevopt= - continue - fi - - # Have we seen a non-optional argument yet? - case "$arg" in - --help) - show_help=yes - ;; - - --version) - echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP" - exit 0 - ;; - - --config) - sed -e '1,/^### BEGIN LIBTOOL CONFIG/d' -e '/^### END LIBTOOL CONFIG/,$d' $0 - exit 0 - ;; - - --debug) - echo "$progname: enabling shell trace mode" - set -x - ;; - - --dry-run | -n) - run=: - ;; - - --features) - echo "host: $host" - if test "$build_libtool_libs" = yes; then - echo "enable shared libraries" - else - echo "disable shared libraries" - fi - if test "$build_old_libs" = yes; then - echo "enable static libraries" - else - echo "disable static libraries" - fi - exit 0 - ;; - - --finish) mode="finish" ;; - - --mode) prevopt="--mode" prev=mode ;; - --mode=*) mode="$optarg" ;; - - --quiet | --silent) - show=: - ;; - - -dlopen) - prevopt="-dlopen" - prev=execute_dlfiles - ;; - - -*) - $echo "$modename: unrecognized option \`$arg'" 1>&2 - $echo "$help" 1>&2 - exit 1 - ;; - - *) - nonopt="$arg" - break - ;; - esac -done - -if test -n "$prevopt"; then - $echo "$modename: option \`$prevopt' requires an argument" 1>&2 - $echo "$help" 1>&2 - exit 1 -fi - -if test -z "$show_help"; then - - # Infer the operation mode. - if test -z "$mode"; then - case "$nonopt" in - *cc | *++ | gcc* | *-gcc*) - mode=link - for arg - do - case "$arg" in - -c) - mode=compile - break - ;; - esac - done - ;; - *db | *dbx | *strace | *truss) - mode=execute - ;; - *install*|cp|mv) - mode=install - ;; - *rm) - mode=uninstall - ;; - *) - # If we have no mode, but dlfiles were specified, then do execute mode. - test -n "$execute_dlfiles" && mode=execute - - # Just use the default operation mode. - if test -z "$mode"; then - if test -n "$nonopt"; then - $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2 - else - $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2 - fi - fi - ;; - esac - fi - - # Only execute mode is allowed to have -dlopen flags. - if test -n "$execute_dlfiles" && test "$mode" != execute; then - $echo "$modename: unrecognized option \`-dlopen'" 1>&2 - $echo "$help" 1>&2 - exit 1 - fi - - # Change the help message to a mode-specific one. - generic_help="$help" - help="Try \`$modename --help --mode=$mode' for more information." - - # These modes are in order of execution frequency so that they run quickly. - case "$mode" in - # libtool compile mode - compile) - modename="$modename: compile" - # Get the compilation command and the source file. - base_compile= - lastarg= - srcfile="$nonopt" - suppress_output= - - user_target=no - for arg - do - # Accept any command-line options. - case "$arg" in - -o) - if test "$user_target" != "no"; then - $echo "$modename: you cannot specify \`-o' more than once" 1>&2 - exit 1 - fi - user_target=next - ;; - - -static) - build_old_libs=yes - continue - ;; - esac - - case "$user_target" in - next) - # The next one is the -o target name - user_target=yes - continue - ;; - yes) - # We got the output file - user_target=set - libobj="$arg" - continue - ;; - esac - - # Accept the current argument as the source file. - lastarg="$srcfile" - srcfile="$arg" - - # Aesthetically quote the previous argument. - - # Backslashify any backslashes, double quotes, and dollar signs. - # These are the only characters that are still specially - # interpreted inside of double-quoted scrings. - lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"` - - # Double-quote args containing other shell metacharacters. - # Many Bourne shells cannot handle close brackets correctly in scan - # sets, so we specify it separately. - case "$lastarg" in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) - lastarg="\"$lastarg\"" - ;; - esac - - # Add the previous argument to base_compile. - if test -z "$base_compile"; then - base_compile="$lastarg" - else - base_compile="$base_compile $lastarg" - fi - done - - case "$user_target" in - set) - ;; - no) - # Get the name of the library object. - libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'` - ;; - *) - $echo "$modename: you must specify a target with \`-o'" 1>&2 - exit 1 - ;; - esac - - # Recognize several different file suffixes. - # If the user specifies -o file.o, it is replaced with file.lo - xform='[cCFSfmso]' - case "$libobj" in - *.ada) xform=ada ;; - *.adb) xform=adb ;; - *.ads) xform=ads ;; - *.asm) xform=asm ;; - *.c++) xform=c++ ;; - *.cc) xform=cc ;; - *.cpp) xform=cpp ;; - *.cxx) xform=cxx ;; - *.f90) xform=f90 ;; - *.for) xform=for ;; - esac - - libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"` - - case "$libobj" in - *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;; - *) - $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2 - exit 1 - ;; - esac - - if test -z "$base_compile"; then - $echo "$modename: you must specify a compilation command" 1>&2 - $echo "$help" 1>&2 - exit 1 - fi - - # Delete any leftover library objects. - if test "$build_old_libs" = yes; then - removelist="$obj $libobj" - else - removelist="$libobj" - fi - - $run $rm $removelist - trap "$run $rm $removelist; exit 1" 1 2 15 - - # Calculate the filename of the output object if compiler does - # not support -o with -c - if test "$compiler_c_o" = no; then - output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\..*$%%'`.${objext} - lockfile="$output_obj.lock" - removelist="$removelist $output_obj $lockfile" - trap "$run $rm $removelist; exit 1" 1 2 15 - else - need_locks=no - lockfile= - fi - - # Lock this critical section if it is needed - # We use this script file to make the link, it avoids creating a new file - if test "$need_locks" = yes; then - until ln "$0" "$lockfile" 2>/dev/null; do - $show "Waiting for $lockfile to be removed" - sleep 2 - done - elif test "$need_locks" = warn; then - if test -f "$lockfile"; then - echo "\ -*** ERROR, $lockfile exists and contains: -`cat $lockfile 2>/dev/null` - -This indicates that another process is trying to use the same -temporary object file, and libtool could not work around it because -your compiler does not support \`-c' and \`-o' together. If you -repeat this compilation, it may succeed, by chance, but you had better -avoid parallel builds (make -j) in this platform, or get a better -compiler." - - $run $rm $removelist - exit 1 - fi - echo $srcfile > "$lockfile" - fi - - if test -n "$fix_srcfile_path"; then - eval srcfile=\"$fix_srcfile_path\" - fi - - # Only build a PIC object if we are building libtool libraries. - if test "$build_libtool_libs" = yes; then - # Without this assignment, base_compile gets emptied. - fbsd_hideous_sh_bug=$base_compile - - # All platforms use -DPIC, to notify preprocessed assembler code. - command="$base_compile $srcfile $pic_flag -DPIC" - if test "$build_old_libs" = yes; then - lo_libobj="$libobj" - dir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'` - if test "X$dir" = "X$libobj"; then - dir="$objdir" - else - dir="$dir/$objdir" - fi - libobj="$dir/"`$echo "X$libobj" | $Xsed -e 's%^.*/%%'` - - if test -d "$dir"; then - $show "$rm $libobj" - $run $rm $libobj - else - $show "$mkdir $dir" - $run $mkdir $dir - status=$? - if test $status -ne 0 && test ! -d $dir; then - exit $status - fi - fi - fi - if test "$compiler_o_lo" = yes; then - output_obj="$libobj" - command="$command -o $output_obj" - elif test "$compiler_c_o" = yes; then - output_obj="$obj" - command="$command -o $output_obj" - fi - - $run $rm "$output_obj" - $show "$command" - if $run eval "$command"; then : - else - test -n "$output_obj" && $run $rm $removelist - exit 1 - fi - - if test "$need_locks" = warn && - test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then - echo "\ -*** ERROR, $lockfile contains: -`cat $lockfile 2>/dev/null` - -but it should contain: -$srcfile - -This indicates that another process is trying to use the same -temporary object file, and libtool could not work around it because -your compiler does not support \`-c' and \`-o' together. If you -repeat this compilation, it may succeed, by chance, but you had better -avoid parallel builds (make -j) in this platform, or get a better -compiler." - - $run $rm $removelist - exit 1 - fi - - # Just move the object if needed, then go on to compile the next one - if test x"$output_obj" != x"$libobj"; then - $show "$mv $output_obj $libobj" - if $run $mv $output_obj $libobj; then : - else - error=$? - $run $rm $removelist - exit $error - fi - fi - - # If we have no pic_flag, then copy the object into place and finish. - if test -z "$pic_flag" && test "$build_old_libs" = yes; then - # Rename the .lo from within objdir to obj - if test -f $obj; then - $show $rm $obj - $run $rm $obj - fi - - $show "$mv $libobj $obj" - if $run $mv $libobj $obj; then : - else - error=$? - $run $rm $removelist - exit $error - fi - - xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` - if test "X$xdir" = "X$obj"; then - xdir="." - else - xdir="$xdir" - fi - baseobj=`$echo "X$obj" | $Xsed -e "s%.*/%%"` - libobj=`$echo "X$baseobj" | $Xsed -e "$o2lo"` - # Now arrange that obj and lo_libobj become the same file - $show "(cd $xdir && $LN_S $baseobj $libobj)" - if $run eval '(cd $xdir && $LN_S $baseobj $libobj)'; then - exit 0 - else - error=$? - $run $rm $removelist - exit $error - fi - fi - - # Allow error messages only from the first compilation. - suppress_output=' >/dev/null 2>&1' - fi - - # Only build a position-dependent object if we build old libraries. - if test "$build_old_libs" = yes; then - command="$base_compile $srcfile" - if test "$compiler_c_o" = yes; then - command="$command -o $obj" - output_obj="$obj" - fi - - # Suppress compiler output if we already did a PIC compilation. - command="$command$suppress_output" - $run $rm "$output_obj" - $show "$command" - if $run eval "$command"; then : - else - $run $rm $removelist - exit 1 - fi - - if test "$need_locks" = warn && - test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then - echo "\ -*** ERROR, $lockfile contains: -`cat $lockfile 2>/dev/null` - -but it should contain: -$srcfile - -This indicates that another process is trying to use the same -temporary object file, and libtool could not work around it because -your compiler does not support \`-c' and \`-o' together. If you -repeat this compilation, it may succeed, by chance, but you had better -avoid parallel builds (make -j) in this platform, or get a better -compiler." - - $run $rm $removelist - exit 1 - fi - - # Just move the object if needed - if test x"$output_obj" != x"$obj"; then - $show "$mv $output_obj $obj" - if $run $mv $output_obj $obj; then : - else - error=$? - $run $rm $removelist - exit $error - fi - fi - - # Create an invalid libtool object if no PIC, so that we do not - # accidentally link it into a program. - if test "$build_libtool_libs" != yes; then - $show "echo timestamp > $libobj" - $run eval "echo timestamp > \$libobj" || exit $? - else - # Move the .lo from within objdir - $show "$mv $libobj $lo_libobj" - if $run $mv $libobj $lo_libobj; then : - else - error=$? - $run $rm $removelist - exit $error - fi - fi - fi - - # Unlock the critical section if it was locked - if test "$need_locks" != no; then - $rm "$lockfile" - fi - - exit 0 - ;; - - # libtool link mode - link) - modename="$modename: link" - case "$host" in - *-*-cygwin* | *-*-mingw* | *-*-os2*) - # It is impossible to link a dll without this setting, and - # we shouldn't force the makefile maintainer to figure out - # which system we are compiling for in order to pass an extra - # flag for every libtool invokation. - # allow_undefined=no - - # FIXME: Unfortunately, there are problems with the above when trying - # to make a dll which has undefined symbols, in which case not - # even a static library is built. For now, we need to specify - # -no-undefined on the libtool link line when we can be certain - # that all symbols are satisfied, otherwise we get a static library. - allow_undefined=yes - - # This is a source program that is used to create dlls on Windows - # Don't remove nor modify the starting and closing comments -# /* ltdll.c starts here */ -# #define WIN32_LEAN_AND_MEAN -# #include -# #undef WIN32_LEAN_AND_MEAN -# #include -# -# #ifndef __CYGWIN__ -# # ifdef __CYGWIN32__ -# # define __CYGWIN__ __CYGWIN32__ -# # endif -# #endif -# -# #ifdef __cplusplus -# extern "C" { -# #endif -# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved); -# #ifdef __cplusplus -# } -# #endif -# -# #ifdef __CYGWIN__ -# #include -# DECLARE_CYGWIN_DLL( DllMain ); -# #endif -# HINSTANCE __hDllInstance_base; -# -# BOOL APIENTRY -# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved) -# { -# __hDllInstance_base = hInst; -# return TRUE; -# } -# /* ltdll.c ends here */ - # This is a source program that is used to create import libraries - # on Windows for dlls which lack them. Don't remove nor modify the - # starting and closing comments -# /* impgen.c starts here */ -# /* Copyright (C) 1999 Free Software Foundation, Inc. -# -# This file is part of GNU libtool. -# -# 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 2 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# */ -# -# #include /* for printf() */ -# #include /* for open(), lseek(), read() */ -# #include /* for O_RDONLY, O_BINARY */ -# #include /* for strdup() */ -# -# static unsigned int -# pe_get16 (fd, offset) -# int fd; -# int offset; -# { -# unsigned char b[2]; -# lseek (fd, offset, SEEK_SET); -# read (fd, b, 2); -# return b[0] + (b[1]<<8); -# } -# -# static unsigned int -# pe_get32 (fd, offset) -# int fd; -# int offset; -# { -# unsigned char b[4]; -# lseek (fd, offset, SEEK_SET); -# read (fd, b, 4); -# return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24); -# } -# -# static unsigned int -# pe_as32 (ptr) -# void *ptr; -# { -# unsigned char *b = ptr; -# return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24); -# } -# -# int -# main (argc, argv) -# int argc; -# char *argv[]; -# { -# int dll; -# unsigned long pe_header_offset, opthdr_ofs, num_entries, i; -# unsigned long export_rva, export_size, nsections, secptr, expptr; -# unsigned long name_rvas, nexp; -# unsigned char *expdata, *erva; -# char *filename, *dll_name; -# -# filename = argv[1]; -# -# dll = open(filename, O_RDONLY|O_BINARY); -# if (!dll) -# return 1; -# -# dll_name = filename; -# -# for (i=0; filename[i]; i++) -# if (filename[i] == '/' || filename[i] == '\\' || filename[i] == ':') -# dll_name = filename + i +1; -# -# pe_header_offset = pe_get32 (dll, 0x3c); -# opthdr_ofs = pe_header_offset + 4 + 20; -# num_entries = pe_get32 (dll, opthdr_ofs + 92); -# -# if (num_entries < 1) /* no exports */ -# return 1; -# -# export_rva = pe_get32 (dll, opthdr_ofs + 96); -# export_size = pe_get32 (dll, opthdr_ofs + 100); -# nsections = pe_get16 (dll, pe_header_offset + 4 +2); -# secptr = (pe_header_offset + 4 + 20 + -# pe_get16 (dll, pe_header_offset + 4 + 16)); -# -# expptr = 0; -# for (i = 0; i < nsections; i++) -# { -# char sname[8]; -# unsigned long secptr1 = secptr + 40 * i; -# unsigned long vaddr = pe_get32 (dll, secptr1 + 12); -# unsigned long vsize = pe_get32 (dll, secptr1 + 16); -# unsigned long fptr = pe_get32 (dll, secptr1 + 20); -# lseek(dll, secptr1, SEEK_SET); -# read(dll, sname, 8); -# if (vaddr <= export_rva && vaddr+vsize > export_rva) -# { -# expptr = fptr + (export_rva - vaddr); -# if (export_rva + export_size > vaddr + vsize) -# export_size = vsize - (export_rva - vaddr); -# break; -# } -# } -# -# expdata = (unsigned char*)malloc(export_size); -# lseek (dll, expptr, SEEK_SET); -# read (dll, expdata, export_size); -# erva = expdata - export_rva; -# -# nexp = pe_as32 (expdata+24); -# name_rvas = pe_as32 (expdata+32); -# -# printf ("EXPORTS\n"); -# for (i = 0; i&2 - fi - if test -n "$link_static_flag"; then - dlopen_self=$dlopen_self_static - fi - else - if test -z "$pic_flag" && test -n "$link_static_flag"; then - dlopen_self=$dlopen_self_static - fi - fi - build_libtool_libs=no - build_old_libs=yes - prefer_static_libs=yes - break - ;; - esac - done - - # See if our shared archives depend on static archives. - test -n "$old_archive_from_new_cmds" && build_old_libs=yes - - # Go through the arguments, transforming them on the way. - while test $# -gt 0; do - arg="$1" - shift - - # If the previous option needs an argument, assign it. - if test -n "$prev"; then - case "$prev" in - output) - compile_command="$compile_command @OUTPUT@" - finalize_command="$finalize_command @OUTPUT@" - ;; - esac - - case "$prev" in - dlfiles|dlprefiles) - if test "$preload" = no; then - # Add the symbol object into the linking commands. - compile_command="$compile_command @SYMFILE@" - finalize_command="$finalize_command @SYMFILE@" - preload=yes - fi - case "$arg" in - *.la | *.lo) ;; # We handle these cases below. - force) - if test "$dlself" = no; then - dlself=needless - export_dynamic=yes - fi - prev= - continue - ;; - self) - if test "$prev" = dlprefiles; then - dlself=yes - elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then - dlself=yes - else - dlself=needless - export_dynamic=yes - fi - prev= - continue - ;; - *) - if test "$prev" = dlfiles; then - dlfiles="$dlfiles $arg" - else - dlprefiles="$dlprefiles $arg" - fi - prev= - ;; - esac - ;; - expsyms) - export_symbols="$arg" - if test ! -f "$arg"; then - $echo "$modename: symbol file \`$arg' does not exist" - exit 1 - fi - prev= - continue - ;; - expsyms_regex) - export_symbols_regex="$arg" - prev= - continue - ;; - release) - release="-$arg" - prev= - continue - ;; - rpath | xrpath) - # We need an absolute path. - case "$arg" in - [\\/]* | [A-Za-z]:[\\/]*) ;; - *) - $echo "$modename: only absolute run-paths are allowed" 1>&2 - exit 1 - ;; - esac - if test "$prev" = rpath; then - case "$rpath " in - *" $arg "*) ;; - *) rpath="$rpath $arg" ;; - esac - else - case "$xrpath " in - *" $arg "*) ;; - *) xrpath="$xrpath $arg" ;; - esac - fi - prev= - continue - ;; - *) - eval "$prev=\"\$arg\"" - prev= - continue - ;; - esac - fi - - prevarg="$arg" - - case "$arg" in - -all-static) - if test -n "$link_static_flag"; then - compile_command="$compile_command $link_static_flag" - finalize_command="$finalize_command $link_static_flag" - fi - continue - ;; - - -allow-undefined) - # FIXME: remove this flag sometime in the future. - $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2 - continue - ;; - - -avoid-version) - avoid_version=yes - continue - ;; - - -dlopen) - prev=dlfiles - continue - ;; - - -dlpreopen) - prev=dlprefiles - continue - ;; - - -export-dynamic) - export_dynamic=yes - continue - ;; - - -export-symbols | -export-symbols-regex) - if test -n "$export_symbols" || test -n "$export_symbols_regex"; then - $echo "$modename: not more than one -exported-symbols argument allowed" - exit 1 - fi - if test "X$arg" = "X-export-symbols"; then - prev=expsyms - else - prev=expsyms_regex - fi - continue - ;; - - -L*) - dir=`$echo "X$arg" | $Xsed -e 's/^-L//'` - # We need an absolute path. - case "$dir" in - [\\/]* | [A-Za-z]:[\\/]*) ;; - *) - absdir=`cd "$dir" && pwd` - if test -z "$absdir"; then - $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2 - $echo "$modename: passing it literally to the linker, although it might fail" 1>&2 - absdir="$dir" - fi - dir="$absdir" - ;; - esac - case " $deplibs " in - *" $arg "*) ;; - *) deplibs="$deplibs $arg";; - esac - case " $lib_search_path " in - *" $dir "*) ;; - *) lib_search_path="$lib_search_path $dir";; - esac - case "$host" in - *-*-cygwin* | *-*-mingw* | *-*-os2*) - dllsearchdir=`cd "$dir" && pwd || echo "$dir"` - case ":$dllsearchpath:" in - ::) dllsearchpath="$dllsearchdir";; - *":$dllsearchdir:"*) ;; - *) dllsearchpath="$dllsearchpath:$dllsearchdir";; - esac - ;; - esac - ;; - - -l*) - if test "$arg" = "-lc"; then - case "$host" in - *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos*) - # These systems don't actually have c library (as such) - continue - ;; - *-*-rhapsody* | *-*-darwin1.[012]) - # Rhapsody C library is in the System framework - deplibs="$deplibs -framework System" - continue - ;; - esac - elif test "$arg" = "-lm"; then - case "$host" in - *-*-cygwin* | *-*-beos*) - # These systems don't actually have math library (as such) - continue - ;; - *-*-rhapsody* | *-*-darwin1.[012]) - # Rhapsody math library is in the System framework - deplibs="$deplibs -framework System" - continue - ;; - esac - fi - deplibs="$deplibs $arg" - ;; - - -module) - module=yes - continue - ;; - - -no-undefined) - allow_undefined=no - continue - ;; - - -o) prev=output ;; - - -release) - prev=release - continue - ;; - - -rpath) - prev=rpath - continue - ;; - - -R) - prev=xrpath - continue - ;; - - -R*) - dir=`$echo "X$arg" | $Xsed -e 's/^-R//'` - # We need an absolute path. - case "$dir" in - [\\/]* | [A-Za-z]:[\\/]*) ;; - *) - $echo "$modename: only absolute run-paths are allowed" 1>&2 - exit 1 - ;; - esac - case "$xrpath " in - *" $dir "*) ;; - *) xrpath="$xrpath $dir" ;; - esac - continue - ;; - - -static) - # If we have no pic_flag, then this is the same as -all-static. - if test -z "$pic_flag" && test -n "$link_static_flag"; then - compile_command="$compile_command $link_static_flag" - finalize_command="$finalize_command $link_static_flag" - fi - continue - ;; - - -thread-safe) - thread_safe=yes - continue - ;; - - -version-info) - prev=vinfo - continue - ;; - - # Some other compiler flag. - -* | +*) - # Unknown arguments in both finalize_command and compile_command need - # to be aesthetically quoted because they are evaled later. - arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` - case "$arg" in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) - arg="\"$arg\"" - ;; - esac - ;; - - *.o | *.obj | *.a | *.lib) - # A standard object. - objs="$objs $arg" - ;; - - *.lo) - # A library object. - if test "$prev" = dlfiles; then - dlfiles="$dlfiles $arg" - if test "$build_libtool_libs" = yes && test "$dlopen" = yes; then - prev= - continue - else - # If libtool objects are unsupported, then we need to preload. - prev=dlprefiles - fi - fi - - if test "$prev" = dlprefiles; then - # Preload the old-style object. - dlprefiles="$dlprefiles "`$echo "X$arg" | $Xsed -e "$lo2o"` - prev= - fi - libobjs="$libobjs $arg" - ;; - - *.la) - # A libtool-controlled library. - - dlname= - libdir= - library_names= - old_library= - - # Check to see that this really is a libtool archive. - if (sed -e '2q' $arg | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : - else - $echo "$modename: \`$arg' is not a valid libtool archive" 1>&2 - exit 1 - fi - - # If the library was installed with an old release of libtool, - # it will not redefine variable installed. - installed=yes - - # Read the .la file - # If there is no directory component, then add one. - case "$arg" in - */* | *\\*) . $arg ;; - *) . ./$arg ;; - esac - - # Get the name of the library we link against. - linklib= - for l in $old_library $library_names; do - linklib="$l" - done - - if test -z "$linklib"; then - $echo "$modename: cannot find name of link library for \`$arg'" 1>&2 - exit 1 - fi - - # Find the relevant object directory and library name. - name=`$echo "X$arg" | $Xsed -e 's%^.*/%%' -e 's/\.la$//' -e 's/^lib//'` - - if test "X$installed" = Xyes; then - dir="$libdir" - else - dir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` - if test "X$dir" = "X$arg"; then - dir="$objdir" - else - dir="$dir/$objdir" - fi - fi - - if test -n "$dependency_libs"; then - # Extract -R and -L from dependency_libs - temp_deplibs= - for deplib in $dependency_libs; do - case "$deplib" in - -R*) temp_xrpath=`$echo "X$deplib" | $Xsed -e 's/^-R//'` - case " $rpath $xrpath " in - *" $temp_xrpath "*) ;; - *) xrpath="$xrpath $temp_xrpath";; - esac;; - -L*) case "$compile_command $temp_deplibs " in - *" $deplib "*) ;; - *) temp_deplibs="$temp_deplibs $deplib";; - esac - temp_dir=`$echo "X$deplib" | $Xsed -e 's/^-L//'` - case " $lib_search_path " in - *" $temp_dir "*) ;; - *) lib_search_path="$lib_search_path $temp_dir";; - esac - ;; - *) temp_deplibs="$temp_deplibs $deplib";; - esac - done - dependency_libs="$temp_deplibs" - fi - - if test -z "$libdir"; then - # It is a libtool convenience library, so add in its objects. - convenience="$convenience $dir/$old_library" - old_convenience="$old_convenience $dir/$old_library" - deplibs="$deplibs$dependency_libs" - compile_command="$compile_command $dir/$old_library$dependency_libs" - finalize_command="$finalize_command $dir/$old_library$dependency_libs" - continue - fi - - # This library was specified with -dlopen. - if test "$prev" = dlfiles; then - dlfiles="$dlfiles $arg" - if test -z "$dlname" || test "$dlopen" != yes || test "$build_libtool_libs" = no; then - # If there is no dlname, no dlopen support or we're linking statically, - # we need to preload. - prev=dlprefiles - else - # We should not create a dependency on this library, but we - # may need any libraries it requires. - compile_command="$compile_command$dependency_libs" - finalize_command="$finalize_command$dependency_libs" - prev= - continue - fi - fi - - # The library was specified with -dlpreopen. - if test "$prev" = dlprefiles; then - # Prefer using a static library (so that no silly _DYNAMIC symbols - # are required to link). - if test -n "$old_library"; then - dlprefiles="$dlprefiles $dir/$old_library" - else - dlprefiles="$dlprefiles $dir/$linklib" - fi - prev= - fi - - if test -n "$library_names" && - { test "$prefer_static_libs" = no || test -z "$old_library"; }; then - link_against_libtool_libs="$link_against_libtool_libs $arg" - if test -n "$shlibpath_var"; then - # Make sure the rpath contains only unique directories. - case "$temp_rpath " in - *" $dir "*) ;; - *) temp_rpath="$temp_rpath $dir" ;; - esac - fi - - # We need an absolute path. - case "$dir" in - [\\/] | [A-Za-z]:[\\/]*) absdir="$dir" ;; - *) - absdir=`cd "$dir" && pwd` - if test -z "$absdir"; then - $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2 - $echo "$modename: passing it literally to the linker, although it might fail" 1>&2 - absdir="$dir" - fi - ;; - esac - - # This is the magic to use -rpath. - # Skip directories that are in the system default run-time - # search path, unless they have been requested with -R. - case " $sys_lib_dlsearch_path " in - *" $absdir "*) ;; - *) - case "$compile_rpath " in - *" $absdir "*) ;; - *) compile_rpath="$compile_rpath $absdir" - esac - ;; - esac - - case " $sys_lib_dlsearch_path " in - *" $libdir "*) ;; - *) - case "$finalize_rpath " in - *" $libdir "*) ;; - *) finalize_rpath="$finalize_rpath $libdir" - esac - ;; - esac - - lib_linked=yes - case "$hardcode_action" in - immediate | unsupported) - if test "$hardcode_direct" = no; then - compile_command="$compile_command $dir/$linklib" - deplibs="$deplibs $dir/$linklib" - case "$host" in - *-*-cygwin* | *-*-mingw* | *-*-os2*) - dllsearchdir=`cd "$dir" && pwd || echo "$dir"` - if test -n "$dllsearchpath"; then - dllsearchpath="$dllsearchpath:$dllsearchdir" - else - dllsearchpath="$dllsearchdir" - fi - ;; - esac - elif test "$hardcode_minus_L" = no; then - case "$host" in - *-*-sunos*) - compile_shlibpath="$compile_shlibpath$dir:" - ;; - esac - case "$compile_command " in - *" -L$dir "*) ;; - *) compile_command="$compile_command -L$dir";; - esac - compile_command="$compile_command -l$name" - deplibs="$deplibs -L$dir -l$name" - elif test "$hardcode_shlibpath_var" = no; then - case ":$compile_shlibpath:" in - *":$dir:"*) ;; - *) compile_shlibpath="$compile_shlibpath$dir:";; - esac - compile_command="$compile_command -l$name" - deplibs="$deplibs -l$name" - else - lib_linked=no - fi - ;; - - relink) - if test "$hardcode_direct" = yes; then - compile_command="$compile_command $absdir/$linklib" - deplibs="$deplibs $absdir/$linklib" - elif test "$hardcode_minus_L" = yes; then - case "$compile_command " in - *" -L$absdir "*) ;; - *) compile_command="$compile_command -L$absdir";; - esac - compile_command="$compile_command -l$name" - deplibs="$deplibs -L$absdir -l$name" - elif test "$hardcode_shlibpath_var" = yes; then - case ":$compile_shlibpath:" in - *":$absdir:"*) ;; - *) compile_shlibpath="$compile_shlibpath$absdir:";; - esac - compile_command="$compile_command -l$name" - deplibs="$deplibs -l$name" - else - lib_linked=no - fi - ;; - - *) - lib_linked=no - ;; - esac - - if test "$lib_linked" != yes; then - $echo "$modename: configuration error: unsupported hardcode properties" - exit 1 - fi - - # Finalize command for both is simple: just hardcode it. - if test "$hardcode_direct" = yes; then - finalize_command="$finalize_command $libdir/$linklib" - elif test "$hardcode_minus_L" = yes; then - case "$finalize_command " in - *" -L$libdir "*) ;; - *) finalize_command="$finalize_command -L$libdir";; - esac - finalize_command="$finalize_command -l$name" - elif test "$hardcode_shlibpath_var" = yes; then - case ":$finalize_shlibpath:" in - *":$libdir:"*) ;; - *) finalize_shlibpath="$finalize_shlibpath$libdir:";; - esac - finalize_command="$finalize_command -l$name" - else - # We cannot seem to hardcode it, guess we'll fake it. - case "$finalize_command " in - *" -L$dir "*) ;; - *) finalize_command="$finalize_command -L$libdir";; - esac - finalize_command="$finalize_command -l$name" - fi - else - # Transform directly to old archives if we don't build new libraries. - if test -n "$pic_flag" && test -z "$old_library"; then - $echo "$modename: cannot find static library for \`$arg'" 1>&2 - exit 1 - fi - - # Here we assume that one of hardcode_direct or hardcode_minus_L - # is not unsupported. This is valid on all known static and - # shared platforms. - if test "$hardcode_direct" != unsupported; then - test -n "$old_library" && linklib="$old_library" - compile_command="$compile_command $dir/$linklib" - finalize_command="$finalize_command $dir/$linklib" - else - case "$compile_command " in - *" -L$dir "*) ;; - *) compile_command="$compile_command -L$dir";; - esac - compile_command="$compile_command -l$name" - case "$finalize_command " in - *" -L$dir "*) ;; - *) finalize_command="$finalize_command -L$dir";; - esac - finalize_command="$finalize_command -l$name" - fi - fi - - # Add in any libraries that this one depends upon. - compile_command="$compile_command$dependency_libs" - finalize_command="$finalize_command$dependency_libs" - continue - ;; - - # Some other compiler argument. - *) - # Unknown arguments in both finalize_command and compile_command need - # to be aesthetically quoted because they are evaled later. - arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` - case "$arg" in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) - arg="\"$arg\"" - ;; - esac - ;; - esac - - # Now actually substitute the argument into the commands. - if test -n "$arg"; then - compile_command="$compile_command $arg" - finalize_command="$finalize_command $arg" - fi - done - - if test -n "$prev"; then - $echo "$modename: the \`$prevarg' option requires an argument" 1>&2 - $echo "$help" 1>&2 - exit 1 - fi - - if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then - eval arg=\"$export_dynamic_flag_spec\" - compile_command="$compile_command $arg" - finalize_command="$finalize_command $arg" - fi - - oldlibs= - # calculate the name of the file, without its directory - outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'` - libobjs_save="$libobjs" - - case "$output" in - "") - $echo "$modename: you must specify an output file" 1>&2 - $echo "$help" 1>&2 - exit 1 - ;; - - *.a | *.lib) - if test -n "$link_against_libtool_libs"; then - $echo "$modename: error: cannot link libtool libraries into archives" 1>&2 - exit 1 - fi - - if test -n "$deplibs"; then - $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2 - fi - - if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then - $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2 - fi - - if test -n "$rpath"; then - $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2 - fi - - if test -n "$xrpath"; then - $echo "$modename: warning: \`-R' is ignored for archives" 1>&2 - fi - - if test -n "$vinfo"; then - $echo "$modename: warning: \`-version-info' is ignored for archives" 1>&2 - fi - - if test -n "$release"; then - $echo "$modename: warning: \`-release' is ignored for archives" 1>&2 - fi - - if test -n "$export_symbols" || test -n "$export_symbols_regex"; then - $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2 - fi - - # Now set the variables for building old libraries. - build_libtool_libs=no - oldlibs="$output" - ;; - - *.la) - # Make sure we only generate libraries of the form `libNAME.la'. - case "$outputname" in - lib*) - name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` - eval libname=\"$libname_spec\" - ;; - *) - if test "$module" = no; then - $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2 - $echo "$help" 1>&2 - exit 1 - fi - if test "$need_lib_prefix" != no; then - # Add the "lib" prefix for modules if required - name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` - eval libname=\"$libname_spec\" - else - libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` - fi - ;; - esac - - output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'` - if test "X$output_objdir" = "X$output"; then - output_objdir="$objdir" - else - output_objdir="$output_objdir/$objdir" - fi - - if test -n "$objs"; then - $echo "$modename: cannot build libtool library \`$output' from non-libtool objects:$objs" 2>&1 - exit 1 - fi - - # How the heck are we supposed to write a wrapper for a shared library? - if test -n "$link_against_libtool_libs"; then - $echo "$modename: error: cannot link shared libraries into libtool libraries" 1>&2 - exit 1 - fi - - if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then - $echo "$modename: warning: \`-dlopen' is ignored for libtool libraries" 1>&2 - fi - - set dummy $rpath - if test $# -gt 2; then - $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2 - fi - install_libdir="$2" - - oldlibs= - if test -z "$rpath"; then - if test "$build_libtool_libs" = yes; then - # Building a libtool convenience library. - libext=al - oldlibs="$output_objdir/$libname.$libext $oldlibs" - build_libtool_libs=convenience - build_old_libs=yes - fi - dependency_libs="$deplibs" - - if test -n "$vinfo"; then - $echo "$modename: warning: \`-version-info' is ignored for convenience libraries" 1>&2 - fi - - if test -n "$release"; then - $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2 - fi - else - - # Parse the version information argument. - IFS="${IFS= }"; save_ifs="$IFS"; IFS=':' - set dummy $vinfo 0 0 0 - IFS="$save_ifs" - - if test -n "$8"; then - $echo "$modename: too many parameters to \`-version-info'" 1>&2 - $echo "$help" 1>&2 - exit 1 - fi - - current="$2" - revision="$3" - age="$4" - - # Check that each of the things are valid numbers. - case "$current" in - 0 | [1-9] | [1-9][0-9]*) ;; - *) - $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2 - $echo "$modename: \`$vinfo' is not valid version information" 1>&2 - exit 1 - ;; - esac - - case "$revision" in - 0 | [1-9] | [1-9][0-9]*) ;; - *) - $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2 - $echo "$modename: \`$vinfo' is not valid version information" 1>&2 - exit 1 - ;; - esac - - case "$age" in - 0 | [1-9] | [1-9][0-9]*) ;; - *) - $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2 - $echo "$modename: \`$vinfo' is not valid version information" 1>&2 - exit 1 - ;; - esac - - if test $age -gt $current; then - $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2 - $echo "$modename: \`$vinfo' is not valid version information" 1>&2 - exit 1 - fi - - # Calculate the version variables. - major= - versuffix= - verstring= - case "$version_type" in - none) ;; - - irix) - major=`expr $current - $age + 1` - versuffix="$major.$revision" - verstring="sgi$major.$revision" - - # Add in all the interfaces that we are compatible with. - loop=$revision - while test $loop != 0; do - iface=`expr $revision - $loop` - loop=`expr $loop - 1` - verstring="sgi$major.$iface:$verstring" - done - ;; - - linux) - major=.`expr $current - $age` - versuffix="$major.$age.$revision" - ;; - - osf) - major=`expr $current - $age` - versuffix=".$current.$age.$revision" - verstring="$current.$age.$revision" - - # Add in all the interfaces that we are compatible with. - loop=$age - while test $loop != 0; do - iface=`expr $current - $loop` - loop=`expr $loop - 1` - verstring="$verstring:${iface}.0" - done - - # Make executables depend on our current version. - verstring="$verstring:${current}.0" - ;; - - sunos) - major=".$current" - versuffix=".$current.$revision" - ;; - - freebsd-aout) - major=".$current" - versuffix=".$current.$revision"; - ;; - - freebsd-elf) - major=".$current" - versuffix=".$current"; - ;; - - windows) - # Like Linux, but with '-' rather than '.', since we only - # want one extension on Windows 95. - major=`expr $current - $age` - versuffix="-$major-$age-$revision" - ;; - - darwin) - # Like Linux, but with the current version available in - # verstring for coding it into the library header - major=`expr $current - $age` - versuffix=".$major.$age.$revision" - # Darwin ld doesn't like 0 for these options... - minor_current=`expr $current + 1` - verstring="-compatibility_version $major -current_version $major.$age.$revision" - major=".$major" - ;; - - *) - $echo "$modename: unknown library version type \`$version_type'" 1>&2 - echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 - exit 1 - ;; - esac - - # Clear the version info if we defaulted, and they specified a release. - if test -z "$vinfo" && test -n "$release"; then - major= - verstring="0.0" - if test "$need_version" = no; then - versuffix= - else - versuffix=".0.0" - fi - fi - - # Remove version info from name if versioning should be avoided - if test "$avoid_version" = yes && test "$need_version" = no; then - major= - versuffix= - verstring="" - fi - - # Check to see if the archive will have undefined symbols. - if test "$allow_undefined" = yes; then - if test "$allow_undefined_flag" = unsupported; then - $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2 - build_libtool_libs=no - build_old_libs=yes - fi - else - # Don't allow undefined symbols. - allow_undefined_flag="$no_undefined_flag" - fi - - dependency_libs="$deplibs" - case "$host" in - *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos*) - # these systems don't actually have a c library (as such)! - ;; - *-*-rhapsody* | *-*-darwin1.[012]) - # Rhapsody C library is in the System framework - deplibs="$deplibs -framework System" - ;; - *) - # Add libc to deplibs on all other systems. - deplibs="$deplibs -lc" - ;; - esac - fi - - # Create the output directory, or remove our outputs if we need to. - if test -d $output_objdir; then - $show "${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.*" - $run ${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.* - else - $show "$mkdir $output_objdir" - $run $mkdir $output_objdir - status=$? - if test $status -ne 0 && test ! -d $output_objdir; then - exit $status - fi - fi - - # Now set the variables for building old libraries. - if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then - oldlibs="$oldlibs $output_objdir/$libname.$libext" - - # Transform .lo files to .o files. - oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` - fi - - if test "$build_libtool_libs" = yes; then - # Transform deplibs into only deplibs that can be linked in shared. - name_save=$name - libname_save=$libname - release_save=$release - versuffix_save=$versuffix - major_save=$major - # I'm not sure if I'm treating the release correctly. I think - # release should show up in the -l (ie -lgmp5) so we don't want to - # add it in twice. Is that correct? - release="" - versuffix="" - major="" - newdeplibs= - droppeddeps=no - case "$deplibs_check_method" in - pass_all) - # Don't check for shared/static. Everything works. - # This might be a little naive. We might want to check - # whether the library exists or not. But this is on - # osf3 & osf4 and I'm not really sure... Just - # implementing what was already the behaviour. - newdeplibs=$deplibs - ;; - test_compile) - # This code stresses the "libraries are programs" paradigm to its - # limits. Maybe even breaks it. We compile a program, linking it - # against the deplibs as a proxy for the library. Then we can check - # whether they linked in statically or dynamically with ldd. - $rm conftest.c - cat > conftest.c </dev/null` - for potent_lib in $potential_libs; do - # Follow soft links. - if ls -lLd "$potent_lib" 2>/dev/null \ - | grep " -> " >/dev/null; then - continue - fi - # The statement above tries to avoid entering an - # endless loop below, in case of cyclic links. - # We might still enter an endless loop, since a link - # loop can be closed while we follow links, - # but so what? - potlib="$potent_lib" - while test -h "$potlib" 2>/dev/null; do - potliblink=`ls -ld $potlib | sed 's/.* -> //'` - case "$potliblink" in - [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; - *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; - esac - done - if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \ - | sed 10q \ - | egrep "$file_magic_regex" > /dev/null; then - newdeplibs="$newdeplibs $a_deplib" - a_deplib="" - break 2 - fi - done - done - if test -n "$a_deplib" ; then - droppeddeps=yes - echo - echo "*** Warning: This library needs some functionality provided by $a_deplib." - echo "*** I have the capability to make that library automatically link in when" - echo "*** you link to this library. But I can only do this if you have a" - echo "*** shared version of the library, which you do not appear to have." - fi - else - # Add a -L argument. - newdeplibs="$newdeplibs $a_deplib" - fi - done # Gone through all deplibs. - ;; - none | unknown | *) - newdeplibs="" - if $echo "X $deplibs" | $Xsed -e 's/ -lc$//' \ - -e 's/ -[LR][^ ]*//g' -e 's/[ ]//g' | - grep . >/dev/null; then - echo - if test "X$deplibs_check_method" = "Xnone"; then - echo "*** Warning: inter-library dependencies are not supported in this platform." - else - echo "*** Warning: inter-library dependencies are not known to be supported." - fi - echo "*** All declared inter-library dependencies are being dropped." - droppeddeps=yes - fi - ;; - esac - versuffix=$versuffix_save - major=$major_save - release=$release_save - libname=$libname_save - name=$name_save - - if test "$droppeddeps" = yes; then - if test "$module" = yes; then - echo - echo "*** Warning: libtool could not satisfy all declared inter-library" - echo "*** dependencies of module $libname. Therefore, libtool will create" - echo "*** a static module, that should work as long as the dlopening" - echo "*** application is linked with the -dlopen flag." - if test -z "$global_symbol_pipe"; then - echo - echo "*** However, this would only work if libtool was able to extract symbol" - echo "*** lists from a program, using \`nm' or equivalent, but libtool could" - echo "*** not find such a program. So, this module is probably useless." - echo "*** \`nm' from GNU binutils and a full rebuild may help." - fi - if test "$build_old_libs" = no; then - oldlibs="$output_objdir/$libname.$libext" - build_libtool_libs=module - build_old_libs=yes - else - build_libtool_libs=no - fi - else - echo "*** The inter-library dependencies that have been dropped here will be" - echo "*** automatically added whenever a program is linked with this library" - echo "*** or is declared to -dlopen it." - fi - fi - # Done checking deplibs! - deplibs=$newdeplibs - fi - - # All the library-specific variables (install_libdir is set above). - library_names= - old_library= - dlname= - - # Test again, we may have decided not to build it any more - if test "$build_libtool_libs" = yes; then - # Get the real and link names of the library. - eval library_names=\"$library_names_spec\" - set dummy $library_names - realname="$2" - shift; shift - - if test -n "$soname_spec"; then - eval soname=\"$soname_spec\" - else - soname="$realname" - fi - - lib="$output_objdir/$realname" - for link - do - linknames="$linknames $link" - done - - # Ensure that we have .o objects for linkers which dislike .lo - # (e.g. aix) in case we are running --disable-static - for obj in $libobjs; do - xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` - if test "X$xdir" = "X$obj"; then - xdir="." - else - xdir="$xdir" - fi - baseobj=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` - oldobj=`$echo "X$baseobj" | $Xsed -e "$lo2o"` - if test ! -f $xdir/$oldobj; then - $show "(cd $xdir && ${LN_S} $baseobj $oldobj)" - $run eval '(cd $xdir && ${LN_S} $baseobj $oldobj)' || exit $? - fi - done - - # Use standard objects if they are pic - test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` - - # Prepare the list of exported symbols - if test -z "$export_symbols"; then - if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then - $show "generating symbol list for \`$libname.la'" - export_symbols="$output_objdir/$libname.exp" - $run $rm $export_symbols - eval cmds=\"$export_symbols_cmds\" - IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - $show "$cmd" - $run eval "$cmd" || exit $? - done - IFS="$save_ifs" - if test -n "$export_symbols_regex"; then - $show "egrep -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\"" - $run eval 'egrep -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' - $show "$mv \"${export_symbols}T\" \"$export_symbols\"" - $run eval '$mv "${export_symbols}T" "$export_symbols"' - fi - fi - fi - - if test -n "$export_symbols" && test -n "$include_expsyms"; then - $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"' - fi - - if test -n "$convenience"; then - if test -n "$whole_archive_flag_spec"; then - eval libobjs=\"\$libobjs $whole_archive_flag_spec\" - else - gentop="$output_objdir/${outputname}x" - $show "${rm}r $gentop" - $run ${rm}r "$gentop" - $show "mkdir $gentop" - $run mkdir "$gentop" - status=$? - if test $status -ne 0 && test ! -d "$gentop"; then - exit $status - fi - generated="$generated $gentop" - - for xlib in $convenience; do - # Extract the objects. - case "$xlib" in - [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; - *) xabs=`pwd`"/$xlib" ;; - esac - xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` - xdir="$gentop/$xlib" - - $show "${rm}r $xdir" - $run ${rm}r "$xdir" - $show "mkdir $xdir" - $run mkdir "$xdir" - status=$? - if test $status -ne 0 && test ! -d "$xdir"; then - exit $status - fi - $show "(cd $xdir && $AR x $xabs)" - $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? - - libobjs="$libobjs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP` - done - fi - fi - - if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then - eval flag=\"$thread_safe_flag_spec\" - linkopts="$linkopts $flag" - fi - - # Do each of the archive commands. - if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then - eval cmds=\"$archive_expsym_cmds\" - else - if test "x$verstring" = "x0.0"; then - tmp_verstring= - else - tmp_verstring="$verstring" - fi - eval cmds=\"$archive_cmds\" - fi - IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - $show "$cmd" - $run eval "$cmd" || exit $? - done - IFS="$save_ifs" - - # Create links to the real library. - for linkname in $linknames; do - if test "$realname" != "$linkname"; then - $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)" - $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $? - fi - done - - # If -module or -export-dynamic was specified, set the dlname. - if test "$module" = yes || test "$export_dynamic" = yes; then - # On all known operating systems, these are identical. - dlname="$soname" - fi - fi - ;; - - *.lo | *.o | *.obj) - if test -n "$link_against_libtool_libs"; then - $echo "$modename: error: cannot link libtool libraries into objects" 1>&2 - exit 1 - fi - - if test -n "$deplibs"; then - $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2 - fi - - if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then - $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2 - fi - - if test -n "$rpath"; then - $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2 - fi - - if test -n "$xrpath"; then - $echo "$modename: warning: \`-R' is ignored for objects" 1>&2 - fi - - if test -n "$vinfo"; then - $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2 - fi - - if test -n "$release"; then - $echo "$modename: warning: \`-release' is ignored for objects" 1>&2 - fi - - case "$output" in - *.lo) - if test -n "$objs"; then - $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2 - exit 1 - fi - libobj="$output" - obj=`$echo "X$output" | $Xsed -e "$lo2o"` - ;; - *) - libobj= - obj="$output" - ;; - esac - - # Delete the old objects. - $run $rm $obj $libobj - - # Objects from convenience libraries. This assumes - # single-version convenience libraries. Whenever we create - # different ones for PIC/non-PIC, this we'll have to duplicate - # the extraction. - reload_conv_objs= - gentop= - # reload_cmds runs $LD directly, so let us get rid of - # -Wl from whole_archive_flag_spec - wl= - - if test -n "$convenience"; then - if test -n "$whole_archive_flag_spec"; then - eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\" - else - gentop="$output_objdir/${obj}x" - $show "${rm}r $gentop" - $run ${rm}r "$gentop" - $show "mkdir $gentop" - $run mkdir "$gentop" - status=$? - if test $status -ne 0 && test ! -d "$gentop"; then - exit $status - fi - generated="$generated $gentop" - - for xlib in $convenience; do - # Extract the objects. - case "$xlib" in - [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; - *) xabs=`pwd`"/$xlib" ;; - esac - xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` - xdir="$gentop/$xlib" - - $show "${rm}r $xdir" - $run ${rm}r "$xdir" - $show "mkdir $xdir" - $run mkdir "$xdir" - status=$? - if test $status -ne 0 && test ! -d "$xdir"; then - exit $status - fi - $show "(cd $xdir && $AR x $xabs)" - $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? - - reload_conv_objs="$reload_objs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP` - done - fi - fi - - # Create the old-style object. - reload_objs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" - - output="$obj" - eval cmds=\"$reload_cmds\" - IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - $show "$cmd" - $run eval "$cmd" || exit $? - done - IFS="$save_ifs" - - # Exit if we aren't doing a library object file. - if test -z "$libobj"; then - if test -n "$gentop"; then - $show "${rm}r $gentop" - $run ${rm}r $gentop - fi - - exit 0 - fi - - if test "$build_libtool_libs" != yes; then - if test -n "$gentop"; then - $show "${rm}r $gentop" - $run ${rm}r $gentop - fi - - # Create an invalid libtool object if no PIC, so that we don't - # accidentally link it into a program. - $show "echo timestamp > $libobj" - $run eval "echo timestamp > $libobj" || exit $? - exit 0 - fi - - if test -n "$pic_flag"; then - # Only do commands if we really have different PIC objects. - reload_objs="$libobjs $reload_conv_objs" - output="$libobj" - eval cmds=\"$reload_cmds\" - IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - $show "$cmd" - $run eval "$cmd" || exit $? - done - IFS="$save_ifs" - else - # Just create a symlink. - $show $rm $libobj - $run $rm $libobj - xdir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'` - if test "X$xdir" = "X$libobj"; then - xdir="." - else - xdir="$xdir" - fi - baseobj=`$echo "X$libobj" | $Xsed -e 's%^.*/%%'` - oldobj=`$echo "X$baseobj" | $Xsed -e "$lo2o"` - $show "(cd $xdir && $LN_S $oldobj $baseobj)" - $run eval '(cd $xdir && $LN_S $oldobj $baseobj)' || exit $? - fi - - if test -n "$gentop"; then - $show "${rm}r $gentop" - $run ${rm}r $gentop - fi - - exit 0 - ;; - - # Anything else should be a program. - *) - if test -n "$vinfo"; then - $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2 - fi - - if test -n "$release"; then - $echo "$modename: warning: \`-release' is ignored for programs" 1>&2 - fi - - if test "$preload" = yes; then - if test "$dlopen" = unknown && test "$dlopen_self" = unknown && - test "$dlopen_self_static" = unknown; then - $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support." - fi - fi - - if test -n "$rpath$xrpath"; then - # If the user specified any rpath flags, then add them. - for libdir in $rpath $xrpath; do - # This is the magic to use -rpath. - case "$compile_rpath " in - *" $libdir "*) ;; - *) compile_rpath="$compile_rpath $libdir" ;; - esac - case "$finalize_rpath " in - *" $libdir "*) ;; - *) finalize_rpath="$finalize_rpath $libdir" ;; - esac - done - fi - - # Now hardcode the library paths - rpath= - hardcode_libdirs= - for libdir in $compile_rpath $finalize_rpath; do - if test -n "$hardcode_libdir_flag_spec"; then - if test -n "$hardcode_libdir_separator"; then - if test -z "$hardcode_libdirs"; then - hardcode_libdirs="$libdir" - else - # Just accumulate the unique libdirs. - case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in - *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) - ;; - *) - hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" - ;; - esac - fi - else - eval flag=\"$hardcode_libdir_flag_spec\" - rpath="$rpath $flag" - fi - elif test -n "$runpath_var"; then - case "$perm_rpath " in - *" $libdir "*) ;; - *) perm_rpath="$perm_rpath $libdir" ;; - esac - fi - done - # Substitute the hardcoded libdirs into the rpath. - if test -n "$hardcode_libdir_separator" && - test -n "$hardcode_libdirs"; then - libdir="$hardcode_libdirs" - eval rpath=\" $hardcode_libdir_flag_spec\" - fi - compile_rpath="$rpath" - - rpath= - hardcode_libdirs= - for libdir in $finalize_rpath; do - if test -n "$hardcode_libdir_flag_spec"; then - if test -n "$hardcode_libdir_separator"; then - if test -z "$hardcode_libdirs"; then - hardcode_libdirs="$libdir" - else - # Just accumulate the unique libdirs. - case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in - *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) - ;; - *) - hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" - ;; - esac - fi - else - eval flag=\"$hardcode_libdir_flag_spec\" - rpath="$rpath $flag" - fi - elif test -n "$runpath_var"; then - case "$finalize_perm_rpath " in - *" $libdir "*) ;; - *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;; - esac - fi - done - # Substitute the hardcoded libdirs into the rpath. - if test -n "$hardcode_libdir_separator" && - test -n "$hardcode_libdirs"; then - libdir="$hardcode_libdirs" - eval rpath=\" $hardcode_libdir_flag_spec\" - fi - finalize_rpath="$rpath" - - output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'` - if test "X$output_objdir" = "X$output"; then - output_objdir="$objdir" - else - output_objdir="$output_objdir/$objdir" - fi - - # Create the binary in the object directory, then wrap it. - if test ! -d $output_objdir; then - $show "$mkdir $output_objdir" - $run $mkdir $output_objdir - status=$? - if test $status -ne 0 && test ! -d $output_objdir; then - exit $status - fi - fi - - if test -n "$libobjs" && test "$build_old_libs" = yes; then - # Transform all the library objects into standard objects. - compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` - finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` - fi - - dlsyms= - if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then - if test -n "$NM" && test -n "$global_symbol_pipe"; then - dlsyms="${outputname}S.c" - else - $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2 - fi - fi - - if test -n "$dlsyms"; then - case "$dlsyms" in - "") ;; - *.c) - # Discover the nlist of each of the dlfiles. - nlist="$output_objdir/${outputname}.nm" - - $show "$rm $nlist ${nlist}S ${nlist}T" - $run $rm "$nlist" "${nlist}S" "${nlist}T" - - # Parse the name list into a source file. - $show "creating $output_objdir/$dlsyms" - - test -z "$run" && $echo > "$output_objdir/$dlsyms" "\ -/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */ -/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */ - -#ifdef __cplusplus -extern \"C\" { -#endif - -/* Prevent the only kind of declaration conflicts we can make. */ -#define lt_preloaded_symbols some_other_symbol - -/* External symbol declarations for the compiler. */\ -" - - if test "$dlself" = yes; then - $show "generating symbol list for \`$output'" - - test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist" - - # Add our own program objects to the symbol list. - progfiles=`$echo "X$objs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` - for arg in $progfiles; do - $show "extracting global C symbols from \`$arg'" - $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" - done - - if test -n "$exclude_expsyms"; then - $run eval 'egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' - $run eval '$mv "$nlist"T "$nlist"' - fi - - if test -n "$export_symbols_regex"; then - $run eval 'egrep -e "$export_symbols_regex" "$nlist" > "$nlist"T' - $run eval '$mv "$nlist"T "$nlist"' - fi - - # Prepare the list of exported symbols - if test -z "$export_symbols"; then - export_symbols="$output_objdir/$output.exp" - $run $rm $export_symbols - $run eval "sed -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' - else - $run eval "sed -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"' - $run eval 'grep -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T' - $run eval 'mv "$nlist"T "$nlist"' - fi - fi - - for arg in $dlprefiles; do - $show "extracting global C symbols from \`$arg'" - name=`echo "$arg" | sed -e 's%^.*/%%'` - $run eval 'echo ": $name " >> "$nlist"' - $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" - done - - if test -z "$run"; then - # Make sure we have at least an empty file. - test -f "$nlist" || : > "$nlist" - - if test -n "$exclude_expsyms"; then - egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T - $mv "$nlist"T "$nlist" - fi - - # Try sorting and uniquifying the output. - if grep -v "^: " < "$nlist" | sort +2 | uniq > "$nlist"S; then - : - else - grep -v "^: " < "$nlist" > "$nlist"S - fi - - if test -f "$nlist"S; then - eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"' - else - echo '/* NONE */' >> "$output_objdir/$dlsyms" - fi - - $echo >> "$output_objdir/$dlsyms" "\ - -#undef lt_preloaded_symbols - -#if defined (__STDC__) && __STDC__ -# define lt_ptr_t void * -#else -# define lt_ptr_t char * -# define const -#endif - -/* The mapping between symbol names and symbols. */ -const struct { - const char *name; - lt_ptr_t address; -} -lt_preloaded_symbols[] = -{\ -" - - sed -n -e 's/^: \([^ ]*\) $/ {\"\1\", (lt_ptr_t) 0},/p' \ - -e 's/^. \([^ ]*\) \([^ ]*\)$/ {"\2", (lt_ptr_t) \&\2},/p' \ - < "$nlist" >> "$output_objdir/$dlsyms" - - $echo >> "$output_objdir/$dlsyms" "\ - {0, (lt_ptr_t) 0} -}; - -/* This works around a problem in FreeBSD linker */ -#ifdef FREEBSD_WORKAROUND -static const void *lt_preloaded_setup() { - return lt_preloaded_symbols; -} -#endif - -#ifdef __cplusplus -} -#endif\ -" - fi - - pic_flag_for_symtable= - case "$host" in - # compiling the symbol table file with pic_flag works around - # a FreeBSD bug that causes programs to crash when -lm is - # linked before any other PIC object. But we must not use - # pic_flag when linking with -static. The problem exists in - # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. - *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) - case "$compile_command " in - *" -static "*) ;; - *) pic_flag_for_symtable=" $pic_flag -DPIC -DFREEBSD_WORKAROUND";; - esac;; - *-*-hpux*) - case "$compile_command " in - *" -static "*) ;; - *) pic_flag_for_symtable=" $pic_flag -DPIC";; - esac - esac - - # Now compile the dynamic symbol file. - $show "(cd $output_objdir && $CC -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")" - $run eval '(cd $output_objdir && $CC -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $? - - # Clean up the generated files. - $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T" - $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T" - - # Transform the symbol file into the correct name. - compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` - finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` - ;; - *) - $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2 - exit 1 - ;; - esac - else - # We keep going just in case the user didn't refer to - # lt_preloaded_symbols. The linker will fail if global_symbol_pipe - # really was required. - - # Nullify the symbol file. - compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` - finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` - fi - - if test -z "$link_against_libtool_libs" || test "$build_libtool_libs" != yes; then - # Replace the output file specification. - compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` - link_command="$compile_command$compile_rpath" - - # We have no uninstalled library dependencies, so finalize right now. - $show "$link_command" - $run eval "$link_command" - status=$? - - # Delete the generated files. - if test -n "$dlsyms"; then - $show "$rm $output_objdir/${outputname}S.${objext}" - $run $rm "$output_objdir/${outputname}S.${objext}" - fi - - exit $status - fi - - if test -n "$shlibpath_var"; then - # We should set the shlibpath_var - rpath= - for dir in $temp_rpath; do - case "$dir" in - [\\/]* | [A-Za-z]:[\\/]*) - # Absolute path. - rpath="$rpath$dir:" - ;; - *) - # Relative path: add a thisdir entry. - rpath="$rpath\$thisdir/$dir:" - ;; - esac - done - temp_rpath="$rpath" - fi - - if test -n "$compile_shlibpath$finalize_shlibpath"; then - compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" - fi - if test -n "$finalize_shlibpath"; then - finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" - fi - - compile_var= - finalize_var= - if test -n "$runpath_var"; then - if test -n "$perm_rpath"; then - # We should set the runpath_var. - rpath= - for dir in $perm_rpath; do - rpath="$rpath$dir:" - done - compile_var="$runpath_var=\"$rpath\$$runpath_var\" " - fi - if test -n "$finalize_perm_rpath"; then - # We should set the runpath_var. - rpath= - for dir in $finalize_perm_rpath; do - rpath="$rpath$dir:" - done - finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " - fi - fi - - if test "$hardcode_action" = relink; then - # Fast installation is not supported - link_command="$compile_var$compile_command$compile_rpath" - relink_command="$finalize_var$finalize_command$finalize_rpath" - - $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2 - $echo "$modename: \`$output' will be relinked during installation" 1>&2 - else - if test "$fast_install" != no; then - link_command="$finalize_var$compile_command$finalize_rpath" - if test "$fast_install" = yes; then - relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'` - else - # fast_install is set to needless - relink_command= - fi - else - link_command="$compile_var$compile_command$compile_rpath" - relink_command="$finalize_var$finalize_command$finalize_rpath" - fi - fi - - # Replace the output file specification. - link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` - - # Delete the old output files. - $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname - - $show "$link_command" - $run eval "$link_command" || exit $? - - # Now create the wrapper script. - $show "creating $output" - - # Quote the relink command for shipping. - if test -n "$relink_command"; then - relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` - fi - - # Quote $echo for shipping. - if test "X$echo" = "X$SHELL $0 --fallback-echo"; then - case "$0" in - [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $0 --fallback-echo";; - *) qecho="$SHELL `pwd`/$0 --fallback-echo";; - esac - qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"` - else - qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"` - fi - - # Only actually do things if our run command is non-null. - if test -z "$run"; then - # win32 will think the script is a binary if it has - # a .exe suffix, so we strip it off here. - case $output in - *.exe) output=`echo $output|sed 's,.exe$,,'` ;; - esac - $rm $output - trap "$rm $output; exit 1" 1 2 15 - - $echo > $output "\ -#! $SHELL - -# $output - temporary wrapper script for $objdir/$outputname -# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP -# -# The $output program cannot be directly executed until all the libtool -# libraries that it depends on are installed. -# -# This wrapper script should never be moved out of the build directory. -# If it is, it will not operate correctly. - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -Xsed='sed -e 1s/^X//' -sed_quote_subst='$sed_quote_subst' - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -if test \"\${CDPATH+set}\" = set; then CDPATH=:; export CDPATH; fi - -relink_command=\"$relink_command\" - -# This environment variable determines our operation mode. -if test \"\$libtool_install_magic\" = \"$magic\"; then - # install mode needs the following variable: - link_against_libtool_libs='$link_against_libtool_libs' -else - # When we are sourced in execute mode, \$file and \$echo are already set. - if test \"\$libtool_execute_magic\" != \"$magic\"; then - echo=\"$qecho\" - file=\"\$0\" - # Make sure echo works. - if test \"X\$1\" = X--no-reexec; then - # Discard the --no-reexec flag, and continue. - shift - elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then - # Yippee, \$echo works! - : - else - # Restart under the correct shell, and then maybe \$echo will work. - exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} - fi - fi\ -" - $echo >> $output "\ - - # Find the directory that this script lives in. - thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` - test \"x\$thisdir\" = \"x\$file\" && thisdir=. - - # Follow symbolic links until we get to the real thisdir. - file=\`ls -ld \"\$file\" | sed -n 's/.*-> //p'\` - while test -n \"\$file\"; do - destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` - - # If there was a directory component, then change thisdir. - if test \"x\$destdir\" != \"x\$file\"; then - case \"\$destdir\" in - [\\/]* | [A-Za-z]:[\\/]*) thisdir=\"\$destdir\" ;; - *) thisdir=\"\$thisdir/\$destdir\" ;; - esac - fi - - file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\` - file=\`ls -ld \"\$thisdir/\$file\" | sed -n 's/.*-> //p'\` - done - - # Try to get the absolute directory name. - absdir=\`cd \"\$thisdir\" && pwd\` - test -n \"\$absdir\" && thisdir=\"\$absdir\" -" - - if test "$fast_install" = yes; then - echo >> $output "\ - program=lt-'$outputname' - progdir=\"\$thisdir/$objdir\" - - if test ! -f \"\$progdir/\$program\" || \\ - { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | sed 1q\`; \\ - test \"X\$file\" != \"X\$progdir/\$program\"; }; then - - file=\"\$\$-\$program\" - - if test ! -d \"\$progdir\"; then - $mkdir \"\$progdir\" - else - $rm \"\$progdir/\$file\" - fi" - - echo >> $output "\ - - # relink executable if necessary - if test -n \"\$relink_command\"; then - if (cd \"\$thisdir\" && eval \$relink_command); then : - else - $rm \"\$progdir/\$file\" - exit 1 - fi - fi - - $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || - { $rm \"\$progdir/\$program\"; - $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; } - $rm \"\$progdir/\$file\" - fi" - else - echo >> $output "\ - program='$outputname' - progdir=\"\$thisdir/$objdir\" -" - fi - - echo >> $output "\ - - if test -f \"\$progdir/\$program\"; then" - - # Export our shlibpath_var if we have one. - if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then - $echo >> $output "\ - # Add our own library path to $shlibpath_var - $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" - - # Some systems cannot cope with colon-terminated $shlibpath_var - # The second colon is a workaround for a bug in BeOS R4 sed - $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` - - export $shlibpath_var -" - fi - - # fixup the dll searchpath if we need to. - if test -n "$dllsearchpath"; then - $echo >> $output "\ - # Add the dll search path components to the executable PATH - PATH=$dllsearchpath:\$PATH -" - fi - - $echo >> $output "\ - if test \"\$libtool_execute_magic\" != \"$magic\"; then - # Run the actual program with our arguments. -" - case $host in - # win32 systems need to use the prog path for dll - # lookup to work - *-*-cygwin*) - $echo >> $output "\ - exec \$progdir/\$program \${1+\"\$@\"} -" - ;; - - # Backslashes separate directories on plain windows - *-*-mingw | *-*-os2*) - $echo >> $output "\ - exec \$progdir\\\\\$program \${1+\"\$@\"} -" - ;; - - *) - $echo >> $output "\ - # Export the path to the program. - PATH=\"\$progdir:\$PATH\" - export PATH - - exec \$program \${1+\"\$@\"} -" - ;; - esac - $echo >> $output "\ - \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\" - exit 1 - fi - else - # The program doesn't exist. - \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2 - \$echo \"This script is just a wrapper for \$program.\" 1>&2 - echo \"See the $PACKAGE documentation for more information.\" 1>&2 - exit 1 - fi -fi\ -" - chmod +x $output - fi - exit 0 - ;; - esac - - # See if we need to build an old-fashioned archive. - for oldlib in $oldlibs; do - - if test "$build_libtool_libs" = convenience; then - oldobjs="$libobjs_save" - addlibs="$convenience" - build_libtool_libs=no - else - if test "$build_libtool_libs" = module; then - oldobjs="$libobjs_save" - build_libtool_libs=no - else - oldobjs="$objs "`$echo "X$libobjs_save" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP` - fi - addlibs="$old_convenience" - fi - - if test -n "$addlibs"; then - gentop="$output_objdir/${outputname}x" - $show "${rm}r $gentop" - $run ${rm}r "$gentop" - $show "mkdir $gentop" - $run mkdir "$gentop" - status=$? - if test $status -ne 0 && test ! -d "$gentop"; then - exit $status - fi - generated="$generated $gentop" - - # Add in members from convenience archives. - for xlib in $addlibs; do - # Extract the objects. - case "$xlib" in - [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; - *) xabs=`pwd`"/$xlib" ;; - esac - xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` - xdir="$gentop/$xlib" - - $show "${rm}r $xdir" - $run ${rm}r "$xdir" - $show "mkdir $xdir" - $run mkdir "$xdir" - status=$? - if test $status -ne 0 && test ! -d "$xdir"; then - exit $status - fi - $show "(cd $xdir && $AR x $xabs)" - $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? - - oldobjs="$oldobjs "`find $xdir -name \*.${objext} -print -o -name \*.lo -print | $NL2SP` - done - fi - - # Do each command in the archive commands. - if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then - eval cmds=\"$old_archive_from_new_cmds\" - else - # Ensure that we have .o objects in place in case we decided - # not to build a shared library, and have fallen back to building - # static libs even though --disable-static was passed! - for oldobj in $oldobjs; do - if test ! -f $oldobj; then - xdir=`$echo "X$oldobj" | $Xsed -e 's%/[^/]*$%%'` - if test "X$xdir" = "X$oldobj"; then - xdir="." - else - xdir="$xdir" - fi - baseobj=`$echo "X$oldobj" | $Xsed -e 's%^.*/%%'` - obj=`$echo "X$baseobj" | $Xsed -e "$o2lo"` - $show "(cd $xdir && ${LN_S} $obj $baseobj)" - $run eval '(cd $xdir && ${LN_S} $obj $baseobj)' || exit $? - fi - done - - eval cmds=\"$old_archive_cmds\" - fi - IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - $show "$cmd" - $run eval "$cmd" || exit $? - done - IFS="$save_ifs" - done - - if test -n "$generated"; then - $show "${rm}r$generated" - $run ${rm}r$generated - fi - - # Now create the libtool archive. - case "$output" in - *.la) - old_library= - test "$build_old_libs" = yes && old_library="$libname.$libext" - $show "creating $output" - - if test -n "$xrpath"; then - temp_xrpath= - for libdir in $xrpath; do - temp_xrpath="$temp_xrpath -R$libdir" - done - dependency_libs="$temp_xrpath $dependency_libs" - fi - - # Only create the output if not a dry run. - if test -z "$run"; then - for installed in no yes; do - if test "$installed" = yes; then - if test -z "$install_libdir"; then - break - fi - output="$output_objdir/$outputname"i - fi - $rm $output - $echo > $output "\ -# $outputname - a libtool library file -# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP -# -# Please DO NOT delete this file! -# It is necessary for linking the library. - -# The name that we can dlopen(3). -dlname='$dlname' - -# Names of this library. -library_names='$library_names' - -# The name of the static archive. -old_library='$old_library' - -# Libraries that this one depends upon. -dependency_libs='$dependency_libs' - -# Version information for $libname. -current=$current -age=$age -revision=$revision - -# Is this an already installed library? -installed=$installed - -# Directory that this library needs to be installed in: -libdir='$install_libdir'\ -" - done - fi - - # Do a symbolic link so that the libtool archive can be found in - # LD_LIBRARY_PATH before the program is installed. - $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" - $run eval "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" || exit $? - ;; - esac - exit 0 - ;; - - # libtool install mode - install) - modename="$modename: install" - - # There may be an optional sh(1) argument at the beginning of - # install_prog (especially on Windows NT). - if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh; then - # Aesthetically quote it. - arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"` - case "$arg" in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) - arg="\"$arg\"" - ;; - esac - install_prog="$arg " - arg="$1" - shift - else - install_prog= - arg="$nonopt" - fi - - # The real first argument should be the name of the installation program. - # Aesthetically quote it. - arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` - case "$arg" in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) - arg="\"$arg\"" - ;; - esac - install_prog="$install_prog$arg" - - # We need to accept at least all the BSD install flags. - dest= - files= - opts= - prev= - install_type= - isdir=no - stripme= - for arg - do - if test -n "$dest"; then - files="$files $dest" - dest="$arg" - continue - fi - - case "$arg" in - -d) isdir=yes ;; - -f) prev="-f" ;; - -g) prev="-g" ;; - -m) prev="-m" ;; - -o) prev="-o" ;; - -s) - stripme=" -s" - continue - ;; - -*) ;; - - *) - # If the previous option needed an argument, then skip it. - if test -n "$prev"; then - prev= - else - dest="$arg" - continue - fi - ;; - esac - - # Aesthetically quote the argument. - arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` - case "$arg" in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) - arg="\"$arg\"" - ;; - esac - install_prog="$install_prog $arg" - done - - if test -z "$install_prog"; then - $echo "$modename: you must specify an install program" 1>&2 - $echo "$help" 1>&2 - exit 1 - fi - - if test -n "$prev"; then - $echo "$modename: the \`$prev' option requires an argument" 1>&2 - $echo "$help" 1>&2 - exit 1 - fi - - if test -z "$files"; then - if test -z "$dest"; then - $echo "$modename: no file or destination specified" 1>&2 - else - $echo "$modename: you must specify a destination" 1>&2 - fi - $echo "$help" 1>&2 - exit 1 - fi - - # Strip any trailing slash from the destination. - dest=`$echo "X$dest" | $Xsed -e 's%/$%%'` - - # Check to see that the destination is a directory. - test -d "$dest" && isdir=yes - if test "$isdir" = yes; then - destdir="$dest" - destname= - else - destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'` - test "X$destdir" = "X$dest" && destdir=. - destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'` - - # Not a directory, so check to see that there is only one file specified. - set dummy $files - if test $# -gt 2; then - $echo "$modename: \`$dest' is not a directory" 1>&2 - $echo "$help" 1>&2 - exit 1 - fi - fi - case "$destdir" in - [\\/]* | [A-Za-z]:[\\/]*) ;; - *) - for file in $files; do - case "$file" in - *.lo) ;; - *) - $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2 - $echo "$help" 1>&2 - exit 1 - ;; - esac - done - ;; - esac - - # This variable tells wrapper scripts just to set variables rather - # than running their programs. - libtool_install_magic="$magic" - - staticlibs= - future_libdirs= - current_libdirs= - for file in $files; do - - # Do each installation. - case "$file" in - *.a | *.lib) - # Do the static libraries later. - staticlibs="$staticlibs $file" - ;; - - *.la) - # Check to see that this really is a libtool archive. - if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : - else - $echo "$modename: \`$file' is not a valid libtool archive" 1>&2 - $echo "$help" 1>&2 - exit 1 - fi - - library_names= - old_library= - # If there is no directory component, then add one. - case "$file" in - */* | *\\*) . $file ;; - *) . ./$file ;; - esac - - # Add the libdir to current_libdirs if it is the destination. - if test "X$destdir" = "X$libdir"; then - case "$current_libdirs " in - *" $libdir "*) ;; - *) current_libdirs="$current_libdirs $libdir" ;; - esac - else - # Note the libdir as a future libdir. - case "$future_libdirs " in - *" $libdir "*) ;; - *) future_libdirs="$future_libdirs $libdir" ;; - esac - fi - - dir="`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/" - test "X$dir" = "X$file/" && dir= - dir="$dir$objdir" - - # See the names of the shared library. - set dummy $library_names - if test -n "$2"; then - realname="$2" - shift - shift - - # Install the shared library and build the symlinks. - $show "$install_prog $dir/$realname $destdir/$realname" - $run eval "$install_prog $dir/$realname $destdir/$realname" || exit $? - - if test $# -gt 0; then - # Delete the old symlinks, and create new ones. - for linkname - do - if test "$linkname" != "$realname"; then - $show "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)" - $run eval "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)" - fi - done - fi - - # Do each command in the postinstall commands. - lib="$destdir/$realname" - eval cmds=\"$postinstall_cmds\" - IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - $show "$cmd" - $run eval "$cmd" || exit $? - done - IFS="$save_ifs" - fi - - # Install the pseudo-library for information purposes. - name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` - instname="$dir/$name"i - $show "$install_prog $instname $destdir/$name" - $run eval "$install_prog $instname $destdir/$name" || exit $? - - # Maybe install the static library, too. - test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" - ;; - - *.lo) - # Install (i.e. copy) a libtool object. - - # Figure out destination file name, if it wasn't already specified. - if test -n "$destname"; then - destfile="$destdir/$destname" - else - destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` - destfile="$destdir/$destfile" - fi - - # Deduce the name of the destination old-style object file. - case "$destfile" in - *.lo) - staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"` - ;; - *.o | *.obj) - staticdest="$destfile" - destfile= - ;; - *) - $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2 - $echo "$help" 1>&2 - exit 1 - ;; - esac - - # Install the libtool object if requested. - if test -n "$destfile"; then - $show "$install_prog $file $destfile" - $run eval "$install_prog $file $destfile" || exit $? - fi - - # Install the old object if enabled. - if test "$build_old_libs" = yes; then - # Deduce the name of the old-style object file. - staticobj=`$echo "X$file" | $Xsed -e "$lo2o"` - - $show "$install_prog $staticobj $staticdest" - $run eval "$install_prog \$staticobj \$staticdest" || exit $? - fi - exit 0 - ;; - - *) - # Figure out destination file name, if it wasn't already specified. - if test -n "$destname"; then - destfile="$destdir/$destname" - else - destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` - destfile="$destdir/$destfile" - fi - - # Do a test to see if this is really a libtool program. - if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then - link_against_libtool_libs= - relink_command= - - # If there is no directory component, then add one. - case "$file" in - */* | *\\*) . $file ;; - *) . ./$file ;; - esac - - # Check the variables that should have been set. - if test -z "$link_against_libtool_libs"; then - $echo "$modename: invalid libtool wrapper script \`$file'" 1>&2 - exit 1 - fi - - finalize=yes - for lib in $link_against_libtool_libs; do - # Check to see that each library is installed. - libdir= - if test -f "$lib"; then - # If there is no directory component, then add one. - case "$lib" in - */* | *\\*) . $lib ;; - *) . ./$lib ;; - esac - fi - libfile="$libdir/`$echo "X$lib" | $Xsed -e 's%^.*/%%g'`" - if test -n "$libdir" && test ! -f "$libfile"; then - $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2 - finalize=no - fi - done - - outputname= - if test "$fast_install" = no && test -n "$relink_command"; then - if test "$finalize" = yes && test -z "$run"; then - tmpdir="/tmp" - test -n "$TMPDIR" && tmpdir="$TMPDIR" - tmpdir="$tmpdir/libtool-$$" - if $mkdir -p "$tmpdir" && chmod 700 "$tmpdir"; then : - else - $echo "$modename: error: cannot create temporary directory \`$tmpdir'" 1>&2 - continue - fi - outputname="$tmpdir/$file" - # Replace the output file specification. - relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` - - $show "$relink_command" - if $run eval "$relink_command"; then : - else - $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 - ${rm}r "$tmpdir" - continue - fi - file="$outputname" - else - $echo "$modename: warning: cannot relink \`$file'" 1>&2 - fi - else - # Install the binary that we compiled earlier. - file=`$echo "X$file" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` - fi - fi - - $show "$install_prog$stripme $file $destfile" - $run eval "$install_prog\$stripme \$file \$destfile" || exit $? - test -n "$outputname" && ${rm}r "$tmpdir" - ;; - esac - done - - for file in $staticlibs; do - name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` - - # Set up the ranlib parameters. - oldlib="$destdir/$name" - - $show "$install_prog $file $oldlib" - $run eval "$install_prog \$file \$oldlib" || exit $? - - # Do each command in the postinstall commands. - eval cmds=\"$old_postinstall_cmds\" - IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - $show "$cmd" - $run eval "$cmd" || exit $? - done - IFS="$save_ifs" - done - - if test -n "$future_libdirs"; then - $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2 - fi - - if test -n "$current_libdirs"; then - # Maybe just do a dry run. - test -n "$run" && current_libdirs=" -n$current_libdirs" - exec $SHELL $0 --finish$current_libdirs - exit 1 - fi - - exit 0 - ;; - - # libtool finish mode - finish) - modename="$modename: finish" - libdirs="$nonopt" - admincmds= - - if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then - for dir - do - libdirs="$libdirs $dir" - done - - for libdir in $libdirs; do - if test -n "$finish_cmds"; then - # Do each command in the finish commands. - eval cmds=\"$finish_cmds\" - IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - $show "$cmd" - $run eval "$cmd" || admincmds="$admincmds - $cmd" - done - IFS="$save_ifs" - fi - if test -n "$finish_eval"; then - # Do the single finish_eval. - eval cmds=\"$finish_eval\" - $run eval "$cmds" || admincmds="$admincmds - $cmds" - fi - done - fi - - # Exit here if they wanted silent mode. - test "$show" = : && exit 0 - - echo "----------------------------------------------------------------------" - echo "Libraries have been installed in:" - for libdir in $libdirs; do - echo " $libdir" - done - echo - echo "If you ever happen to want to link against installed libraries" - echo "in a given directory, LIBDIR, you must either use libtool, and" - echo "specify the full pathname of the library, or use \`-LLIBDIR'" - echo "flag during linking and do at least one of the following:" - if test -n "$shlibpath_var"; then - echo " - add LIBDIR to the \`$shlibpath_var' environment variable" - echo " during execution" - fi - if test -n "$runpath_var"; then - echo " - add LIBDIR to the \`$runpath_var' environment variable" - echo " during linking" - fi - if test -n "$hardcode_libdir_flag_spec"; then - libdir=LIBDIR - eval flag=\"$hardcode_libdir_flag_spec\" - - echo " - use the \`$flag' linker flag" - fi - if test -n "$admincmds"; then - echo " - have your system administrator run these commands:$admincmds" - fi - if test -f /etc/ld.so.conf; then - echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" - fi - echo - echo "See any operating system documentation about shared libraries for" - echo "more information, such as the ld(1) and ld.so(8) manual pages." - echo "----------------------------------------------------------------------" - exit 0 - ;; - - # libtool execute mode - execute) - modename="$modename: execute" - - # The first argument is the command name. - cmd="$nonopt" - if test -z "$cmd"; then - $echo "$modename: you must specify a COMMAND" 1>&2 - $echo "$help" - exit 1 - fi - - # Handle -dlopen flags immediately. - for file in $execute_dlfiles; do - if test ! -f "$file"; then - $echo "$modename: \`$file' is not a file" 1>&2 - $echo "$help" 1>&2 - exit 1 - fi - - dir= - case "$file" in - *.la) - # Check to see that this really is a libtool archive. - if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : - else - $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 - $echo "$help" 1>&2 - exit 1 - fi - - # Read the libtool library. - dlname= - library_names= - - # If there is no directory component, then add one. - case "$file" in - */* | *\\*) . $file ;; - *) . ./$file ;; - esac - - # Skip this library if it cannot be dlopened. - if test -z "$dlname"; then - # Warn if it was a shared library. - test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'" - continue - fi - - dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` - test "X$dir" = "X$file" && dir=. - - if test -f "$dir/$objdir/$dlname"; then - dir="$dir/$objdir" - else - $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2 - exit 1 - fi - ;; - - *.lo) - # Just add the directory containing the .lo file. - dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` - test "X$dir" = "X$file" && dir=. - ;; - - *) - $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2 - continue - ;; - esac - - # Get the absolute pathname. - absdir=`cd "$dir" && pwd` - test -n "$absdir" && dir="$absdir" - - # Now add the directory to shlibpath_var. - if eval "test -z \"\$$shlibpath_var\""; then - eval "$shlibpath_var=\"\$dir\"" - else - eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" - fi - done - - # This variable tells wrapper scripts just to set shlibpath_var - # rather than running their programs. - libtool_execute_magic="$magic" - - # Check if any of the arguments is a wrapper script. - args= - for file - do - case "$file" in - -*) ;; - *) - # Do a test to see if this is really a libtool program. - if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then - # If there is no directory component, then add one. - case "$file" in - */* | *\\*) . $file ;; - *) . ./$file ;; - esac - - # Transform arg to wrapped name. - file="$progdir/$program" - fi - ;; - esac - # Quote arguments (to preserve shell metacharacters). - file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"` - args="$args \"$file\"" - done - - if test -z "$run"; then - if test -n "$shlibpath_var"; then - # Export the shlibpath_var. - eval "export $shlibpath_var" - fi - - # Restore saved enviroment variables - if test "${save_LC_ALL+set}" = set; then - LC_ALL="$save_LC_ALL"; export LC_ALL - fi - if test "${save_LANG+set}" = set; then - LANG="$save_LANG"; export LANG - fi - - # Now actually exec the command. - eval "exec \$cmd$args" - - $echo "$modename: cannot exec \$cmd$args" - exit 1 - else - # Display what would be done. - if test -n "$shlibpath_var"; then - eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\"" - $echo "export $shlibpath_var" - fi - $echo "$cmd$args" - exit 0 - fi - ;; - - # libtool uninstall mode - uninstall) - modename="$modename: uninstall" - rm="$nonopt" - files= - - for arg - do - case "$arg" in - -*) rm="$rm $arg" ;; - *) files="$files $arg" ;; - esac - done - - if test -z "$rm"; then - $echo "$modename: you must specify an RM program" 1>&2 - $echo "$help" 1>&2 - exit 1 - fi - - for file in $files; do - dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` - test "X$dir" = "X$file" && dir=. - name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` - - rmfiles="$file" - - case "$name" in - *.la) - # Possibly a libtool archive, so verify it. - if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then - . $dir/$name - - # Delete the libtool libraries and symlinks. - for n in $library_names; do - rmfiles="$rmfiles $dir/$n" - done - test -n "$old_library" && rmfiles="$rmfiles $dir/$old_library" - - $show "$rm $rmfiles" - $run $rm $rmfiles - - if test -n "$library_names"; then - # Do each command in the postuninstall commands. - eval cmds=\"$postuninstall_cmds\" - IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - $show "$cmd" - $run eval "$cmd" - done - IFS="$save_ifs" - fi - - if test -n "$old_library"; then - # Do each command in the old_postuninstall commands. - eval cmds=\"$old_postuninstall_cmds\" - IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - $show "$cmd" - $run eval "$cmd" - done - IFS="$save_ifs" - fi - - # FIXME: should reinstall the best remaining shared library. - fi - ;; - - *.lo) - if test "$build_old_libs" = yes; then - oldobj=`$echo "X$name" | $Xsed -e "$lo2o"` - rmfiles="$rmfiles $dir/$oldobj" - fi - $show "$rm $rmfiles" - $run $rm $rmfiles - ;; - - *) - $show "$rm $rmfiles" - $run $rm $rmfiles - ;; - esac - done - exit 0 - ;; - - "") - $echo "$modename: you must specify a MODE" 1>&2 - $echo "$generic_help" 1>&2 - exit 1 - ;; - esac - - $echo "$modename: invalid operation mode \`$mode'" 1>&2 - $echo "$generic_help" 1>&2 - exit 1 -fi # test -z "$show_help" - -# We need to display help for each of the modes. -case "$mode" in -"") $echo \ -"Usage: $modename [OPTION]... [MODE-ARG]... - -Provide generalized library-building support services. - - --config show all configuration variables - --debug enable verbose shell tracing --n, --dry-run display commands without modifying any files - --features display basic configuration information and exit - --finish same as \`--mode=finish' - --help display this help message and exit - --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS] - --quiet same as \`--silent' - --silent don't print informational messages - --version print version information - -MODE must be one of the following: - - compile compile a source file into a libtool object - execute automatically set library path, then run a program - finish complete the installation of libtool libraries - install install libraries or executables - link create a library or an executable - uninstall remove libraries from an installed directory - -MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for -a more detailed description of MODE." - exit 0 - ;; - -compile) - $echo \ -"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE - -Compile a source file into a libtool library object. - -This mode accepts the following additional options: - - -o OUTPUT-FILE set the output file name to OUTPUT-FILE - -static always build a \`.o' file suitable for static linking - -COMPILE-COMMAND is a command to be used in creating a \`standard' object file -from the given SOURCEFILE. - -The output file name is determined by removing the directory component from -SOURCEFILE, then substituting the C source code suffix \`.c' with the -library object suffix, \`.lo'." - ;; - -execute) - $echo \ -"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]... - -Automatically set library path, then run a program. - -This mode accepts the following additional options: - - -dlopen FILE add the directory containing FILE to the library path - -This mode sets the library path environment variable according to \`-dlopen' -flags. - -If any of the ARGS are libtool executable wrappers, then they are translated -into their corresponding uninstalled binary, and any of their required library -directories are added to the library path. - -Then, COMMAND is executed, with ARGS as arguments." - ;; - -finish) - $echo \ -"Usage: $modename [OPTION]... --mode=finish [LIBDIR]... - -Complete the installation of libtool libraries. - -Each LIBDIR is a directory that contains libtool libraries. - -The commands that this mode executes may require superuser privileges. Use -the \`--dry-run' option if you just want to see what would be executed." - ;; - -install) - $echo \ -"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND... - -Install executables or libraries. - -INSTALL-COMMAND is the installation command. The first component should be -either the \`install' or \`cp' program. - -The rest of the components are interpreted as arguments to that command (only -BSD-compatible install options are recognized)." - ;; - -link) - $echo \ -"Usage: $modename [OPTION]... --mode=link LINK-COMMAND... - -Link object files or libraries together to form another library, or to -create an executable program. - -LINK-COMMAND is a command using the C compiler that you would use to create -a program from several object files. - -The following components of LINK-COMMAND are treated specially: - - -all-static do not do any dynamic linking at all - -avoid-version do not add a version suffix if possible - -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime - -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols - -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) - -export-symbols SYMFILE - try to export only the symbols listed in SYMFILE - -export-symbols-regex REGEX - try to export only the symbols matching REGEX - -LLIBDIR search LIBDIR for required installed libraries - -lNAME OUTPUT-FILE requires the installed library libNAME - -module build a library that can dlopened - -no-undefined declare that a library does not refer to external symbols - -o OUTPUT-FILE create OUTPUT-FILE from the specified objects - -release RELEASE specify package release information - -rpath LIBDIR the created library will eventually be installed in LIBDIR - -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries - -static do not do any dynamic linking of libtool libraries - -version-info CURRENT[:REVISION[:AGE]] - specify library version info [each variable defaults to 0] - -All other options (arguments beginning with \`-') are ignored. - -Every other argument is treated as a filename. Files ending in \`.la' are -treated as uninstalled libtool libraries, other files are standard or library -object files. - -If the OUTPUT-FILE ends in \`.la', then a libtool library is created, -only library objects (\`.lo' files) may be specified, and \`-rpath' is -required, except when creating a convenience library. - -If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created -using \`ar' and \`ranlib', or on Windows using \`lib'. - -If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file -is created, otherwise an executable program is created." - ;; - -uninstall) - $echo \ -"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... - -Remove libraries from an installation directory. - -RM is the name of the program to use to delete files associated with each FILE -(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed -to RM. - -If FILE is a libtool library, all the files associated with it are deleted. -Otherwise, only FILE itself is deleted using RM." - ;; - -*) - $echo "$modename: invalid operation mode \`$mode'" 1>&2 - $echo "$help" 1>&2 - exit 1 - ;; -esac - -echo -$echo "Try \`$modename --help' for more information about other modes." - -exit 0 - -# Local Variables: -# mode:shell-script -# sh-indentation:2 -# End: diff --git a/config/missing b/config/missing deleted file mode 100755 index 6a37006e..00000000 --- a/config/missing +++ /dev/null @@ -1,336 +0,0 @@ -#! /bin/sh -# Common stub for a few missing GNU programs while installing. -# Copyright (C) 1996, 1997, 1999, 2000, 2002 Free Software Foundation, Inc. -# Originally by Fran,cois Pinard , 1996. - -# 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 2, 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -if test $# -eq 0; then - echo 1>&2 "Try \`$0 --help' for more information" - exit 1 -fi - -run=: - -# In the cases where this matters, `missing' is being run in the -# srcdir already. -if test -f configure.ac; then - configure_ac=configure.ac -else - configure_ac=configure.in -fi - -case "$1" in ---run) - # Try to run requested program, and just exit if it succeeds. - run= - shift - "$@" && exit 0 - ;; -esac - -# If it does not exist, or fails to run (possibly an outdated version), -# try to emulate it. -case "$1" in - - -h|--h|--he|--hel|--help) - echo "\ -$0 [OPTION]... PROGRAM [ARGUMENT]... - -Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an -error status if there is no known handling for PROGRAM. - -Options: - -h, --help display this help and exit - -v, --version output version information and exit - --run try to run the given command, and emulate it if it fails - -Supported PROGRAM values: - aclocal touch file \`aclocal.m4' - autoconf touch file \`configure' - autoheader touch file \`config.h.in' - automake touch all \`Makefile.in' files - bison create \`y.tab.[ch]', if possible, from existing .[ch] - flex create \`lex.yy.c', if possible, from existing .c - help2man touch the output file - lex create \`lex.yy.c', if possible, from existing .c - makeinfo touch the output file - tar try tar, gnutar, gtar, then tar without non-portable flags - yacc create \`y.tab.[ch]', if possible, from existing .[ch]" - ;; - - -v|--v|--ve|--ver|--vers|--versi|--versio|--version) - echo "missing 0.4 - GNU automake" - ;; - - -*) - echo 1>&2 "$0: Unknown \`$1' option" - echo 1>&2 "Try \`$0 --help' for more information" - exit 1 - ;; - - aclocal*) - if test -z "$run" && ($1 --version) > /dev/null 2>&1; then - # We have it, but it failed. - exit 1 - fi - - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified \`acinclude.m4' or \`${configure_ac}'. You might want - to install the \`Automake' and \`Perl' packages. Grab them from - any GNU archive site." - touch aclocal.m4 - ;; - - autoconf) - if test -z "$run" && ($1 --version) > /dev/null 2>&1; then - # We have it, but it failed. - exit 1 - fi - - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified \`${configure_ac}'. You might want to install the - \`Autoconf' and \`GNU m4' packages. Grab them from any GNU - archive site." - touch configure - ;; - - autoheader) - if test -z "$run" && ($1 --version) > /dev/null 2>&1; then - # We have it, but it failed. - exit 1 - fi - - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified \`acconfig.h' or \`${configure_ac}'. You might want - to install the \`Autoconf' and \`GNU m4' packages. Grab them - from any GNU archive site." - files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` - test -z "$files" && files="config.h" - touch_files= - for f in $files; do - case "$f" in - *:*) touch_files="$touch_files "`echo "$f" | - sed -e 's/^[^:]*://' -e 's/:.*//'`;; - *) touch_files="$touch_files $f.in";; - esac - done - touch $touch_files - ;; - - automake*) - if test -z "$run" && ($1 --version) > /dev/null 2>&1; then - # We have it, but it failed. - exit 1 - fi - - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. - You might want to install the \`Automake' and \`Perl' packages. - Grab them from any GNU archive site." - find . -type f -name Makefile.am -print | - sed 's/\.am$/.in/' | - while read f; do touch "$f"; done - ;; - - autom4te) - if test -z "$run" && ($1 --version) > /dev/null 2>&1; then - # We have it, but it failed. - exit 1 - fi - - echo 1>&2 "\ -WARNING: \`$1' is needed, and you do not seem to have it handy on your - system. You might have modified some files without having the - proper tools for further handling them. - You can get \`$1Help2man' as part of \`Autoconf' from any GNU - archive site." - - file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` - test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'` - if test -f "$file"; then - touch $file - else - test -z "$file" || exec >$file - echo "#! /bin/sh" - echo "# Created by GNU Automake missing as a replacement of" - echo "# $ $@" - echo "exit 0" - chmod +x $file - exit 1 - fi - ;; - - bison|yacc) - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified a \`.y' file. You may need the \`Bison' package - in order for those modifications to take effect. You can get - \`Bison' from any GNU archive site." - rm -f y.tab.c y.tab.h - if [ $# -ne 1 ]; then - eval LASTARG="\${$#}" - case "$LASTARG" in - *.y) - SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` - if [ -f "$SRCFILE" ]; then - cp "$SRCFILE" y.tab.c - fi - SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` - if [ -f "$SRCFILE" ]; then - cp "$SRCFILE" y.tab.h - fi - ;; - esac - fi - if [ ! -f y.tab.h ]; then - echo >y.tab.h - fi - if [ ! -f y.tab.c ]; then - echo 'main() { return 0; }' >y.tab.c - fi - ;; - - lex|flex) - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified a \`.l' file. You may need the \`Flex' package - in order for those modifications to take effect. You can get - \`Flex' from any GNU archive site." - rm -f lex.yy.c - if [ $# -ne 1 ]; then - eval LASTARG="\${$#}" - case "$LASTARG" in - *.l) - SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` - if [ -f "$SRCFILE" ]; then - cp "$SRCFILE" lex.yy.c - fi - ;; - esac - fi - if [ ! -f lex.yy.c ]; then - echo 'main() { return 0; }' >lex.yy.c - fi - ;; - - help2man) - if test -z "$run" && ($1 --version) > /dev/null 2>&1; then - # We have it, but it failed. - exit 1 - fi - - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified a dependency of a manual page. You may need the - \`Help2man' package in order for those modifications to take - effect. You can get \`Help2man' from any GNU archive site." - - file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` - if test -z "$file"; then - file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` - fi - if [ -f "$file" ]; then - touch $file - else - test -z "$file" || exec >$file - echo ".ab help2man is required to generate this page" - exit 1 - fi - ;; - - makeinfo) - if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then - # We have makeinfo, but it failed. - exit 1 - fi - - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified a \`.texi' or \`.texinfo' file, or any other file - indirectly affecting the aspect of the manual. The spurious - call might also be the consequence of using a buggy \`make' (AIX, - DU, IRIX). You might want to install the \`Texinfo' package or - the \`GNU make' package. Grab either from any GNU archive site." - file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` - if test -z "$file"; then - file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` - file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` - fi - touch $file - ;; - - tar) - shift - if test -n "$run"; then - echo 1>&2 "ERROR: \`tar' requires --run" - exit 1 - fi - - # We have already tried tar in the generic part. - # Look for gnutar/gtar before invocation to avoid ugly error - # messages. - if (gnutar --version > /dev/null 2>&1); then - gnutar "$@" && exit 0 - fi - if (gtar --version > /dev/null 2>&1); then - gtar "$@" && exit 0 - fi - firstarg="$1" - if shift; then - case "$firstarg" in - *o*) - firstarg=`echo "$firstarg" | sed s/o//` - tar "$firstarg" "$@" && exit 0 - ;; - esac - case "$firstarg" in - *h*) - firstarg=`echo "$firstarg" | sed s/h//` - tar "$firstarg" "$@" && exit 0 - ;; - esac - fi - - echo 1>&2 "\ -WARNING: I can't seem to be able to run \`tar' with the given arguments. - You may want to install GNU tar or Free paxutils, or check the - command line arguments." - exit 1 - ;; - - *) - echo 1>&2 "\ -WARNING: \`$1' is needed, and you do not seem to have it handy on your - system. You might have modified some files without having the - proper tools for further handling them. Check the \`README' file, - it often tells you about the needed prerequirements for installing - this package. You may also peek at any GNU archive site, in case - some other package would contain this missing \`$1' program." - exit 1 - ;; -esac - -exit 0 diff --git a/config/mkinstalldirs b/config/mkinstalldirs deleted file mode 100755 index d2d5f21b..00000000 --- a/config/mkinstalldirs +++ /dev/null @@ -1,111 +0,0 @@ -#! /bin/sh -# mkinstalldirs --- make directory hierarchy -# Author: Noah Friedman -# Created: 1993-05-16 -# Public domain - -errstatus=0 -dirmode="" - -usage="\ -Usage: mkinstalldirs [-h] [--help] [-m mode] dir ..." - -# process command line arguments -while test $# -gt 0 ; do - case $1 in - -h | --help | --h*) # -h for help - echo "$usage" 1>&2 - exit 0 - ;; - -m) # -m PERM arg - shift - test $# -eq 0 && { echo "$usage" 1>&2; exit 1; } - dirmode=$1 - shift - ;; - --) # stop option processing - shift - break - ;; - -*) # unknown option - echo "$usage" 1>&2 - exit 1 - ;; - *) # first non-opt arg - break - ;; - esac -done - -for file -do - if test -d "$file"; then - shift - else - break - fi -done - -case $# in - 0) exit 0 ;; -esac - -case $dirmode in - '') - if mkdir -p -- . 2>/dev/null; then - echo "mkdir -p -- $*" - exec mkdir -p -- "$@" - fi - ;; - *) - if mkdir -m "$dirmode" -p -- . 2>/dev/null; then - echo "mkdir -m $dirmode -p -- $*" - exec mkdir -m "$dirmode" -p -- "$@" - fi - ;; -esac - -for file -do - set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` - shift - - pathcomp= - for d - do - pathcomp="$pathcomp$d" - case $pathcomp in - -*) pathcomp=./$pathcomp ;; - esac - - if test ! -d "$pathcomp"; then - echo "mkdir $pathcomp" - - mkdir "$pathcomp" || lasterr=$? - - if test ! -d "$pathcomp"; then - errstatus=$lasterr - else - if test ! -z "$dirmode"; then - echo "chmod $dirmode $pathcomp" - lasterr="" - chmod "$dirmode" "$pathcomp" || lasterr=$? - - if test ! -z "$lasterr"; then - errstatus=$lasterr - fi - fi - fi - fi - - pathcomp="$pathcomp/" - done -done - -exit $errstatus - -# Local Variables: -# mode: shell-script -# sh-indentation: 2 -# End: -# mkinstalldirs ends here diff --git a/configure.in b/configure.in index 5f750641..06d41d7d 100644 --- a/configure.in +++ b/configure.in @@ -43,6 +43,7 @@ dnl OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. dnl AC_INIT(lib/saslint.h) AC_PREREQ([2.54]) +AC_CONFIG_MACRO_DIR([config]) dnl use ./config.cache as the default cache file. dnl we require a cache file to successfully configure our build. diff --git a/sample/Makefile.in b/sample/Makefile.in deleted file mode 100644 index 29929a8f..00000000 --- a/sample/Makefile.in +++ /dev/null @@ -1,607 +0,0 @@ -# Makefile.in generated by automake 1.11 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, -# Inc. -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -# Makefile.am -- automake input for sample SASL programs -# Rob Earhart -# -################################################################ -# Copyright (c) 2000 Carnegie Mellon University. All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in -# the documentation and/or other materials provided with the -# distribution. -# -# 3. The name "Carnegie Mellon University" must not be used to -# endorse or promote products derived from this software without -# prior written permission. For permission or any other legal -# details, please contact -# Office of Technology Transfer -# Carnegie Mellon University -# 5000 Forbes Avenue -# Pittsburgh, PA 15213-3890 -# (412) 268-4387, fax: (412) 268-7395 -# tech-transfer@andrew.cmu.edu -# -# 4. Redistributions of any form whatsoever must retain the following -# acknowledgment: -# "This product includes software developed by Computing Services -# at Carnegie Mellon University (http://www.cmu.edu/computing/)." -# -# CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO -# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -# AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE -# FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN -# AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING -# OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# -################################################################ - -VPATH = @srcdir@ -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -target_triplet = @target@ -noinst_PROGRAMS = client$(EXEEXT) server$(EXEEXT) -EXTRA_PROGRAMS = sample-client$(EXEEXT) sample-server$(EXEEXT) -EXTRA_DIST = http_digest_client.c -subdir = sample -DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in $(srcdir)/NTMakefile -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/config/kerberos_v4.m4 \ - $(top_srcdir)/config/libtool.m4 $(top_srcdir)/config/plain.m4 \ - $(top_srcdir)/config/sasldb.m4 \ - $(top_srcdir)/cmulocal/berkdb.m4 \ - $(top_srcdir)/cmulocal/bsd_sockets.m4 \ - $(top_srcdir)/cmulocal/c-attribute.m4 \ - $(top_srcdir)/cmulocal/common.m4 \ - $(top_srcdir)/cmulocal/cyrus.m4 \ - $(top_srcdir)/cmulocal/init_automake.m4 \ - $(top_srcdir)/cmulocal/ipv6.m4 \ - $(top_srcdir)/cmulocal/openldap.m4 \ - $(top_srcdir)/cmulocal/openssl.m4 \ - $(top_srcdir)/cmulocal/sasl2.m4 $(top_srcdir)/configure.in -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs -CONFIG_HEADER = $(top_builddir)/config.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_FILES = -PROGRAMS = $(noinst_PROGRAMS) -am_client_OBJECTS = client.$(OBJEXT) common.$(OBJEXT) -client_OBJECTS = $(am_client_OBJECTS) -am__DEPENDENCIES_1 = -client_DEPENDENCIES = ../lib/libsasl2.la $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) -am_sample_client_OBJECTS = sample-client.$(OBJEXT) -sample_client_OBJECTS = $(am_sample_client_OBJECTS) -sample_client_DEPENDENCIES = ../lib/libsasl2.la $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) -am_sample_server_OBJECTS = sample-server.$(OBJEXT) -sample_server_OBJECTS = $(am_sample_server_OBJECTS) -sample_server_DEPENDENCIES = ../lib/libsasl2.la $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) -am_server_OBJECTS = server.$(OBJEXT) common.$(OBJEXT) -server_OBJECTS = $(am_server_OBJECTS) -server_DEPENDENCIES = ../lib/libsasl2.la $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) -DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) -depcomp = $(SHELL) $(top_srcdir)/config/depcomp -am__depfiles_maybe = depfiles -am__mv = mv -f -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ - --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ - $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -CCLD = $(CC) -LINK = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ - $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ -SOURCES = $(client_SOURCES) $(sample_client_SOURCES) \ - $(sample_server_SOURCES) $(server_SOURCES) -DIST_SOURCES = $(client_SOURCES) $(sample_client_SOURCES) \ - $(sample_server_SOURCES) $(server_SOURCES) -ETAGS = etags -CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -AMTAR = @AMTAR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CMU_LIB_SUBDIR = @CMU_LIB_SUBDIR@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DIRS = @DIRS@ -DMALLOC_LIBS = @DMALLOC_LIBS@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -GETADDRINFOOBJS = @GETADDRINFOOBJS@ -GETNAMEINFOOBJS = @GETNAMEINFOOBJS@ -GETSUBOPT = @GETSUBOPT@ -GREP = @GREP@ -GSSAPIBASE_LIBS = @GSSAPIBASE_LIBS@ -GSSAPI_LIBS = @GSSAPI_LIBS@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -IPCTYPE = @IPCTYPE@ -JAVAC = @JAVAC@ -JAVADOC = @JAVADOC@ -JAVAH = @JAVAH@ -JAVAROOT = @JAVAROOT@ -JAVA_INCLUDES = @JAVA_INCLUDES@ -LDFLAGS = @LDFLAGS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LIB_CRYPT = @LIB_CRYPT@ -LIB_DES = @LIB_DES@ -LIB_DOOR = @LIB_DOOR@ -LIB_LDAP = @LIB_LDAP@ -LIB_MYSQL = @LIB_MYSQL@ -LIB_PGSQL = @LIB_PGSQL@ -LIB_SOCKET = @LIB_SOCKET@ -LIB_SQLITE = @LIB_SQLITE@ -LIB_SQLITE3 = @LIB_SQLITE3@ -LN_S = @LN_S@ -LTGETADDRINFOOBJS = @LTGETADDRINFOOBJS@ -LTGETNAMEINFOOBJS = @LTGETNAMEINFOOBJS@ -LTLIBOBJS = @LTLIBOBJS@ -LTSNPRINTFOBJS = @LTSNPRINTFOBJS@ -MAKEINFO = @MAKEINFO@ -MKDIR_P = @MKDIR_P@ -NM = @NM@ -NTLM_LIBS = @NTLM_LIBS@ -OBJEXT = @OBJEXT@ -OTP_LIBS = @OTP_LIBS@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PASSDSS_LIBS = @PASSDSS_LIBS@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PLAIN_LIBS = @PLAIN_LIBS@ -PURECOV = @PURECOV@ -PURIFY = @PURIFY@ -PWCHECKMETH = @PWCHECKMETH@ -RANLIB = @RANLIB@ -SASL_DB_BACKEND = @SASL_DB_BACKEND@ -SASL_DB_BACKEND_STATIC = @SASL_DB_BACKEND_STATIC@ -SASL_DB_INC = @SASL_DB_INC@ -SASL_DB_LIB = @SASL_DB_LIB@ -SASL_DB_MANS = @SASL_DB_MANS@ -SASL_DB_UTILS = @SASL_DB_UTILS@ -SASL_DL_LIB = @SASL_DL_LIB@ -SASL_KRB_LIB = @SASL_KRB_LIB@ -SASL_MECHS = @SASL_MECHS@ -SASL_STATIC_LIBS = @SASL_STATIC_LIBS@ -SASL_STATIC_OBJS = @SASL_STATIC_OBJS@ -SASL_STATIC_SRCS = @SASL_STATIC_SRCS@ -SASL_UTIL_HEADERS_EXTRA = @SASL_UTIL_HEADERS_EXTRA@ -SASL_UTIL_LIBS_EXTRA = @SASL_UTIL_LIBS_EXTRA@ -SCRAM_LIBS = @SCRAM_LIBS@ -SET_MAKE = @SET_MAKE@ -SFIO_INC_FLAGS = @SFIO_INC_FLAGS@ -SFIO_LIB_FLAGS = @SFIO_LIB_FLAGS@ -SHELL = @SHELL@ -SMTPTEST_PROGRAM = @SMTPTEST_PROGRAM@ -SNPRINTFOBJS = @SNPRINTFOBJS@ -SRP_LIBS = @SRP_LIBS@ -STRIP = @STRIP@ -VERSION = @VERSION@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_CC = @ac_ct_CC@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -configdir = @configdir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -plugindir = @plugindir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -subdirs = @subdirs@ -sysconfdir = @sysconfdir@ -target = @target@ -target_alias = @target_alias@ -target_cpu = @target_cpu@ -target_os = @target_os@ -target_vendor = @target_vendor@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -INCLUDES = -I$(top_srcdir)/include -CLEANFILES = sample-client sample-server ./.libs/*sample-client ./.libs/*sample-server -sample_client_SOURCES = sample-client.c -sample_server_SOURCES = sample-server.c -server_SOURCES = server.c common.c common.h -client_SOURCES = client.c common.c common.h -server_LDADD = ../lib/libsasl2.la $(GSSAPIBASE_LIBS) $(GSSAPI_LIBS) $(LIB_SOCKET) -client_LDADD = ../lib/libsasl2.la $(GSSAPIBASE_LIBS) $(GSSAPI_LIBS) $(LIB_SOCKET) -sample_client_LDADD = ../lib/libsasl2.la $(GSSAPIBASE_LIBS) $(GSSAPI_LIBS) $(LIB_SOCKET) -sample_server_LDADD = ../lib/libsasl2.la $(GSSAPIBASE_LIBS) $(GSSAPI_LIBS) $(LIB_SOCKET) -all: all-am - -.SUFFIXES: -.SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu sample/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnu sample/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): - -clean-noinstPROGRAMS: - @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ - echo " rm -f" $$list; \ - rm -f $$list || exit $$?; \ - test -n "$(EXEEXT)" || exit 0; \ - list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ - echo " rm -f" $$list; \ - rm -f $$list -client$(EXEEXT): $(client_OBJECTS) $(client_DEPENDENCIES) - @rm -f client$(EXEEXT) - $(LINK) $(client_OBJECTS) $(client_LDADD) $(LIBS) -sample-client$(EXEEXT): $(sample_client_OBJECTS) $(sample_client_DEPENDENCIES) - @rm -f sample-client$(EXEEXT) - $(LINK) $(sample_client_OBJECTS) $(sample_client_LDADD) $(LIBS) -sample-server$(EXEEXT): $(sample_server_OBJECTS) $(sample_server_DEPENDENCIES) - @rm -f sample-server$(EXEEXT) - $(LINK) $(sample_server_OBJECTS) $(sample_server_LDADD) $(LIBS) -server$(EXEEXT): $(server_OBJECTS) $(server_DEPENDENCIES) - @rm -f server$(EXEEXT) - $(LINK) $(server_OBJECTS) $(server_LDADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/client.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sample-client.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sample-server.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server.Po@am__quote@ - -.c.o: -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c $< - -.c.obj: -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` - -.c.lo: -@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs - -ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - mkid -fID $$unique -tags: TAGS - -TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - set x; \ - here=`pwd`; \ - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: CTAGS -CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - test -z "$(CTAGS_ARGS)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__cd) $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) "$$here" - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile $(PROGRAMS) -installdirs: -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install -mostlyclean-generic: - -clean-generic: - -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ - mostlyclean-am - -distclean: distclean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-compile mostlyclean-generic \ - mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: - -.MAKE: install-am install-strip - -.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ - clean-libtool clean-noinstPROGRAMS ctags distclean \ - distclean-compile distclean-generic distclean-libtool \ - distclean-tags distdir dvi dvi-am html html-am info info-am \ - install install-am install-data install-data-am install-dvi \ - install-dvi-am install-exec install-exec-am install-html \ - install-html-am install-info install-info-am install-man \ - install-pdf install-pdf-am install-ps install-ps-am \ - install-strip installcheck installcheck-am installdirs \ - maintainer-clean maintainer-clean-generic mostlyclean \ - mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ - pdf pdf-am ps ps-am tags uninstall uninstall-am - - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/saslauthd/Makefile.am b/saslauthd/Makefile.am index ce1e92bc..894322a4 100644 --- a/saslauthd/Makefile.am +++ b/saslauthd/Makefile.am @@ -15,7 +15,7 @@ saslauthd_SOURCES = mechanisms.c globals.h \ EXTRA_saslauthd_sources = getaddrinfo.c getnameinfo.c saslauthd_DEPENDENCIES = saslauthd-main.o @LTLIBOBJS@ saslauthd_LDADD = @SASL_KRB_LIB@ \ - @GSSAPIBASE_LIBS@ @GSSAPI_LIBS@ @LIB_CRYPT@ @LIB_SIA@ \ + @GSSAPIBASE_LIBS@ @LIB_CRYPT@ @LIB_SIA@ \ @LIB_SOCKET@ @SASL_DB_LIB@ @LIB_PAM@ @LDAP_LIBS@ @LTLIBOBJS@ testsaslauthd_SOURCES = testsaslauthd.c utils.c diff --git a/saslauthd/config/config.guess b/saslauthd/config/config.guess deleted file mode 100755 index f7dd69ec..00000000 --- a/saslauthd/config/config.guess +++ /dev/null @@ -1,1516 +0,0 @@ -#! /bin/sh -# Attempt to guess a canonical system name. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, -# 2011 Free Software Foundation, Inc. - -timestamp='2011-08-20' - -# This file 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 2 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, write to the Free Software -# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA -# 02110-1301, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - - -# Originally written by Per Bothner. Please send patches (context -# diff format) to and include a ChangeLog -# entry. -# -# This script attempts to guess a canonical system name similar to -# config.sub. If it succeeds, it prints the system name on stdout, and -# exits with 0. Otherwise, it exits with 1. -# -# You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] - -Output the configuration name of the system \`$me' is run on. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.guess ($timestamp) - -Originally written by Per Bothner. -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, -2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free -Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" >&2 - exit 1 ;; - * ) - break ;; - esac -done - -if test $# != 0; then - echo "$me: too many arguments$help" >&2 - exit 1 -fi - -trap 'exit 1' 1 2 15 - -# CC_FOR_BUILD -- compiler used by this script. Note that the use of a -# compiler to aid in system detection is discouraged as it requires -# temporary files to be created and, as you can see below, it is a -# headache to deal with in a portable fashion. - -# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still -# use `HOST_CC' if defined, but it is deprecated. - -# Portable tmp directory creation inspired by the Autoconf team. - -set_cc_for_build=' -trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; -trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; -: ${TMPDIR=/tmp} ; - { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || - { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || - { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || - { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; -dummy=$tmp/dummy ; -tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; -case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int x;" > $dummy.c ; - for c in cc gcc c89 c99 ; do - if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then - CC_FOR_BUILD="$c"; break ; - fi ; - done ; - if test x"$CC_FOR_BUILD" = x ; then - CC_FOR_BUILD=no_compiler_found ; - fi - ;; - ,,*) CC_FOR_BUILD=$CC ;; - ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac ; set_cc_for_build= ;' - -# This is needed to find uname on a Pyramid OSx when run in the BSD universe. -# (ghazi@noc.rutgers.edu 1994-08-24) -if (test -f /.attbin/uname) >/dev/null 2>&1 ; then - PATH=$PATH:/.attbin ; export PATH -fi - -UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown -UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown -UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown -UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown - -# Note: order is significant - the case branches are not exclusive. - -case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in - *:NetBSD:*:*) - # NetBSD (nbsd) targets should (where applicable) match one or - # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, - # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently - # switched to ELF, *-*-netbsd* would select the old - # object file format. This provides both forward - # compatibility and a consistent mechanism for selecting the - # object file format. - # - # Note: NetBSD doesn't particularly care about the vendor - # portion of the name. We always set it to "unknown". - sysctl="sysctl -n hw.machine_arch" - UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ - /usr/sbin/$sysctl 2>/dev/null || echo unknown)` - case "${UNAME_MACHINE_ARCH}" in - armeb) machine=armeb-unknown ;; - arm*) machine=arm-unknown ;; - sh3el) machine=shl-unknown ;; - sh3eb) machine=sh-unknown ;; - sh5el) machine=sh5le-unknown ;; - *) machine=${UNAME_MACHINE_ARCH}-unknown ;; - esac - # The Operating System including object format, if it has switched - # to ELF recently, or will in the future. - case "${UNAME_MACHINE_ARCH}" in - arm*|i386|m68k|ns32k|sh3*|sparc|vax) - eval $set_cc_for_build - if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ELF__ - then - # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). - # Return netbsd for either. FIX? - os=netbsd - else - os=netbsdelf - fi - ;; - *) - os=netbsd - ;; - esac - # The OS release - # Debian GNU/NetBSD machines have a different userland, and - # thus, need a distinct triplet. However, they do not need - # kernel version information, so it can be replaced with a - # suitable tag, in the style of linux-gnu. - case "${UNAME_VERSION}" in - Debian*) - release='-gnu' - ;; - *) - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` - ;; - esac - # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: - # contains redundant information, the shorter form: - # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}" - exit ;; - *:OpenBSD:*:*) - UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} - exit ;; - *:ekkoBSD:*:*) - echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} - exit ;; - *:SolidBSD:*:*) - echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} - exit ;; - macppc:MirBSD:*:*) - echo powerpc-unknown-mirbsd${UNAME_RELEASE} - exit ;; - *:MirBSD:*:*) - echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} - exit ;; - alpha:OSF1:*:*) - case $UNAME_RELEASE in - *4.0) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` - ;; - *5.*) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` - ;; - esac - # According to Compaq, /usr/sbin/psrinfo has been available on - # OSF/1 and Tru64 systems produced since 1995. I hope that - # covers most systems running today. This code pipes the CPU - # types through head -n 1, so we only detect the type of CPU 0. - ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` - case "$ALPHA_CPU_TYPE" in - "EV4 (21064)") - UNAME_MACHINE="alpha" ;; - "EV4.5 (21064)") - UNAME_MACHINE="alpha" ;; - "LCA4 (21066/21068)") - UNAME_MACHINE="alpha" ;; - "EV5 (21164)") - UNAME_MACHINE="alphaev5" ;; - "EV5.6 (21164A)") - UNAME_MACHINE="alphaev56" ;; - "EV5.6 (21164PC)") - UNAME_MACHINE="alphapca56" ;; - "EV5.7 (21164PC)") - UNAME_MACHINE="alphapca57" ;; - "EV6 (21264)") - UNAME_MACHINE="alphaev6" ;; - "EV6.7 (21264A)") - UNAME_MACHINE="alphaev67" ;; - "EV6.8CB (21264C)") - UNAME_MACHINE="alphaev68" ;; - "EV6.8AL (21264B)") - UNAME_MACHINE="alphaev68" ;; - "EV6.8CX (21264D)") - UNAME_MACHINE="alphaev68" ;; - "EV6.9A (21264/EV69A)") - UNAME_MACHINE="alphaev69" ;; - "EV7 (21364)") - UNAME_MACHINE="alphaev7" ;; - "EV7.9 (21364A)") - UNAME_MACHINE="alphaev79" ;; - esac - # A Pn.n version is a patched version. - # A Vn.n version is a released version. - # A Tn.n version is a released field test version. - # A Xn.n version is an unreleased experimental baselevel. - # 1.2 uses "1.2" for uname -r. - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - # Reset EXIT trap before exiting to avoid spurious non-zero exit code. - exitcode=$? - trap '' 0 - exit $exitcode ;; - Alpha\ *:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # Should we change UNAME_MACHINE based on the output of uname instead - # of the specific Alpha model? - echo alpha-pc-interix - exit ;; - 21064:Windows_NT:50:3) - echo alpha-dec-winnt3.5 - exit ;; - Amiga*:UNIX_System_V:4.0:*) - echo m68k-unknown-sysv4 - exit ;; - *:[Aa]miga[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-amigaos - exit ;; - *:[Mm]orph[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-morphos - exit ;; - *:OS/390:*:*) - echo i370-ibm-openedition - exit ;; - *:z/VM:*:*) - echo s390-ibm-zvmoe - exit ;; - *:OS400:*:*) - echo powerpc-ibm-os400 - exit ;; - arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix${UNAME_RELEASE} - exit ;; - arm:riscos:*:*|arm:RISCOS:*:*) - echo arm-unknown-riscos - exit ;; - SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) - echo hppa1.1-hitachi-hiuxmpp - exit ;; - Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) - # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. - if test "`(/bin/universe) 2>/dev/null`" = att ; then - echo pyramid-pyramid-sysv3 - else - echo pyramid-pyramid-bsd - fi - exit ;; - NILE*:*:*:dcosx) - echo pyramid-pyramid-svr4 - exit ;; - DRS?6000:unix:4.0:6*) - echo sparc-icl-nx6 - exit ;; - DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) - case `/usr/bin/uname -p` in - sparc) echo sparc-icl-nx7; exit ;; - esac ;; - s390x:SunOS:*:*) - echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) - echo i386-pc-auroraux${UNAME_RELEASE} - exit ;; - i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) - eval $set_cc_for_build - SUN_ARCH="i386" - # If there is a compiler, see if it is configured for 64-bit objects. - # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. - # This test works for both compilers. - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then - if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - SUN_ARCH="x86_64" - fi - fi - echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:6*:*) - # According to config.sub, this is the proper way to canonicalize - # SunOS6. Hard to guess exactly what SunOS6 will be like, but - # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:*:*) - case "`/usr/bin/arch -k`" in - Series*|S4*) - UNAME_RELEASE=`uname -v` - ;; - esac - # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` - exit ;; - sun3*:SunOS:*:*) - echo m68k-sun-sunos${UNAME_RELEASE} - exit ;; - sun*:*:4.2BSD:*) - UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 - case "`/bin/arch`" in - sun3) - echo m68k-sun-sunos${UNAME_RELEASE} - ;; - sun4) - echo sparc-sun-sunos${UNAME_RELEASE} - ;; - esac - exit ;; - aushp:SunOS:*:*) - echo sparc-auspex-sunos${UNAME_RELEASE} - exit ;; - # The situation for MiNT is a little confusing. The machine name - # can be virtually everything (everything which is not - # "atarist" or "atariste" at least should have a processor - # > m68000). The system name ranges from "MiNT" over "FreeMiNT" - # to the lowercase version "mint" (or "freemint"). Finally - # the system name "TOS" denotes a system which is actually not - # MiNT. But MiNT is downward compatible to TOS, so this should - # be no problem. - atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} - exit ;; - hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} - exit ;; - *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} - exit ;; - m68k:machten:*:*) - echo m68k-apple-machten${UNAME_RELEASE} - exit ;; - powerpc:machten:*:*) - echo powerpc-apple-machten${UNAME_RELEASE} - exit ;; - RISC*:Mach:*:*) - echo mips-dec-mach_bsd4.3 - exit ;; - RISC*:ULTRIX:*:*) - echo mips-dec-ultrix${UNAME_RELEASE} - exit ;; - VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix${UNAME_RELEASE} - exit ;; - 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix${UNAME_RELEASE} - exit ;; - mips:*:*:UMIPS | mips:*:*:RISCos) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c -#ifdef __cplusplus -#include /* for printf() prototype */ - int main (int argc, char *argv[]) { -#else - int main (argc, argv) int argc; char *argv[]; { -#endif - #if defined (host_mips) && defined (MIPSEB) - #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_SVR4) - printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) - printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); - #endif - #endif - exit (-1); - } -EOF - $CC_FOR_BUILD -o $dummy $dummy.c && - dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && - SYSTEM_NAME=`$dummy $dummyarg` && - { echo "$SYSTEM_NAME"; exit; } - echo mips-mips-riscos${UNAME_RELEASE} - exit ;; - Motorola:PowerMAX_OS:*:*) - echo powerpc-motorola-powermax - exit ;; - Motorola:*:4.3:PL8-*) - echo powerpc-harris-powermax - exit ;; - Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) - echo powerpc-harris-powermax - exit ;; - Night_Hawk:Power_UNIX:*:*) - echo powerpc-harris-powerunix - exit ;; - m88k:CX/UX:7*:*) - echo m88k-harris-cxux7 - exit ;; - m88k:*:4*:R4*) - echo m88k-motorola-sysv4 - exit ;; - m88k:*:3*:R3*) - echo m88k-motorola-sysv3 - exit ;; - AViiON:dgux:*:*) - # DG/UX returns AViiON for all architectures - UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] - then - if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ - [ ${TARGET_BINARY_INTERFACE}x = x ] - then - echo m88k-dg-dgux${UNAME_RELEASE} - else - echo m88k-dg-dguxbcs${UNAME_RELEASE} - fi - else - echo i586-dg-dgux${UNAME_RELEASE} - fi - exit ;; - M88*:DolphinOS:*:*) # DolphinOS (SVR3) - echo m88k-dolphin-sysv3 - exit ;; - M88*:*:R3*:*) - # Delta 88k system running SVR3 - echo m88k-motorola-sysv3 - exit ;; - XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) - echo m88k-tektronix-sysv3 - exit ;; - Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) - echo m68k-tektronix-bsd - exit ;; - *:IRIX*:*:*) - echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` - exit ;; - ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. - echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id - exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' - i*86:AIX:*:*) - echo i386-ibm-aix - exit ;; - ia64:AIX:*:*) - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} - exit ;; - *:AIX:2:3) - if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - - main() - { - if (!__power_pc()) - exit(1); - puts("powerpc-ibm-aix3.2.5"); - exit(0); - } -EOF - if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` - then - echo "$SYSTEM_NAME" - else - echo rs6000-ibm-aix3.2.5 - fi - elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then - echo rs6000-ibm-aix3.2.4 - else - echo rs6000-ibm-aix3.2 - fi - exit ;; - *:AIX:*:[4567]) - IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` - if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then - IBM_ARCH=rs6000 - else - IBM_ARCH=powerpc - fi - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${IBM_ARCH}-ibm-aix${IBM_REV} - exit ;; - *:AIX:*:*) - echo rs6000-ibm-aix - exit ;; - ibmrt:4.4BSD:*|romp-ibm:BSD:*) - echo romp-ibm-bsd4.4 - exit ;; - ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to - exit ;; # report: romp-ibm BSD 4.3 - *:BOSX:*:*) - echo rs6000-bull-bosx - exit ;; - DPX/2?00:B.O.S.:*:*) - echo m68k-bull-sysv3 - exit ;; - 9000/[34]??:4.3bsd:1.*:*) - echo m68k-hp-bsd - exit ;; - hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) - echo m68k-hp-bsd4.4 - exit ;; - 9000/[34678]??:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - case "${UNAME_MACHINE}" in - 9000/31? ) HP_ARCH=m68000 ;; - 9000/[34]?? ) HP_ARCH=m68k ;; - 9000/[678][0-9][0-9]) - if [ -x /usr/bin/getconf ]; then - sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` - sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in - 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 - 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 - 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in - 32) HP_ARCH="hppa2.0n" ;; - 64) HP_ARCH="hppa2.0w" ;; - '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 - esac ;; - esac - fi - if [ "${HP_ARCH}" = "" ]; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - - #define _HPUX_SOURCE - #include - #include - - int main () - { - #if defined(_SC_KERNEL_BITS) - long bits = sysconf(_SC_KERNEL_BITS); - #endif - long cpu = sysconf (_SC_CPU_VERSION); - - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1"); break; - case CPU_PA_RISC2_0: - #if defined(_SC_KERNEL_BITS) - switch (bits) - { - case 64: puts ("hppa2.0w"); break; - case 32: puts ("hppa2.0n"); break; - default: puts ("hppa2.0"); break; - } break; - #else /* !defined(_SC_KERNEL_BITS) */ - puts ("hppa2.0"); break; - #endif - default: puts ("hppa1.0"); break; - } - exit (0); - } -EOF - (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` - test -z "$HP_ARCH" && HP_ARCH=hppa - fi ;; - esac - if [ ${HP_ARCH} = "hppa2.0w" ] - then - eval $set_cc_for_build - - # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating - # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler - # generating 64-bit code. GNU and HP use different nomenclature: - # - # $ CC_FOR_BUILD=cc ./config.guess - # => hppa2.0w-hp-hpux11.23 - # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess - # => hppa64-hp-hpux11.23 - - if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | - grep -q __LP64__ - then - HP_ARCH="hppa2.0w" - else - HP_ARCH="hppa64" - fi - fi - echo ${HP_ARCH}-hp-hpux${HPUX_REV} - exit ;; - ia64:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - echo ia64-hp-hpux${HPUX_REV} - exit ;; - 3050*:HI-UX:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - int - main () - { - long cpu = sysconf (_SC_CPU_VERSION); - /* The order matters, because CPU_IS_HP_MC68K erroneously returns - true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct - results, however. */ - if (CPU_IS_PA_RISC (cpu)) - { - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; - case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; - default: puts ("hppa-hitachi-hiuxwe2"); break; - } - } - else if (CPU_IS_HP_MC68K (cpu)) - puts ("m68k-hitachi-hiuxwe2"); - else puts ("unknown-hitachi-hiuxwe2"); - exit (0); - } -EOF - $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && - { echo "$SYSTEM_NAME"; exit; } - echo unknown-hitachi-hiuxwe2 - exit ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) - echo hppa1.1-hp-bsd - exit ;; - 9000/8??:4.3bsd:*:*) - echo hppa1.0-hp-bsd - exit ;; - *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) - echo hppa1.0-hp-mpeix - exit ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) - echo hppa1.1-hp-osf - exit ;; - hp8??:OSF1:*:*) - echo hppa1.0-hp-osf - exit ;; - i*86:OSF1:*:*) - if [ -x /usr/sbin/sysversion ] ; then - echo ${UNAME_MACHINE}-unknown-osf1mk - else - echo ${UNAME_MACHINE}-unknown-osf1 - fi - exit ;; - parisc*:Lites*:*:*) - echo hppa1.1-hp-lites - exit ;; - C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) - echo c1-convex-bsd - exit ;; - C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) - echo c34-convex-bsd - exit ;; - C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) - echo c38-convex-bsd - exit ;; - C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) - echo c4-convex-bsd - exit ;; - CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*[A-Z]90:*:*:*) - echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ - | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ - -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ - -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*TS:*:*:*) - echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*SV1:*:*:*) - echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - *:UNICOS/mp:*:*) - echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` - echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; - 5000:UNIX_System_V:4.*:*) - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` - echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; - i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} - exit ;; - sparc*:BSD/OS:*:*) - echo sparc-unknown-bsdi${UNAME_RELEASE} - exit ;; - *:BSD/OS:*:*) - echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} - exit ;; - *:FreeBSD:*:*) - UNAME_PROCESSOR=`/usr/bin/uname -p` - case ${UNAME_PROCESSOR} in - amd64) - echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - *) - echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - esac - exit ;; - i*:CYGWIN*:*) - echo ${UNAME_MACHINE}-pc-cygwin - exit ;; - *:MINGW*:*) - echo ${UNAME_MACHINE}-pc-mingw32 - exit ;; - i*:windows32*:*) - # uname -m includes "-pc" on this system. - echo ${UNAME_MACHINE}-mingw32 - exit ;; - i*:PW*:*) - echo ${UNAME_MACHINE}-pc-pw32 - exit ;; - *:Interix*:*) - case ${UNAME_MACHINE} in - x86) - echo i586-pc-interix${UNAME_RELEASE} - exit ;; - authenticamd | genuineintel | EM64T) - echo x86_64-unknown-interix${UNAME_RELEASE} - exit ;; - IA64) - echo ia64-unknown-interix${UNAME_RELEASE} - exit ;; - esac ;; - [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) - echo i${UNAME_MACHINE}-pc-mks - exit ;; - 8664:Windows_NT:*) - echo x86_64-pc-mks - exit ;; - i*:Windows_NT*:* | Pentium*:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we - # UNAME_MACHINE based on the output of uname instead of i386? - echo i586-pc-interix - exit ;; - i*:UWIN*:*) - echo ${UNAME_MACHINE}-pc-uwin - exit ;; - amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) - echo x86_64-unknown-cygwin - exit ;; - p*:CYGWIN*:*) - echo powerpcle-unknown-cygwin - exit ;; - prep*:SunOS:5.*:*) - echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - *:GNU:*:*) - # the GNU system - echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` - exit ;; - *:GNU/*:*:*) - # other systems with GNU libc and userland - echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu - exit ;; - i*86:Minix:*:*) - echo ${UNAME_MACHINE}-pc-minix - exit ;; - alpha:Linux:*:*) - case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in - EV5) UNAME_MACHINE=alphaev5 ;; - EV56) UNAME_MACHINE=alphaev56 ;; - PCA56) UNAME_MACHINE=alphapca56 ;; - PCA57) UNAME_MACHINE=alphapca56 ;; - EV6) UNAME_MACHINE=alphaev6 ;; - EV67) UNAME_MACHINE=alphaev67 ;; - EV68*) UNAME_MACHINE=alphaev68 ;; - esac - objdump --private-headers /bin/sh | grep -q ld.so.1 - if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi - echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} - exit ;; - arm*:Linux:*:*) - eval $set_cc_for_build - if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_EABI__ - then - echo ${UNAME_MACHINE}-unknown-linux-gnu - else - if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_PCS_VFP - then - echo ${UNAME_MACHINE}-unknown-linux-gnueabi - else - echo ${UNAME_MACHINE}-unknown-linux-gnueabihf - fi - fi - exit ;; - avr32*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - cris:Linux:*:*) - echo cris-axis-linux-gnu - exit ;; - crisv32:Linux:*:*) - echo crisv32-axis-linux-gnu - exit ;; - frv:Linux:*:*) - echo frv-unknown-linux-gnu - exit ;; - i*86:Linux:*:*) - LIBC=gnu - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #ifdef __dietlibc__ - LIBC=dietlibc - #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` - echo "${UNAME_MACHINE}-pc-linux-${LIBC}" - exit ;; - ia64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - m32r*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - m68*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - mips:Linux:*:* | mips64:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #undef CPU - #undef ${UNAME_MACHINE} - #undef ${UNAME_MACHINE}el - #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=${UNAME_MACHINE}el - #else - #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=${UNAME_MACHINE} - #else - CPU= - #endif - #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` - test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } - ;; - or32:Linux:*:*) - echo or32-unknown-linux-gnu - exit ;; - padre:Linux:*:*) - echo sparc-unknown-linux-gnu - exit ;; - parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-gnu - exit ;; - parisc:Linux:*:* | hppa:Linux:*:*) - # Look for CPU level - case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-unknown-linux-gnu ;; - PA8*) echo hppa2.0-unknown-linux-gnu ;; - *) echo hppa-unknown-linux-gnu ;; - esac - exit ;; - ppc64:Linux:*:*) - echo powerpc64-unknown-linux-gnu - exit ;; - ppc:Linux:*:*) - echo powerpc-unknown-linux-gnu - exit ;; - s390:Linux:*:* | s390x:Linux:*:*) - echo ${UNAME_MACHINE}-ibm-linux - exit ;; - sh64*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - sh*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - sparc:Linux:*:* | sparc64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - tile*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - vax:Linux:*:*) - echo ${UNAME_MACHINE}-dec-linux-gnu - exit ;; - x86_64:Linux:*:*) - echo x86_64-unknown-linux-gnu - exit ;; - xtensa*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - i*86:DYNIX/ptx:4*:*) - # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. - # earlier versions are messed up and put the nodename in both - # sysname and nodename. - echo i386-sequent-sysv4 - exit ;; - i*86:UNIX_SV:4.2MP:2.*) - # Unixware is an offshoot of SVR4, but it has its own version - # number series starting with 2... - # I am not positive that other SVR4 systems won't match this, - # I just have to hope. -- rms. - # Use sysv4.2uw... so that sysv4* matches it. - echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} - exit ;; - i*86:OS/2:*:*) - # If we were able to find `uname', then EMX Unix compatibility - # is probably installed. - echo ${UNAME_MACHINE}-pc-os2-emx - exit ;; - i*86:XTS-300:*:STOP) - echo ${UNAME_MACHINE}-unknown-stop - exit ;; - i*86:atheos:*:*) - echo ${UNAME_MACHINE}-unknown-atheos - exit ;; - i*86:syllable:*:*) - echo ${UNAME_MACHINE}-pc-syllable - exit ;; - i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) - echo i386-unknown-lynxos${UNAME_RELEASE} - exit ;; - i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp - exit ;; - i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) - UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` - if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} - else - echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} - fi - exit ;; - i*86:*:5:[678]*) - # UnixWare 7.x, OpenUNIX and OpenServer 6. - case `/bin/uname -X | grep "^Machine"` in - *486*) UNAME_MACHINE=i486 ;; - *Pentium) UNAME_MACHINE=i586 ;; - *Pent*|*Celeron) UNAME_MACHINE=i686 ;; - esac - echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} - exit ;; - i*86:*:3.2:*) - if test -f /usr/options/cb.name; then - UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then - UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` - (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 - (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ - && UNAME_MACHINE=i586 - (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ - && UNAME_MACHINE=i686 - (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ - && UNAME_MACHINE=i686 - echo ${UNAME_MACHINE}-pc-sco$UNAME_REL - else - echo ${UNAME_MACHINE}-pc-sysv32 - fi - exit ;; - pc:*:*:*) - # Left here for compatibility: - # uname -m prints for DJGPP always 'pc', but it prints nothing about - # the processor, so we play safe by assuming i586. - # Note: whatever this is, it MUST be the same as what config.sub - # prints for the "djgpp" host, or else GDB configury will decide that - # this is a cross-build. - echo i586-pc-msdosdjgpp - exit ;; - Intel:Mach:3*:*) - echo i386-pc-mach3 - exit ;; - paragon:*:*:*) - echo i860-intel-osf1 - exit ;; - i860:*:4.*:*) # i860-SVR4 - if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 - else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 - fi - exit ;; - mini*:CTIX:SYS*5:*) - # "miniframe" - echo m68010-convergent-sysv - exit ;; - mc68k:UNIX:SYSTEM5:3.51m) - echo m68k-convergent-sysv - exit ;; - M680?0:D-NIX:5.3:*) - echo m68k-diab-dnix - exit ;; - M68*:*:R3V[5678]*:*) - test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; - 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) - OS_REL='' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; - 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4; exit; } ;; - NCR*:*:4.2:* | MPRAS*:*:4.2:*) - OS_REL='.3' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; - m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - echo m68k-unknown-lynxos${UNAME_RELEASE} - exit ;; - mc68030:UNIX_System_V:4.*:*) - echo m68k-atari-sysv4 - exit ;; - TSUNAMI:LynxOS:2.*:*) - echo sparc-unknown-lynxos${UNAME_RELEASE} - exit ;; - rs6000:LynxOS:2.*:*) - echo rs6000-unknown-lynxos${UNAME_RELEASE} - exit ;; - PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) - echo powerpc-unknown-lynxos${UNAME_RELEASE} - exit ;; - SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv${UNAME_RELEASE} - exit ;; - RM*:ReliantUNIX-*:*:*) - echo mips-sni-sysv4 - exit ;; - RM*:SINIX-*:*:*) - echo mips-sni-sysv4 - exit ;; - *:SINIX-*:*:*) - if uname -p 2>/dev/null >/dev/null ; then - UNAME_MACHINE=`(uname -p) 2>/dev/null` - echo ${UNAME_MACHINE}-sni-sysv4 - else - echo ns32k-sni-sysv - fi - exit ;; - PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort - # says - echo i586-unisys-sysv4 - exit ;; - *:UNIX_System_V:4*:FTX*) - # From Gerald Hewes . - # How about differentiating between stratus architectures? -djm - echo hppa1.1-stratus-sysv4 - exit ;; - *:*:*:FTX*) - # From seanf@swdc.stratus.com. - echo i860-stratus-sysv4 - exit ;; - i*86:VOS:*:*) - # From Paul.Green@stratus.com. - echo ${UNAME_MACHINE}-stratus-vos - exit ;; - *:VOS:*:*) - # From Paul.Green@stratus.com. - echo hppa1.1-stratus-vos - exit ;; - mc68*:A/UX:*:*) - echo m68k-apple-aux${UNAME_RELEASE} - exit ;; - news*:NEWS-OS:6*:*) - echo mips-sony-newsos6 - exit ;; - R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) - if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} - else - echo mips-unknown-sysv${UNAME_RELEASE} - fi - exit ;; - BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. - echo powerpc-be-beos - exit ;; - BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. - echo powerpc-apple-beos - exit ;; - BePC:BeOS:*:*) # BeOS running on Intel PC compatible. - echo i586-pc-beos - exit ;; - BePC:Haiku:*:*) # Haiku running on Intel PC compatible. - echo i586-pc-haiku - exit ;; - SX-4:SUPER-UX:*:*) - echo sx4-nec-superux${UNAME_RELEASE} - exit ;; - SX-5:SUPER-UX:*:*) - echo sx5-nec-superux${UNAME_RELEASE} - exit ;; - SX-6:SUPER-UX:*:*) - echo sx6-nec-superux${UNAME_RELEASE} - exit ;; - SX-7:SUPER-UX:*:*) - echo sx7-nec-superux${UNAME_RELEASE} - exit ;; - SX-8:SUPER-UX:*:*) - echo sx8-nec-superux${UNAME_RELEASE} - exit ;; - SX-8R:SUPER-UX:*:*) - echo sx8r-nec-superux${UNAME_RELEASE} - exit ;; - Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody${UNAME_RELEASE} - exit ;; - *:Rhapsody:*:*) - echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} - exit ;; - *:Darwin:*:*) - UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown - case $UNAME_PROCESSOR in - i386) - eval $set_cc_for_build - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then - if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - UNAME_PROCESSOR="x86_64" - fi - fi ;; - unknown) UNAME_PROCESSOR=powerpc ;; - esac - echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} - exit ;; - *:procnto*:*:* | *:QNX:[0123456789]*:*) - UNAME_PROCESSOR=`uname -p` - if test "$UNAME_PROCESSOR" = "x86"; then - UNAME_PROCESSOR=i386 - UNAME_MACHINE=pc - fi - echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} - exit ;; - *:QNX:*:4*) - echo i386-pc-qnx - exit ;; - NEO-?:NONSTOP_KERNEL:*:*) - echo neo-tandem-nsk${UNAME_RELEASE} - exit ;; - NSE-?:NONSTOP_KERNEL:*:*) - echo nse-tandem-nsk${UNAME_RELEASE} - exit ;; - NSR-?:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk${UNAME_RELEASE} - exit ;; - *:NonStop-UX:*:*) - echo mips-compaq-nonstopux - exit ;; - BS2000:POSIX*:*:*) - echo bs2000-siemens-sysv - exit ;; - DS/*:UNIX_System_V:*:*) - echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} - exit ;; - *:Plan9:*:*) - # "uname -m" is not consistent, so use $cputype instead. 386 - # is converted to i386 for consistency with other x86 - # operating systems. - if test "$cputype" = "386"; then - UNAME_MACHINE=i386 - else - UNAME_MACHINE="$cputype" - fi - echo ${UNAME_MACHINE}-unknown-plan9 - exit ;; - *:TOPS-10:*:*) - echo pdp10-unknown-tops10 - exit ;; - *:TENEX:*:*) - echo pdp10-unknown-tenex - exit ;; - KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) - echo pdp10-dec-tops20 - exit ;; - XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) - echo pdp10-xkl-tops20 - exit ;; - *:TOPS-20:*:*) - echo pdp10-unknown-tops20 - exit ;; - *:ITS:*:*) - echo pdp10-unknown-its - exit ;; - SEI:*:*:SEIUX) - echo mips-sei-seiux${UNAME_RELEASE} - exit ;; - *:DragonFly:*:*) - echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` - exit ;; - *:*VMS:*:*) - UNAME_MACHINE=`(uname -p) 2>/dev/null` - case "${UNAME_MACHINE}" in - A*) echo alpha-dec-vms ; exit ;; - I*) echo ia64-dec-vms ; exit ;; - V*) echo vax-dec-vms ; exit ;; - esac ;; - *:XENIX:*:SysV) - echo i386-pc-xenix - exit ;; - i*86:skyos:*:*) - echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' - exit ;; - i*86:rdos:*:*) - echo ${UNAME_MACHINE}-pc-rdos - exit ;; - i*86:AROS:*:*) - echo ${UNAME_MACHINE}-pc-aros - exit ;; -esac - -#echo '(No uname command or uname output not recognized.)' 1>&2 -#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 - -eval $set_cc_for_build -cat >$dummy.c < -# include -#endif -main () -{ -#if defined (sony) -#if defined (MIPSEB) - /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, - I don't know.... */ - printf ("mips-sony-bsd\n"); exit (0); -#else -#include - printf ("m68k-sony-newsos%s\n", -#ifdef NEWSOS4 - "4" -#else - "" -#endif - ); exit (0); -#endif -#endif - -#if defined (__arm) && defined (__acorn) && defined (__unix) - printf ("arm-acorn-riscix\n"); exit (0); -#endif - -#if defined (hp300) && !defined (hpux) - printf ("m68k-hp-bsd\n"); exit (0); -#endif - -#if defined (NeXT) -#if !defined (__ARCHITECTURE__) -#define __ARCHITECTURE__ "m68k" -#endif - int version; - version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; - if (version < 4) - printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); - else - printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); - exit (0); -#endif - -#if defined (MULTIMAX) || defined (n16) -#if defined (UMAXV) - printf ("ns32k-encore-sysv\n"); exit (0); -#else -#if defined (CMU) - printf ("ns32k-encore-mach\n"); exit (0); -#else - printf ("ns32k-encore-bsd\n"); exit (0); -#endif -#endif -#endif - -#if defined (__386BSD__) - printf ("i386-pc-bsd\n"); exit (0); -#endif - -#if defined (sequent) -#if defined (i386) - printf ("i386-sequent-dynix\n"); exit (0); -#endif -#if defined (ns32000) - printf ("ns32k-sequent-dynix\n"); exit (0); -#endif -#endif - -#if defined (_SEQUENT_) - struct utsname un; - - uname(&un); - - if (strncmp(un.version, "V2", 2) == 0) { - printf ("i386-sequent-ptx2\n"); exit (0); - } - if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ - printf ("i386-sequent-ptx1\n"); exit (0); - } - printf ("i386-sequent-ptx\n"); exit (0); - -#endif - -#if defined (vax) -# if !defined (ultrix) -# include -# if defined (BSD) -# if BSD == 43 - printf ("vax-dec-bsd4.3\n"); exit (0); -# else -# if BSD == 199006 - printf ("vax-dec-bsd4.3reno\n"); exit (0); -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# endif -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# else - printf ("vax-dec-ultrix\n"); exit (0); -# endif -#endif - -#if defined (alliant) && defined (i860) - printf ("i860-alliant-bsd\n"); exit (0); -#endif - - exit (1); -} -EOF - -$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && - { echo "$SYSTEM_NAME"; exit; } - -# Apollos put the system type in the environment. - -test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } - -# Convex versions that predate uname can use getsysinfo(1) - -if [ -x /usr/convex/getsysinfo ] -then - case `getsysinfo -f cpu_type` in - c1*) - echo c1-convex-bsd - exit ;; - c2*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - c34*) - echo c34-convex-bsd - exit ;; - c38*) - echo c38-convex-bsd - exit ;; - c4*) - echo c4-convex-bsd - exit ;; - esac -fi - -cat >&2 < in order to provide the needed -information to handle your system. - -config.guess timestamp = $timestamp - -uname -m = `(uname -m) 2>/dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null` - -hostinfo = `(hostinfo) 2>/dev/null` -/bin/universe = `(/bin/universe) 2>/dev/null` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` -/bin/arch = `(/bin/arch) 2>/dev/null` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` - -UNAME_MACHINE = ${UNAME_MACHINE} -UNAME_RELEASE = ${UNAME_RELEASE} -UNAME_SYSTEM = ${UNAME_SYSTEM} -UNAME_VERSION = ${UNAME_VERSION} -EOF - -exit 1 - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/saslauthd/config/config.sub b/saslauthd/config/config.sub deleted file mode 100755 index da19a880..00000000 --- a/saslauthd/config/config.sub +++ /dev/null @@ -1,1764 +0,0 @@ -#! /bin/sh -# Configuration validation subroutine script. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, -# 2011 Free Software Foundation, Inc. - -timestamp='2011-08-23' - -# This file is (in principle) common to ALL GNU software. -# The presence of a machine in this file suggests that SOME GNU software -# can handle that machine. It does not imply ALL GNU software can. -# -# This file 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 2 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, write to the Free Software -# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA -# 02110-1301, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - - -# Please send patches to . Submit a context -# diff and a properly formatted GNU ChangeLog entry. -# -# Configuration subroutine to validate and canonicalize a configuration type. -# Supply the specified configuration type as an argument. -# If it is invalid, we print an error message on stderr and exit with code 1. -# Otherwise, we print the canonical config type on stdout and succeed. - -# You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD - -# This file is supposed to be the same for all GNU packages -# and recognize all the CPU types, system types and aliases -# that are meaningful with *any* GNU software. -# Each package is responsible for reporting which valid configurations -# it does not support. The user should be able to distinguish -# a failure to support a valid configuration from a meaningless -# configuration. - -# The goal of this file is to map all the various variations of a given -# machine specification into a single specification in the form: -# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM -# or in some cases, the newer four-part form: -# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM -# It is wrong to echo any other type of specification. - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS - $0 [OPTION] ALIAS - -Canonicalize a configuration name. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.sub ($timestamp) - -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, -2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free -Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" - exit 1 ;; - - *local*) - # First pass through any local machine types. - echo $1 - exit ;; - - * ) - break ;; - esac -done - -case $# in - 0) echo "$me: missing argument$help" >&2 - exit 1;; - 1) ;; - *) echo "$me: too many arguments$help" >&2 - exit 1;; -esac - -# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). -# Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` -case $maybe_os in - nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ - linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ - knetbsd*-gnu* | netbsd*-gnu* | \ - kopensolaris*-gnu* | \ - storm-chaos* | os2-emx* | rtmk-nova*) - os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` - ;; - *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] - then os=`echo $1 | sed 's/.*-/-/'` - else os=; fi - ;; -esac - -### Let's recognize common machines as not being operating systems so -### that things like config.sub decstation-3100 work. We also -### recognize some manufacturers as not being operating systems, so we -### can provide default operating systems below. -case $os in - -sun*os*) - # Prevent following clause from handling this invalid input. - ;; - -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ - -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ - -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ - -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ - -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ - -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis | -knuth | -cray | -microblaze) - os= - basic_machine=$1 - ;; - -bluegene*) - os=-cnk - ;; - -sim | -cisco | -oki | -wec | -winbond) - os= - basic_machine=$1 - ;; - -scout) - ;; - -wrs) - os=-vxworks - basic_machine=$1 - ;; - -chorusos*) - os=-chorusos - basic_machine=$1 - ;; - -chorusrdb) - os=-chorusrdb - basic_machine=$1 - ;; - -hiux*) - os=-hiuxwe2 - ;; - -sco6) - os=-sco5v6 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5) - os=-sco3.2v5 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco4) - os=-sco3.2v4 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2.[4-9]*) - os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2v[4-9]*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5v6*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco*) - os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -udk*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -isc) - os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -clix*) - basic_machine=clipper-intergraph - ;; - -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -lynx*) - os=-lynxos - ;; - -ptx*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` - ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` - ;; - -psos*) - os=-psos - ;; - -mint | -mint[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; -esac - -# Decode aliases for certain CPU-COMPANY combinations. -case $basic_machine in - # Recognize the basic CPU types without company name. - # Some are omitted here because they have special meanings below. - 1750a | 580 \ - | a29k \ - | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ - | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ - | am33_2.0 \ - | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ - | be32 | be64 \ - | bfin \ - | c4x | clipper \ - | d10v | d30v | dlx | dsp16xx \ - | fido | fr30 | frv \ - | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ - | i370 | i860 | i960 | ia64 \ - | ip2k | iq2000 \ - | le32 | le64 \ - | lm32 \ - | m32c | m32r | m32rle | m68000 | m68k | m88k \ - | maxq | mb | microblaze | mcore | mep | metag \ - | mips | mipsbe | mipseb | mipsel | mipsle \ - | mips16 \ - | mips64 | mips64el \ - | mips64octeon | mips64octeonel \ - | mips64orion | mips64orionel \ - | mips64r5900 | mips64r5900el \ - | mips64vr | mips64vrel \ - | mips64vr4100 | mips64vr4100el \ - | mips64vr4300 | mips64vr4300el \ - | mips64vr5000 | mips64vr5000el \ - | mips64vr5900 | mips64vr5900el \ - | mipsisa32 | mipsisa32el \ - | mipsisa32r2 | mipsisa32r2el \ - | mipsisa64 | mipsisa64el \ - | mipsisa64r2 | mipsisa64r2el \ - | mipsisa64sb1 | mipsisa64sb1el \ - | mipsisa64sr71k | mipsisa64sr71kel \ - | mipstx39 | mipstx39el \ - | mn10200 | mn10300 \ - | moxie \ - | mt \ - | msp430 \ - | nds32 | nds32le | nds32be \ - | nios | nios2 \ - | ns16k | ns32k \ - | open8 \ - | or32 \ - | pdp10 | pdp11 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle \ - | pyramid \ - | rx \ - | score \ - | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ - | sh64 | sh64le \ - | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ - | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ - | spu \ - | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ - | ubicom32 \ - | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ - | we32k \ - | x86 | xc16x | xstormy16 | xtensa \ - | z8k | z80) - basic_machine=$basic_machine-unknown - ;; - c54x) - basic_machine=tic54x-unknown - ;; - c55x) - basic_machine=tic55x-unknown - ;; - c6x) - basic_machine=tic6x-unknown - ;; - m6811 | m68hc11 | m6812 | m68hc12 | picochip) - # Motorola 68HC11/12. - basic_machine=$basic_machine-unknown - os=-none - ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) - ;; - ms1) - basic_machine=mt-unknown - ;; - - strongarm | thumb | xscale) - basic_machine=arm-unknown - ;; - - xscaleeb) - basic_machine=armeb-unknown - ;; - - xscaleel) - basic_machine=armel-unknown - ;; - - # We use `pc' rather than `unknown' - # because (1) that's what they normally are, and - # (2) the word "unknown" tends to confuse beginning users. - i*86 | x86_64) - basic_machine=$basic_machine-pc - ;; - # Object if more than one company name word. - *-*-*) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; - # Recognize the basic CPU types with company name. - 580-* \ - | a29k-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ - | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ - | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ - | avr-* | avr32-* \ - | be32-* | be64-* \ - | bfin-* | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* \ - | clipper-* | craynv-* | cydra-* \ - | d10v-* | d30v-* | dlx-* \ - | elxsi-* \ - | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ - | h8300-* | h8500-* \ - | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ - | i*86-* | i860-* | i960-* | ia64-* \ - | ip2k-* | iq2000-* \ - | le32-* | le64-* \ - | lm32-* \ - | m32c-* | m32r-* | m32rle-* \ - | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ - | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ - | mips16-* \ - | mips64-* | mips64el-* \ - | mips64octeon-* | mips64octeonel-* \ - | mips64orion-* | mips64orionel-* \ - | mips64r5900-* | mips64r5900el-* \ - | mips64vr-* | mips64vrel-* \ - | mips64vr4100-* | mips64vr4100el-* \ - | mips64vr4300-* | mips64vr4300el-* \ - | mips64vr5000-* | mips64vr5000el-* \ - | mips64vr5900-* | mips64vr5900el-* \ - | mipsisa32-* | mipsisa32el-* \ - | mipsisa32r2-* | mipsisa32r2el-* \ - | mipsisa64-* | mipsisa64el-* \ - | mipsisa64r2-* | mipsisa64r2el-* \ - | mipsisa64sb1-* | mipsisa64sb1el-* \ - | mipsisa64sr71k-* | mipsisa64sr71kel-* \ - | mipstx39-* | mipstx39el-* \ - | mmix-* \ - | mt-* \ - | msp430-* \ - | nds32-* | nds32le-* | nds32be-* \ - | nios-* | nios2-* \ - | none-* | np1-* | ns16k-* | ns32k-* \ - | open8-* \ - | orion-* \ - | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ - | pyramid-* \ - | romp-* | rs6000-* | rx-* \ - | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ - | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ - | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ - | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ - | tahoe-* \ - | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ - | tile*-* \ - | tron-* \ - | ubicom32-* \ - | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ - | vax-* \ - | we32k-* \ - | x86-* | x86_64-* | xc16x-* | xps100-* \ - | xstormy16-* | xtensa*-* \ - | ymp-* \ - | z8k-* | z80-*) - ;; - # Recognize the basic CPU types without company name, with glob match. - xtensa*) - basic_machine=$basic_machine-unknown - ;; - # Recognize the various machine names and aliases which stand - # for a CPU type and a company and sometimes even an OS. - 386bsd) - basic_machine=i386-unknown - os=-bsd - ;; - 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) - basic_machine=m68000-att - ;; - 3b*) - basic_machine=we32k-att - ;; - a29khif) - basic_machine=a29k-amd - os=-udi - ;; - abacus) - basic_machine=abacus-unknown - ;; - adobe68k) - basic_machine=m68010-adobe - os=-scout - ;; - alliant | fx80) - basic_machine=fx80-alliant - ;; - altos | altos3068) - basic_machine=m68k-altos - ;; - am29k) - basic_machine=a29k-none - os=-bsd - ;; - amd64) - basic_machine=x86_64-pc - ;; - amd64-*) - basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - amdahl) - basic_machine=580-amdahl - os=-sysv - ;; - amiga | amiga-*) - basic_machine=m68k-unknown - ;; - amigaos | amigados) - basic_machine=m68k-unknown - os=-amigaos - ;; - amigaunix | amix) - basic_machine=m68k-unknown - os=-sysv4 - ;; - apollo68) - basic_machine=m68k-apollo - os=-sysv - ;; - apollo68bsd) - basic_machine=m68k-apollo - os=-bsd - ;; - aros) - basic_machine=i386-pc - os=-aros - ;; - aux) - basic_machine=m68k-apple - os=-aux - ;; - balance) - basic_machine=ns32k-sequent - os=-dynix - ;; - blackfin) - basic_machine=bfin-unknown - os=-linux - ;; - blackfin-*) - basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - bluegene*) - basic_machine=powerpc-ibm - os=-cnk - ;; - c54x-*) - basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c55x-*) - basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c6x-*) - basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c90) - basic_machine=c90-cray - os=-unicos - ;; - cegcc) - basic_machine=arm-unknown - os=-cegcc - ;; - convex-c1) - basic_machine=c1-convex - os=-bsd - ;; - convex-c2) - basic_machine=c2-convex - os=-bsd - ;; - convex-c32) - basic_machine=c32-convex - os=-bsd - ;; - convex-c34) - basic_machine=c34-convex - os=-bsd - ;; - convex-c38) - basic_machine=c38-convex - os=-bsd - ;; - cray | j90) - basic_machine=j90-cray - os=-unicos - ;; - craynv) - basic_machine=craynv-cray - os=-unicosmp - ;; - cr16 | cr16-*) - basic_machine=cr16-unknown - os=-elf - ;; - crds | unos) - basic_machine=m68k-crds - ;; - crisv32 | crisv32-* | etraxfs*) - basic_machine=crisv32-axis - ;; - cris | cris-* | etrax*) - basic_machine=cris-axis - ;; - crx) - basic_machine=crx-unknown - os=-elf - ;; - da30 | da30-*) - basic_machine=m68k-da30 - ;; - decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) - basic_machine=mips-dec - ;; - decsystem10* | dec10*) - basic_machine=pdp10-dec - os=-tops10 - ;; - decsystem20* | dec20*) - basic_machine=pdp10-dec - os=-tops20 - ;; - delta | 3300 | motorola-3300 | motorola-delta \ - | 3300-motorola | delta-motorola) - basic_machine=m68k-motorola - ;; - delta88) - basic_machine=m88k-motorola - os=-sysv3 - ;; - dicos) - basic_machine=i686-pc - os=-dicos - ;; - djgpp) - basic_machine=i586-pc - os=-msdosdjgpp - ;; - dpx20 | dpx20-*) - basic_machine=rs6000-bull - os=-bosx - ;; - dpx2* | dpx2*-bull) - basic_machine=m68k-bull - os=-sysv3 - ;; - ebmon29k) - basic_machine=a29k-amd - os=-ebmon - ;; - elxsi) - basic_machine=elxsi-elxsi - os=-bsd - ;; - encore | umax | mmax) - basic_machine=ns32k-encore - ;; - es1800 | OSE68k | ose68k | ose | OSE) - basic_machine=m68k-ericsson - os=-ose - ;; - fx2800) - basic_machine=i860-alliant - ;; - genix) - basic_machine=ns32k-ns - ;; - gmicro) - basic_machine=tron-gmicro - os=-sysv - ;; - go32) - basic_machine=i386-pc - os=-go32 - ;; - h3050r* | hiux*) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - h8300hms) - basic_machine=h8300-hitachi - os=-hms - ;; - h8300xray) - basic_machine=h8300-hitachi - os=-xray - ;; - h8500hms) - basic_machine=h8500-hitachi - os=-hms - ;; - harris) - basic_machine=m88k-harris - os=-sysv3 - ;; - hp300-*) - basic_machine=m68k-hp - ;; - hp300bsd) - basic_machine=m68k-hp - os=-bsd - ;; - hp300hpux) - basic_machine=m68k-hp - os=-hpux - ;; - hp3k9[0-9][0-9] | hp9[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k2[0-9][0-9] | hp9k31[0-9]) - basic_machine=m68000-hp - ;; - hp9k3[2-9][0-9]) - basic_machine=m68k-hp - ;; - hp9k6[0-9][0-9] | hp6[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k7[0-79][0-9] | hp7[0-79][0-9]) - basic_machine=hppa1.1-hp - ;; - hp9k78[0-9] | hp78[0-9]) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][13679] | hp8[0-9][13679]) - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][0-9] | hp8[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hppa-next) - os=-nextstep3 - ;; - hppaosf) - basic_machine=hppa1.1-hp - os=-osf - ;; - hppro) - basic_machine=hppa1.1-hp - os=-proelf - ;; - i370-ibm* | ibm*) - basic_machine=i370-ibm - ;; -# I'm not sure what "Sysv32" means. Should this be sysv3.2? - i*86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv32 - ;; - i*86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv4 - ;; - i*86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv - ;; - i*86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-solaris2 - ;; - i386mach) - basic_machine=i386-mach - os=-mach - ;; - i386-vsta | vsta) - basic_machine=i386-unknown - os=-vsta - ;; - iris | iris4d) - basic_machine=mips-sgi - case $os in - -irix*) - ;; - *) - os=-irix4 - ;; - esac - ;; - isi68 | isi) - basic_machine=m68k-isi - os=-sysv - ;; - m68knommu) - basic_machine=m68k-unknown - os=-linux - ;; - m68knommu-*) - basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - m88k-omron*) - basic_machine=m88k-omron - ;; - magnum | m3230) - basic_machine=mips-mips - os=-sysv - ;; - merlin) - basic_machine=ns32k-utek - os=-sysv - ;; - microblaze) - basic_machine=microblaze-xilinx - ;; - mingw32) - basic_machine=i386-pc - os=-mingw32 - ;; - mingw32ce) - basic_machine=arm-unknown - os=-mingw32ce - ;; - miniframe) - basic_machine=m68000-convergent - ;; - *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; - mips3*-*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` - ;; - mips3*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown - ;; - monitor) - basic_machine=m68k-rom68k - os=-coff - ;; - morphos) - basic_machine=powerpc-unknown - os=-morphos - ;; - msdos) - basic_machine=i386-pc - os=-msdos - ;; - ms1-*) - basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` - ;; - mvs) - basic_machine=i370-ibm - os=-mvs - ;; - nacl) - basic_machine=le32-unknown - os=-nacl - ;; - ncr3000) - basic_machine=i486-ncr - os=-sysv4 - ;; - netbsd386) - basic_machine=i386-unknown - os=-netbsd - ;; - netwinder) - basic_machine=armv4l-rebel - os=-linux - ;; - news | news700 | news800 | news900) - basic_machine=m68k-sony - os=-newsos - ;; - news1000) - basic_machine=m68030-sony - os=-newsos - ;; - news-3600 | risc-news) - basic_machine=mips-sony - os=-newsos - ;; - necv70) - basic_machine=v70-nec - os=-sysv - ;; - next | m*-next ) - basic_machine=m68k-next - case $os in - -nextstep* ) - ;; - -ns2*) - os=-nextstep2 - ;; - *) - os=-nextstep3 - ;; - esac - ;; - nh3000) - basic_machine=m68k-harris - os=-cxux - ;; - nh[45]000) - basic_machine=m88k-harris - os=-cxux - ;; - nindy960) - basic_machine=i960-intel - os=-nindy - ;; - mon960) - basic_machine=i960-intel - os=-mon960 - ;; - nonstopux) - basic_machine=mips-compaq - os=-nonstopux - ;; - np1) - basic_machine=np1-gould - ;; - neo-tandem) - basic_machine=neo-tandem - ;; - nse-tandem) - basic_machine=nse-tandem - ;; - nsr-tandem) - basic_machine=nsr-tandem - ;; - op50n-* | op60c-*) - basic_machine=hppa1.1-oki - os=-proelf - ;; - openrisc | openrisc-*) - basic_machine=or32-unknown - ;; - os400) - basic_machine=powerpc-ibm - os=-os400 - ;; - OSE68000 | ose68000) - basic_machine=m68000-ericsson - os=-ose - ;; - os68k) - basic_machine=m68k-none - os=-os68k - ;; - pa-hitachi) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - paragon) - basic_machine=i860-intel - os=-osf - ;; - parisc) - basic_machine=hppa-unknown - os=-linux - ;; - parisc-*) - basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - pbd) - basic_machine=sparc-tti - ;; - pbb) - basic_machine=m68k-tti - ;; - pc532 | pc532-*) - basic_machine=ns32k-pc532 - ;; - pc98) - basic_machine=i386-pc - ;; - pc98-*) - basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium | p5 | k5 | k6 | nexgen | viac3) - basic_machine=i586-pc - ;; - pentiumpro | p6 | 6x86 | athlon | athlon_*) - basic_machine=i686-pc - ;; - pentiumii | pentium2 | pentiumiii | pentium3) - basic_machine=i686-pc - ;; - pentium4) - basic_machine=i786-pc - ;; - pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium4-*) - basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pn) - basic_machine=pn-gould - ;; - power) basic_machine=power-ibm - ;; - ppc | ppcbe) basic_machine=powerpc-unknown - ;; - ppc-* | ppcbe-*) - basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppcle | powerpclittle | ppc-le | powerpc-little) - basic_machine=powerpcle-unknown - ;; - ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64) basic_machine=powerpc64-unknown - ;; - ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64le | powerpc64little | ppc64-le | powerpc64-little) - basic_machine=powerpc64le-unknown - ;; - ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ps2) - basic_machine=i386-ibm - ;; - pw32) - basic_machine=i586-unknown - os=-pw32 - ;; - rdos) - basic_machine=i386-pc - os=-rdos - ;; - rom68k) - basic_machine=m68k-rom68k - os=-coff - ;; - rm[46]00) - basic_machine=mips-siemens - ;; - rtpc | rtpc-*) - basic_machine=romp-ibm - ;; - s390 | s390-*) - basic_machine=s390-ibm - ;; - s390x | s390x-*) - basic_machine=s390x-ibm - ;; - sa29200) - basic_machine=a29k-amd - os=-udi - ;; - sb1) - basic_machine=mipsisa64sb1-unknown - ;; - sb1el) - basic_machine=mipsisa64sb1el-unknown - ;; - sde) - basic_machine=mipsisa32-sde - os=-elf - ;; - sei) - basic_machine=mips-sei - os=-seiux - ;; - sequent) - basic_machine=i386-sequent - ;; - sh) - basic_machine=sh-hitachi - os=-hms - ;; - sh5el) - basic_machine=sh5le-unknown - ;; - sh64) - basic_machine=sh64-unknown - ;; - sparclite-wrs | simso-wrs) - basic_machine=sparclite-wrs - os=-vxworks - ;; - sps7) - basic_machine=m68k-bull - os=-sysv2 - ;; - spur) - basic_machine=spur-unknown - ;; - st2000) - basic_machine=m68k-tandem - ;; - stratus) - basic_machine=i860-stratus - os=-sysv4 - ;; - strongarm-* | thumb-*) - basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - sun2) - basic_machine=m68000-sun - ;; - sun2os3) - basic_machine=m68000-sun - os=-sunos3 - ;; - sun2os4) - basic_machine=m68000-sun - os=-sunos4 - ;; - sun3os3) - basic_machine=m68k-sun - os=-sunos3 - ;; - sun3os4) - basic_machine=m68k-sun - os=-sunos4 - ;; - sun4os3) - basic_machine=sparc-sun - os=-sunos3 - ;; - sun4os4) - basic_machine=sparc-sun - os=-sunos4 - ;; - sun4sol2) - basic_machine=sparc-sun - os=-solaris2 - ;; - sun3 | sun3-*) - basic_machine=m68k-sun - ;; - sun4) - basic_machine=sparc-sun - ;; - sun386 | sun386i | roadrunner) - basic_machine=i386-sun - ;; - sv1) - basic_machine=sv1-cray - os=-unicos - ;; - symmetry) - basic_machine=i386-sequent - os=-dynix - ;; - t3e) - basic_machine=alphaev5-cray - os=-unicos - ;; - t90) - basic_machine=t90-cray - os=-unicos - ;; - tile*) - basic_machine=$basic_machine-unknown - os=-linux-gnu - ;; - tx39) - basic_machine=mipstx39-unknown - ;; - tx39el) - basic_machine=mipstx39el-unknown - ;; - toad1) - basic_machine=pdp10-xkl - os=-tops20 - ;; - tower | tower-32) - basic_machine=m68k-ncr - ;; - tpf) - basic_machine=s390x-ibm - os=-tpf - ;; - udi29k) - basic_machine=a29k-amd - os=-udi - ;; - ultra3) - basic_machine=a29k-nyu - os=-sym1 - ;; - v810 | necv810) - basic_machine=v810-nec - os=-none - ;; - vaxv) - basic_machine=vax-dec - os=-sysv - ;; - vms) - basic_machine=vax-dec - os=-vms - ;; - vpp*|vx|vx-*) - basic_machine=f301-fujitsu - ;; - vxworks960) - basic_machine=i960-wrs - os=-vxworks - ;; - vxworks68) - basic_machine=m68k-wrs - os=-vxworks - ;; - vxworks29k) - basic_machine=a29k-wrs - os=-vxworks - ;; - w65*) - basic_machine=w65-wdc - os=-none - ;; - w89k-*) - basic_machine=hppa1.1-winbond - os=-proelf - ;; - xbox) - basic_machine=i686-pc - os=-mingw32 - ;; - xps | xps100) - basic_machine=xps100-honeywell - ;; - xscale-* | xscalee[bl]-*) - basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` - ;; - ymp) - basic_machine=ymp-cray - os=-unicos - ;; - z8k-*-coff) - basic_machine=z8k-unknown - os=-sim - ;; - z80-*-coff) - basic_machine=z80-unknown - os=-sim - ;; - none) - basic_machine=none-none - os=-none - ;; - -# Here we handle the default manufacturer of certain CPU types. It is in -# some cases the only manufacturer, in others, it is the most popular. - w89k) - basic_machine=hppa1.1-winbond - ;; - op50n) - basic_machine=hppa1.1-oki - ;; - op60c) - basic_machine=hppa1.1-oki - ;; - romp) - basic_machine=romp-ibm - ;; - mmix) - basic_machine=mmix-knuth - ;; - rs6000) - basic_machine=rs6000-ibm - ;; - vax) - basic_machine=vax-dec - ;; - pdp10) - # there are many clones, so DEC is not a safe bet - basic_machine=pdp10-unknown - ;; - pdp11) - basic_machine=pdp11-dec - ;; - we32k) - basic_machine=we32k-att - ;; - sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) - basic_machine=sh-unknown - ;; - sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) - basic_machine=sparc-sun - ;; - cydra) - basic_machine=cydra-cydrome - ;; - orion) - basic_machine=orion-highlevel - ;; - orion105) - basic_machine=clipper-highlevel - ;; - mac | mpw | mac-mpw) - basic_machine=m68k-apple - ;; - pmac | pmac-mpw) - basic_machine=powerpc-apple - ;; - *-unknown) - # Make sure to match an already-canonicalized machine name. - ;; - *) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; -esac - -# Here we canonicalize certain aliases for manufacturers. -case $basic_machine in - *-digital*) - basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` - ;; - *-commodore*) - basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` - ;; - *) - ;; -esac - -# Decode manufacturer-specific aliases for certain operating systems. - -if [ x"$os" != x"" ] -then -case $os in - # First match some system type aliases - # that might get confused with valid system types. - # -solaris* is a basic system type, with this one exception. - -auroraux) - os=-auroraux - ;; - -solaris1 | -solaris1.*) - os=`echo $os | sed -e 's|solaris1|sunos4|'` - ;; - -solaris) - os=-solaris2 - ;; - -svr4*) - os=-sysv4 - ;; - -unixware*) - os=-sysv4.2uw - ;; - -gnu/linux*) - os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` - ;; - # First accept the basic system types. - # The portable systems comes first. - # Each alternative MUST END IN A *, to match a version number. - # -sysv* is not here because it comes later, after sysvr4. - -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ - | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ - | -sym* | -kopensolaris* \ - | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* | -aros* \ - | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ - | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ - | -openbsd* | -solidbsd* \ - | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ - | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ - | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ - | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* | -cegcc* \ - | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -linux-gnu* | -linux-android* \ - | -linux-newlib* | -linux-uclibc* \ - | -uxpv* | -beos* | -mpeix* | -udk* \ - | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ - | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ - | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ - | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ - | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) - # Remember, each alternative MUST END IN *, to match a version number. - ;; - -qnx*) - case $basic_machine in - x86-* | i*86-*) - ;; - *) - os=-nto$os - ;; - esac - ;; - -nto-qnx*) - ;; - -nto*) - os=`echo $os | sed -e 's|nto|nto-qnx|'` - ;; - -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ - | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) - ;; - -mac*) - os=`echo $os | sed -e 's|mac|macos|'` - ;; - -linux-dietlibc) - os=-linux-dietlibc - ;; - -linux*) - os=`echo $os | sed -e 's|linux|linux-gnu|'` - ;; - -sunos5*) - os=`echo $os | sed -e 's|sunos5|solaris2|'` - ;; - -sunos6*) - os=`echo $os | sed -e 's|sunos6|solaris3|'` - ;; - -opened*) - os=-openedition - ;; - -os400*) - os=-os400 - ;; - -wince*) - os=-wince - ;; - -osfrose*) - os=-osfrose - ;; - -osf*) - os=-osf - ;; - -utek*) - os=-bsd - ;; - -dynix*) - os=-bsd - ;; - -acis*) - os=-aos - ;; - -atheos*) - os=-atheos - ;; - -syllable*) - os=-syllable - ;; - -386bsd) - os=-bsd - ;; - -ctix* | -uts*) - os=-sysv - ;; - -nova*) - os=-rtmk-nova - ;; - -ns2 ) - os=-nextstep2 - ;; - -nsk*) - os=-nsk - ;; - # Preserve the version number of sinix5. - -sinix5.*) - os=`echo $os | sed -e 's|sinix|sysv|'` - ;; - -sinix*) - os=-sysv4 - ;; - -tpf*) - os=-tpf - ;; - -triton*) - os=-sysv3 - ;; - -oss*) - os=-sysv3 - ;; - -svr4) - os=-sysv4 - ;; - -svr3) - os=-sysv3 - ;; - -sysvr4) - os=-sysv4 - ;; - # This must come after -sysvr4. - -sysv*) - ;; - -ose*) - os=-ose - ;; - -es1800*) - os=-ose - ;; - -xenix) - os=-xenix - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - os=-mint - ;; - -aros*) - os=-aros - ;; - -kaos*) - os=-kaos - ;; - -zvmoe) - os=-zvmoe - ;; - -dicos*) - os=-dicos - ;; - -nacl*) - ;; - -none) - ;; - *) - # Get rid of the `-' at the beginning of $os. - os=`echo $os | sed 's/[^-]*-//'` - echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 - exit 1 - ;; -esac -else - -# Here we handle the default operating systems that come with various machines. -# The value should be what the vendor currently ships out the door with their -# machine or put another way, the most popular os provided with the machine. - -# Note that if you're going to try to match "-MANUFACTURER" here (say, -# "-sun"), then you have to tell the case statement up towards the top -# that MANUFACTURER isn't an operating system. Otherwise, code above -# will signal an error saying that MANUFACTURER isn't an operating -# system, and we'll never get to this point. - -case $basic_machine in - score-*) - os=-elf - ;; - spu-*) - os=-elf - ;; - *-acorn) - os=-riscix1.2 - ;; - arm*-rebel) - os=-linux - ;; - arm*-semi) - os=-aout - ;; - c4x-* | tic4x-*) - os=-coff - ;; - tic54x-*) - os=-coff - ;; - tic55x-*) - os=-coff - ;; - tic6x-*) - os=-coff - ;; - # This must come before the *-dec entry. - pdp10-*) - os=-tops20 - ;; - pdp11-*) - os=-none - ;; - *-dec | vax-*) - os=-ultrix4.2 - ;; - m68*-apollo) - os=-domain - ;; - i386-sun) - os=-sunos4.0.2 - ;; - m68000-sun) - os=-sunos3 - # This also exists in the configure program, but was not the - # default. - # os=-sunos4 - ;; - m68*-cisco) - os=-aout - ;; - mep-*) - os=-elf - ;; - mips*-cisco) - os=-elf - ;; - mips*-*) - os=-elf - ;; - or32-*) - os=-coff - ;; - *-tti) # must be before sparc entry or we get the wrong os. - os=-sysv3 - ;; - sparc-* | *-sun) - os=-sunos4.1.1 - ;; - *-be) - os=-beos - ;; - *-haiku) - os=-haiku - ;; - *-ibm) - os=-aix - ;; - *-knuth) - os=-mmixware - ;; - *-wec) - os=-proelf - ;; - *-winbond) - os=-proelf - ;; - *-oki) - os=-proelf - ;; - *-hp) - os=-hpux - ;; - *-hitachi) - os=-hiux - ;; - i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) - os=-sysv - ;; - *-cbm) - os=-amigaos - ;; - *-dg) - os=-dgux - ;; - *-dolphin) - os=-sysv3 - ;; - m68k-ccur) - os=-rtu - ;; - m88k-omron*) - os=-luna - ;; - *-next ) - os=-nextstep - ;; - *-sequent) - os=-ptx - ;; - *-crds) - os=-unos - ;; - *-ns) - os=-genix - ;; - i370-*) - os=-mvs - ;; - *-next) - os=-nextstep3 - ;; - *-gould) - os=-sysv - ;; - *-highlevel) - os=-bsd - ;; - *-encore) - os=-bsd - ;; - *-sgi) - os=-irix - ;; - *-siemens) - os=-sysv4 - ;; - *-masscomp) - os=-rtu - ;; - f30[01]-fujitsu | f700-fujitsu) - os=-uxpv - ;; - *-rom68k) - os=-coff - ;; - *-*bug) - os=-coff - ;; - *-apple) - os=-macos - ;; - *-atari*) - os=-mint - ;; - *) - os=-none - ;; -esac -fi - -# Here we handle the case where we know the os, and the CPU type, but not the -# manufacturer. We pick the logical manufacturer. -vendor=unknown -case $basic_machine in - *-unknown) - case $os in - -riscix*) - vendor=acorn - ;; - -sunos*) - vendor=sun - ;; - -cnk*|-aix*) - vendor=ibm - ;; - -beos*) - vendor=be - ;; - -hpux*) - vendor=hp - ;; - -mpeix*) - vendor=hp - ;; - -hiux*) - vendor=hitachi - ;; - -unos*) - vendor=crds - ;; - -dgux*) - vendor=dg - ;; - -luna*) - vendor=omron - ;; - -genix*) - vendor=ns - ;; - -mvs* | -opened*) - vendor=ibm - ;; - -os400*) - vendor=ibm - ;; - -ptx*) - vendor=sequent - ;; - -tpf*) - vendor=ibm - ;; - -vxsim* | -vxworks* | -windiss*) - vendor=wrs - ;; - -aux*) - vendor=apple - ;; - -hms*) - vendor=hitachi - ;; - -mpw* | -macos*) - vendor=apple - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - vendor=atari - ;; - -vos*) - vendor=stratus - ;; - esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` - ;; -esac - -echo $basic_machine$os -exit - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/saslauthd/config/depcomp b/saslauthd/config/depcomp deleted file mode 100755 index 807b991f..00000000 --- a/saslauthd/config/depcomp +++ /dev/null @@ -1,423 +0,0 @@ -#! /bin/sh - -# depcomp - compile a program generating dependencies as side-effects -# Copyright 1999, 2000 Free Software Foundation, Inc. - -# 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 2, 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# Originally written by Alexandre Oliva . - -if test -z "$depmode" || test -z "$source" || test -z "$object"; then - echo "depcomp: Variables source, object and depmode must be set" 1>&2 - exit 1 -fi -# `libtool' can also be set to `yes' or `no'. - -if test -z "$depfile"; then - base=`echo "$object" | sed -e 's,^.*/,,' -e 's,\.\([^.]*\)$,.P\1,'` - dir=`echo "$object" | sed 's,/.*$,/,'` - if test "$dir" = "$object"; then - dir= - fi - # FIXME: should be _deps on DOS. - depfile="$dir.deps/$base" -fi - -tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} - -rm -f "$tmpdepfile" - -# Some modes work just like other modes, but use different flags. We -# parameterize here, but still list the modes in the big case below, -# to make depend.m4 easier to write. Note that we *cannot* use a case -# here, because this file can only contain one case statement. -if test "$depmode" = hp; then - # HP compiler uses -M and no extra arg. - gccflag=-M - depmode=gcc -fi - -if test "$depmode" = dashXmstdout; then - # This is just like dashmstdout with a different argument. - dashmflag=-xM - depmode=dashmstdout -fi - -case "$depmode" in -gcc3) -## gcc 3 implements dependency tracking that does exactly what -## we want. Yay! Note: for some reason libtool 1.4 doesn't like -## it if -MD -MP comes after the -MF stuff. Hmm. - "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile" - exit $stat - fi - mv "$tmpdepfile" "$depfile" - ;; - -gcc) -## There are various ways to get dependency output from gcc. Here's -## why we pick this rather obscure method: -## - Don't want to use -MD because we'd like the dependencies to end -## up in a subdir. Having to rename by hand is ugly. -## (We might end up doing this anyway to support other compilers.) -## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like -## -MM, not -M (despite what the docs say). -## - Using -M directly means running the compiler twice (even worse -## than renaming). - if test -z "$gccflag"; then - gccflag=-MD, - fi - "$@" -Wp,"$gccflag$tmpdepfile" - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - echo "$object : \\" > "$depfile" - alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz -## The second -e expression handles DOS-style file names with drive letters. - sed -e 's/^[^:]*: / /' \ - -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" -## This next piece of magic avoids the `deleted header file' problem. -## The problem is that when a header file which appears in a .P file -## is deleted, the dependency causes make to die (because there is -## typically no way to rebuild the header). We avoid this by adding -## dummy dependencies for each header file. Too bad gcc doesn't do -## this for us directly. - tr ' ' ' -' < "$tmpdepfile" | -## Some versions of gcc put a space before the `:'. On the theory -## that the space means something, we add a space to the output as -## well. -## Some versions of the HPUX 10.20 sed can't process this invocation -## correctly. Breaking it into two sed invocations is a workaround. - sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -hp) - # This case exists only to let depend.m4 do its work. It works by - # looking at the text of this script. This case will never be run, - # since it is checked for above. - exit 1 - ;; - -sgi) - if test "$libtool" = yes; then - "$@" "-Wp,-MDupdate,$tmpdepfile" - else - "$@" -MDupdate "$tmpdepfile" - fi - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - - if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files - echo "$object : \\" > "$depfile" - - # Clip off the initial element (the dependent). Don't try to be - # clever and replace this with sed code, as IRIX sed won't handle - # lines with more than a fixed number of characters (4096 in - # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; - # the IRIX cc adds comments like `#:fec' to the end of the - # dependency line. - tr ' ' ' -' < "$tmpdepfile" \ - | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ - tr ' -' ' ' >> $depfile - echo >> $depfile - - # The second pass generates a dummy entry for each header file. - tr ' ' ' -' < "$tmpdepfile" \ - | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ - >> $depfile - else - # The sourcefile does not contain any dependencies, so just - # store a dummy comment line, to avoid errors with the Makefile - # "include basename.Plo" scheme. - echo "#dummy" > "$depfile" - fi - rm -f "$tmpdepfile" - ;; - -aix) - # The C for AIX Compiler uses -M and outputs the dependencies - # in a .u file. This file always lives in the current directory. - # Also, the AIX compiler puts `$object:' at the start of each line; - # $object doesn't have directory information. - stripped=`echo "$object" | sed -e 's,^.*/,,' -e 's/\(.*\)\..*$/\1/'` - tmpdepfile="$stripped.u" - outname="$stripped.o" - if test "$libtool" = yes; then - "$@" -Wc,-M - else - "$@" -M - fi - - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile" - exit $stat - fi - - if test -f "$tmpdepfile"; then - # Each line is of the form `foo.o: dependent.h'. - # Do two passes, one to just change these to - # `$object: dependent.h' and one to simply `dependent.h:'. - sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" - sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" - else - # The sourcefile does not contain any dependencies, so just - # store a dummy comment line, to avoid errors with the Makefile - # "include basename.Plo" scheme. - echo "#dummy" > "$depfile" - fi - rm -f "$tmpdepfile" - ;; - -tru64) - # The Tru64 compiler uses -MD to generate dependencies as a side - # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. - # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put - # dependencies in `foo.d' instead, so we check for that too. - # Subdirectories are respected. - dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` - test "x$dir" = "x$object" && dir= - base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` - - if test "$libtool" = yes; then - tmpdepfile1="$dir.libs/$base.lo.d" - tmpdepfile2="$dir.libs/$base.d" - "$@" -Wc,-MD - else - tmpdepfile1="$dir$base.o.d" - tmpdepfile2="$dir$base.d" - "$@" -MD - fi - - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile1" "$tmpdepfile2" - exit $stat - fi - - if test -f "$tmpdepfile1"; then - tmpdepfile="$tmpdepfile1" - else - tmpdepfile="$tmpdepfile2" - fi - if test -f "$tmpdepfile"; then - sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" - # That's a space and a tab in the []. - sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" - else - echo "#dummy" > "$depfile" - fi - rm -f "$tmpdepfile" - ;; - -#nosideeffect) - # This comment above is used by automake to tell side-effect - # dependency tracking mechanisms from slower ones. - -dashmstdout) - # Important note: in order to support this mode, a compiler *must* - # always write the proprocessed file to stdout, regardless of -o. - "$@" || exit $? - - # Remove the call to Libtool. - if test "$libtool" = yes; then - while test $1 != '--mode=compile'; do - shift - done - shift - fi - - # Remove `-o $object'. We will use -o /dev/null later, - # however we can't do the remplacement now because - # `-o $object' might simply not be used - IFS=" " - for arg - do - case $arg in - -o) - shift - ;; - $object) - shift - ;; - *) - set fnord "$@" "$arg" - shift # fnord - shift # $arg - ;; - esac - done - - test -z "$dashmflag" && dashmflag=-M - "$@" -o /dev/null $dashmflag | sed 's:^[^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" - rm -f "$depfile" - cat < "$tmpdepfile" > "$depfile" - tr ' ' ' -' < "$tmpdepfile" | \ -## Some versions of the HPUX 10.20 sed can't process this invocation -## correctly. Breaking it into two sed invocations is a workaround. - sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -dashXmstdout) - # This case only exists to satisfy depend.m4. It is never actually - # run, as this mode is specially recognized in the preamble. - exit 1 - ;; - -makedepend) - "$@" || exit $? - # X makedepend - shift - cleared=no - for arg in "$@"; do - case $cleared in - no) - set ""; shift - cleared=yes ;; - esac - case "$arg" in - -D*|-I*) - set fnord "$@" "$arg"; shift ;; - -*) - ;; - *) - set fnord "$@" "$arg"; shift ;; - esac - done - obj_suffix="`echo $object | sed 's/^.*\././'`" - touch "$tmpdepfile" - ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" - rm -f "$depfile" - cat < "$tmpdepfile" > "$depfile" - sed '1,2d' "$tmpdepfile" | tr ' ' ' -' | \ -## Some versions of the HPUX 10.20 sed can't process this invocation -## correctly. Breaking it into two sed invocations is a workaround. - sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" "$tmpdepfile".bak - ;; - -cpp) - # Important note: in order to support this mode, a compiler *must* - # always write the proprocessed file to stdout. - "$@" || exit $? - - # Remove the call to Libtool. - if test "$libtool" = yes; then - while test $1 != '--mode=compile'; do - shift - done - shift - fi - - # Remove `-o $object'. - IFS=" " - for arg - do - case $arg in - -o) - shift - ;; - $object) - shift - ;; - *) - set fnord "$@" "$arg" - shift # fnord - shift # $arg - ;; - esac - done - - "$@" -E | - sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | - sed '$ s: \\$::' > "$tmpdepfile" - rm -f "$depfile" - echo "$object : \\" > "$depfile" - cat < "$tmpdepfile" >> "$depfile" - sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -msvisualcpp) - # Important note: in order to support this mode, a compiler *must* - # always write the proprocessed file to stdout, regardless of -o, - # because we must use -o when running libtool. - "$@" || exit $? - IFS=" " - for arg - do - case "$arg" in - "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") - set fnord "$@" - shift - shift - ;; - *) - set fnord "$@" "$arg" - shift - shift - ;; - esac - done - "$@" -E | - sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" - rm -f "$depfile" - echo "$object : \\" > "$depfile" - . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" - echo " " >> "$depfile" - . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -none) - exec "$@" - ;; - -*) - echo "Unknown depmode $depmode" 1>&2 - exit 1 - ;; -esac - -exit 0 diff --git a/saslauthd/config/install-sh b/saslauthd/config/install-sh deleted file mode 100755 index 36f96f3e..00000000 --- a/saslauthd/config/install-sh +++ /dev/null @@ -1,276 +0,0 @@ -#!/bin/sh -# -# install - install a program, script, or datafile -# This comes from X11R5 (mit/util/scripts/install.sh). -# -# Copyright 1991 by the Massachusetts Institute of Technology -# -# Permission to use, copy, modify, distribute, and sell this software and its -# documentation for any purpose is hereby granted without fee, provided that -# the above copyright notice appear in all copies and that both that -# copyright notice and this permission notice appear in supporting -# documentation, and that the name of M.I.T. not be used in advertising or -# publicity pertaining to distribution of the software without specific, -# written prior permission. M.I.T. makes no representations about the -# suitability of this software for any purpose. It is provided "as is" -# without express or implied warranty. -# -# Calling this script install-sh is preferred over install.sh, to prevent -# `make' implicit rules from creating a file called install from it -# when there is no Makefile. -# -# This script is compatible with the BSD install script, but was written -# from scratch. It can only install one file at a time, a restriction -# shared with many OS's install programs. - - -# set DOITPROG to echo to test this script - -# Don't use :- since 4.3BSD and earlier shells don't like it. -doit="${DOITPROG-}" - - -# put in absolute paths if you don't have them in your path; or use env. vars. - -mvprog="${MVPROG-mv}" -cpprog="${CPPROG-cp}" -chmodprog="${CHMODPROG-chmod}" -chownprog="${CHOWNPROG-chown}" -chgrpprog="${CHGRPPROG-chgrp}" -stripprog="${STRIPPROG-strip}" -rmprog="${RMPROG-rm}" -mkdirprog="${MKDIRPROG-mkdir}" - -transformbasename="" -transform_arg="" -instcmd="$mvprog" -chmodcmd="$chmodprog 0755" -chowncmd="" -chgrpcmd="" -stripcmd="" -rmcmd="$rmprog -f" -mvcmd="$mvprog" -src="" -dst="" -dir_arg="" - -while [ x"$1" != x ]; do - case $1 in - -c) instcmd=$cpprog - shift - continue;; - - -d) dir_arg=true - shift - continue;; - - -m) chmodcmd="$chmodprog $2" - shift - shift - continue;; - - -o) chowncmd="$chownprog $2" - shift - shift - continue;; - - -g) chgrpcmd="$chgrpprog $2" - shift - shift - continue;; - - -s) stripcmd=$stripprog - shift - continue;; - - -t=*) transformarg=`echo $1 | sed 's/-t=//'` - shift - continue;; - - -b=*) transformbasename=`echo $1 | sed 's/-b=//'` - shift - continue;; - - *) if [ x"$src" = x ] - then - src=$1 - else - # this colon is to work around a 386BSD /bin/sh bug - : - dst=$1 - fi - shift - continue;; - esac -done - -if [ x"$src" = x ] -then - echo "$0: no input file specified" >&2 - exit 1 -else - : -fi - -if [ x"$dir_arg" != x ]; then - dst=$src - src="" - - if [ -d "$dst" ]; then - instcmd=: - chmodcmd="" - else - instcmd=$mkdirprog - fi -else - -# Waiting for this to be detected by the "$instcmd $src $dsttmp" command -# might cause directories to be created, which would be especially bad -# if $src (and thus $dsttmp) contains '*'. - - if [ -f "$src" ] || [ -d "$src" ] - then - : - else - echo "$0: $src does not exist" >&2 - exit 1 - fi - - if [ x"$dst" = x ] - then - echo "$0: no destination specified" >&2 - exit 1 - else - : - fi - -# If destination is a directory, append the input filename; if your system -# does not like double slashes in filenames, you may need to add some logic - - if [ -d "$dst" ] - then - dst=$dst/`basename "$src"` - else - : - fi -fi - -## this sed command emulates the dirname command -dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` - -# Make sure that the destination directory exists. -# this part is taken from Noah Friedman's mkinstalldirs script - -# Skip lots of stat calls in the usual case. -if [ ! -d "$dstdir" ]; then -defaultIFS=' - ' -IFS="${IFS-$defaultIFS}" - -oIFS=$IFS -# Some sh's can't handle IFS=/ for some reason. -IFS='%' -set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` -IFS=$oIFS - -pathcomp='' - -while [ $# -ne 0 ] ; do - pathcomp=$pathcomp$1 - shift - - if [ ! -d "$pathcomp" ] ; - then - $mkdirprog "$pathcomp" - else - : - fi - - pathcomp=$pathcomp/ -done -fi - -if [ x"$dir_arg" != x ] -then - $doit $instcmd "$dst" && - - if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi && - if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi && - if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi && - if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi -else - -# If we're going to rename the final executable, determine the name now. - - if [ x"$transformarg" = x ] - then - dstfile=`basename "$dst"` - else - dstfile=`basename "$dst" $transformbasename | - sed $transformarg`$transformbasename - fi - -# don't allow the sed command to completely eliminate the filename - - if [ x"$dstfile" = x ] - then - dstfile=`basename "$dst"` - else - : - fi - -# Make a couple of temp file names in the proper directory. - - dsttmp=$dstdir/#inst.$$# - rmtmp=$dstdir/#rm.$$# - -# Trap to clean up temp files at exit. - - trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0 - trap '(exit $?); exit' 1 2 13 15 - -# Move or copy the file name to the temp name - - $doit $instcmd "$src" "$dsttmp" && - -# and set any options; do chmod last to preserve setuid bits - -# If any of these fail, we abort the whole thing. If we want to -# ignore errors from any of these, just make sure not to ignore -# errors from the above "$doit $instcmd $src $dsttmp" command. - - if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi && - if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi && - if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi && - if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi && - -# Now remove or move aside any old file at destination location. We try this -# two ways since rm can't unlink itself on some systems and the destination -# file might be busy for other reasons. In this case, the final cleanup -# might fail but the new file should still install successfully. - -{ - if [ -f "$dstdir/$dstfile" ] - then - $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null || - $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null || - { - echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 - (exit 1); exit - } - else - : - fi -} && - -# Now rename the file to the real destination. - - $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" - -fi && - -# The final little trick to "correctly" pass the exit status to the exit trap. - -{ - (exit 0); exit -} diff --git a/saslauthd/config/ltconfig b/saslauthd/config/ltconfig deleted file mode 100755 index 888addc0..00000000 --- a/saslauthd/config/ltconfig +++ /dev/null @@ -1,3150 +0,0 @@ -#! /bin/sh - -# ltconfig - Create a system-specific libtool. -# Copyright (C) 1996-1999 Free Software Foundation, Inc. -# Originally by Gordon Matzigkeit , 1996 -# -# This file 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 2 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# A lot of this script is taken from autoconf-2.10. - -# Check that we are running under the correct shell. -SHELL=${CONFIG_SHELL-/bin/sh} -echo=echo -if test "X$1" = X--no-reexec; then - # Discard the --no-reexec flag, and continue. - shift -elif test "X$1" = X--fallback-echo; then - # Avoid inline document here, it may be left over - : -elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then - # Yippee, $echo works! - : -else - # Restart under the correct shell. - exec "$SHELL" "$0" --no-reexec ${1+"$@"} -fi - -if test "X$1" = X--fallback-echo; then - # used as fallback echo - shift - cat </dev/null`} - case X$UNAME in - *-DOS) PATH_SEPARATOR=';' ;; - *) PATH_SEPARATOR=':' ;; - esac -fi - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -if test "X${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi - -if test "X${echo_test_string+set}" != Xset; then - # find a string as large as possible, as long as the shell can cope with it - for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do - # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... - if (echo_test_string="`eval $cmd`") 2>/dev/null && - echo_test_string="`eval $cmd`" && - (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null; then - break - fi - done -fi - -if test "X`($echo '\t') 2>/dev/null`" != 'X\t' || - test "X`($echo "$echo_test_string") 2>/dev/null`" != X"$echo_test_string"; then - # The Solaris, AIX, and Digital Unix default echo programs unquote - # backslashes. This makes it impossible to quote backslashes using - # echo "$something" | sed 's/\\/\\\\/g' - # - # So, first we look for a working echo in the user's PATH. - - IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" - for dir in $PATH /usr/ucb; do - if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && - test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && - test "X`($dir/echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then - echo="$dir/echo" - break - fi - done - IFS="$save_ifs" - - if test "X$echo" = Xecho; then - # We didn't find a better echo, so look for alternatives. - if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && - test "X`(print -r "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then - # This shell has a builtin print -r that does the trick. - echo='print -r' - elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && - test "X$CONFIG_SHELL" != X/bin/ksh; then - # If we have ksh, try running ltconfig again with it. - ORIGINAL_CONFIG_SHELL="${CONFIG_SHELL-/bin/sh}" - export ORIGINAL_CONFIG_SHELL - CONFIG_SHELL=/bin/ksh - export CONFIG_SHELL - exec "$CONFIG_SHELL" "$0" --no-reexec ${1+"$@"} - else - # Try using printf. - echo='printf "%s\n"' - if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && - test "X`($echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then - # Cool, printf works - : - elif test "X`("$ORIGINAL_CONFIG_SHELL" "$0" --fallback-echo '\t') 2>/dev/null`" = 'X\t' && - test "X`("$ORIGINAL_CONFIG_SHELL" "$0" --fallback-echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then - CONFIG_SHELL="$ORIGINAL_CONFIG_SHELL" - export CONFIG_SHELL - SHELL="$CONFIG_SHELL" - export SHELL - echo="$CONFIG_SHELL $0 --fallback-echo" - elif test "X`("$CONFIG_SHELL" "$0" --fallback-echo '\t') 2>/dev/null`" = 'X\t' && - test "X`("$CONFIG_SHELL" "$0" --fallback-echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then - echo="$CONFIG_SHELL $0 --fallback-echo" - else - # maybe with a smaller string... - prev=: - - for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do - if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null; then - break - fi - prev="$cmd" - done - - if test "$prev" != 'sed 50q "$0"'; then - echo_test_string=`eval $prev` - export echo_test_string - exec "${ORIGINAL_CONFIG_SHELL}" "$0" ${1+"$@"} - else - # Oops. We lost completely, so just stick with echo. - echo=echo - fi - fi - fi - fi -fi - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -Xsed='sed -e s/^X//' -sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g' - -# Same as above, but do not quote variable references. -double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g' - -# Sed substitution to delay expansion of an escaped shell variable in a -# double_quote_subst'ed string. -delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' - -# The name of this program. -progname=`$echo "X$0" | $Xsed -e 's%^.*/%%'` - -# Constants: -PROGRAM=ltconfig -PACKAGE=libtool -VERSION=1.3.5 -TIMESTAMP=" (1.385.2.206 2000/05/27 11:12:27)" -ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' -ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' -rm="rm -f" - -help="Try \`$progname --help' for more information." - -# Global variables: -default_ofile=libtool -can_build_shared=yes -enable_shared=yes -# All known linkers require a `.a' archive for static linking (except M$VC, -# which needs '.lib'). -enable_static=yes -enable_fast_install=yes -enable_dlopen=unknown -enable_win32_dll=no -ltmain= -silent= -srcdir= -ac_config_guess= -ac_config_sub= -host= -nonopt= -ofile="$default_ofile" -verify_host=yes -with_gcc=no -with_gnu_ld=no -need_locks=yes -ac_ext=c -objext=o -libext=a -exeext= -cache_file= - -old_AR="$AR" -old_CC="$CC" -old_CFLAGS="$CFLAGS" -old_CPPFLAGS="$CPPFLAGS" -old_LDFLAGS="$LDFLAGS" -old_LD="$LD" -old_LN_S="$LN_S" -old_LIBS="$LIBS" -old_NM="$NM" -old_RANLIB="$RANLIB" -old_DLLTOOL="$DLLTOOL" -old_OBJDUMP="$OBJDUMP" -old_AS="$AS" - -# Parse the command line options. -args= -prev= -for option -do - case "$option" in - -*=*) optarg=`echo "$option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; - *) optarg= ;; - esac - - # If the previous option needs an argument, assign it. - if test -n "$prev"; then - eval "$prev=\$option" - prev= - continue - fi - - case "$option" in - --help) cat <&2 - echo "$help" 1>&2 - exit 1 - ;; - - *) - if test -z "$ltmain"; then - ltmain="$option" - elif test -z "$host"; then -# This generates an unnecessary warning for sparc-sun-solaris4.1.3_U1 -# if test -n "`echo $option| sed 's/[-a-z0-9.]//g'`"; then -# echo "$progname: warning \`$option' is not a valid host type" 1>&2 -# fi - host="$option" - else - echo "$progname: too many arguments" 1>&2 - echo "$help" 1>&2 - exit 1 - fi ;; - esac -done - -if test -z "$ltmain"; then - echo "$progname: you must specify a LTMAIN file" 1>&2 - echo "$help" 1>&2 - exit 1 -fi - -if test ! -f "$ltmain"; then - echo "$progname: \`$ltmain' does not exist" 1>&2 - echo "$help" 1>&2 - exit 1 -fi - -# Quote any args containing shell metacharacters. -ltconfig_args= -for arg -do - case "$arg" in - *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) - ltconfig_args="$ltconfig_args '$arg'" ;; - *) ltconfig_args="$ltconfig_args $arg" ;; - esac -done - -# A relevant subset of AC_INIT. - -# File descriptor usage: -# 0 standard input -# 1 file creation -# 2 errors and warnings -# 3 some systems may open it to /dev/tty -# 4 used on the Kubota Titan -# 5 compiler messages saved in config.log -# 6 checking for... messages and results -if test "$silent" = yes; then - exec 6>/dev/null -else - exec 6>&1 -fi -exec 5>>./config.log - -# NLS nuisances. -# Only set LANG and LC_ALL to C if already set. -# These must not be set unconditionally because not all systems understand -# e.g. LANG=C (notably SCO). -if test "X${LC_ALL+set}" = Xset; then LC_ALL=C; export LC_ALL; fi -if test "X${LANG+set}" = Xset; then LANG=C; export LANG; fi - -if test -n "$cache_file" && test -r "$cache_file"; then - echo "loading cache $cache_file within ltconfig" - . $cache_file -fi - -if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then - # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. - if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then - ac_n= ac_c=' -' ac_t=' ' - else - ac_n=-n ac_c= ac_t= - fi -else - ac_n= ac_c='\c' ac_t= -fi - -if test -z "$srcdir"; then - # Assume the source directory is the same one as the path to LTMAIN. - srcdir=`$echo "X$ltmain" | $Xsed -e 's%/[^/]*$%%'` - test "$srcdir" = "$ltmain" && srcdir=. -fi - -trap "$rm conftest*; exit 1" 1 2 15 -if test "$verify_host" = yes; then - # Check for config.guess and config.sub. - ac_aux_dir= - for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do - if test -f $ac_dir/config.guess; then - ac_aux_dir=$ac_dir - break - fi - done - if test -z "$ac_aux_dir"; then - echo "$progname: cannot find config.guess in $srcdir $srcdir/.. $srcdir/../.." 1>&2 - echo "$help" 1>&2 - exit 1 - fi - ac_config_guess=$ac_aux_dir/config.guess - ac_config_sub=$ac_aux_dir/config.sub - - # Make sure we can run config.sub. - if $SHELL $ac_config_sub sun4 >/dev/null 2>&1; then : - else - echo "$progname: cannot run $ac_config_sub" 1>&2 - echo "$help" 1>&2 - exit 1 - fi - - echo $ac_n "checking host system type""... $ac_c" 1>&6 - - host_alias=$host - case "$host_alias" in - "") - if host_alias=`$SHELL $ac_config_guess`; then : - else - echo "$progname: cannot guess host type; you must specify one" 1>&2 - echo "$help" 1>&2 - exit 1 - fi ;; - esac - host=`$SHELL $ac_config_sub $host_alias` - echo "$ac_t$host" 1>&6 - - # Make sure the host verified. - test -z "$host" && exit 1 - -elif test -z "$host"; then - echo "$progname: you must specify a host type if you use \`--no-verify'" 1>&2 - echo "$help" 1>&2 - exit 1 -else - host_alias=$host -fi - -# Transform linux* to *-*-linux-gnu*, to support old configure scripts. -case "$host_os" in -linux-gnu*) ;; -linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'` -esac - -host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` -host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` -host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` - -case "$host_os" in -aix3*) - # AIX sometimes has problems with the GCC collect2 program. For some - # reason, if we set the COLLECT_NAMES environment variable, the problems - # vanish in a puff of smoke. - if test "X${COLLECT_NAMES+set}" != Xset; then - COLLECT_NAMES= - export COLLECT_NAMES - fi - ;; -esac - -# Determine commands to create old-style static archives. -old_archive_cmds='$AR cru $oldlib$oldobjs' -old_postinstall_cmds='chmod 644 $oldlib' -old_postuninstall_cmds= - -# Set a sane default for `AR'. -test -z "$AR" && AR=ar - -# Set a sane default for `OBJDUMP'. -test -z "$OBJDUMP" && OBJDUMP=objdump - -# If RANLIB is not set, then run the test. -if test "${RANLIB+set}" != "set"; then - result=no - - echo $ac_n "checking for ranlib... $ac_c" 1>&6 - IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" - for dir in $PATH; do - test -z "$dir" && dir=. - if test -f $dir/ranlib || test -f $dir/ranlib$ac_exeext; then - RANLIB="ranlib" - result="ranlib" - break - fi - done - IFS="$save_ifs" - - echo "$ac_t$result" 1>&6 -fi - -if test -n "$RANLIB"; then - old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" - old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds" -fi - -# Set sane defaults for `DLLTOOL', `OBJDUMP', and `AS', used on cygwin. -test -z "$DLLTOOL" && DLLTOOL=dlltool -test -z "$OBJDUMP" && OBJDUMP=objdump -test -z "$AS" && AS=as - -# Check to see if we are using GCC. -if test "$with_gcc" != yes || test -z "$CC"; then - # If CC is not set, then try to find GCC or a usable CC. - if test -z "$CC"; then - echo $ac_n "checking for gcc... $ac_c" 1>&6 - IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" - for dir in $PATH; do - test -z "$dir" && dir=. - if test -f $dir/gcc || test -f $dir/gcc$ac_exeext; then - CC="gcc" - break - fi - done - IFS="$save_ifs" - - if test -n "$CC"; then - echo "$ac_t$CC" 1>&6 - else - echo "$ac_t"no 1>&6 - fi - fi - - # Not "gcc", so try "cc", rejecting "/usr/ucb/cc". - if test -z "$CC"; then - echo $ac_n "checking for cc... $ac_c" 1>&6 - IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" - cc_rejected=no - for dir in $PATH; do - test -z "$dir" && dir=. - if test -f $dir/cc || test -f $dir/cc$ac_exeext; then - if test "$dir/cc" = "/usr/ucb/cc"; then - cc_rejected=yes - continue - fi - CC="cc" - break - fi - done - IFS="$save_ifs" - if test $cc_rejected = yes; then - # We found a bogon in the path, so make sure we never use it. - set dummy $CC - shift - if test $# -gt 0; then - # We chose a different compiler from the bogus one. - # However, it has the same name, so the bogon will be chosen - # first if we set CC to just the name; use the full file name. - shift - set dummy "$dir/cc" "$@" - shift - CC="$@" - fi - fi - - if test -n "$CC"; then - echo "$ac_t$CC" 1>&6 - else - echo "$ac_t"no 1>&6 - fi - - if test -z "$CC"; then - echo "$progname: error: no acceptable cc found in \$PATH" 1>&2 - exit 1 - fi - fi - - # Now see if the compiler is really GCC. - with_gcc=no - echo $ac_n "checking whether we are using GNU C... $ac_c" 1>&6 - echo "$progname:581: checking whether we are using GNU C" >&5 - - $rm conftest.c - cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then - with_gcc=yes - fi - $rm conftest.c - echo "$ac_t$with_gcc" 1>&6 -fi - -# Allow CC to be a program name with arguments. -set dummy $CC -compiler="$2" - -echo $ac_n "checking for object suffix... $ac_c" 1>&6 -$rm conftest* -echo 'int i = 1;' > conftest.c -echo "$progname:603: checking for object suffix" >& 5 -if { (eval echo $progname:604: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; }; then - # Append any warnings to the config.log. - cat conftest.err 1>&5 - - for ac_file in conftest.*; do - case $ac_file in - *.c) ;; - *) objext=`echo $ac_file | sed -e s/conftest.//` ;; - esac - done -else - cat conftest.err 1>&5 - echo "$progname: failed program was:" >&5 - cat conftest.c >&5 -fi -$rm conftest* -echo "$ac_t$objext" 1>&6 - -echo $ac_n "checking for executable suffix... $ac_c" 1>&6 -if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - ac_cv_exeext="no" - $rm conftest* - echo 'main () { return 0; }' > conftest.c - echo "$progname:629: checking for executable suffix" >& 5 - if { (eval echo $progname:630: \"$ac_link\") 1>&5; (eval $ac_link) 2>conftest.err; }; then - # Append any warnings to the config.log. - cat conftest.err 1>&5 - - for ac_file in conftest.*; do - case $ac_file in - *.c | *.err | *.$objext ) ;; - *) ac_cv_exeext=.`echo $ac_file | sed -e s/conftest.//` ;; - esac - done - else - cat conftest.err 1>&5 - echo "$progname: failed program was:" >&5 - cat conftest.c >&5 - fi - $rm conftest* -fi -if test "X$ac_cv_exeext" = Xno; then - exeext="" -else - exeext="$ac_cv_exeext" -fi -echo "$ac_t$ac_cv_exeext" 1>&6 - -echo $ac_n "checking for $compiler option to produce PIC... $ac_c" 1>&6 -pic_flag= -special_shlib_compile_flags= -wl= -link_static_flag= -no_builtin_flag= - -if test "$with_gcc" = yes; then - wl='-Wl,' - link_static_flag='-static' - - case "$host_os" in - beos* | irix5* | irix6* | osf3* | osf4* | osf5*) - # PIC is the default for these OSes. - ;; - aix*) - # Below there is a dirty hack to force normal static linking with -ldl - # The problem is because libdl dynamically linked with both libc and - # libC (AIX C++ library), which obviously doesn't included in libraries - # list by gcc. This cause undefined symbols with -static flags. - # This hack allows C programs to be linked with "-static -ldl", but - # we not sure about C++ programs. - link_static_flag="$link_static_flag ${wl}-lC" - ;; - cygwin* | mingw* | os2*) - # We can build DLLs from non-PIC. - ;; - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - pic_flag='-fno-common' - ;; - amigaos*) - # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. - pic_flag='-m68020 -resident32 -malways-restore-a4' - ;; - sysv4*MP*) - if test -d /usr/nec; then - pic_flag=-Kconform_pic - fi - ;; - *) - pic_flag='-fPIC' - ;; - esac -else - # PORTME Check for PIC flags for the system compiler. - case "$host_os" in - aix3* | aix4*) - # All AIX code is PIC. - link_static_flag='-bnso -bI:/lib/syscalls.exp' - ;; - - hpux9* | hpux10* | hpux11*) - # Is there a better link_static_flag that works with the bundled CC? - wl='-Wl,' - link_static_flag="${wl}-a ${wl}archive" - pic_flag='+Z' - ;; - - irix5* | irix6*) - wl='-Wl,' - link_static_flag='-non_shared' - # PIC (with -KPIC) is the default. - ;; - - cygwin* | mingw* | os2*) - # We can build DLLs from non-PIC. - ;; - - osf3* | osf4* | osf5*) - # All OSF/1 code is PIC. - wl='-Wl,' - link_static_flag='-non_shared' - ;; - - sco3.2v5*) - pic_flag='-Kpic' - link_static_flag='-dn' - special_shlib_compile_flags='-belf' - ;; - - solaris*) - pic_flag='-KPIC' - link_static_flag='-Bstatic' - wl='-Wl,' - ;; - - sunos4*) - pic_flag='-PIC' - link_static_flag='-Bstatic' - wl='-Qoption ld ' - ;; - - sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) - pic_flag='-KPIC' - link_static_flag='-Bstatic' - wl='-Wl,' - ;; - - uts4*) - pic_flag='-pic' - link_static_flag='-Bstatic' - ;; - sysv4*MP*) - if test -d /usr/nec ;then - pic_flag='-Kconform_pic' - link_static_flag='-Bstatic' - fi - ;; - *) - can_build_shared=no - ;; - esac -fi - -if test -n "$pic_flag"; then - echo "$ac_t$pic_flag" 1>&6 - - # Check to make sure the pic_flag actually works. - echo $ac_n "checking if $compiler PIC flag $pic_flag works... $ac_c" 1>&6 - $rm conftest* - echo "int some_variable = 0;" > conftest.c - save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $pic_flag -DPIC" - echo "$progname:781: checking if $compiler PIC flag $pic_flag works" >&5 - if { (eval echo $progname:782: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.$objext; then - # Append any warnings to the config.log. - cat conftest.err 1>&5 - - case "$host_os" in - hpux9* | hpux10* | hpux11*) - # On HP-UX, both CC and GCC only warn that PIC is supported... then they - # create non-PIC objects. So, if there were any warnings, we assume that - # PIC is not supported. - if test -s conftest.err; then - echo "$ac_t"no 1>&6 - can_build_shared=no - pic_flag= - else - echo "$ac_t"yes 1>&6 - pic_flag=" $pic_flag" - fi - ;; - *) - echo "$ac_t"yes 1>&6 - pic_flag=" $pic_flag" - ;; - esac - else - # Append any errors to the config.log. - cat conftest.err 1>&5 - can_build_shared=no - pic_flag= - echo "$ac_t"no 1>&6 - fi - CFLAGS="$save_CFLAGS" - $rm conftest* -else - echo "$ac_t"none 1>&6 -fi - -# Check to see if options -o and -c are simultaneously supported by compiler -echo $ac_n "checking if $compiler supports -c -o file.o... $ac_c" 1>&6 -$rm -r conftest 2>/dev/null -mkdir conftest -cd conftest -$rm conftest* -echo "int some_variable = 0;" > conftest.c -mkdir out -# According to Tom Tromey, Ian Lance Taylor reported there are C compilers -# that will create temporary files in the current directory regardless of -# the output directory. Thus, making CWD read-only will cause this test -# to fail, enabling locking or at least warning the user not to do parallel -# builds. -chmod -w . -save_CFLAGS="$CFLAGS" -CFLAGS="$CFLAGS -o out/conftest2.o" -echo "$progname:834: checking if $compiler supports -c -o file.o" >&5 -if { (eval echo $progname:835: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.o; then - - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - if test -s out/conftest.err; then - echo "$ac_t"no 1>&6 - compiler_c_o=no - else - echo "$ac_t"yes 1>&6 - compiler_c_o=yes - fi -else - # Append any errors to the config.log. - cat out/conftest.err 1>&5 - compiler_c_o=no - echo "$ac_t"no 1>&6 -fi -CFLAGS="$save_CFLAGS" -chmod u+w . -$rm conftest* out/* -rmdir out -cd .. -rmdir conftest -$rm -r conftest 2>/dev/null - -if test x"$compiler_c_o" = x"yes"; then - # Check to see if we can write to a .lo - echo $ac_n "checking if $compiler supports -c -o file.lo... $ac_c" 1>&6 - $rm conftest* - echo "int some_variable = 0;" > conftest.c - save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS -c -o conftest.lo" - echo "$progname:867: checking if $compiler supports -c -o file.lo" >&5 -if { (eval echo $progname:868: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.lo; then - - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - if test -s conftest.err; then - echo "$ac_t"no 1>&6 - compiler_o_lo=no - else - echo "$ac_t"yes 1>&6 - compiler_o_lo=yes - fi - else - # Append any errors to the config.log. - cat conftest.err 1>&5 - compiler_o_lo=no - echo "$ac_t"no 1>&6 - fi - CFLAGS="$save_CFLAGS" - $rm conftest* -else - compiler_o_lo=no -fi - -# Check to see if we can do hard links to lock some files if needed -hard_links="nottested" -if test "$compiler_c_o" = no && test "$need_locks" != no; then - # do not overwrite the value of need_locks provided by the user - echo $ac_n "checking if we can lock with hard links... $ac_c" 1>&6 - hard_links=yes - $rm conftest* - ln conftest.a conftest.b 2>/dev/null && hard_links=no - touch conftest.a - ln conftest.a conftest.b 2>&5 || hard_links=no - ln conftest.a conftest.b 2>/dev/null && hard_links=no - echo "$ac_t$hard_links" 1>&6 - $rm conftest* - if test "$hard_links" = no; then - echo "*** WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2 - need_locks=warn - fi -else - need_locks=no -fi - -if test "$with_gcc" = yes; then - # Check to see if options -fno-rtti -fno-exceptions are supported by compiler - echo $ac_n "checking if $compiler supports -fno-rtti -fno-exceptions ... $ac_c" 1>&6 - $rm conftest* - echo "int some_variable = 0;" > conftest.c - save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -c conftest.c" - echo "$progname:919: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 - if { (eval echo $progname:920: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.o; then - - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - if test -s conftest.err; then - echo "$ac_t"no 1>&6 - compiler_rtti_exceptions=no - else - echo "$ac_t"yes 1>&6 - compiler_rtti_exceptions=yes - fi - else - # Append any errors to the config.log. - cat conftest.err 1>&5 - compiler_rtti_exceptions=no - echo "$ac_t"no 1>&6 - fi - CFLAGS="$save_CFLAGS" - $rm conftest* - - if test "$compiler_rtti_exceptions" = "yes"; then - no_builtin_flag=' -fno-builtin -fno-rtti -fno-exceptions' - else - no_builtin_flag=' -fno-builtin' - fi - -fi - -# Check for any special shared library compilation flags. -if test -n "$special_shlib_compile_flags"; then - echo "$progname: warning: \`$CC' requires \`$special_shlib_compile_flags' to build shared libraries" 1>&2 - if echo "$old_CC $old_CFLAGS " | egrep -e "[ ]$special_shlib_compile_flags[ ]" >/dev/null; then : - else - echo "$progname: add \`$special_shlib_compile_flags' to the CC or CFLAGS env variable and reconfigure" 1>&2 - can_build_shared=no - fi -fi - -echo $ac_n "checking if $compiler static flag $link_static_flag works... $ac_c" 1>&6 -$rm conftest* -echo 'main(){return(0);}' > conftest.c -save_LDFLAGS="$LDFLAGS" -LDFLAGS="$LDFLAGS $link_static_flag" -echo "$progname:963: checking if $compiler static flag $link_static_flag works" >&5 -if { (eval echo $progname:964: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then - echo "$ac_t$link_static_flag" 1>&6 -else - echo "$ac_t"none 1>&6 - link_static_flag= -fi -LDFLAGS="$save_LDFLAGS" -$rm conftest* - -if test -z "$LN_S"; then - # Check to see if we can use ln -s, or we need hard links. - echo $ac_n "checking whether ln -s works... $ac_c" 1>&6 - $rm conftest.dat - if ln -s X conftest.dat 2>/dev/null; then - $rm conftest.dat - LN_S="ln -s" - else - LN_S=ln - fi - if test "$LN_S" = "ln -s"; then - echo "$ac_t"yes 1>&6 - else - echo "$ac_t"no 1>&6 - fi -fi - -# Make sure LD is an absolute path. -if test -z "$LD"; then - ac_prog=ld - if test "$with_gcc" = yes; then - # Check if gcc -print-prog-name=ld gives a path. - echo $ac_n "checking for ld used by GCC... $ac_c" 1>&6 - echo "$progname:996: checking for ld used by GCC" >&5 - ac_prog=`($CC -print-prog-name=ld) 2>&5` - case "$ac_prog" in - # Accept absolute paths. - [\\/]* | [A-Za-z]:[\\/]*) - re_direlt='/[^/][^/]*/\.\./' - # Canonicalize the path of ld - ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` - while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do - ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` - done - test -z "$LD" && LD="$ac_prog" - ;; - "") - # If it fails, then pretend we are not using GCC. - ac_prog=ld - ;; - *) - # If it is relative, then search for the first ld in PATH. - with_gnu_ld=unknown - ;; - esac - elif test "$with_gnu_ld" = yes; then - echo $ac_n "checking for GNU ld... $ac_c" 1>&6 - echo "$progname:1020: checking for GNU ld" >&5 - else - echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6 - echo "$progname:1023: checking for non-GNU ld" >&5 - fi - - if test -z "$LD"; then - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" - for ac_dir in $PATH; do - test -z "$ac_dir" && ac_dir=. - if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then - LD="$ac_dir/$ac_prog" - # Check to see if the program is GNU ld. I'd rather use --version, - # but apparently some GNU ld's only accept -v. - # Break only if it was the GNU/non-GNU ld that we prefer. - if "$LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then - test "$with_gnu_ld" != no && break - else - test "$with_gnu_ld" != yes && break - fi - fi - done - IFS="$ac_save_ifs" - fi - - if test -n "$LD"; then - echo "$ac_t$LD" 1>&6 - else - echo "$ac_t"no 1>&6 - fi - - if test -z "$LD"; then - echo "$progname: error: no acceptable ld found in \$PATH" 1>&2 - exit 1 - fi -fi - -# Check to see if it really is or is not GNU ld. -echo $ac_n "checking if the linker ($LD) is GNU ld... $ac_c" 1>&6 -# I'd rather use --version here, but apparently some GNU ld's only accept -v. -if $LD -v 2>&1 &5; then - with_gnu_ld=yes -else - with_gnu_ld=no -fi -echo "$ac_t$with_gnu_ld" 1>&6 - -# See if the linker supports building shared libraries. -echo $ac_n "checking whether the linker ($LD) supports shared libraries... $ac_c" 1>&6 - -allow_undefined_flag= -no_undefined_flag= -need_lib_prefix=unknown -need_version=unknown -# when you set need_version to no, make sure it does not cause -set_version -# flags to be left without arguments -archive_cmds= -archive_expsym_cmds= -old_archive_from_new_cmds= -export_dynamic_flag_spec= -whole_archive_flag_spec= -thread_safe_flag_spec= -hardcode_libdir_flag_spec= -hardcode_libdir_separator= -hardcode_direct=no -hardcode_minus_L=no -hardcode_shlibpath_var=unsupported -runpath_var= -always_export_symbols=no -export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | sed '\''s/.* //'\'' | sort | uniq > $export_symbols' -# include_expsyms should be a list of space-separated symbols to be *always* -# included in the symbol list -include_expsyms= -# exclude_expsyms can be an egrep regular expression of symbols to exclude -# it will be wrapped by ` (' and `)$', so one must not match beginning or -# end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', -# as well as any symbol that contains `d'. -exclude_expsyms="_GLOBAL_OFFSET_TABLE_" -# Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out -# platforms (ab)use it in PIC code, but their linkers get confused if -# the symbol is explicitly referenced. Since portable code cannot -# rely on this symbol name, it's probably fine to never include it in -# preloaded symbol tables. - -case "$host_os" in -cygwin* | mingw*) - # FIXME: the MSVC++ port hasn't been tested in a loooong time - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - if test "$with_gcc" != yes; then - with_gnu_ld=no - fi - ;; - -esac - -ld_shlibs=yes -if test "$with_gnu_ld" = yes; then - # If archive_cmds runs LD, not CC, wlarc should be empty - wlarc='${wl}' - - # See if GNU ld supports shared libraries. - case "$host_os" in - aix3* | aix4*) - # On AIX, the GNU linker is very broken - ld_shlibs=no - cat <&2 - -*** Warning: the GNU linker, at least up to release 2.9.1, is reported -*** to be unable to reliably create shared libraries on AIX. -*** Therefore, libtool is disabling shared libraries support. If you -*** really care for shared libraries, you may want to modify your PATH -*** so that a non-GNU linker is found, and then restart. - -EOF - ;; - - amigaos*) - archive_cmds='$rm $objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $objdir/a2ixlibrary.data~$AR cru $lib $libobjs~$RANLIB $lib~(cd $objdir && a2ixlibrary -32)' - hardcode_libdir_flag_spec='-L$libdir' - hardcode_minus_L=yes - - # Samuel A. Falvo II reports - # that the semantics of dynamic libraries on AmigaOS, at least up - # to version 4, is to share data among multiple programs linked - # with the same dynamic library. Since this doesn't match the - # behavior of shared libraries on other platforms, we can use - # them. - ld_shlibs=no - ;; - - beos*) - if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then - allow_undefined_flag=unsupported - # Joseph Beckenbach says some releases of gcc - # support --undefined. This deserves some investigation. FIXME - archive_cmds='$CC -nostart $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib' - else - ld_shlibs=no - fi - ;; - - cygwin* | mingw*) - # hardcode_libdir_flag_spec is actually meaningless, as there is - # no search path for DLLs. - hardcode_libdir_flag_spec='-L$libdir' - allow_undefined_flag=unsupported - always_export_symbols=yes - - # Extract the symbol export list from an `--export-all' def file, - # then regenerate the def file from the symbol export list, so that - # the compiled dll only exports the symbol export list. - # Be careful not to strip the DATA tag left by newer dlltools. - export_symbols_cmds='test -f $objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $0 > $objdir/$soname-ltdll.c~ - test -f $objdir/$soname-ltdll.$objext || (cd $objdir && $CC -c $soname-ltdll.c)~ - $DLLTOOL --export-all --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --output-def $objdir/$soname-def $objdir/$soname-ltdll.$objext $libobjs $convenience~ - sed -e "1,/EXPORTS/d" -e "s/ @ [0-9]*//" -e "s/ *;.*$//" < $objdir/$soname-def > $export_symbols' - - # If DATA tags from a recent dlltool are present, honour them! - archive_expsym_cmds='echo EXPORTS > $objdir/$soname-def~ - _lt_hint=1; - cat $export_symbols | while read symbol; do - set dummy \$symbol; - case \$# in - 2) echo " \$2 @ \$_lt_hint ; " >> $objdir/$soname-def;; - *) echo " \$2 @ \$_lt_hint \$3 ; " >> $objdir/$soname-def;; - esac; - _lt_hint=`expr 1 + \$_lt_hint`; - done~ - test -f $objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $0 > $objdir/$soname-ltdll.c~ - test -f $objdir/$soname-ltdll.$objext || (cd $objdir && $CC -c $soname-ltdll.c)~ - $CC -Wl,--base-file,$objdir/$soname-base -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts~ - $DLLTOOL --as=$AS --dllname $soname --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --def $objdir/$soname-def --base-file $objdir/$soname-base --output-exp $objdir/$soname-exp~ - $CC -Wl,--base-file,$objdir/$soname-base $objdir/$soname-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts~ - $DLLTOOL --as=$AS --dllname $soname --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --def $objdir/$soname-def --base-file $objdir/$soname-base --output-exp $objdir/$soname-exp~ - $CC $objdir/$soname-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts' - - old_archive_from_new_cmds='$DLLTOOL --as=$AS --dllname $soname --def $objdir/$soname-def --output-lib $objdir/$libname.a' - ;; - - netbsd*) - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - archive_cmds='$LD -Bshareable $libobjs $deplibs $linkopts -o $lib' - # can we support soname and/or expsyms with a.out? -oliva - fi - ;; - - solaris* | sysv5*) - if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then - ld_shlibs=no - cat <&2 - -*** Warning: The releases 2.8.* of the GNU linker cannot reliably -*** create shared libraries on Solaris systems. Therefore, libtool -*** is disabling shared libraries support. We urge you to upgrade GNU -*** binutils to release 2.9.1 or newer. Another option is to modify -*** your PATH or compiler configuration so that the native linker is -*** used, and then restart. - -EOF - elif $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then - archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - ld_shlibs=no - fi - ;; - - sunos4*) - archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linkopts' - wlarc= - hardcode_direct=yes - hardcode_shlibpath_var=no - ;; - - *) - if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then - archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - ld_shlibs=no - fi - ;; - esac - - if test "$ld_shlibs" = yes; then - runpath_var=LD_RUN_PATH - hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir' - export_dynamic_flag_spec='${wl}--export-dynamic' - case $host_os in - cygwin* | mingw*) - # dlltool doesn't understand --whole-archive et. al. - whole_archive_flag_spec= - ;; - *) - # ancient GNU ld didn't support --whole-archive et. al. - if $LD --help 2>&1 | egrep 'no-whole-archive' > /dev/null; then - whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - else - whole_archive_flag_spec= - fi - ;; - esac - fi -else - # PORTME fill in a description of your system's linker (not GNU ld) - case "$host_os" in - aix3*) - allow_undefined_flag=unsupported - always_export_symbols=yes - archive_expsym_cmds='$LD -o $objdir/$soname $libobjs $deplibs $linkopts -bE:$export_symbols -T512 -H512 -bM:SRE~$AR cru $lib $objdir/$soname' - # Note: this linker hardcodes the directories in LIBPATH if there - # are no directories specified by -L. - hardcode_minus_L=yes - if test "$with_gcc" = yes && test -z "$link_static_flag"; then - # Neither direct hardcoding nor static linking is supported with a - # broken collect2. - hardcode_direct=unsupported - fi - ;; - - aix4*) - hardcode_libdir_flag_spec='${wl}-b ${wl}nolibpath ${wl}-b ${wl}libpath:$libdir:/usr/lib:/lib' - hardcode_libdir_separator=':' - if test "$with_gcc" = yes; then - collect2name=`${CC} -print-prog-name=collect2` - if test -f "$collect2name" && \ - strings "$collect2name" | grep resolve_lib_name >/dev/null - then - # We have reworked collect2 - hardcode_direct=yes - else - # We have old collect2 - hardcode_direct=unsupported - # It fails to find uninstalled libraries when the uninstalled - # path is not listed in the libpath. Setting hardcode_minus_L - # to unsupported forces relinking - hardcode_minus_L=yes - hardcode_libdir_flag_spec='-L$libdir' - hardcode_libdir_separator= - fi - shared_flag='-shared' - else - shared_flag='${wl}-bM:SRE' - hardcode_direct=yes - fi - allow_undefined_flag=' ${wl}-berok' - archive_cmds="\$CC $shared_flag"' -o $objdir/$soname $libobjs $deplibs $linkopts ${wl}-bexpall ${wl}-bnoentry${allow_undefined_flag}' - archive_expsym_cmds="\$CC $shared_flag"' -o $objdir/$soname $libobjs $deplibs $linkopts ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}' - case "$host_os" in aix4.[01]|aix4.[01].*) - # According to Greg Wooledge, -bexpall is only supported from AIX 4.2 on - always_export_symbols=yes ;; - esac - ;; - - amigaos*) - archive_cmds='$rm $objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $objdir/a2ixlibrary.data~$AR cru $lib $libobjs~$RANLIB $lib~(cd $objdir && a2ixlibrary -32)' - hardcode_libdir_flag_spec='-L$libdir' - hardcode_minus_L=yes - # see comment about different semantics on the GNU ld section - ld_shlibs=no - ;; - - cygwin* | mingw*) - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - # hardcode_libdir_flag_spec is actually meaningless, as there is - # no search path for DLLs. - hardcode_libdir_flag_spec=' ' - allow_undefined_flag=unsupported - # Tell ltmain to make .lib files, not .a files. - libext=lib - # FIXME: Setting linknames here is a bad hack. - archive_cmds='$CC -o $lib $libobjs $linkopts `echo "$deplibs" | sed -e '\''s/ -lc$//'\''` -link -dll~linknames=' - # The linker will automatically build a .lib file if we build a DLL. - old_archive_from_new_cmds='true' - # FIXME: Should let the user specify the lib program. - old_archive_cmds='lib /OUT:$oldlib$oldobjs' - fix_srcfile_path='`cygpath -w $srcfile`' - ;; - - freebsd1*) - ld_shlibs=no - ;; - - # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor - # support. Future versions do this automatically, but an explicit c++rt0.o - # does not break anything, and helps significantly (at the cost of a little - # extra space). - freebsd2.2*) - archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts /usr/lib/c++rt0.o' - hardcode_libdir_flag_spec='-R$libdir' - hardcode_direct=yes - hardcode_shlibpath_var=no - ;; - - # Unfortunately, older versions of FreeBSD 2 do not have this feature. - freebsd2*) - archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts' - hardcode_direct=yes - hardcode_minus_L=yes - hardcode_shlibpath_var=no - ;; - - # FreeBSD 3 and greater uses gcc -shared to do shared libraries. - freebsd*) - archive_cmds='$CC -shared -o $lib $libobjs $deplibs $linkopts' - hardcode_libdir_flag_spec='-R$libdir' - hardcode_direct=yes - hardcode_shlibpath_var=no - ;; - - darwin[15].* | rhapsody*) - allow_undefined_flag='-undefined error' - archive_cmds='$CC $(test x$module = xyes && echo -bundle || echo -dynamiclib) $allow_undefined_flag -o $lib $libobjs $deplibs $linkopts $(test x$module != xyes && echo -install_name $rpath/$soname) $(test -n "$verstring" -a x$verstring != x0.0 && echo $verstring)' - # We need to add '_' to the symbols in $export_symbols first - #archive_expsym_cmds="$archive_cmds"' && strip -s $export_symbols $lib' - hardcode_direct=yes - hardcode_shlibpath_var=no - whole_archive_flag_spec='-all_load $convenience' - ;; - - # Mac OS X v10.2 uses bash for /bin/sh instead of zsh, and the quoting syntax is incompatible - darwin*) - allow_undefined_flag='-undefined error' - archive_cmds='$CC $(test x$module = xyes && echo -bundle || echo -dynamiclib) $allow_undefined_flag -o $lib $libobjs $deplibs $linkopts $(test x$module != xyes && echo -install_name $rpath/$soname $tmp_verstring)' - # We need to add '_' to the symbols in $export_symbols first - #archive_expsym_cmds="$archive_cmds"' && strip -s $export_symbols $lib' - hardcode_direct=yes - hardcode_shlibpath_var=no - whole_archive_flag_spec='-all_load $convenience' - ;; - - hpux9* | hpux10* | hpux11*) - case "$host_os" in - hpux9*) archive_cmds='$rm $objdir/$soname~$LD -b +b $install_libdir -o $objdir/$soname $libobjs $deplibs $linkopts~test $objdir/$soname = $lib || mv $objdir/$soname $lib' ;; - *) archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linkopts' ;; - esac - hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' - hardcode_libdir_separator=: - hardcode_direct=yes - hardcode_minus_L=yes # Not in the search PATH, but as the default - # location of the library. - export_dynamic_flag_spec='${wl}-E' - ;; - - irix5* | irix6*) - if test "$with_gcc" = yes; then - archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' - else - archive_cmds='$LD -shared $libobjs $deplibs $linkopts -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' - fi - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator=: - ;; - - netbsd*) - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts' # a.out - else - archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linkopts' # ELF - fi - hardcode_libdir_flag_spec='${wl}-R$libdir' - hardcode_direct=yes - hardcode_shlibpath_var=no - ;; - - openbsd*) - archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts' - hardcode_libdir_flag_spec='-R$libdir' - hardcode_direct=yes - hardcode_shlibpath_var=no - ;; - - os2*) - hardcode_libdir_flag_spec='-L$libdir' - hardcode_minus_L=yes - allow_undefined_flag=unsupported - archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $objdir/$libname.def~$echo DATA >> $objdir/$libname.def~$echo " SINGLE NONSHARED" >> $objdir/$libname.def~$echo EXPORTS >> $objdir/$libname.def~emxexp $libobjs >> $objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $linkopts $objdir/$libname.def' - old_archive_from_new_cmds='emximp -o $objdir/$libname.a $objdir/$libname.def' - ;; - - osf3*) - if test "$with_gcc" = yes; then - allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $linkopts ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' - else - allow_undefined_flag=' -expect_unresolved \*' - archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linkopts -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' - fi - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator=: - ;; - - osf4* | osf5*) # As osf3* with the addition of the -msym flag - if test "$with_gcc" = yes; then - allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $linkopts ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' - else - allow_undefined_flag=' -expect_unresolved \*' - archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linkopts -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' - fi - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator=: - ;; - - sco3.2v5*) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' - hardcode_shlibpath_var=no - runpath_var=LD_RUN_PATH - hardcode_runpath_var=yes - ;; - - solaris*) - no_undefined_flag=' -z text' - # $CC -shared without GNU ld will not create a library from C++ - # object files and a static libstdc++, better avoid it by now - archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linkopts' - archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linkopts~$rm $lib.exp' - hardcode_libdir_flag_spec='-R$libdir' - hardcode_shlibpath_var=no - case "$host_os" in - solaris2.[0-5] | solaris2.[0-5].*) ;; - *) # Supported since Solaris 2.6 (maybe 2.5.1?) - whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;; - esac - ;; - - sunos4*) - archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linkopts' - hardcode_libdir_flag_spec='-L$libdir' - hardcode_direct=yes - hardcode_minus_L=yes - hardcode_shlibpath_var=no - ;; - - sysv4) - if test "x$host_vendor" = xsequent; then - # Use $CC to link under sequent, because it throws in some extra .o - # files that make .init and .fini sections work. - archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $linkopts' - else - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' - fi - runpath_var='LD_RUN_PATH' - hardcode_shlibpath_var=no - hardcode_direct=no #Motorola manual says yes, but my tests say they lie - ;; - - sysv4.3*) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' - hardcode_shlibpath_var=no - export_dynamic_flag_spec='-Bexport' - ;; - - sysv5*) - no_undefined_flag=' -z text' - # $CC -shared without GNU ld will not create a library from C++ - # object files and a static libstdc++, better avoid it by now - archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linkopts' - archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linkopts~$rm $lib.exp' - hardcode_libdir_flag_spec= - hardcode_shlibpath_var=no - runpath_var='LD_RUN_PATH' - ;; - - uts4*) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' - hardcode_libdir_flag_spec='-L$libdir' - hardcode_shlibpath_var=no - ;; - - dgux*) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' - hardcode_libdir_flag_spec='-L$libdir' - hardcode_shlibpath_var=no - ;; - - sysv4*MP*) - if test -d /usr/nec; then - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' - hardcode_shlibpath_var=no - runpath_var=LD_RUN_PATH - hardcode_runpath_var=yes - ld_shlibs=yes - fi - ;; - - sysv4.2uw2*) - archive_cmds='$LD -G -o $lib $libobjs $deplibs $linkopts' - hardcode_direct=yes - hardcode_minus_L=no - hardcode_shlibpath_var=no - hardcode_runpath_var=yes - runpath_var=LD_RUN_PATH - ;; - - unixware7*) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' - runpath_var='LD_RUN_PATH' - hardcode_shlibpath_var=no - ;; - - *) - ld_shlibs=no - ;; - esac -fi -echo "$ac_t$ld_shlibs" 1>&6 -test "$ld_shlibs" = no && can_build_shared=no - -if test -z "$NM"; then - echo $ac_n "checking for BSD-compatible nm... $ac_c" 1>&6 - case "$NM" in - [\\/]* | [A-Za-z]:[\\/]*) ;; # Let the user override the test with a path. - *) - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" - for ac_dir in $PATH /usr/ucb /usr/ccs/bin /bin; do - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/nm || test -f $ac_dir/nm$ac_exeext; then - # Check to see if the nm accepts a BSD-compat flag. - # Adding the `sed 1q' prevents false positives on HP-UX, which says: - # nm: unknown option "B" ignored - if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then - NM="$ac_dir/nm -B" - break - elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then - NM="$ac_dir/nm -p" - break - else - NM=${NM="$ac_dir/nm"} # keep the first match, but - continue # so that we can try to find one that supports BSD flags - fi - fi - done - IFS="$ac_save_ifs" - test -z "$NM" && NM=nm - ;; - esac - echo "$ac_t$NM" 1>&6 -fi - -# Check for command to grab the raw symbol name followed by C symbol from nm. -echo $ac_n "checking command to parse $NM output... $ac_c" 1>&6 - -# These are sane defaults that work on at least a few old systems. -# [They come from Ultrix. What could be older than Ultrix?!! ;)] - -# Character class describing NM global symbol codes. -symcode='[BCDEGRST]' - -# Regexp to match symbols that can be accessed directly from C. -sympat='\([_A-Za-z][_A-Za-z0-9]*\)' - -# Transform the above into a raw symbol and a C symbol. -symxfrm='\1 \2\3 \3' - -# Transform an extracted symbol line into a proper C declaration -global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'" - -# Define system-specific variables. -case "$host_os" in -aix*) - symcode='[BCDT]' - ;; -cygwin* | mingw*) - symcode='[ABCDGISTW]' - ;; -hpux*) # Its linker distinguishes data from code symbols - global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^. .* \(.*\)$/extern char \1;/p'" - ;; -irix*) - symcode='[BCDEGRST]' - ;; -solaris*) - symcode='[BDT]' - ;; -sysv4) - symcode='[DFNSTU]' - ;; -esac - -# If we're using GNU nm, then use its standard symbol codes. -if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then - symcode='[ABCDGISTW]' -fi - -# Try without a prefix undercore, then with it. -for ac_symprfx in "" "_"; do - - # Write the raw and C identifiers. - global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode\)[ ][ ]*\($ac_symprfx\)$sympat$/$symxfrm/p'" - - # Check to see that the pipe works correctly. - pipe_works=no - $rm conftest* - cat > conftest.c <&5 - if { (eval echo $progname:1663: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; } && test -s conftest.$objext; then - # Now try to grab the symbols. - nlist=conftest.nm - if { echo "$progname:1666: eval \"$NM conftest.$objext | $global_symbol_pipe > $nlist\"" >&5; eval "$NM conftest.$objext | $global_symbol_pipe > $nlist 2>&5"; } && test -s "$nlist"; then - - # Try sorting and uniquifying the output. - if sort "$nlist" | uniq > "$nlist"T; then - mv -f "$nlist"T "$nlist" - else - rm -f "$nlist"T - fi - - # Make sure that we snagged all the symbols we need. - if egrep ' nm_test_var$' "$nlist" >/dev/null; then - if egrep ' nm_test_func$' "$nlist" >/dev/null; then - cat < conftest.c -#ifdef __cplusplus -extern "C" { -#endif - -EOF - # Now generate the symbol file. - eval "$global_symbol_to_cdecl"' < "$nlist" >> conftest.c' - - cat <> conftest.c -#if defined (__STDC__) && __STDC__ -# define lt_ptr_t void * -#else -# define lt_ptr_t char * -# define const -#endif - -/* The mapping between symbol names and symbols. */ -const struct { - const char *name; - lt_ptr_t address; -} -lt_preloaded_symbols[] = -{ -EOF - sed 's/^. \(.*\) \(.*\)$/ {"\2", (lt_ptr_t) \&\2},/' < "$nlist" >> conftest.c - cat <<\EOF >> conftest.c - {0, (lt_ptr_t) 0} -}; - -#ifdef __cplusplus -} -#endif -EOF - # Now try linking the two files. - mv conftest.$objext conftstm.$objext - save_LIBS="$LIBS" - save_CFLAGS="$CFLAGS" - LIBS="conftstm.$objext" - CFLAGS="$CFLAGS$no_builtin_flag" - if { (eval echo $progname:1718: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then - pipe_works=yes - else - echo "$progname: failed program was:" >&5 - cat conftest.c >&5 - fi - LIBS="$save_LIBS" - else - echo "cannot find nm_test_func in $nlist" >&5 - fi - else - echo "cannot find nm_test_var in $nlist" >&5 - fi - else - echo "cannot run $global_symbol_pipe" >&5 - fi - else - echo "$progname: failed program was:" >&5 - cat conftest.c >&5 - fi - $rm conftest* conftst* - - # Do not use the global_symbol_pipe unless it works. - if test "$pipe_works" = yes; then - break - else - global_symbol_pipe= - fi -done -if test "$pipe_works" = yes; then - echo "${ac_t}ok" 1>&6 -else - echo "${ac_t}failed" 1>&6 -fi - -if test -z "$global_symbol_pipe"; then - global_symbol_to_cdecl= -fi - -# Check hardcoding attributes. -echo $ac_n "checking how to hardcode library paths into programs... $ac_c" 1>&6 -hardcode_action= -if test -n "$hardcode_libdir_flag_spec" || \ - test -n "$runpath_var"; then - - # We can hardcode non-existant directories. - if test "$hardcode_direct" != no && - # If the only mechanism to avoid hardcoding is shlibpath_var, we - # have to relink, otherwise we might link with an installed library - # when we should be linking with a yet-to-be-installed one - ## test "$hardcode_shlibpath_var" != no && - test "$hardcode_minus_L" != no; then - # Linking always hardcodes the temporary library directory. - hardcode_action=relink - else - # We can link without hardcoding, and we can hardcode nonexisting dirs. - hardcode_action=immediate - fi -else - # We cannot hardcode anything, or else we can only hardcode existing - # directories. - hardcode_action=unsupported -fi -echo "$ac_t$hardcode_action" 1>&6 - - -reload_flag= -reload_cmds='$LD$reload_flag -o $output$reload_objs' -echo $ac_n "checking for $LD option to reload object files... $ac_c" 1>&6 -# PORTME Some linkers may need a different reload flag. -reload_flag='-r' -echo "$ac_t$reload_flag" 1>&6 -test -n "$reload_flag" && reload_flag=" $reload_flag" - -# PORTME Fill in your ld.so characteristics -library_names_spec= -libname_spec='lib$name' -soname_spec= -postinstall_cmds= -postuninstall_cmds= -finish_cmds= -finish_eval= -shlibpath_var= -shlibpath_overrides_runpath=unknown -version_type=none -dynamic_linker="$host_os ld.so" -sys_lib_dlsearch_path_spec="/lib /usr/lib" -sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" -file_magic_cmd= -file_magic_test_file= -deplibs_check_method='unknown' -# Need to set the preceding variable on all platforms that support -# interlibrary dependencies. -# 'none' -- dependencies not supported. -# `unknown' -- same as none, but documents that we really don't know. -# 'pass_all' -- all dependencies passed with no checks. -# 'test_compile' -- check by making test program. -# 'file_magic [regex]' -- check by looking for files in library path -# which responds to the $file_magic_cmd with a given egrep regex. -# If you have `file' or equivalent on your system and you're not sure -# whether `pass_all' will *always* work, you probably want this one. -echo $ac_n "checking dynamic linker characteristics... $ac_c" 1>&6 -case "$host_os" in -aix3*) - version_type=linux - library_names_spec='${libname}${release}.so$versuffix $libname.a' - shlibpath_var=LIBPATH - - # AIX has no versioning support, so we append a major version to the name. - soname_spec='${libname}${release}.so$major' - ;; - -aix4*) - version_type=linux - # AIX has no versioning support, so currently we can not hardcode correct - # soname into executable. Probably we can add versioning support to - # collect2, so additional links can be useful in future. - # We preserve .a as extension for shared libraries though AIX4.2 - # and later linker supports .so - library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.a' - shlibpath_var=LIBPATH - deplibs_check_method=pass_all - ;; - -amigaos*) - library_names_spec='$libname.ixlibrary $libname.a' - # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done' - ;; - -beos*) - library_names_spec='${libname}.so' - dynamic_linker="$host_os ld.so" - shlibpath_var=LIBRARY_PATH - deplibs_check_method=pass_all - lt_cv_dlopen="load_add_on" - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - ;; - -bsdi4*) - version_type=linux - need_version=no - library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' - soname_spec='${libname}${release}.so$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' - file_magic_cmd=/usr/bin/file - file_magic_test_file=/shlib/libc.so - sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" - sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" - export_dynamic_flag_spec=-rdynamic - # the default ld.so.conf also contains /usr/contrib/lib and - # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow - # libtool to hard-code these into programs - ;; - -cygwin* | mingw*) - version_type=windows - need_version=no - need_lib_prefix=no - if test "$with_gcc" = yes; then - library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.a' - else - library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.lib' - fi - dynamic_linker='Win32 ld.exe' - deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' - file_magic_cmd='${OBJDUMP} -f' - # FIXME: first we should search . and the directory the executable is in - shlibpath_var=PATH - lt_cv_dlopen="LoadLibrary" - lt_cv_dlopen_libs= - ;; - -freebsd1*) - dynamic_linker=no - ;; - -freebsd*) - objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` - version_type=freebsd-$objformat - case "$version_type" in - freebsd-elf*) - deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB shared object' - file_magic_cmd=/usr/bin/file - file_magic_test_file=`echo /usr/lib/libc.so*` - library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so' - need_version=no - need_lib_prefix=no - ;; - freebsd-*) - deplibs_check_method=unknown - library_names_spec='${libname}${release}.so$versuffix $libname.so$versuffix' - need_version=yes - ;; - esac - shlibpath_var=LD_LIBRARY_PATH - case "$host_os" in - freebsd2* | freebsd3.[01]* | freebsdelf3.[01]*) - shlibpath_overrides_runpath=yes - ;; - *) # from 3.2 on - shlibpath_overrides_runpath=no - ;; - esac - ;; - -darwin* | rhapsody*) - dynamic_linker="$host_os dyld" - version_type=darwin - need_lib_prefix=no - need_version=no - deplibs_check_method='file_magic Mach-O (64-bit )?dynamically linked shared library' - file_magic_cmd='/usr/bin/file -L' - case "$host_os" in - rhapsody* | darwin1.[012]) - file_magic_test_file='/System/Library/Frameworks/System.framework/System' - ;; - *) # Darwin 1.3 on - file_magic_test_file='/usr/lib/libSystem.dylib' - ;; - esac - library_names_spec='${libname}${release}${versuffix}.$(test x$module = xyes && echo so || echo dylib) ${libname}${release}${major}.$(test x$module = xyes && echo so || echo dylib) ${libname}.$(test x$module = xyes && echo so || echo dylib)' - soname_spec='${libname}${release}${major}.$(test x$module = xyes && echo so || echo dylib)' - shlibpath_overrides_runpath=yes - shlibpath_var=DYLD_LIBRARY_PATH - ;; - -gnu*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so${major} ${libname}.so' - soname_spec='${libname}${release}.so$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -hpux9* | hpux10* | hpux11*) - # Give a soname corresponding to the major version so that dld.sl refuses to - # link against other versions. - dynamic_linker="$host_os dld.sl" - version_type=sunos - need_lib_prefix=no - need_version=no - shlibpath_var=SHLIB_PATH - shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH - library_names_spec='${libname}${release}.sl$versuffix ${libname}${release}.sl$major $libname.sl' - soname_spec='${libname}${release}.sl$major' - # HP-UX runs *really* slowly unless shared libraries are mode 555. - postinstall_cmds='chmod 555 $lib' - case "$host_os" in - hpux10.20*) - # TODO: Does this work for hpux-11 too? - deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library' - file_magic_cmd=/usr/bin/file - file_magic_test_file=/usr/lib/libc.sl - ;; - esac - ;; - -irix5* | irix6*) - version_type=irix - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}.so.$major' - library_names_spec='${libname}${release}.so.$versuffix ${libname}${release}.so.$major ${libname}${release}.so $libname.so' - case "$host_os" in - irix5*) - libsuff= shlibsuff= - # this will be overridden with pass_all, but let us keep it just in case - deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1" - ;; - *) - case "$LD" in # libtool.m4 will add one of these switches to LD - *-32|*"-32 ") libsuff= shlibsuff= libmagic=32-bit;; - *-n32|*"-n32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; - *-64|*"-64 ") libsuff=64 shlibsuff=64 libmagic=64-bit;; - *) libsuff= shlibsuff= libmagic=never-match;; - esac - ;; - esac - shlibpath_var=LD_LIBRARY${shlibsuff}_PATH - shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" - sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" - file_magic_cmd=/usr/bin/file - file_magic_test_file=`echo /lib${libsuff}/libc.so*` - deplibs_check_method='pass_all' - ;; - -# No shared lib support for Linux oldld, aout, or coff. -linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*) - dynamic_linker=no - ;; - -# This must be Linux ELF. -linux-gnu*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' - soname_spec='${libname}${release}.so$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - deplibs_check_method=pass_all - - if test -f /lib/ld.so.1; then - dynamic_linker='GNU ld.so' - else - # Only the GNU ld.so supports shared libraries on MkLinux. - case "$host_cpu" in - powerpc*) dynamic_linker=no ;; - *) dynamic_linker='Linux ld.so' ;; - esac - fi - ;; - -netbsd*) - version_type=sunos - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - dynamic_linker='NetBSD (a.out) ld.so' - else - library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so ${libname}.so' - soname_spec='${libname}${release}.so$major' - dynamic_linker='NetBSD ld.elf_so' - fi - shlibpath_var=LD_LIBRARY_PATH - ;; - -openbsd*) - version_type=sunos - if test "$with_gnu_ld" = yes; then - need_lib_prefix=no - need_version=no - fi - library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - shlibpath_var=LD_LIBRARY_PATH - ;; - -os2*) - libname_spec='$name' - need_lib_prefix=no - library_names_spec='$libname.dll $libname.a' - dynamic_linker='OS/2 ld.exe' - shlibpath_var=LIBPATH - ;; - -osf3* | osf4* | osf5*) - version_type=osf - need_version=no - soname_spec='${libname}${release}.so' - library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so' - shlibpath_var=LD_LIBRARY_PATH - # this will be overridden with pass_all, but let us keep it just in case - deplibs_check_method='file_magic COFF format alpha shared library' - file_magic_cmd=/usr/bin/file - file_magic_test_file=/shlib/libc.so - deplibs_check_method='pass_all' - sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" - sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" - ;; - -sco3.2v5*) - version_type=osf - soname_spec='${libname}${release}.so$major' - library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' - shlibpath_var=LD_LIBRARY_PATH - ;; - -solaris*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' - soname_spec='${libname}${release}.so$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - # ldd complains unless libraries are executable - postinstall_cmds='chmod +x $lib' - deplibs_check_method="file_magic ELF [0-9][0-9]-bit [LM]SB dynamic lib" - file_magic_cmd=/usr/bin/file - file_magic_test_file=/lib/libc.so - ;; - -sunos4*) - version_type=sunos - library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' - finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - if test "$with_gnu_ld" = yes; then - need_lib_prefix=no - fi - need_version=yes - ;; - -sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) - version_type=linux - library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' - soname_spec='${libname}${release}.so$major' - shlibpath_var=LD_LIBRARY_PATH - case "$host_vendor" in - sequent) - file_magic_cmd='/bin/file' - deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' - ;; - ncr) - deplibs_check_method='pass_all' - ;; - motorola) - need_lib_prefix=no - need_version=no - shlibpath_overrides_runpath=no - sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' - deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' - file_magic_cmd=/usr/bin/file - file_magic_test_file=`echo /usr/lib/libc.so*` - ;; - esac - ;; - -uts4*) - version_type=linux - library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' - soname_spec='${libname}${release}.so$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -dgux*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' - soname_spec='${libname}${release}.so$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -sysv4*MP*) - if test -d /usr/nec ;then - version_type=linux - library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so' - soname_spec='$libname.so.$major' - shlibpath_var=LD_LIBRARY_PATH - fi - ;; - -*) - dynamic_linker=no - ;; -esac -echo "$ac_t$dynamic_linker" 1>&6 -test "$dynamic_linker" = no && can_build_shared=no - -# Report the final consequences. -echo "checking if libtool supports shared libraries... $can_build_shared" 1>&6 - -# Only try to build win32 dlls if AC_LIBTOOL_WIN32_DLL was used in -# configure.in, otherwise build static only libraries. -case "$host_os" in -cygwin* | mingw* | os2*) - if test x$can_build_shared = xyes; then - test x$enable_win32_dll = xno && can_build_shared=no - echo "checking if package supports dlls... $can_build_shared" 1>&6 - fi -;; -esac - -if test -n "$file_magic_test_file" && test -n "$file_magic_cmd"; then - case "$deplibs_check_method" in - "file_magic "*) - file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`" - if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | - egrep "$file_magic_regex" > /dev/null; then - : - else - cat <&2 - -*** Warning: the command libtool uses to detect shared libraries, -*** $file_magic_cmd, produces output that libtool cannot recognize. -*** The result is that libtool may fail to recognize shared libraries -*** as such. This will affect the creation of libtool libraries that -*** depend on shared libraries, but programs linked with such libtool -*** libraries will work regardless of this problem. Nevertheless, you -*** may want to report the problem to your system manager and/or to -*** bug-libtool@gnu.org - -EOF - fi ;; - esac -fi - -echo $ac_n "checking whether to build shared libraries... $ac_c" 1>&6 -test "$can_build_shared" = "no" && enable_shared=no - -# On AIX, shared libraries and static libraries use the same namespace, and -# are all built from PIC. -case "$host_os" in -aix3*) - test "$enable_shared" = yes && enable_static=no - if test -n "$RANLIB"; then - archive_cmds="$archive_cmds~\$RANLIB \$lib" - postinstall_cmds='$RANLIB $lib' - fi - ;; - -aix4*) - test "$enable_shared" = yes && enable_static=no - ;; -esac - -echo "$ac_t$enable_shared" 1>&6 - -# Make sure either enable_shared or enable_static is yes. -test "$enable_shared" = yes || enable_static=yes - -# Propagate what we've learned... -ac_cv_can_build_shared="$can_build_shared" - -echo "checking whether to build static libraries... $enable_static" 1>&6 - -if test "$hardcode_action" = relink; then - # Fast installation is not supported - enable_fast_install=no -elif test "$shlibpath_overrides_runpath" = yes || - test "$enable_shared" = no; then - # Fast installation is not necessary - enable_fast_install=needless -fi - -echo $ac_n "checking for objdir... $ac_c" 1>&6 -rm -f .libs 2>/dev/null -mkdir .libs 2>/dev/null -if test -d .libs; then - objdir=.libs -else - # MS-DOS does not allow filenames that begin with a dot. - objdir=_libs -fi -rmdir .libs 2>/dev/null -echo "$ac_t$objdir" 1>&6 - -if test "x$enable_dlopen" != xyes; then - enable_dlopen=unknown - enable_dlopen_self=unknown - enable_dlopen_self_static=unknown -else -if eval "test \"`echo '$''{'lt_cv_dlopen'+set}'`\" != set"; then - lt_cv_dlopen=no lt_cv_dlopen_libs= -echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6 -echo "$progname:2270: checking for dlopen in -ldl" >&5 -ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'` -if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - ac_save_LIBS="$LIBS" -LIBS="-ldl $LIBS" -cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=yes" -else - echo "$progname: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=no" -fi -rm -f conftest* -LIBS="$ac_save_LIBS" - -fi -if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then - echo "$ac_t""yes" 1>&6 - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" -else - echo "$ac_t""no" 1>&6 -echo $ac_n "checking for dlopen""... $ac_c" 1>&6 -echo "$progname:2310: checking for dlopen" >&5 -if eval "test \"`echo '$''{'ac_cv_func_dlopen'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext < -/* Override any gcc2 internal prototype to avoid an error. */ -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char dlopen(); - -int main() { - -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_dlopen) || defined (__stub___dlopen) -choke me -#else -dlopen(); -#endif - -; return 0; } -EOF -if { (eval echo $progname:2340: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - eval "ac_cv_func_dlopen=yes" -else - echo "$progname: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_func_dlopen=no" -fi -rm -f conftest* -fi -if eval "test \"`echo '$ac_cv_func_'dlopen`\" = yes"; then - echo "$ac_t""yes" 1>&6 - lt_cv_dlopen="dlopen" -else - echo "$ac_t""no" 1>&6 -echo $ac_n "checking for dld_link in -ldld""... $ac_c" 1>&6 -echo "$progname:2357: checking for dld_link in -ldld" >&5 -ac_lib_var=`echo dld'_'dld_link | sed 'y%./+-%__p_%'` -if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - ac_save_LIBS="$LIBS" -LIBS="-ldld $LIBS" -cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=yes" -else - echo "$progname: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=no" -fi -rm -f conftest* -LIBS="$ac_save_LIBS" - -fi -if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then - echo "$ac_t""yes" 1>&6 - lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" -else - echo "$ac_t""no" 1>&6 -echo $ac_n "checking for shl_load""... $ac_c" 1>&6 -echo "$progname:2397: checking for shl_load" >&5 -if eval "test \"`echo '$''{'ac_cv_func_shl_load'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext < -/* Override any gcc2 internal prototype to avoid an error. */ -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char shl_load(); - -int main() { - -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_shl_load) || defined (__stub___shl_load) -choke me -#else -shl_load(); -#endif - -; return 0; } -EOF -if { (eval echo $progname:2427: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - eval "ac_cv_func_shl_load=yes" -else - echo "$progname: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_func_shl_load=no" -fi -rm -f conftest* -fi - -if eval "test \"`echo '$ac_cv_func_'shl_load`\" = yes"; then - echo "$ac_t""yes" 1>&6 - lt_cv_dlopen="shl_load" -else - echo "$ac_t""no" 1>&6 -echo $ac_n "checking for shl_load in -ldld""... $ac_c" 1>&6 -echo "$progname:2445: checking for shl_load in -ldld" >&5 -ac_lib_var=`echo dld'_'shl_load | sed 'y%./+-%__p_%'` -if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - ac_save_LIBS="$LIBS" -LIBS="-ldld $LIBS" -cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=yes" -else - echo "$progname: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=no" -fi -rm -f conftest* -LIBS="$ac_save_LIBS" - -fi -if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then - echo "$ac_t""yes" 1>&6 - lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" -else - echo "$ac_t""no" 1>&6 -fi - - -fi - - -fi - - -fi - - -fi - -fi - - if test "x$lt_cv_dlopen" != xno; then - enable_dlopen=yes - fi - - case "$lt_cv_dlopen" in - dlopen) -for ac_hdr in dlfcn.h; do -ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` -echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "$progname:2510: checking for $ac_hdr" >&5 -if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext < -int fnord = 0; -EOF -ac_try="$ac_compile >/dev/null 2>conftest.out" -{ (eval echo $progname:2520: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } -ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` -if test -z "$ac_err"; then - rm -rf conftest* - eval "ac_cv_header_$ac_safe=yes" -else - echo "$ac_err" >&5 - echo "$progname: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_header_$ac_safe=no" -fi -rm -f conftest* -fi -if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then - echo "$ac_t""yes" 1>&6 -else - echo "$ac_t""no" 1>&6 -fi -done - - if test "x$ac_cv_header_dlfcn_h" = xyes; then - CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" - fi - eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" - LIBS="$lt_cv_dlopen_libs $LIBS" - - echo $ac_n "checking whether a program can dlopen itself""... $ac_c" 1>&6 -echo "$progname:2548: checking whether a program can dlopen itself" >&5 -if test "${lt_cv_dlopen_self+set}" = set; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test "$cross_compiling" = yes; then - lt_cv_dlopen_self=cross - else - cat > conftest.c < -#endif - -#include - -#ifdef RTLD_GLOBAL -# define LTDL_GLOBAL RTLD_GLOBAL -#else -# ifdef DL_GLOBAL -# define LTDL_GLOBAL DL_GLOBAL -# else -# define LTDL_GLOBAL 0 -# endif -#endif - -/* We may have to define LTDL_LAZY_OR_NOW in the command line if we - find out it does not work in some platform. */ -#ifndef LTDL_LAZY_OR_NOW -# ifdef RTLD_LAZY -# define LTDL_LAZY_OR_NOW RTLD_LAZY -# else -# ifdef DL_LAZY -# define LTDL_LAZY_OR_NOW DL_LAZY -# else -# ifdef RTLD_NOW -# define LTDL_LAZY_OR_NOW RTLD_NOW -# else -# ifdef DL_NOW -# define LTDL_LAZY_OR_NOW DL_NOW -# else -# define LTDL_LAZY_OR_NOW 0 -# endif -# endif -# endif -# endif -#endif - -fnord() { int i=42;} -main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW); - if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord"); - if(ptr1 || ptr2) { dlclose(self); exit(0); } } exit(1); } - -EOF -if { (eval echo $progname:2602: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null -then - lt_cv_dlopen_self=yes -else - echo "$progname: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -fr conftest* - lt_cv_dlopen_self=no -fi -rm -fr conftest* -fi - -fi - -echo "$ac_t""$lt_cv_dlopen_self" 1>&6 - - if test "$lt_cv_dlopen_self" = yes; then - LDFLAGS="$LDFLAGS $link_static_flag" - echo $ac_n "checking whether a statically linked program can dlopen itself""... $ac_c" 1>&6 -echo "$progname:2621: checking whether a statically linked program can dlopen itself" >&5 -if test "${lt_cv_dlopen_self_static+set}" = set; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test "$cross_compiling" = yes; then - lt_cv_dlopen_self_static=cross - else - cat > conftest.c < -#endif - -#include - -#ifdef RTLD_GLOBAL -# define LTDL_GLOBAL RTLD_GLOBAL -#else -# ifdef DL_GLOBAL -# define LTDL_GLOBAL DL_GLOBAL -# else -# define LTDL_GLOBAL 0 -# endif -#endif - -/* We may have to define LTDL_LAZY_OR_NOW in the command line if we - find out it does not work in some platform. */ -#ifndef LTDL_LAZY_OR_NOW -# ifdef RTLD_LAZY -# define LTDL_LAZY_OR_NOW RTLD_LAZY -# else -# ifdef DL_LAZY -# define LTDL_LAZY_OR_NOW DL_LAZY -# else -# ifdef RTLD_NOW -# define LTDL_LAZY_OR_NOW RTLD_NOW -# else -# ifdef DL_NOW -# define LTDL_LAZY_OR_NOW DL_NOW -# else -# define LTDL_LAZY_OR_NOW 0 -# endif -# endif -# endif -# endif -#endif - -fnord() { int i=42;} -main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW); - if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord"); - if(ptr1 || ptr2) { dlclose(self); exit(0); } } exit(1); } - -EOF -if { (eval echo $progname:2675: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null -then - lt_cv_dlopen_self_static=yes -else - echo "$progname: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -fr conftest* - lt_cv_dlopen_self_static=no -fi -rm -fr conftest* -fi - -fi - -echo "$ac_t""$lt_cv_dlopen_self_static" 1>&6 -fi - ;; - esac - - case "$lt_cv_dlopen_self" in - yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; - *) enable_dlopen_self=unknown ;; - esac - - case "$lt_cv_dlopen_self_static" in - yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; - *) enable_dlopen_self_static=unknown ;; - esac -fi - -# Copy echo and quote the copy, instead of the original, because it is -# used later. -ltecho="$echo" -if test "X$ltecho" = "X$CONFIG_SHELL $0 --fallback-echo"; then - ltecho="$CONFIG_SHELL \$0 --fallback-echo" -fi -LTSHELL="$SHELL" - -LTCONFIG_VERSION="$VERSION" - -# Only quote variables if we're using ltmain.sh. -case "$ltmain" in -*.sh) - # Now quote all the things that may contain metacharacters. - for var in ltecho old_CC old_CFLAGS old_CPPFLAGS \ - old_LD old_LDFLAGS old_LIBS \ - old_NM old_RANLIB old_LN_S old_DLLTOOL old_OBJDUMP old_AS \ - AR CC LD LN_S NM LTSHELL LTCONFIG_VERSION \ - reload_flag reload_cmds wl \ - pic_flag link_static_flag no_builtin_flag export_dynamic_flag_spec \ - thread_safe_flag_spec whole_archive_flag_spec libname_spec \ - library_names_spec soname_spec \ - RANLIB old_archive_cmds old_archive_from_new_cmds old_postinstall_cmds \ - old_postuninstall_cmds archive_cmds archive_expsym_cmds postinstall_cmds postuninstall_cmds \ - file_magic_cmd export_symbols_cmds deplibs_check_method allow_undefined_flag no_undefined_flag \ - finish_cmds finish_eval global_symbol_pipe global_symbol_to_cdecl \ - hardcode_libdir_flag_spec hardcode_libdir_separator \ - sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ - compiler_c_o compiler_o_lo need_locks exclude_expsyms include_expsyms; do - - case "$var" in - reload_cmds | old_archive_cmds | old_archive_from_new_cmds | \ - old_postinstall_cmds | old_postuninstall_cmds | \ - export_symbols_cmds | archive_cmds | archive_expsym_cmds | \ - postinstall_cmds | postuninstall_cmds | \ - finish_cmds | sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) - # Double-quote double-evaled strings. - eval "$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" - ;; - *) - eval "$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" - ;; - esac - done - - case "$ltecho" in - *'\$0 --fallback-echo"') - ltecho=`$echo "X$ltecho" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` - ;; - esac - - trap "$rm \"$ofile\"; exit 1" 1 2 15 - echo "creating $ofile" - $rm "$ofile" - cat < "$ofile" -#! $SHELL - -# `$echo "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. -# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) -# NOTE: Changes made to this file will be lost: look at ltconfig or ltmain.sh. -# -# Copyright (C) 1996-1999 Free Software Foundation, Inc. -# Originally by Gordon Matzigkeit , 1996 -# -# 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 2 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# Sed that helps us avoid accidentally triggering echo(1) options like -n. -Xsed="sed -e s/^X//" - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi - -### BEGIN LIBTOOL CONFIG -EOF - cfgfile="$ofile" - ;; - -*) - # Double-quote the variables that need it (for aesthetics). - for var in old_CC old_CFLAGS old_CPPFLAGS \ - old_LD old_LDFLAGS old_LIBS \ - old_NM old_RANLIB old_LN_S old_DLLTOOL old_OBJDUMP old_AS; do - eval "$var=\\\"\$var\\\"" - done - - # Just create a config file. - cfgfile="$ofile.cfg" - trap "$rm \"$cfgfile\"; exit 1" 1 2 15 - echo "creating $cfgfile" - $rm "$cfgfile" - cat < "$cfgfile" -# `$echo "$cfgfile" | sed 's%^.*/%%'` - Libtool configuration file. -# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) -EOF - ;; -esac - -cat <> "$cfgfile" -# Libtool was configured as follows, on host `(hostname || uname -n) 2>/dev/null | sed 1q`: -# -# CC=$old_CC CFLAGS=$old_CFLAGS CPPFLAGS=$old_CPPFLAGS \\ -# LD=$old_LD LDFLAGS=$old_LDFLAGS LIBS=$old_LIBS \\ -# NM=$old_NM RANLIB=$old_RANLIB LN_S=$old_LN_S \\ -# DLLTOOL=$old_DLLTOOL OBJDUMP=$old_OBJDUMP AS=$old_AS \\ -# $0$ltconfig_args -# -# Compiler and other test output produced by $progname, useful for -# debugging $progname, is in ./config.log if it exists. - -# The version of $progname that generated this script. -LTCONFIG_VERSION=$LTCONFIG_VERSION - -# Shell to use when invoking shell scripts. -SHELL=$LTSHELL - -# Whether or not to build shared libraries. -build_libtool_libs=$enable_shared - -# Whether or not to build static libraries. -build_old_libs=$enable_static - -# Whether or not to optimize for fast installation. -fast_install=$enable_fast_install - -# The host system. -host_alias=$host_alias -host=$host - -# An echo program that does not interpret backslashes. -echo=$ltecho - -# The archiver. -AR=$AR - -# The default C compiler. -CC=$CC - -# The linker used to build libraries. -LD=$LD - -# Whether we need hard or soft links. -LN_S=$LN_S - -# A BSD-compatible nm program. -NM=$NM - -# Used on cygwin: DLL creation program. -DLLTOOL="$DLLTOOL" - -# Used on cygwin: object dumper. -OBJDUMP="$OBJDUMP" - -# Used on cygwin: assembler. -AS="$AS" - -# The name of the directory that contains temporary libtool files. -objdir=$objdir - -# How to create reloadable object files. -reload_flag=$reload_flag -reload_cmds=$reload_cmds - -# How to pass a linker flag through the compiler. -wl=$wl - -# Object file suffix (normally "o"). -objext="$objext" - -# Old archive suffix (normally "a"). -libext="$libext" - -# Executable file suffix (normally ""). -exeext="$exeext" - -# Additional compiler flags for building library objects. -pic_flag=$pic_flag - -# Does compiler simultaneously support -c and -o options? -compiler_c_o=$compiler_c_o - -# Can we write directly to a .lo ? -compiler_o_lo=$compiler_o_lo - -# Must we lock files when doing compilation ? -need_locks=$need_locks - -# Do we need the lib prefix for modules? -need_lib_prefix=$need_lib_prefix - -# Do we need a version for libraries? -need_version=$need_version - -# Whether dlopen is supported. -dlopen=$enable_dlopen - -# Whether dlopen of programs is supported. -dlopen_self=$enable_dlopen_self - -# Whether dlopen of statically linked programs is supported. -dlopen_self_static=$enable_dlopen_self_static - -# Compiler flag to prevent dynamic linking. -link_static_flag=$link_static_flag - -# Compiler flag to turn off builtin functions. -no_builtin_flag=$no_builtin_flag - -# Compiler flag to allow reflexive dlopens. -export_dynamic_flag_spec=$export_dynamic_flag_spec - -# Compiler flag to generate shared objects directly from archives. -whole_archive_flag_spec=$whole_archive_flag_spec - -# Compiler flag to generate thread-safe objects. -thread_safe_flag_spec=$thread_safe_flag_spec - -# Library versioning type. -version_type=$version_type - -# Format of library name prefix. -libname_spec=$libname_spec - -# List of archive names. First name is the real one, the rest are links. -# The last name is the one that the linker finds with -lNAME. -library_names_spec=$library_names_spec - -# The coded name of the library, if different from the real name. -soname_spec=$soname_spec - -# Commands used to build and install an old-style archive. -RANLIB=$RANLIB -old_archive_cmds=$old_archive_cmds -old_postinstall_cmds=$old_postinstall_cmds -old_postuninstall_cmds=$old_postuninstall_cmds - -# Create an old-style archive from a shared archive. -old_archive_from_new_cmds=$old_archive_from_new_cmds - -# Commands used to build and install a shared archive. -archive_cmds=$archive_cmds -archive_expsym_cmds=$archive_expsym_cmds -postinstall_cmds=$postinstall_cmds -postuninstall_cmds=$postuninstall_cmds - -# Method to check whether dependent libraries are shared objects. -deplibs_check_method=$deplibs_check_method - -# Command to use when deplibs_check_method == file_magic. -file_magic_cmd=$file_magic_cmd - -# Flag that allows shared libraries with undefined symbols to be built. -allow_undefined_flag=$allow_undefined_flag - -# Flag that forces no undefined symbols. -no_undefined_flag=$no_undefined_flag - -# Commands used to finish a libtool library installation in a directory. -finish_cmds=$finish_cmds - -# Same as above, but a single script fragment to be evaled but not shown. -finish_eval=$finish_eval - -# Take the output of nm and produce a listing of raw symbols and C names. -global_symbol_pipe=$global_symbol_pipe - -# Transform the output of nm in a proper C declaration -global_symbol_to_cdecl=$global_symbol_to_cdecl - -# This is the shared library runtime path variable. -runpath_var=$runpath_var - -# This is the shared library path variable. -shlibpath_var=$shlibpath_var - -# Is shlibpath searched before the hard-coded library search path? -shlibpath_overrides_runpath=$shlibpath_overrides_runpath - -# How to hardcode a shared library path into an executable. -hardcode_action=$hardcode_action - -# Flag to hardcode \$libdir into a binary during linking. -# This must work even if \$libdir does not exist. -hardcode_libdir_flag_spec=$hardcode_libdir_flag_spec - -# Whether we need a single -rpath flag with a separated argument. -hardcode_libdir_separator=$hardcode_libdir_separator - -# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the -# resulting binary. -hardcode_direct=$hardcode_direct - -# Set to yes if using the -LDIR flag during linking hardcodes DIR into the -# resulting binary. -hardcode_minus_L=$hardcode_minus_L - -# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into -# the resulting binary. -hardcode_shlibpath_var=$hardcode_shlibpath_var - -# Compile-time system search path for libraries -sys_lib_search_path_spec=$sys_lib_search_path_spec - -# Run-time system search path for libraries -sys_lib_dlsearch_path_spec=$sys_lib_dlsearch_path_spec - -# Fix the shell variable \$srcfile for the compiler. -fix_srcfile_path="$fix_srcfile_path" - -# Set to yes if exported symbols are required. -always_export_symbols=$always_export_symbols - -# The commands to list exported symbols. -export_symbols_cmds=$export_symbols_cmds - -# Symbols that should not be listed in the preloaded symbols. -exclude_expsyms=$exclude_expsyms - -# Symbols that must always be exported. -include_expsyms=$include_expsyms - -EOF - -case "$ltmain" in -*.sh) - echo '### END LIBTOOL CONFIG' >> "$ofile" - echo >> "$ofile" - case "$host_os" in - aix3*) - cat <<\EOF >> "$ofile" - -# AIX sometimes has problems with the GCC collect2 program. For some -# reason, if we set the COLLECT_NAMES environment variable, the problems -# vanish in a puff of smoke. -if test "X${COLLECT_NAMES+set}" != Xset; then - COLLECT_NAMES= - export COLLECT_NAMES -fi -EOF - ;; - esac - - # Append the ltmain.sh script. - sed '$q' "$ltmain" >> "$ofile" || (rm -f "$ofile"; exit 1) - # We use sed instead of cat because bash on DJGPP gets confused if - # if finds mixed CR/LF and LF-only lines. Since sed operates in - # text mode, it properly converts lines to CR/LF. This bash problem - # is reportedly fixed, but why not run on old versions too? - - chmod +x "$ofile" - ;; - -*) - # Compile the libtool program. - echo "FIXME: would compile $ltmain" - ;; -esac - -test -n "$cache_file" || exit 0 - -# AC_CACHE_SAVE -trap '' 1 2 15 -cat > confcache <<\EOF -# This file is a shell script that caches the results of configure -# tests run on this system so they can be shared between configure -# scripts and configure runs. It is not useful on other systems. -# If it contains results you don't want to keep, you may remove or edit it. -# -# By default, configure uses ./config.cache as the cache file, -# creating it if it does not exist already. You can give configure -# the --cache-file=FILE option to use a different cache file; that is -# what configure does when it calls configure scripts in -# subdirectories, so they share the cache. -# Giving --cache-file=/dev/null disables caching, for debugging configure. -# config.status only pays attention to the cache file if you give it the -# --recheck option to rerun configure. -# -EOF -# The following way of writing the cache mishandles newlines in values, -# but we know of no workaround that is simple, portable, and efficient. -# So, don't put newlines in cache variables' values. -# Ultrix sh set writes to stderr and can't be redirected directly, -# and sets the high bit in the cache file unless we assign to the vars. -(set) 2>&1 | - case `(ac_space=' '; set | grep ac_space) 2>&1` in - *ac_space=\ *) - # `set' does not quote correctly, so add quotes (double-quote substitution - # turns \\\\ into \\, and sed turns \\ into \). - sed -n \ - -e "s/'/'\\\\''/g" \ - -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" - ;; - *) - # `set' quotes correctly as required by POSIX, so do not add quotes. - sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' - ;; - esac >> confcache -if cmp -s $cache_file confcache; then - : -else - if test -w $cache_file; then - echo "updating cache $cache_file" - cat confcache > $cache_file - else - echo "not updating unwritable cache $cache_file" - fi -fi -rm -f confcache - -exit 0 - -# Local Variables: -# mode:shell-script -# sh-indentation:2 -# End: diff --git a/saslauthd/config/ltmain.sh b/saslauthd/config/ltmain.sh deleted file mode 100644 index 3e728869..00000000 --- a/saslauthd/config/ltmain.sh +++ /dev/null @@ -1,4053 +0,0 @@ -# ltmain.sh - Provide generalized library-building support services. -# NOTE: Changing this file will not affect anything until you rerun ltconfig. -# -# Copyright (C) 1996-1999 Free Software Foundation, Inc. -# Originally by Gordon Matzigkeit , 1996 -# -# 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 2 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# Check that we have a working $echo. -if test "X$1" = X--no-reexec; then - # Discard the --no-reexec flag, and continue. - shift -elif test "X$1" = X--fallback-echo; then - # Avoid inline document here, it may be left over - : -elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then - # Yippee, $echo works! - : -else - # Restart under the correct shell, and then maybe $echo will work. - exec $SHELL "$0" --no-reexec ${1+"$@"} -fi - -if test "X$1" = X--fallback-echo; then - # used as fallback echo - shift - cat <&2 - echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 - exit 1 -fi - -if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then - echo "$modename: not configured to build any kind of library" 1>&2 - echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 - exit 1 -fi - -# Global variables. -mode=$default_mode -nonopt= -prev= -prevopt= -run= -show="$echo" -show_help= -execute_dlfiles= -lo2o="s/\\.lo\$/.${objext}/" -o2lo="s/\\.${objext}\$/.lo/" - -# Parse our command line options once, thoroughly. -while test $# -gt 0 -do - arg="$1" - shift - - case "$arg" in - -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;; - *) optarg= ;; - esac - - # If the previous option needs an argument, assign it. - if test -n "$prev"; then - case "$prev" in - execute_dlfiles) - eval "$prev=\"\$$prev \$arg\"" - ;; - *) - eval "$prev=\$arg" - ;; - esac - - prev= - prevopt= - continue - fi - - # Have we seen a non-optional argument yet? - case "$arg" in - --help) - show_help=yes - ;; - - --version) - echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP" - exit 0 - ;; - - --config) - sed -e '1,/^### BEGIN LIBTOOL CONFIG/d' -e '/^### END LIBTOOL CONFIG/,$d' $0 - exit 0 - ;; - - --debug) - echo "$progname: enabling shell trace mode" - set -x - ;; - - --dry-run | -n) - run=: - ;; - - --features) - echo "host: $host" - if test "$build_libtool_libs" = yes; then - echo "enable shared libraries" - else - echo "disable shared libraries" - fi - if test "$build_old_libs" = yes; then - echo "enable static libraries" - else - echo "disable static libraries" - fi - exit 0 - ;; - - --finish) mode="finish" ;; - - --mode) prevopt="--mode" prev=mode ;; - --mode=*) mode="$optarg" ;; - - --quiet | --silent) - show=: - ;; - - -dlopen) - prevopt="-dlopen" - prev=execute_dlfiles - ;; - - -*) - $echo "$modename: unrecognized option \`$arg'" 1>&2 - $echo "$help" 1>&2 - exit 1 - ;; - - *) - nonopt="$arg" - break - ;; - esac -done - -if test -n "$prevopt"; then - $echo "$modename: option \`$prevopt' requires an argument" 1>&2 - $echo "$help" 1>&2 - exit 1 -fi - -if test -z "$show_help"; then - - # Infer the operation mode. - if test -z "$mode"; then - case "$nonopt" in - *cc | *++ | gcc* | *-gcc*) - mode=link - for arg - do - case "$arg" in - -c) - mode=compile - break - ;; - esac - done - ;; - *db | *dbx | *strace | *truss) - mode=execute - ;; - *install*|cp|mv) - mode=install - ;; - *rm) - mode=uninstall - ;; - *) - # If we have no mode, but dlfiles were specified, then do execute mode. - test -n "$execute_dlfiles" && mode=execute - - # Just use the default operation mode. - if test -z "$mode"; then - if test -n "$nonopt"; then - $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2 - else - $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2 - fi - fi - ;; - esac - fi - - # Only execute mode is allowed to have -dlopen flags. - if test -n "$execute_dlfiles" && test "$mode" != execute; then - $echo "$modename: unrecognized option \`-dlopen'" 1>&2 - $echo "$help" 1>&2 - exit 1 - fi - - # Change the help message to a mode-specific one. - generic_help="$help" - help="Try \`$modename --help --mode=$mode' for more information." - - # These modes are in order of execution frequency so that they run quickly. - case "$mode" in - # libtool compile mode - compile) - modename="$modename: compile" - # Get the compilation command and the source file. - base_compile= - lastarg= - srcfile="$nonopt" - suppress_output= - - user_target=no - for arg - do - # Accept any command-line options. - case "$arg" in - -o) - if test "$user_target" != "no"; then - $echo "$modename: you cannot specify \`-o' more than once" 1>&2 - exit 1 - fi - user_target=next - ;; - - -static) - build_old_libs=yes - continue - ;; - esac - - case "$user_target" in - next) - # The next one is the -o target name - user_target=yes - continue - ;; - yes) - # We got the output file - user_target=set - libobj="$arg" - continue - ;; - esac - - # Accept the current argument as the source file. - lastarg="$srcfile" - srcfile="$arg" - - # Aesthetically quote the previous argument. - - # Backslashify any backslashes, double quotes, and dollar signs. - # These are the only characters that are still specially - # interpreted inside of double-quoted scrings. - lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"` - - # Double-quote args containing other shell metacharacters. - # Many Bourne shells cannot handle close brackets correctly in scan - # sets, so we specify it separately. - case "$lastarg" in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) - lastarg="\"$lastarg\"" - ;; - esac - - # Add the previous argument to base_compile. - if test -z "$base_compile"; then - base_compile="$lastarg" - else - base_compile="$base_compile $lastarg" - fi - done - - case "$user_target" in - set) - ;; - no) - # Get the name of the library object. - libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'` - ;; - *) - $echo "$modename: you must specify a target with \`-o'" 1>&2 - exit 1 - ;; - esac - - # Recognize several different file suffixes. - # If the user specifies -o file.o, it is replaced with file.lo - xform='[cCFSfmso]' - case "$libobj" in - *.ada) xform=ada ;; - *.adb) xform=adb ;; - *.ads) xform=ads ;; - *.asm) xform=asm ;; - *.c++) xform=c++ ;; - *.cc) xform=cc ;; - *.cpp) xform=cpp ;; - *.cxx) xform=cxx ;; - *.f90) xform=f90 ;; - *.for) xform=for ;; - esac - - libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"` - - case "$libobj" in - *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;; - *) - $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2 - exit 1 - ;; - esac - - if test -z "$base_compile"; then - $echo "$modename: you must specify a compilation command" 1>&2 - $echo "$help" 1>&2 - exit 1 - fi - - # Delete any leftover library objects. - if test "$build_old_libs" = yes; then - removelist="$obj $libobj" - else - removelist="$libobj" - fi - - $run $rm $removelist - trap "$run $rm $removelist; exit 1" 1 2 15 - - # Calculate the filename of the output object if compiler does - # not support -o with -c - if test "$compiler_c_o" = no; then - output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\..*$%%'`.${objext} - lockfile="$output_obj.lock" - removelist="$removelist $output_obj $lockfile" - trap "$run $rm $removelist; exit 1" 1 2 15 - else - need_locks=no - lockfile= - fi - - # Lock this critical section if it is needed - # We use this script file to make the link, it avoids creating a new file - if test "$need_locks" = yes; then - until ln "$0" "$lockfile" 2>/dev/null; do - $show "Waiting for $lockfile to be removed" - sleep 2 - done - elif test "$need_locks" = warn; then - if test -f "$lockfile"; then - echo "\ -*** ERROR, $lockfile exists and contains: -`cat $lockfile 2>/dev/null` - -This indicates that another process is trying to use the same -temporary object file, and libtool could not work around it because -your compiler does not support \`-c' and \`-o' together. If you -repeat this compilation, it may succeed, by chance, but you had better -avoid parallel builds (make -j) in this platform, or get a better -compiler." - - $run $rm $removelist - exit 1 - fi - echo $srcfile > "$lockfile" - fi - - if test -n "$fix_srcfile_path"; then - eval srcfile=\"$fix_srcfile_path\" - fi - - # Only build a PIC object if we are building libtool libraries. - if test "$build_libtool_libs" = yes; then - # Without this assignment, base_compile gets emptied. - fbsd_hideous_sh_bug=$base_compile - - # All platforms use -DPIC, to notify preprocessed assembler code. - command="$base_compile $srcfile $pic_flag -DPIC" - if test "$build_old_libs" = yes; then - lo_libobj="$libobj" - dir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'` - if test "X$dir" = "X$libobj"; then - dir="$objdir" - else - dir="$dir/$objdir" - fi - libobj="$dir/"`$echo "X$libobj" | $Xsed -e 's%^.*/%%'` - - if test -d "$dir"; then - $show "$rm $libobj" - $run $rm $libobj - else - $show "$mkdir $dir" - $run $mkdir $dir - status=$? - if test $status -ne 0 && test ! -d $dir; then - exit $status - fi - fi - fi - if test "$compiler_o_lo" = yes; then - output_obj="$libobj" - command="$command -o $output_obj" - elif test "$compiler_c_o" = yes; then - output_obj="$obj" - command="$command -o $output_obj" - fi - - $run $rm "$output_obj" - $show "$command" - if $run eval "$command"; then : - else - test -n "$output_obj" && $run $rm $removelist - exit 1 - fi - - if test "$need_locks" = warn && - test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then - echo "\ -*** ERROR, $lockfile contains: -`cat $lockfile 2>/dev/null` - -but it should contain: -$srcfile - -This indicates that another process is trying to use the same -temporary object file, and libtool could not work around it because -your compiler does not support \`-c' and \`-o' together. If you -repeat this compilation, it may succeed, by chance, but you had better -avoid parallel builds (make -j) in this platform, or get a better -compiler." - - $run $rm $removelist - exit 1 - fi - - # Just move the object if needed, then go on to compile the next one - if test x"$output_obj" != x"$libobj"; then - $show "$mv $output_obj $libobj" - if $run $mv $output_obj $libobj; then : - else - error=$? - $run $rm $removelist - exit $error - fi - fi - - # If we have no pic_flag, then copy the object into place and finish. - if test -z "$pic_flag" && test "$build_old_libs" = yes; then - # Rename the .lo from within objdir to obj - if test -f $obj; then - $show $rm $obj - $run $rm $obj - fi - - $show "$mv $libobj $obj" - if $run $mv $libobj $obj; then : - else - error=$? - $run $rm $removelist - exit $error - fi - - xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` - if test "X$xdir" = "X$obj"; then - xdir="." - else - xdir="$xdir" - fi - baseobj=`$echo "X$obj" | $Xsed -e "s%.*/%%"` - libobj=`$echo "X$baseobj" | $Xsed -e "$o2lo"` - # Now arrange that obj and lo_libobj become the same file - $show "(cd $xdir && $LN_S $baseobj $libobj)" - if $run eval '(cd $xdir && $LN_S $baseobj $libobj)'; then - exit 0 - else - error=$? - $run $rm $removelist - exit $error - fi - fi - - # Allow error messages only from the first compilation. - suppress_output=' >/dev/null 2>&1' - fi - - # Only build a position-dependent object if we build old libraries. - if test "$build_old_libs" = yes; then - command="$base_compile $srcfile" - if test "$compiler_c_o" = yes; then - command="$command -o $obj" - output_obj="$obj" - fi - - # Suppress compiler output if we already did a PIC compilation. - command="$command$suppress_output" - $run $rm "$output_obj" - $show "$command" - if $run eval "$command"; then : - else - $run $rm $removelist - exit 1 - fi - - if test "$need_locks" = warn && - test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then - echo "\ -*** ERROR, $lockfile contains: -`cat $lockfile 2>/dev/null` - -but it should contain: -$srcfile - -This indicates that another process is trying to use the same -temporary object file, and libtool could not work around it because -your compiler does not support \`-c' and \`-o' together. If you -repeat this compilation, it may succeed, by chance, but you had better -avoid parallel builds (make -j) in this platform, or get a better -compiler." - - $run $rm $removelist - exit 1 - fi - - # Just move the object if needed - if test x"$output_obj" != x"$obj"; then - $show "$mv $output_obj $obj" - if $run $mv $output_obj $obj; then : - else - error=$? - $run $rm $removelist - exit $error - fi - fi - - # Create an invalid libtool object if no PIC, so that we do not - # accidentally link it into a program. - if test "$build_libtool_libs" != yes; then - $show "echo timestamp > $libobj" - $run eval "echo timestamp > \$libobj" || exit $? - else - # Move the .lo from within objdir - $show "$mv $libobj $lo_libobj" - if $run $mv $libobj $lo_libobj; then : - else - error=$? - $run $rm $removelist - exit $error - fi - fi - fi - - # Unlock the critical section if it was locked - if test "$need_locks" != no; then - $rm "$lockfile" - fi - - exit 0 - ;; - - # libtool link mode - link) - modename="$modename: link" - case "$host" in - *-*-cygwin* | *-*-mingw* | *-*-os2*) - # It is impossible to link a dll without this setting, and - # we shouldn't force the makefile maintainer to figure out - # which system we are compiling for in order to pass an extra - # flag for every libtool invokation. - # allow_undefined=no - - # FIXME: Unfortunately, there are problems with the above when trying - # to make a dll which has undefined symbols, in which case not - # even a static library is built. For now, we need to specify - # -no-undefined on the libtool link line when we can be certain - # that all symbols are satisfied, otherwise we get a static library. - allow_undefined=yes - - # This is a source program that is used to create dlls on Windows - # Don't remove nor modify the starting and closing comments -# /* ltdll.c starts here */ -# #define WIN32_LEAN_AND_MEAN -# #include -# #undef WIN32_LEAN_AND_MEAN -# #include -# -# #ifndef __CYGWIN__ -# # ifdef __CYGWIN32__ -# # define __CYGWIN__ __CYGWIN32__ -# # endif -# #endif -# -# #ifdef __cplusplus -# extern "C" { -# #endif -# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved); -# #ifdef __cplusplus -# } -# #endif -# -# #ifdef __CYGWIN__ -# #include -# DECLARE_CYGWIN_DLL( DllMain ); -# #endif -# HINSTANCE __hDllInstance_base; -# -# BOOL APIENTRY -# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved) -# { -# __hDllInstance_base = hInst; -# return TRUE; -# } -# /* ltdll.c ends here */ - # This is a source program that is used to create import libraries - # on Windows for dlls which lack them. Don't remove nor modify the - # starting and closing comments -# /* impgen.c starts here */ -# /* Copyright (C) 1999 Free Software Foundation, Inc. -# -# This file is part of GNU libtool. -# -# 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 2 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# */ -# -# #include /* for printf() */ -# #include /* for open(), lseek(), read() */ -# #include /* for O_RDONLY, O_BINARY */ -# #include /* for strdup() */ -# -# static unsigned int -# pe_get16 (fd, offset) -# int fd; -# int offset; -# { -# unsigned char b[2]; -# lseek (fd, offset, SEEK_SET); -# read (fd, b, 2); -# return b[0] + (b[1]<<8); -# } -# -# static unsigned int -# pe_get32 (fd, offset) -# int fd; -# int offset; -# { -# unsigned char b[4]; -# lseek (fd, offset, SEEK_SET); -# read (fd, b, 4); -# return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24); -# } -# -# static unsigned int -# pe_as32 (ptr) -# void *ptr; -# { -# unsigned char *b = ptr; -# return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24); -# } -# -# int -# main (argc, argv) -# int argc; -# char *argv[]; -# { -# int dll; -# unsigned long pe_header_offset, opthdr_ofs, num_entries, i; -# unsigned long export_rva, export_size, nsections, secptr, expptr; -# unsigned long name_rvas, nexp; -# unsigned char *expdata, *erva; -# char *filename, *dll_name; -# -# filename = argv[1]; -# -# dll = open(filename, O_RDONLY|O_BINARY); -# if (!dll) -# return 1; -# -# dll_name = filename; -# -# for (i=0; filename[i]; i++) -# if (filename[i] == '/' || filename[i] == '\\' || filename[i] == ':') -# dll_name = filename + i +1; -# -# pe_header_offset = pe_get32 (dll, 0x3c); -# opthdr_ofs = pe_header_offset + 4 + 20; -# num_entries = pe_get32 (dll, opthdr_ofs + 92); -# -# if (num_entries < 1) /* no exports */ -# return 1; -# -# export_rva = pe_get32 (dll, opthdr_ofs + 96); -# export_size = pe_get32 (dll, opthdr_ofs + 100); -# nsections = pe_get16 (dll, pe_header_offset + 4 +2); -# secptr = (pe_header_offset + 4 + 20 + -# pe_get16 (dll, pe_header_offset + 4 + 16)); -# -# expptr = 0; -# for (i = 0; i < nsections; i++) -# { -# char sname[8]; -# unsigned long secptr1 = secptr + 40 * i; -# unsigned long vaddr = pe_get32 (dll, secptr1 + 12); -# unsigned long vsize = pe_get32 (dll, secptr1 + 16); -# unsigned long fptr = pe_get32 (dll, secptr1 + 20); -# lseek(dll, secptr1, SEEK_SET); -# read(dll, sname, 8); -# if (vaddr <= export_rva && vaddr+vsize > export_rva) -# { -# expptr = fptr + (export_rva - vaddr); -# if (export_rva + export_size > vaddr + vsize) -# export_size = vsize - (export_rva - vaddr); -# break; -# } -# } -# -# expdata = (unsigned char*)malloc(export_size); -# lseek (dll, expptr, SEEK_SET); -# read (dll, expdata, export_size); -# erva = expdata - export_rva; -# -# nexp = pe_as32 (expdata+24); -# name_rvas = pe_as32 (expdata+32); -# -# printf ("EXPORTS\n"); -# for (i = 0; i&2 - fi - if test -n "$link_static_flag"; then - dlopen_self=$dlopen_self_static - fi - else - if test -z "$pic_flag" && test -n "$link_static_flag"; then - dlopen_self=$dlopen_self_static - fi - fi - build_libtool_libs=no - build_old_libs=yes - prefer_static_libs=yes - break - ;; - esac - done - - # See if our shared archives depend on static archives. - test -n "$old_archive_from_new_cmds" && build_old_libs=yes - - # Go through the arguments, transforming them on the way. - while test $# -gt 0; do - arg="$1" - shift - - # If the previous option needs an argument, assign it. - if test -n "$prev"; then - case "$prev" in - output) - compile_command="$compile_command @OUTPUT@" - finalize_command="$finalize_command @OUTPUT@" - ;; - esac - - case "$prev" in - dlfiles|dlprefiles) - if test "$preload" = no; then - # Add the symbol object into the linking commands. - compile_command="$compile_command @SYMFILE@" - finalize_command="$finalize_command @SYMFILE@" - preload=yes - fi - case "$arg" in - *.la | *.lo) ;; # We handle these cases below. - force) - if test "$dlself" = no; then - dlself=needless - export_dynamic=yes - fi - prev= - continue - ;; - self) - if test "$prev" = dlprefiles; then - dlself=yes - elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then - dlself=yes - else - dlself=needless - export_dynamic=yes - fi - prev= - continue - ;; - *) - if test "$prev" = dlfiles; then - dlfiles="$dlfiles $arg" - else - dlprefiles="$dlprefiles $arg" - fi - prev= - ;; - esac - ;; - expsyms) - export_symbols="$arg" - if test ! -f "$arg"; then - $echo "$modename: symbol file \`$arg' does not exist" - exit 1 - fi - prev= - continue - ;; - expsyms_regex) - export_symbols_regex="$arg" - prev= - continue - ;; - release) - release="-$arg" - prev= - continue - ;; - rpath | xrpath) - # We need an absolute path. - case "$arg" in - [\\/]* | [A-Za-z]:[\\/]*) ;; - *) - $echo "$modename: only absolute run-paths are allowed" 1>&2 - exit 1 - ;; - esac - if test "$prev" = rpath; then - case "$rpath " in - *" $arg "*) ;; - *) rpath="$rpath $arg" ;; - esac - else - case "$xrpath " in - *" $arg "*) ;; - *) xrpath="$xrpath $arg" ;; - esac - fi - prev= - continue - ;; - *) - eval "$prev=\"\$arg\"" - prev= - continue - ;; - esac - fi - - prevarg="$arg" - - case "$arg" in - -all-static) - if test -n "$link_static_flag"; then - compile_command="$compile_command $link_static_flag" - finalize_command="$finalize_command $link_static_flag" - fi - continue - ;; - - -allow-undefined) - # FIXME: remove this flag sometime in the future. - $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2 - continue - ;; - - -avoid-version) - avoid_version=yes - continue - ;; - - -dlopen) - prev=dlfiles - continue - ;; - - -dlpreopen) - prev=dlprefiles - continue - ;; - - -export-dynamic) - export_dynamic=yes - continue - ;; - - -export-symbols | -export-symbols-regex) - if test -n "$export_symbols" || test -n "$export_symbols_regex"; then - $echo "$modename: not more than one -exported-symbols argument allowed" - exit 1 - fi - if test "X$arg" = "X-export-symbols"; then - prev=expsyms - else - prev=expsyms_regex - fi - continue - ;; - - -L*) - dir=`$echo "X$arg" | $Xsed -e 's/^-L//'` - # We need an absolute path. - case "$dir" in - [\\/]* | [A-Za-z]:[\\/]*) ;; - *) - absdir=`cd "$dir" && pwd` - if test -z "$absdir"; then - $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2 - $echo "$modename: passing it literally to the linker, although it might fail" 1>&2 - absdir="$dir" - fi - dir="$absdir" - ;; - esac - case " $deplibs " in - *" $arg "*) ;; - *) deplibs="$deplibs $arg";; - esac - case " $lib_search_path " in - *" $dir "*) ;; - *) lib_search_path="$lib_search_path $dir";; - esac - case "$host" in - *-*-cygwin* | *-*-mingw* | *-*-os2*) - dllsearchdir=`cd "$dir" && pwd || echo "$dir"` - case ":$dllsearchpath:" in - ::) dllsearchpath="$dllsearchdir";; - *":$dllsearchdir:"*) ;; - *) dllsearchpath="$dllsearchpath:$dllsearchdir";; - esac - ;; - esac - ;; - - -l*) - if test "$arg" = "-lc"; then - case "$host" in - *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos*) - # These systems don't actually have c library (as such) - continue - ;; - *-*-rhapsody* | *-*-darwin1.[012]) - # Rhapsody C library is in the System framework - deplibs="$deplibs -framework System" - continue - ;; - esac - elif test "$arg" = "-lm"; then - case "$host" in - *-*-cygwin* | *-*-beos*) - # These systems don't actually have math library (as such) - continue - ;; - *-*-rhapsody* | *-*-darwin1.[012]) - # Rhapsody math library is in the System framework - deplibs="$deplibs -framework System" - continue - ;; - esac - fi - deplibs="$deplibs $arg" - ;; - - -module) - module=yes - continue - ;; - - -no-undefined) - allow_undefined=no - continue - ;; - - -o) prev=output ;; - - -release) - prev=release - continue - ;; - - -rpath) - prev=rpath - continue - ;; - - -R) - prev=xrpath - continue - ;; - - -R*) - dir=`$echo "X$arg" | $Xsed -e 's/^-R//'` - # We need an absolute path. - case "$dir" in - [\\/]* | [A-Za-z]:[\\/]*) ;; - *) - $echo "$modename: only absolute run-paths are allowed" 1>&2 - exit 1 - ;; - esac - case "$xrpath " in - *" $dir "*) ;; - *) xrpath="$xrpath $dir" ;; - esac - continue - ;; - - -static) - # If we have no pic_flag, then this is the same as -all-static. - if test -z "$pic_flag" && test -n "$link_static_flag"; then - compile_command="$compile_command $link_static_flag" - finalize_command="$finalize_command $link_static_flag" - fi - continue - ;; - - -thread-safe) - thread_safe=yes - continue - ;; - - -version-info) - prev=vinfo - continue - ;; - - # Some other compiler flag. - -* | +*) - # Unknown arguments in both finalize_command and compile_command need - # to be aesthetically quoted because they are evaled later. - arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` - case "$arg" in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) - arg="\"$arg\"" - ;; - esac - ;; - - *.o | *.obj | *.a | *.lib) - # A standard object. - objs="$objs $arg" - ;; - - *.lo) - # A library object. - if test "$prev" = dlfiles; then - dlfiles="$dlfiles $arg" - if test "$build_libtool_libs" = yes && test "$dlopen" = yes; then - prev= - continue - else - # If libtool objects are unsupported, then we need to preload. - prev=dlprefiles - fi - fi - - if test "$prev" = dlprefiles; then - # Preload the old-style object. - dlprefiles="$dlprefiles "`$echo "X$arg" | $Xsed -e "$lo2o"` - prev= - fi - libobjs="$libobjs $arg" - ;; - - *.la) - # A libtool-controlled library. - - dlname= - libdir= - library_names= - old_library= - - # Check to see that this really is a libtool archive. - if (sed -e '2q' $arg | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : - else - $echo "$modename: \`$arg' is not a valid libtool archive" 1>&2 - exit 1 - fi - - # If the library was installed with an old release of libtool, - # it will not redefine variable installed. - installed=yes - - # Read the .la file - # If there is no directory component, then add one. - case "$arg" in - */* | *\\*) . $arg ;; - *) . ./$arg ;; - esac - - # Get the name of the library we link against. - linklib= - for l in $old_library $library_names; do - linklib="$l" - done - - if test -z "$linklib"; then - $echo "$modename: cannot find name of link library for \`$arg'" 1>&2 - exit 1 - fi - - # Find the relevant object directory and library name. - name=`$echo "X$arg" | $Xsed -e 's%^.*/%%' -e 's/\.la$//' -e 's/^lib//'` - - if test "X$installed" = Xyes; then - dir="$libdir" - else - dir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` - if test "X$dir" = "X$arg"; then - dir="$objdir" - else - dir="$dir/$objdir" - fi - fi - - if test -n "$dependency_libs"; then - # Extract -R and -L from dependency_libs - temp_deplibs= - for deplib in $dependency_libs; do - case "$deplib" in - -R*) temp_xrpath=`$echo "X$deplib" | $Xsed -e 's/^-R//'` - case " $rpath $xrpath " in - *" $temp_xrpath "*) ;; - *) xrpath="$xrpath $temp_xrpath";; - esac;; - -L*) case "$compile_command $temp_deplibs " in - *" $deplib "*) ;; - *) temp_deplibs="$temp_deplibs $deplib";; - esac - temp_dir=`$echo "X$deplib" | $Xsed -e 's/^-L//'` - case " $lib_search_path " in - *" $temp_dir "*) ;; - *) lib_search_path="$lib_search_path $temp_dir";; - esac - ;; - *) temp_deplibs="$temp_deplibs $deplib";; - esac - done - dependency_libs="$temp_deplibs" - fi - - if test -z "$libdir"; then - # It is a libtool convenience library, so add in its objects. - convenience="$convenience $dir/$old_library" - old_convenience="$old_convenience $dir/$old_library" - deplibs="$deplibs$dependency_libs" - compile_command="$compile_command $dir/$old_library$dependency_libs" - finalize_command="$finalize_command $dir/$old_library$dependency_libs" - continue - fi - - # This library was specified with -dlopen. - if test "$prev" = dlfiles; then - dlfiles="$dlfiles $arg" - if test -z "$dlname" || test "$dlopen" != yes || test "$build_libtool_libs" = no; then - # If there is no dlname, no dlopen support or we're linking statically, - # we need to preload. - prev=dlprefiles - else - # We should not create a dependency on this library, but we - # may need any libraries it requires. - compile_command="$compile_command$dependency_libs" - finalize_command="$finalize_command$dependency_libs" - prev= - continue - fi - fi - - # The library was specified with -dlpreopen. - if test "$prev" = dlprefiles; then - # Prefer using a static library (so that no silly _DYNAMIC symbols - # are required to link). - if test -n "$old_library"; then - dlprefiles="$dlprefiles $dir/$old_library" - else - dlprefiles="$dlprefiles $dir/$linklib" - fi - prev= - fi - - if test -n "$library_names" && - { test "$prefer_static_libs" = no || test -z "$old_library"; }; then - link_against_libtool_libs="$link_against_libtool_libs $arg" - if test -n "$shlibpath_var"; then - # Make sure the rpath contains only unique directories. - case "$temp_rpath " in - *" $dir "*) ;; - *) temp_rpath="$temp_rpath $dir" ;; - esac - fi - - # We need an absolute path. - case "$dir" in - [\\/] | [A-Za-z]:[\\/]*) absdir="$dir" ;; - *) - absdir=`cd "$dir" && pwd` - if test -z "$absdir"; then - $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2 - $echo "$modename: passing it literally to the linker, although it might fail" 1>&2 - absdir="$dir" - fi - ;; - esac - - # This is the magic to use -rpath. - # Skip directories that are in the system default run-time - # search path, unless they have been requested with -R. - case " $sys_lib_dlsearch_path " in - *" $absdir "*) ;; - *) - case "$compile_rpath " in - *" $absdir "*) ;; - *) compile_rpath="$compile_rpath $absdir" - esac - ;; - esac - - case " $sys_lib_dlsearch_path " in - *" $libdir "*) ;; - *) - case "$finalize_rpath " in - *" $libdir "*) ;; - *) finalize_rpath="$finalize_rpath $libdir" - esac - ;; - esac - - lib_linked=yes - case "$hardcode_action" in - immediate | unsupported) - if test "$hardcode_direct" = no; then - compile_command="$compile_command $dir/$linklib" - deplibs="$deplibs $dir/$linklib" - case "$host" in - *-*-cygwin* | *-*-mingw* | *-*-os2*) - dllsearchdir=`cd "$dir" && pwd || echo "$dir"` - if test -n "$dllsearchpath"; then - dllsearchpath="$dllsearchpath:$dllsearchdir" - else - dllsearchpath="$dllsearchdir" - fi - ;; - esac - elif test "$hardcode_minus_L" = no; then - case "$host" in - *-*-sunos*) - compile_shlibpath="$compile_shlibpath$dir:" - ;; - esac - case "$compile_command " in - *" -L$dir "*) ;; - *) compile_command="$compile_command -L$dir";; - esac - compile_command="$compile_command -l$name" - deplibs="$deplibs -L$dir -l$name" - elif test "$hardcode_shlibpath_var" = no; then - case ":$compile_shlibpath:" in - *":$dir:"*) ;; - *) compile_shlibpath="$compile_shlibpath$dir:";; - esac - compile_command="$compile_command -l$name" - deplibs="$deplibs -l$name" - else - lib_linked=no - fi - ;; - - relink) - if test "$hardcode_direct" = yes; then - compile_command="$compile_command $absdir/$linklib" - deplibs="$deplibs $absdir/$linklib" - elif test "$hardcode_minus_L" = yes; then - case "$compile_command " in - *" -L$absdir "*) ;; - *) compile_command="$compile_command -L$absdir";; - esac - compile_command="$compile_command -l$name" - deplibs="$deplibs -L$absdir -l$name" - elif test "$hardcode_shlibpath_var" = yes; then - case ":$compile_shlibpath:" in - *":$absdir:"*) ;; - *) compile_shlibpath="$compile_shlibpath$absdir:";; - esac - compile_command="$compile_command -l$name" - deplibs="$deplibs -l$name" - else - lib_linked=no - fi - ;; - - *) - lib_linked=no - ;; - esac - - if test "$lib_linked" != yes; then - $echo "$modename: configuration error: unsupported hardcode properties" - exit 1 - fi - - # Finalize command for both is simple: just hardcode it. - if test "$hardcode_direct" = yes; then - finalize_command="$finalize_command $libdir/$linklib" - elif test "$hardcode_minus_L" = yes; then - case "$finalize_command " in - *" -L$libdir "*) ;; - *) finalize_command="$finalize_command -L$libdir";; - esac - finalize_command="$finalize_command -l$name" - elif test "$hardcode_shlibpath_var" = yes; then - case ":$finalize_shlibpath:" in - *":$libdir:"*) ;; - *) finalize_shlibpath="$finalize_shlibpath$libdir:";; - esac - finalize_command="$finalize_command -l$name" - else - # We cannot seem to hardcode it, guess we'll fake it. - case "$finalize_command " in - *" -L$dir "*) ;; - *) finalize_command="$finalize_command -L$libdir";; - esac - finalize_command="$finalize_command -l$name" - fi - else - # Transform directly to old archives if we don't build new libraries. - if test -n "$pic_flag" && test -z "$old_library"; then - $echo "$modename: cannot find static library for \`$arg'" 1>&2 - exit 1 - fi - - # Here we assume that one of hardcode_direct or hardcode_minus_L - # is not unsupported. This is valid on all known static and - # shared platforms. - if test "$hardcode_direct" != unsupported; then - test -n "$old_library" && linklib="$old_library" - compile_command="$compile_command $dir/$linklib" - finalize_command="$finalize_command $dir/$linklib" - else - case "$compile_command " in - *" -L$dir "*) ;; - *) compile_command="$compile_command -L$dir";; - esac - compile_command="$compile_command -l$name" - case "$finalize_command " in - *" -L$dir "*) ;; - *) finalize_command="$finalize_command -L$dir";; - esac - finalize_command="$finalize_command -l$name" - fi - fi - - # Add in any libraries that this one depends upon. - compile_command="$compile_command$dependency_libs" - finalize_command="$finalize_command$dependency_libs" - continue - ;; - - # Some other compiler argument. - *) - # Unknown arguments in both finalize_command and compile_command need - # to be aesthetically quoted because they are evaled later. - arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` - case "$arg" in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) - arg="\"$arg\"" - ;; - esac - ;; - esac - - # Now actually substitute the argument into the commands. - if test -n "$arg"; then - compile_command="$compile_command $arg" - finalize_command="$finalize_command $arg" - fi - done - - if test -n "$prev"; then - $echo "$modename: the \`$prevarg' option requires an argument" 1>&2 - $echo "$help" 1>&2 - exit 1 - fi - - if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then - eval arg=\"$export_dynamic_flag_spec\" - compile_command="$compile_command $arg" - finalize_command="$finalize_command $arg" - fi - - oldlibs= - # calculate the name of the file, without its directory - outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'` - libobjs_save="$libobjs" - - case "$output" in - "") - $echo "$modename: you must specify an output file" 1>&2 - $echo "$help" 1>&2 - exit 1 - ;; - - *.a | *.lib) - if test -n "$link_against_libtool_libs"; then - $echo "$modename: error: cannot link libtool libraries into archives" 1>&2 - exit 1 - fi - - if test -n "$deplibs"; then - $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2 - fi - - if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then - $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2 - fi - - if test -n "$rpath"; then - $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2 - fi - - if test -n "$xrpath"; then - $echo "$modename: warning: \`-R' is ignored for archives" 1>&2 - fi - - if test -n "$vinfo"; then - $echo "$modename: warning: \`-version-info' is ignored for archives" 1>&2 - fi - - if test -n "$release"; then - $echo "$modename: warning: \`-release' is ignored for archives" 1>&2 - fi - - if test -n "$export_symbols" || test -n "$export_symbols_regex"; then - $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2 - fi - - # Now set the variables for building old libraries. - build_libtool_libs=no - oldlibs="$output" - ;; - - *.la) - # Make sure we only generate libraries of the form `libNAME.la'. - case "$outputname" in - lib*) - name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` - eval libname=\"$libname_spec\" - ;; - *) - if test "$module" = no; then - $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2 - $echo "$help" 1>&2 - exit 1 - fi - if test "$need_lib_prefix" != no; then - # Add the "lib" prefix for modules if required - name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` - eval libname=\"$libname_spec\" - else - libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` - fi - ;; - esac - - output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'` - if test "X$output_objdir" = "X$output"; then - output_objdir="$objdir" - else - output_objdir="$output_objdir/$objdir" - fi - - if test -n "$objs"; then - $echo "$modename: cannot build libtool library \`$output' from non-libtool objects:$objs" 2>&1 - exit 1 - fi - - # How the heck are we supposed to write a wrapper for a shared library? - if test -n "$link_against_libtool_libs"; then - $echo "$modename: error: cannot link shared libraries into libtool libraries" 1>&2 - exit 1 - fi - - if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then - $echo "$modename: warning: \`-dlopen' is ignored for libtool libraries" 1>&2 - fi - - set dummy $rpath - if test $# -gt 2; then - $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2 - fi - install_libdir="$2" - - oldlibs= - if test -z "$rpath"; then - if test "$build_libtool_libs" = yes; then - # Building a libtool convenience library. - libext=al - oldlibs="$output_objdir/$libname.$libext $oldlibs" - build_libtool_libs=convenience - build_old_libs=yes - fi - dependency_libs="$deplibs" - - if test -n "$vinfo"; then - $echo "$modename: warning: \`-version-info' is ignored for convenience libraries" 1>&2 - fi - - if test -n "$release"; then - $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2 - fi - else - - # Parse the version information argument. - IFS="${IFS= }"; save_ifs="$IFS"; IFS=':' - set dummy $vinfo 0 0 0 - IFS="$save_ifs" - - if test -n "$8"; then - $echo "$modename: too many parameters to \`-version-info'" 1>&2 - $echo "$help" 1>&2 - exit 1 - fi - - current="$2" - revision="$3" - age="$4" - - # Check that each of the things are valid numbers. - case "$current" in - 0 | [1-9] | [1-9][0-9]*) ;; - *) - $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2 - $echo "$modename: \`$vinfo' is not valid version information" 1>&2 - exit 1 - ;; - esac - - case "$revision" in - 0 | [1-9] | [1-9][0-9]*) ;; - *) - $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2 - $echo "$modename: \`$vinfo' is not valid version information" 1>&2 - exit 1 - ;; - esac - - case "$age" in - 0 | [1-9] | [1-9][0-9]*) ;; - *) - $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2 - $echo "$modename: \`$vinfo' is not valid version information" 1>&2 - exit 1 - ;; - esac - - if test $age -gt $current; then - $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2 - $echo "$modename: \`$vinfo' is not valid version information" 1>&2 - exit 1 - fi - - # Calculate the version variables. - major= - versuffix= - verstring= - case "$version_type" in - none) ;; - - irix) - major=`expr $current - $age + 1` - versuffix="$major.$revision" - verstring="sgi$major.$revision" - - # Add in all the interfaces that we are compatible with. - loop=$revision - while test $loop != 0; do - iface=`expr $revision - $loop` - loop=`expr $loop - 1` - verstring="sgi$major.$iface:$verstring" - done - ;; - - linux) - major=.`expr $current - $age` - versuffix="$major.$age.$revision" - ;; - - osf) - major=`expr $current - $age` - versuffix=".$current.$age.$revision" - verstring="$current.$age.$revision" - - # Add in all the interfaces that we are compatible with. - loop=$age - while test $loop != 0; do - iface=`expr $current - $loop` - loop=`expr $loop - 1` - verstring="$verstring:${iface}.0" - done - - # Make executables depend on our current version. - verstring="$verstring:${current}.0" - ;; - - sunos) - major=".$current" - versuffix=".$current.$revision" - ;; - - freebsd-aout) - major=".$current" - versuffix=".$current.$revision"; - ;; - - freebsd-elf) - major=".$current" - versuffix=".$current"; - ;; - - windows) - # Like Linux, but with '-' rather than '.', since we only - # want one extension on Windows 95. - major=`expr $current - $age` - versuffix="-$major-$age-$revision" - ;; - - darwin) - # Like Linux, but with the current version available in - # verstring for coding it into the library header - major=.`expr $current - $age` - versuffix="$major.$age.$revision" - # Darwin ld doesn't like 0 for these options... - minor_current=`expr $current + 1` - verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" - ;; - - *) - $echo "$modename: unknown library version type \`$version_type'" 1>&2 - echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 - exit 1 - ;; - esac - - # Clear the version info if we defaulted, and they specified a release. - if test -z "$vinfo" && test -n "$release"; then - major= - verstring="0.0" - if test "$need_version" = no; then - versuffix= - else - versuffix=".0.0" - fi - fi - - # Remove version info from name if versioning should be avoided - if test "$avoid_version" = yes && test "$need_version" = no; then - major= - versuffix= - verstring="" - fi - - # Check to see if the archive will have undefined symbols. - if test "$allow_undefined" = yes; then - if test "$allow_undefined_flag" = unsupported; then - $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2 - build_libtool_libs=no - build_old_libs=yes - fi - else - # Don't allow undefined symbols. - allow_undefined_flag="$no_undefined_flag" - fi - - dependency_libs="$deplibs" - case "$host" in - *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos*) - # these systems don't actually have a c library (as such)! - ;; - *-*-rhapsody* | *-*-darwin1.[012]) - # Rhapsody C library is in the System framework - deplibs="$deplibs -framework System" - ;; - *) - # Add libc to deplibs on all other systems. - deplibs="$deplibs -lc" - ;; - esac - fi - - # Create the output directory, or remove our outputs if we need to. - if test -d $output_objdir; then - $show "${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.*" - $run ${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.* - else - $show "$mkdir $output_objdir" - $run $mkdir $output_objdir - status=$? - if test $status -ne 0 && test ! -d $output_objdir; then - exit $status - fi - fi - - # Now set the variables for building old libraries. - if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then - oldlibs="$oldlibs $output_objdir/$libname.$libext" - - # Transform .lo files to .o files. - oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` - fi - - if test "$build_libtool_libs" = yes; then - # Transform deplibs into only deplibs that can be linked in shared. - name_save=$name - libname_save=$libname - release_save=$release - versuffix_save=$versuffix - major_save=$major - # I'm not sure if I'm treating the release correctly. I think - # release should show up in the -l (ie -lgmp5) so we don't want to - # add it in twice. Is that correct? - release="" - versuffix="" - major="" - newdeplibs= - droppeddeps=no - case "$deplibs_check_method" in - pass_all) - # Don't check for shared/static. Everything works. - # This might be a little naive. We might want to check - # whether the library exists or not. But this is on - # osf3 & osf4 and I'm not really sure... Just - # implementing what was already the behaviour. - newdeplibs=$deplibs - ;; - test_compile) - # This code stresses the "libraries are programs" paradigm to its - # limits. Maybe even breaks it. We compile a program, linking it - # against the deplibs as a proxy for the library. Then we can check - # whether they linked in statically or dynamically with ldd. - $rm conftest.c - cat > conftest.c </dev/null` - for potent_lib in $potential_libs; do - # Follow soft links. - if ls -lLd "$potent_lib" 2>/dev/null \ - | grep " -> " >/dev/null; then - continue - fi - # The statement above tries to avoid entering an - # endless loop below, in case of cyclic links. - # We might still enter an endless loop, since a link - # loop can be closed while we follow links, - # but so what? - potlib="$potent_lib" - while test -h "$potlib" 2>/dev/null; do - potliblink=`ls -ld $potlib | sed 's/.* -> //'` - case "$potliblink" in - [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; - *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; - esac - done - if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \ - | sed 10q \ - | egrep "$file_magic_regex" > /dev/null; then - newdeplibs="$newdeplibs $a_deplib" - a_deplib="" - break 2 - fi - done - done - if test -n "$a_deplib" ; then - droppeddeps=yes - echo - echo "*** Warning: This library needs some functionality provided by $a_deplib." - echo "*** I have the capability to make that library automatically link in when" - echo "*** you link to this library. But I can only do this if you have a" - echo "*** shared version of the library, which you do not appear to have." - fi - else - # Add a -L argument. - newdeplibs="$newdeplibs $a_deplib" - fi - done # Gone through all deplibs. - ;; - none | unknown | *) - newdeplibs="" - if $echo "X $deplibs" | $Xsed -e 's/ -lc$//' \ - -e 's/ -[LR][^ ]*//g' -e 's/[ ]//g' | - grep . >/dev/null; then - echo - if test "X$deplibs_check_method" = "Xnone"; then - echo "*** Warning: inter-library dependencies are not supported in this platform." - else - echo "*** Warning: inter-library dependencies are not known to be supported." - fi - echo "*** All declared inter-library dependencies are being dropped." - droppeddeps=yes - fi - ;; - esac - versuffix=$versuffix_save - major=$major_save - release=$release_save - libname=$libname_save - name=$name_save - - if test "$droppeddeps" = yes; then - if test "$module" = yes; then - echo - echo "*** Warning: libtool could not satisfy all declared inter-library" - echo "*** dependencies of module $libname. Therefore, libtool will create" - echo "*** a static module, that should work as long as the dlopening" - echo "*** application is linked with the -dlopen flag." - if test -z "$global_symbol_pipe"; then - echo - echo "*** However, this would only work if libtool was able to extract symbol" - echo "*** lists from a program, using \`nm' or equivalent, but libtool could" - echo "*** not find such a program. So, this module is probably useless." - echo "*** \`nm' from GNU binutils and a full rebuild may help." - fi - if test "$build_old_libs" = no; then - oldlibs="$output_objdir/$libname.$libext" - build_libtool_libs=module - build_old_libs=yes - else - build_libtool_libs=no - fi - else - echo "*** The inter-library dependencies that have been dropped here will be" - echo "*** automatically added whenever a program is linked with this library" - echo "*** or is declared to -dlopen it." - fi - fi - # Done checking deplibs! - deplibs=$newdeplibs - fi - - # All the library-specific variables (install_libdir is set above). - library_names= - old_library= - dlname= - - # Test again, we may have decided not to build it any more - if test "$build_libtool_libs" = yes; then - # Get the real and link names of the library. - eval library_names=\"$library_names_spec\" - set dummy $library_names - realname="$2" - shift; shift - - if test -n "$soname_spec"; then - eval soname=\"$soname_spec\" - else - soname="$realname" - fi - - lib="$output_objdir/$realname" - for link - do - linknames="$linknames $link" - done - - # Ensure that we have .o objects for linkers which dislike .lo - # (e.g. aix) in case we are running --disable-static - for obj in $libobjs; do - xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` - if test "X$xdir" = "X$obj"; then - xdir="." - else - xdir="$xdir" - fi - baseobj=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` - oldobj=`$echo "X$baseobj" | $Xsed -e "$lo2o"` - if test ! -f $xdir/$oldobj; then - $show "(cd $xdir && ${LN_S} $baseobj $oldobj)" - $run eval '(cd $xdir && ${LN_S} $baseobj $oldobj)' || exit $? - fi - done - - # Use standard objects if they are pic - test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` - - # Prepare the list of exported symbols - if test -z "$export_symbols"; then - if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then - $show "generating symbol list for \`$libname.la'" - export_symbols="$output_objdir/$libname.exp" - $run $rm $export_symbols - eval cmds=\"$export_symbols_cmds\" - IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - $show "$cmd" - $run eval "$cmd" || exit $? - done - IFS="$save_ifs" - if test -n "$export_symbols_regex"; then - $show "egrep -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\"" - $run eval 'egrep -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' - $show "$mv \"${export_symbols}T\" \"$export_symbols\"" - $run eval '$mv "${export_symbols}T" "$export_symbols"' - fi - fi - fi - - if test -n "$export_symbols" && test -n "$include_expsyms"; then - $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"' - fi - - if test -n "$convenience"; then - if test -n "$whole_archive_flag_spec"; then - eval libobjs=\"\$libobjs $whole_archive_flag_spec\" - else - gentop="$output_objdir/${outputname}x" - $show "${rm}r $gentop" - $run ${rm}r "$gentop" - $show "mkdir $gentop" - $run mkdir "$gentop" - status=$? - if test $status -ne 0 && test ! -d "$gentop"; then - exit $status - fi - generated="$generated $gentop" - - for xlib in $convenience; do - # Extract the objects. - case "$xlib" in - [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; - *) xabs=`pwd`"/$xlib" ;; - esac - xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` - xdir="$gentop/$xlib" - - $show "${rm}r $xdir" - $run ${rm}r "$xdir" - $show "mkdir $xdir" - $run mkdir "$xdir" - status=$? - if test $status -ne 0 && test ! -d "$xdir"; then - exit $status - fi - $show "(cd $xdir && $AR x $xabs)" - $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? - - libobjs="$libobjs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP` - done - fi - fi - - if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then - eval flag=\"$thread_safe_flag_spec\" - linkopts="$linkopts $flag" - fi - - # Do each of the archive commands. - if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then - eval cmds=\"$archive_expsym_cmds\" - else - eval cmds=\"$archive_cmds\" - fi - IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - $show "$cmd" - $run eval "$cmd" || exit $? - done - IFS="$save_ifs" - - # Create links to the real library. - for linkname in $linknames; do - if test "$realname" != "$linkname"; then - $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)" - $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $? - fi - done - - # If -module or -export-dynamic was specified, set the dlname. - if test "$module" = yes || test "$export_dynamic" = yes; then - # On all known operating systems, these are identical. - dlname="$soname" - fi - fi - ;; - - *.lo | *.o | *.obj) - if test -n "$link_against_libtool_libs"; then - $echo "$modename: error: cannot link libtool libraries into objects" 1>&2 - exit 1 - fi - - if test -n "$deplibs"; then - $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2 - fi - - if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then - $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2 - fi - - if test -n "$rpath"; then - $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2 - fi - - if test -n "$xrpath"; then - $echo "$modename: warning: \`-R' is ignored for objects" 1>&2 - fi - - if test -n "$vinfo"; then - $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2 - fi - - if test -n "$release"; then - $echo "$modename: warning: \`-release' is ignored for objects" 1>&2 - fi - - case "$output" in - *.lo) - if test -n "$objs"; then - $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2 - exit 1 - fi - libobj="$output" - obj=`$echo "X$output" | $Xsed -e "$lo2o"` - ;; - *) - libobj= - obj="$output" - ;; - esac - - # Delete the old objects. - $run $rm $obj $libobj - - # Objects from convenience libraries. This assumes - # single-version convenience libraries. Whenever we create - # different ones for PIC/non-PIC, this we'll have to duplicate - # the extraction. - reload_conv_objs= - gentop= - # reload_cmds runs $LD directly, so let us get rid of - # -Wl from whole_archive_flag_spec - wl= - - if test -n "$convenience"; then - if test -n "$whole_archive_flag_spec"; then - eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\" - else - gentop="$output_objdir/${obj}x" - $show "${rm}r $gentop" - $run ${rm}r "$gentop" - $show "mkdir $gentop" - $run mkdir "$gentop" - status=$? - if test $status -ne 0 && test ! -d "$gentop"; then - exit $status - fi - generated="$generated $gentop" - - for xlib in $convenience; do - # Extract the objects. - case "$xlib" in - [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; - *) xabs=`pwd`"/$xlib" ;; - esac - xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` - xdir="$gentop/$xlib" - - $show "${rm}r $xdir" - $run ${rm}r "$xdir" - $show "mkdir $xdir" - $run mkdir "$xdir" - status=$? - if test $status -ne 0 && test ! -d "$xdir"; then - exit $status - fi - $show "(cd $xdir && $AR x $xabs)" - $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? - - reload_conv_objs="$reload_objs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP` - done - fi - fi - - # Create the old-style object. - reload_objs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" - - output="$obj" - eval cmds=\"$reload_cmds\" - IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - $show "$cmd" - $run eval "$cmd" || exit $? - done - IFS="$save_ifs" - - # Exit if we aren't doing a library object file. - if test -z "$libobj"; then - if test -n "$gentop"; then - $show "${rm}r $gentop" - $run ${rm}r $gentop - fi - - exit 0 - fi - - if test "$build_libtool_libs" != yes; then - if test -n "$gentop"; then - $show "${rm}r $gentop" - $run ${rm}r $gentop - fi - - # Create an invalid libtool object if no PIC, so that we don't - # accidentally link it into a program. - $show "echo timestamp > $libobj" - $run eval "echo timestamp > $libobj" || exit $? - exit 0 - fi - - if test -n "$pic_flag"; then - # Only do commands if we really have different PIC objects. - reload_objs="$libobjs $reload_conv_objs" - output="$libobj" - eval cmds=\"$reload_cmds\" - IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - $show "$cmd" - $run eval "$cmd" || exit $? - done - IFS="$save_ifs" - else - # Just create a symlink. - $show $rm $libobj - $run $rm $libobj - xdir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'` - if test "X$xdir" = "X$libobj"; then - xdir="." - else - xdir="$xdir" - fi - baseobj=`$echo "X$libobj" | $Xsed -e 's%^.*/%%'` - oldobj=`$echo "X$baseobj" | $Xsed -e "$lo2o"` - $show "(cd $xdir && $LN_S $oldobj $baseobj)" - $run eval '(cd $xdir && $LN_S $oldobj $baseobj)' || exit $? - fi - - if test -n "$gentop"; then - $show "${rm}r $gentop" - $run ${rm}r $gentop - fi - - exit 0 - ;; - - # Anything else should be a program. - *) - if test -n "$vinfo"; then - $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2 - fi - - if test -n "$release"; then - $echo "$modename: warning: \`-release' is ignored for programs" 1>&2 - fi - - if test "$preload" = yes; then - if test "$dlopen" = unknown && test "$dlopen_self" = unknown && - test "$dlopen_self_static" = unknown; then - $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support." - fi - fi - - if test -n "$rpath$xrpath"; then - # If the user specified any rpath flags, then add them. - for libdir in $rpath $xrpath; do - # This is the magic to use -rpath. - case "$compile_rpath " in - *" $libdir "*) ;; - *) compile_rpath="$compile_rpath $libdir" ;; - esac - case "$finalize_rpath " in - *" $libdir "*) ;; - *) finalize_rpath="$finalize_rpath $libdir" ;; - esac - done - fi - - # Now hardcode the library paths - rpath= - hardcode_libdirs= - for libdir in $compile_rpath $finalize_rpath; do - if test -n "$hardcode_libdir_flag_spec"; then - if test -n "$hardcode_libdir_separator"; then - if test -z "$hardcode_libdirs"; then - hardcode_libdirs="$libdir" - else - # Just accumulate the unique libdirs. - case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in - *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) - ;; - *) - hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" - ;; - esac - fi - else - eval flag=\"$hardcode_libdir_flag_spec\" - rpath="$rpath $flag" - fi - elif test -n "$runpath_var"; then - case "$perm_rpath " in - *" $libdir "*) ;; - *) perm_rpath="$perm_rpath $libdir" ;; - esac - fi - done - # Substitute the hardcoded libdirs into the rpath. - if test -n "$hardcode_libdir_separator" && - test -n "$hardcode_libdirs"; then - libdir="$hardcode_libdirs" - eval rpath=\" $hardcode_libdir_flag_spec\" - fi - compile_rpath="$rpath" - - rpath= - hardcode_libdirs= - for libdir in $finalize_rpath; do - if test -n "$hardcode_libdir_flag_spec"; then - if test -n "$hardcode_libdir_separator"; then - if test -z "$hardcode_libdirs"; then - hardcode_libdirs="$libdir" - else - # Just accumulate the unique libdirs. - case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in - *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) - ;; - *) - hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" - ;; - esac - fi - else - eval flag=\"$hardcode_libdir_flag_spec\" - rpath="$rpath $flag" - fi - elif test -n "$runpath_var"; then - case "$finalize_perm_rpath " in - *" $libdir "*) ;; - *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;; - esac - fi - done - # Substitute the hardcoded libdirs into the rpath. - if test -n "$hardcode_libdir_separator" && - test -n "$hardcode_libdirs"; then - libdir="$hardcode_libdirs" - eval rpath=\" $hardcode_libdir_flag_spec\" - fi - finalize_rpath="$rpath" - - output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'` - if test "X$output_objdir" = "X$output"; then - output_objdir="$objdir" - else - output_objdir="$output_objdir/$objdir" - fi - - # Create the binary in the object directory, then wrap it. - if test ! -d $output_objdir; then - $show "$mkdir $output_objdir" - $run $mkdir $output_objdir - status=$? - if test $status -ne 0 && test ! -d $output_objdir; then - exit $status - fi - fi - - if test -n "$libobjs" && test "$build_old_libs" = yes; then - # Transform all the library objects into standard objects. - compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` - finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` - fi - - dlsyms= - if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then - if test -n "$NM" && test -n "$global_symbol_pipe"; then - dlsyms="${outputname}S.c" - else - $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2 - fi - fi - - if test -n "$dlsyms"; then - case "$dlsyms" in - "") ;; - *.c) - # Discover the nlist of each of the dlfiles. - nlist="$output_objdir/${outputname}.nm" - - $show "$rm $nlist ${nlist}S ${nlist}T" - $run $rm "$nlist" "${nlist}S" "${nlist}T" - - # Parse the name list into a source file. - $show "creating $output_objdir/$dlsyms" - - test -z "$run" && $echo > "$output_objdir/$dlsyms" "\ -/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */ -/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */ - -#ifdef __cplusplus -extern \"C\" { -#endif - -/* Prevent the only kind of declaration conflicts we can make. */ -#define lt_preloaded_symbols some_other_symbol - -/* External symbol declarations for the compiler. */\ -" - - if test "$dlself" = yes; then - $show "generating symbol list for \`$output'" - - test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist" - - # Add our own program objects to the symbol list. - progfiles=`$echo "X$objs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` - for arg in $progfiles; do - $show "extracting global C symbols from \`$arg'" - $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" - done - - if test -n "$exclude_expsyms"; then - $run eval 'egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' - $run eval '$mv "$nlist"T "$nlist"' - fi - - if test -n "$export_symbols_regex"; then - $run eval 'egrep -e "$export_symbols_regex" "$nlist" > "$nlist"T' - $run eval '$mv "$nlist"T "$nlist"' - fi - - # Prepare the list of exported symbols - if test -z "$export_symbols"; then - export_symbols="$output_objdir/$output.exp" - $run $rm $export_symbols - $run eval "sed -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' - else - $run eval "sed -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"' - $run eval 'grep -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T' - $run eval 'mv "$nlist"T "$nlist"' - fi - fi - - for arg in $dlprefiles; do - $show "extracting global C symbols from \`$arg'" - name=`echo "$arg" | sed -e 's%^.*/%%'` - $run eval 'echo ": $name " >> "$nlist"' - $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" - done - - if test -z "$run"; then - # Make sure we have at least an empty file. - test -f "$nlist" || : > "$nlist" - - if test -n "$exclude_expsyms"; then - egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T - $mv "$nlist"T "$nlist" - fi - - # Try sorting and uniquifying the output. - if grep -v "^: " < "$nlist" | sort +2 | uniq > "$nlist"S; then - : - else - grep -v "^: " < "$nlist" > "$nlist"S - fi - - if test -f "$nlist"S; then - eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"' - else - echo '/* NONE */' >> "$output_objdir/$dlsyms" - fi - - $echo >> "$output_objdir/$dlsyms" "\ - -#undef lt_preloaded_symbols - -#if defined (__STDC__) && __STDC__ -# define lt_ptr_t void * -#else -# define lt_ptr_t char * -# define const -#endif - -/* The mapping between symbol names and symbols. */ -const struct { - const char *name; - lt_ptr_t address; -} -lt_preloaded_symbols[] = -{\ -" - - sed -n -e 's/^: \([^ ]*\) $/ {\"\1\", (lt_ptr_t) 0},/p' \ - -e 's/^. \([^ ]*\) \([^ ]*\)$/ {"\2", (lt_ptr_t) \&\2},/p' \ - < "$nlist" >> "$output_objdir/$dlsyms" - - $echo >> "$output_objdir/$dlsyms" "\ - {0, (lt_ptr_t) 0} -}; - -/* This works around a problem in FreeBSD linker */ -#ifdef FREEBSD_WORKAROUND -static const void *lt_preloaded_setup() { - return lt_preloaded_symbols; -} -#endif - -#ifdef __cplusplus -} -#endif\ -" - fi - - pic_flag_for_symtable= - case "$host" in - # compiling the symbol table file with pic_flag works around - # a FreeBSD bug that causes programs to crash when -lm is - # linked before any other PIC object. But we must not use - # pic_flag when linking with -static. The problem exists in - # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. - *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) - case "$compile_command " in - *" -static "*) ;; - *) pic_flag_for_symtable=" $pic_flag -DPIC -DFREEBSD_WORKAROUND";; - esac;; - *-*-hpux*) - case "$compile_command " in - *" -static "*) ;; - *) pic_flag_for_symtable=" $pic_flag -DPIC";; - esac - esac - - # Now compile the dynamic symbol file. - $show "(cd $output_objdir && $CC -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")" - $run eval '(cd $output_objdir && $CC -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $? - - # Clean up the generated files. - $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T" - $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T" - - # Transform the symbol file into the correct name. - compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` - finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` - ;; - *) - $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2 - exit 1 - ;; - esac - else - # We keep going just in case the user didn't refer to - # lt_preloaded_symbols. The linker will fail if global_symbol_pipe - # really was required. - - # Nullify the symbol file. - compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` - finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` - fi - - if test -z "$link_against_libtool_libs" || test "$build_libtool_libs" != yes; then - # Replace the output file specification. - compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` - link_command="$compile_command$compile_rpath" - - # We have no uninstalled library dependencies, so finalize right now. - $show "$link_command" - $run eval "$link_command" - status=$? - - # Delete the generated files. - if test -n "$dlsyms"; then - $show "$rm $output_objdir/${outputname}S.${objext}" - $run $rm "$output_objdir/${outputname}S.${objext}" - fi - - exit $status - fi - - if test -n "$shlibpath_var"; then - # We should set the shlibpath_var - rpath= - for dir in $temp_rpath; do - case "$dir" in - [\\/]* | [A-Za-z]:[\\/]*) - # Absolute path. - rpath="$rpath$dir:" - ;; - *) - # Relative path: add a thisdir entry. - rpath="$rpath\$thisdir/$dir:" - ;; - esac - done - temp_rpath="$rpath" - fi - - if test -n "$compile_shlibpath$finalize_shlibpath"; then - compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" - fi - if test -n "$finalize_shlibpath"; then - finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" - fi - - compile_var= - finalize_var= - if test -n "$runpath_var"; then - if test -n "$perm_rpath"; then - # We should set the runpath_var. - rpath= - for dir in $perm_rpath; do - rpath="$rpath$dir:" - done - compile_var="$runpath_var=\"$rpath\$$runpath_var\" " - fi - if test -n "$finalize_perm_rpath"; then - # We should set the runpath_var. - rpath= - for dir in $finalize_perm_rpath; do - rpath="$rpath$dir:" - done - finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " - fi - fi - - if test "$hardcode_action" = relink; then - # Fast installation is not supported - link_command="$compile_var$compile_command$compile_rpath" - relink_command="$finalize_var$finalize_command$finalize_rpath" - - $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2 - $echo "$modename: \`$output' will be relinked during installation" 1>&2 - else - if test "$fast_install" != no; then - link_command="$finalize_var$compile_command$finalize_rpath" - if test "$fast_install" = yes; then - relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'` - else - # fast_install is set to needless - relink_command= - fi - else - link_command="$compile_var$compile_command$compile_rpath" - relink_command="$finalize_var$finalize_command$finalize_rpath" - fi - fi - - # Replace the output file specification. - link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` - - # Delete the old output files. - $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname - - $show "$link_command" - $run eval "$link_command" || exit $? - - # Now create the wrapper script. - $show "creating $output" - - # Quote the relink command for shipping. - if test -n "$relink_command"; then - relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` - fi - - # Quote $echo for shipping. - if test "X$echo" = "X$SHELL $0 --fallback-echo"; then - case "$0" in - [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $0 --fallback-echo";; - *) qecho="$SHELL `pwd`/$0 --fallback-echo";; - esac - qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"` - else - qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"` - fi - - # Only actually do things if our run command is non-null. - if test -z "$run"; then - # win32 will think the script is a binary if it has - # a .exe suffix, so we strip it off here. - case $output in - *.exe) output=`echo $output|sed 's,.exe$,,'` ;; - esac - $rm $output - trap "$rm $output; exit 1" 1 2 15 - - $echo > $output "\ -#! $SHELL - -# $output - temporary wrapper script for $objdir/$outputname -# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP -# -# The $output program cannot be directly executed until all the libtool -# libraries that it depends on are installed. -# -# This wrapper script should never be moved out of the build directory. -# If it is, it will not operate correctly. - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -Xsed='sed -e 1s/^X//' -sed_quote_subst='$sed_quote_subst' - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -if test \"\${CDPATH+set}\" = set; then CDPATH=:; export CDPATH; fi - -relink_command=\"$relink_command\" - -# This environment variable determines our operation mode. -if test \"\$libtool_install_magic\" = \"$magic\"; then - # install mode needs the following variable: - link_against_libtool_libs='$link_against_libtool_libs' -else - # When we are sourced in execute mode, \$file and \$echo are already set. - if test \"\$libtool_execute_magic\" != \"$magic\"; then - echo=\"$qecho\" - file=\"\$0\" - # Make sure echo works. - if test \"X\$1\" = X--no-reexec; then - # Discard the --no-reexec flag, and continue. - shift - elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then - # Yippee, \$echo works! - : - else - # Restart under the correct shell, and then maybe \$echo will work. - exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} - fi - fi\ -" - $echo >> $output "\ - - # Find the directory that this script lives in. - thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` - test \"x\$thisdir\" = \"x\$file\" && thisdir=. - - # Follow symbolic links until we get to the real thisdir. - file=\`ls -ld \"\$file\" | sed -n 's/.*-> //p'\` - while test -n \"\$file\"; do - destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` - - # If there was a directory component, then change thisdir. - if test \"x\$destdir\" != \"x\$file\"; then - case \"\$destdir\" in - [\\/]* | [A-Za-z]:[\\/]*) thisdir=\"\$destdir\" ;; - *) thisdir=\"\$thisdir/\$destdir\" ;; - esac - fi - - file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\` - file=\`ls -ld \"\$thisdir/\$file\" | sed -n 's/.*-> //p'\` - done - - # Try to get the absolute directory name. - absdir=\`cd \"\$thisdir\" && pwd\` - test -n \"\$absdir\" && thisdir=\"\$absdir\" -" - - if test "$fast_install" = yes; then - echo >> $output "\ - program=lt-'$outputname' - progdir=\"\$thisdir/$objdir\" - - if test ! -f \"\$progdir/\$program\" || \\ - { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | sed 1q\`; \\ - test \"X\$file\" != \"X\$progdir/\$program\"; }; then - - file=\"\$\$-\$program\" - - if test ! -d \"\$progdir\"; then - $mkdir \"\$progdir\" - else - $rm \"\$progdir/\$file\" - fi" - - echo >> $output "\ - - # relink executable if necessary - if test -n \"\$relink_command\"; then - if (cd \"\$thisdir\" && eval \$relink_command); then : - else - $rm \"\$progdir/\$file\" - exit 1 - fi - fi - - $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || - { $rm \"\$progdir/\$program\"; - $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; } - $rm \"\$progdir/\$file\" - fi" - else - echo >> $output "\ - program='$outputname' - progdir=\"\$thisdir/$objdir\" -" - fi - - echo >> $output "\ - - if test -f \"\$progdir/\$program\"; then" - - # Export our shlibpath_var if we have one. - if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then - $echo >> $output "\ - # Add our own library path to $shlibpath_var - $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" - - # Some systems cannot cope with colon-terminated $shlibpath_var - # The second colon is a workaround for a bug in BeOS R4 sed - $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` - - export $shlibpath_var -" - fi - - # fixup the dll searchpath if we need to. - if test -n "$dllsearchpath"; then - $echo >> $output "\ - # Add the dll search path components to the executable PATH - PATH=$dllsearchpath:\$PATH -" - fi - - $echo >> $output "\ - if test \"\$libtool_execute_magic\" != \"$magic\"; then - # Run the actual program with our arguments. -" - case $host in - # win32 systems need to use the prog path for dll - # lookup to work - *-*-cygwin*) - $echo >> $output "\ - exec \$progdir/\$program \${1+\"\$@\"} -" - ;; - - # Backslashes separate directories on plain windows - *-*-mingw | *-*-os2*) - $echo >> $output "\ - exec \$progdir\\\\\$program \${1+\"\$@\"} -" - ;; - - *) - $echo >> $output "\ - # Export the path to the program. - PATH=\"\$progdir:\$PATH\" - export PATH - - exec \$program \${1+\"\$@\"} -" - ;; - esac - $echo >> $output "\ - \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\" - exit 1 - fi - else - # The program doesn't exist. - \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2 - \$echo \"This script is just a wrapper for \$program.\" 1>&2 - echo \"See the $PACKAGE documentation for more information.\" 1>&2 - exit 1 - fi -fi\ -" - chmod +x $output - fi - exit 0 - ;; - esac - - # See if we need to build an old-fashioned archive. - for oldlib in $oldlibs; do - - if test "$build_libtool_libs" = convenience; then - oldobjs="$libobjs_save" - addlibs="$convenience" - build_libtool_libs=no - else - if test "$build_libtool_libs" = module; then - oldobjs="$libobjs_save" - build_libtool_libs=no - else - oldobjs="$objs "`$echo "X$libobjs_save" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP` - fi - addlibs="$old_convenience" - fi - - if test -n "$addlibs"; then - gentop="$output_objdir/${outputname}x" - $show "${rm}r $gentop" - $run ${rm}r "$gentop" - $show "mkdir $gentop" - $run mkdir "$gentop" - status=$? - if test $status -ne 0 && test ! -d "$gentop"; then - exit $status - fi - generated="$generated $gentop" - - # Add in members from convenience archives. - for xlib in $addlibs; do - # Extract the objects. - case "$xlib" in - [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; - *) xabs=`pwd`"/$xlib" ;; - esac - xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` - xdir="$gentop/$xlib" - - $show "${rm}r $xdir" - $run ${rm}r "$xdir" - $show "mkdir $xdir" - $run mkdir "$xdir" - status=$? - if test $status -ne 0 && test ! -d "$xdir"; then - exit $status - fi - $show "(cd $xdir && $AR x $xabs)" - $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? - - oldobjs="$oldobjs "`find $xdir -name \*.${objext} -print -o -name \*.lo -print | $NL2SP` - done - fi - - # Do each command in the archive commands. - if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then - eval cmds=\"$old_archive_from_new_cmds\" - else - # Ensure that we have .o objects in place in case we decided - # not to build a shared library, and have fallen back to building - # static libs even though --disable-static was passed! - for oldobj in $oldobjs; do - if test ! -f $oldobj; then - xdir=`$echo "X$oldobj" | $Xsed -e 's%/[^/]*$%%'` - if test "X$xdir" = "X$oldobj"; then - xdir="." - else - xdir="$xdir" - fi - baseobj=`$echo "X$oldobj" | $Xsed -e 's%^.*/%%'` - obj=`$echo "X$baseobj" | $Xsed -e "$o2lo"` - $show "(cd $xdir && ${LN_S} $obj $baseobj)" - $run eval '(cd $xdir && ${LN_S} $obj $baseobj)' || exit $? - fi - done - - eval cmds=\"$old_archive_cmds\" - fi - IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - $show "$cmd" - $run eval "$cmd" || exit $? - done - IFS="$save_ifs" - done - - if test -n "$generated"; then - $show "${rm}r$generated" - $run ${rm}r$generated - fi - - # Now create the libtool archive. - case "$output" in - *.la) - old_library= - test "$build_old_libs" = yes && old_library="$libname.$libext" - $show "creating $output" - - if test -n "$xrpath"; then - temp_xrpath= - for libdir in $xrpath; do - temp_xrpath="$temp_xrpath -R$libdir" - done - dependency_libs="$temp_xrpath $dependency_libs" - fi - - # Only create the output if not a dry run. - if test -z "$run"; then - for installed in no yes; do - if test "$installed" = yes; then - if test -z "$install_libdir"; then - break - fi - output="$output_objdir/$outputname"i - fi - $rm $output - $echo > $output "\ -# $outputname - a libtool library file -# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP -# -# Please DO NOT delete this file! -# It is necessary for linking the library. - -# The name that we can dlopen(3). -dlname='$dlname' - -# Names of this library. -library_names='$library_names' - -# The name of the static archive. -old_library='$old_library' - -# Libraries that this one depends upon. -dependency_libs='$dependency_libs' - -# Version information for $libname. -current=$current -age=$age -revision=$revision - -# Is this an already installed library? -installed=$installed - -# Directory that this library needs to be installed in: -libdir='$install_libdir'\ -" - done - fi - - # Do a symbolic link so that the libtool archive can be found in - # LD_LIBRARY_PATH before the program is installed. - $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" - $run eval "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" || exit $? - ;; - esac - exit 0 - ;; - - # libtool install mode - install) - modename="$modename: install" - - # There may be an optional sh(1) argument at the beginning of - # install_prog (especially on Windows NT). - if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh; then - # Aesthetically quote it. - arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"` - case "$arg" in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) - arg="\"$arg\"" - ;; - esac - install_prog="$arg " - arg="$1" - shift - else - install_prog= - arg="$nonopt" - fi - - # The real first argument should be the name of the installation program. - # Aesthetically quote it. - arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` - case "$arg" in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) - arg="\"$arg\"" - ;; - esac - install_prog="$install_prog$arg" - - # We need to accept at least all the BSD install flags. - dest= - files= - opts= - prev= - install_type= - isdir=no - stripme= - for arg - do - if test -n "$dest"; then - files="$files $dest" - dest="$arg" - continue - fi - - case "$arg" in - -d) isdir=yes ;; - -f) prev="-f" ;; - -g) prev="-g" ;; - -m) prev="-m" ;; - -o) prev="-o" ;; - -s) - stripme=" -s" - continue - ;; - -*) ;; - - *) - # If the previous option needed an argument, then skip it. - if test -n "$prev"; then - prev= - else - dest="$arg" - continue - fi - ;; - esac - - # Aesthetically quote the argument. - arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` - case "$arg" in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) - arg="\"$arg\"" - ;; - esac - install_prog="$install_prog $arg" - done - - if test -z "$install_prog"; then - $echo "$modename: you must specify an install program" 1>&2 - $echo "$help" 1>&2 - exit 1 - fi - - if test -n "$prev"; then - $echo "$modename: the \`$prev' option requires an argument" 1>&2 - $echo "$help" 1>&2 - exit 1 - fi - - if test -z "$files"; then - if test -z "$dest"; then - $echo "$modename: no file or destination specified" 1>&2 - else - $echo "$modename: you must specify a destination" 1>&2 - fi - $echo "$help" 1>&2 - exit 1 - fi - - # Strip any trailing slash from the destination. - dest=`$echo "X$dest" | $Xsed -e 's%/$%%'` - - # Check to see that the destination is a directory. - test -d "$dest" && isdir=yes - if test "$isdir" = yes; then - destdir="$dest" - destname= - else - destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'` - test "X$destdir" = "X$dest" && destdir=. - destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'` - - # Not a directory, so check to see that there is only one file specified. - set dummy $files - if test $# -gt 2; then - $echo "$modename: \`$dest' is not a directory" 1>&2 - $echo "$help" 1>&2 - exit 1 - fi - fi - case "$destdir" in - [\\/]* | [A-Za-z]:[\\/]*) ;; - *) - for file in $files; do - case "$file" in - *.lo) ;; - *) - $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2 - $echo "$help" 1>&2 - exit 1 - ;; - esac - done - ;; - esac - - # This variable tells wrapper scripts just to set variables rather - # than running their programs. - libtool_install_magic="$magic" - - staticlibs= - future_libdirs= - current_libdirs= - for file in $files; do - - # Do each installation. - case "$file" in - *.a | *.lib) - # Do the static libraries later. - staticlibs="$staticlibs $file" - ;; - - *.la) - # Check to see that this really is a libtool archive. - if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : - else - $echo "$modename: \`$file' is not a valid libtool archive" 1>&2 - $echo "$help" 1>&2 - exit 1 - fi - - library_names= - old_library= - # If there is no directory component, then add one. - case "$file" in - */* | *\\*) . $file ;; - *) . ./$file ;; - esac - - # Add the libdir to current_libdirs if it is the destination. - if test "X$destdir" = "X$libdir"; then - case "$current_libdirs " in - *" $libdir "*) ;; - *) current_libdirs="$current_libdirs $libdir" ;; - esac - else - # Note the libdir as a future libdir. - case "$future_libdirs " in - *" $libdir "*) ;; - *) future_libdirs="$future_libdirs $libdir" ;; - esac - fi - - dir="`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/" - test "X$dir" = "X$file/" && dir= - dir="$dir$objdir" - - # See the names of the shared library. - set dummy $library_names - if test -n "$2"; then - realname="$2" - shift - shift - - # Install the shared library and build the symlinks. - $show "$install_prog $dir/$realname $destdir/$realname" - $run eval "$install_prog $dir/$realname $destdir/$realname" || exit $? - - if test $# -gt 0; then - # Delete the old symlinks, and create new ones. - for linkname - do - if test "$linkname" != "$realname"; then - $show "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)" - $run eval "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)" - fi - done - fi - - # Do each command in the postinstall commands. - lib="$destdir/$realname" - eval cmds=\"$postinstall_cmds\" - IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - $show "$cmd" - $run eval "$cmd" || exit $? - done - IFS="$save_ifs" - fi - - # Install the pseudo-library for information purposes. - name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` - instname="$dir/$name"i - $show "$install_prog $instname $destdir/$name" - $run eval "$install_prog $instname $destdir/$name" || exit $? - - # Maybe install the static library, too. - test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" - ;; - - *.lo) - # Install (i.e. copy) a libtool object. - - # Figure out destination file name, if it wasn't already specified. - if test -n "$destname"; then - destfile="$destdir/$destname" - else - destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` - destfile="$destdir/$destfile" - fi - - # Deduce the name of the destination old-style object file. - case "$destfile" in - *.lo) - staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"` - ;; - *.o | *.obj) - staticdest="$destfile" - destfile= - ;; - *) - $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2 - $echo "$help" 1>&2 - exit 1 - ;; - esac - - # Install the libtool object if requested. - if test -n "$destfile"; then - $show "$install_prog $file $destfile" - $run eval "$install_prog $file $destfile" || exit $? - fi - - # Install the old object if enabled. - if test "$build_old_libs" = yes; then - # Deduce the name of the old-style object file. - staticobj=`$echo "X$file" | $Xsed -e "$lo2o"` - - $show "$install_prog $staticobj $staticdest" - $run eval "$install_prog \$staticobj \$staticdest" || exit $? - fi - exit 0 - ;; - - *) - # Figure out destination file name, if it wasn't already specified. - if test -n "$destname"; then - destfile="$destdir/$destname" - else - destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` - destfile="$destdir/$destfile" - fi - - # Do a test to see if this is really a libtool program. - if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then - link_against_libtool_libs= - relink_command= - - # If there is no directory component, then add one. - case "$file" in - */* | *\\*) . $file ;; - *) . ./$file ;; - esac - - # Check the variables that should have been set. - if test -z "$link_against_libtool_libs"; then - $echo "$modename: invalid libtool wrapper script \`$file'" 1>&2 - exit 1 - fi - - finalize=yes - for lib in $link_against_libtool_libs; do - # Check to see that each library is installed. - libdir= - if test -f "$lib"; then - # If there is no directory component, then add one. - case "$lib" in - */* | *\\*) . $lib ;; - *) . ./$lib ;; - esac - fi - libfile="$libdir/`$echo "X$lib" | $Xsed -e 's%^.*/%%g'`" - if test -n "$libdir" && test ! -f "$libfile"; then - $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2 - finalize=no - fi - done - - outputname= - if test "$fast_install" = no && test -n "$relink_command"; then - if test "$finalize" = yes && test -z "$run"; then - tmpdir="/tmp" - test -n "$TMPDIR" && tmpdir="$TMPDIR" - tmpdir="$tmpdir/libtool-$$" - if $mkdir -p "$tmpdir" && chmod 700 "$tmpdir"; then : - else - $echo "$modename: error: cannot create temporary directory \`$tmpdir'" 1>&2 - continue - fi - outputname="$tmpdir/$file" - # Replace the output file specification. - relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` - - $show "$relink_command" - if $run eval "$relink_command"; then : - else - $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 - ${rm}r "$tmpdir" - continue - fi - file="$outputname" - else - $echo "$modename: warning: cannot relink \`$file'" 1>&2 - fi - else - # Install the binary that we compiled earlier. - file=`$echo "X$file" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` - fi - fi - - $show "$install_prog$stripme $file $destfile" - $run eval "$install_prog\$stripme \$file \$destfile" || exit $? - test -n "$outputname" && ${rm}r "$tmpdir" - ;; - esac - done - - for file in $staticlibs; do - name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` - - # Set up the ranlib parameters. - oldlib="$destdir/$name" - - $show "$install_prog $file $oldlib" - $run eval "$install_prog \$file \$oldlib" || exit $? - - # Do each command in the postinstall commands. - eval cmds=\"$old_postinstall_cmds\" - IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - $show "$cmd" - $run eval "$cmd" || exit $? - done - IFS="$save_ifs" - done - - if test -n "$future_libdirs"; then - $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2 - fi - - if test -n "$current_libdirs"; then - # Maybe just do a dry run. - test -n "$run" && current_libdirs=" -n$current_libdirs" - exec $SHELL $0 --finish$current_libdirs - exit 1 - fi - - exit 0 - ;; - - # libtool finish mode - finish) - modename="$modename: finish" - libdirs="$nonopt" - admincmds= - - if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then - for dir - do - libdirs="$libdirs $dir" - done - - for libdir in $libdirs; do - if test -n "$finish_cmds"; then - # Do each command in the finish commands. - eval cmds=\"$finish_cmds\" - IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - $show "$cmd" - $run eval "$cmd" || admincmds="$admincmds - $cmd" - done - IFS="$save_ifs" - fi - if test -n "$finish_eval"; then - # Do the single finish_eval. - eval cmds=\"$finish_eval\" - $run eval "$cmds" || admincmds="$admincmds - $cmds" - fi - done - fi - - # Exit here if they wanted silent mode. - test "$show" = : && exit 0 - - echo "----------------------------------------------------------------------" - echo "Libraries have been installed in:" - for libdir in $libdirs; do - echo " $libdir" - done - echo - echo "If you ever happen to want to link against installed libraries" - echo "in a given directory, LIBDIR, you must either use libtool, and" - echo "specify the full pathname of the library, or use \`-LLIBDIR'" - echo "flag during linking and do at least one of the following:" - if test -n "$shlibpath_var"; then - echo " - add LIBDIR to the \`$shlibpath_var' environment variable" - echo " during execution" - fi - if test -n "$runpath_var"; then - echo " - add LIBDIR to the \`$runpath_var' environment variable" - echo " during linking" - fi - if test -n "$hardcode_libdir_flag_spec"; then - libdir=LIBDIR - eval flag=\"$hardcode_libdir_flag_spec\" - - echo " - use the \`$flag' linker flag" - fi - if test -n "$admincmds"; then - echo " - have your system administrator run these commands:$admincmds" - fi - if test -f /etc/ld.so.conf; then - echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" - fi - echo - echo "See any operating system documentation about shared libraries for" - echo "more information, such as the ld(1) and ld.so(8) manual pages." - echo "----------------------------------------------------------------------" - exit 0 - ;; - - # libtool execute mode - execute) - modename="$modename: execute" - - # The first argument is the command name. - cmd="$nonopt" - if test -z "$cmd"; then - $echo "$modename: you must specify a COMMAND" 1>&2 - $echo "$help" - exit 1 - fi - - # Handle -dlopen flags immediately. - for file in $execute_dlfiles; do - if test ! -f "$file"; then - $echo "$modename: \`$file' is not a file" 1>&2 - $echo "$help" 1>&2 - exit 1 - fi - - dir= - case "$file" in - *.la) - # Check to see that this really is a libtool archive. - if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : - else - $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 - $echo "$help" 1>&2 - exit 1 - fi - - # Read the libtool library. - dlname= - library_names= - - # If there is no directory component, then add one. - case "$file" in - */* | *\\*) . $file ;; - *) . ./$file ;; - esac - - # Skip this library if it cannot be dlopened. - if test -z "$dlname"; then - # Warn if it was a shared library. - test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'" - continue - fi - - dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` - test "X$dir" = "X$file" && dir=. - - if test -f "$dir/$objdir/$dlname"; then - dir="$dir/$objdir" - else - $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2 - exit 1 - fi - ;; - - *.lo) - # Just add the directory containing the .lo file. - dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` - test "X$dir" = "X$file" && dir=. - ;; - - *) - $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2 - continue - ;; - esac - - # Get the absolute pathname. - absdir=`cd "$dir" && pwd` - test -n "$absdir" && dir="$absdir" - - # Now add the directory to shlibpath_var. - if eval "test -z \"\$$shlibpath_var\""; then - eval "$shlibpath_var=\"\$dir\"" - else - eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" - fi - done - - # This variable tells wrapper scripts just to set shlibpath_var - # rather than running their programs. - libtool_execute_magic="$magic" - - # Check if any of the arguments is a wrapper script. - args= - for file - do - case "$file" in - -*) ;; - *) - # Do a test to see if this is really a libtool program. - if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then - # If there is no directory component, then add one. - case "$file" in - */* | *\\*) . $file ;; - *) . ./$file ;; - esac - - # Transform arg to wrapped name. - file="$progdir/$program" - fi - ;; - esac - # Quote arguments (to preserve shell metacharacters). - file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"` - args="$args \"$file\"" - done - - if test -z "$run"; then - if test -n "$shlibpath_var"; then - # Export the shlibpath_var. - eval "export $shlibpath_var" - fi - - # Restore saved enviroment variables - if test "${save_LC_ALL+set}" = set; then - LC_ALL="$save_LC_ALL"; export LC_ALL - fi - if test "${save_LANG+set}" = set; then - LANG="$save_LANG"; export LANG - fi - - # Now actually exec the command. - eval "exec \$cmd$args" - - $echo "$modename: cannot exec \$cmd$args" - exit 1 - else - # Display what would be done. - if test -n "$shlibpath_var"; then - eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\"" - $echo "export $shlibpath_var" - fi - $echo "$cmd$args" - exit 0 - fi - ;; - - # libtool uninstall mode - uninstall) - modename="$modename: uninstall" - rm="$nonopt" - files= - - for arg - do - case "$arg" in - -*) rm="$rm $arg" ;; - *) files="$files $arg" ;; - esac - done - - if test -z "$rm"; then - $echo "$modename: you must specify an RM program" 1>&2 - $echo "$help" 1>&2 - exit 1 - fi - - for file in $files; do - dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` - test "X$dir" = "X$file" && dir=. - name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` - - rmfiles="$file" - - case "$name" in - *.la) - # Possibly a libtool archive, so verify it. - if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then - . $dir/$name - - # Delete the libtool libraries and symlinks. - for n in $library_names; do - rmfiles="$rmfiles $dir/$n" - done - test -n "$old_library" && rmfiles="$rmfiles $dir/$old_library" - - $show "$rm $rmfiles" - $run $rm $rmfiles - - if test -n "$library_names"; then - # Do each command in the postuninstall commands. - eval cmds=\"$postuninstall_cmds\" - IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - $show "$cmd" - $run eval "$cmd" - done - IFS="$save_ifs" - fi - - if test -n "$old_library"; then - # Do each command in the old_postuninstall commands. - eval cmds=\"$old_postuninstall_cmds\" - IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - $show "$cmd" - $run eval "$cmd" - done - IFS="$save_ifs" - fi - - # FIXME: should reinstall the best remaining shared library. - fi - ;; - - *.lo) - if test "$build_old_libs" = yes; then - oldobj=`$echo "X$name" | $Xsed -e "$lo2o"` - rmfiles="$rmfiles $dir/$oldobj" - fi - $show "$rm $rmfiles" - $run $rm $rmfiles - ;; - - *) - $show "$rm $rmfiles" - $run $rm $rmfiles - ;; - esac - done - exit 0 - ;; - - "") - $echo "$modename: you must specify a MODE" 1>&2 - $echo "$generic_help" 1>&2 - exit 1 - ;; - esac - - $echo "$modename: invalid operation mode \`$mode'" 1>&2 - $echo "$generic_help" 1>&2 - exit 1 -fi # test -z "$show_help" - -# We need to display help for each of the modes. -case "$mode" in -"") $echo \ -"Usage: $modename [OPTION]... [MODE-ARG]... - -Provide generalized library-building support services. - - --config show all configuration variables - --debug enable verbose shell tracing --n, --dry-run display commands without modifying any files - --features display basic configuration information and exit - --finish same as \`--mode=finish' - --help display this help message and exit - --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS] - --quiet same as \`--silent' - --silent don't print informational messages - --version print version information - -MODE must be one of the following: - - compile compile a source file into a libtool object - execute automatically set library path, then run a program - finish complete the installation of libtool libraries - install install libraries or executables - link create a library or an executable - uninstall remove libraries from an installed directory - -MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for -a more detailed description of MODE." - exit 0 - ;; - -compile) - $echo \ -"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE - -Compile a source file into a libtool library object. - -This mode accepts the following additional options: - - -o OUTPUT-FILE set the output file name to OUTPUT-FILE - -static always build a \`.o' file suitable for static linking - -COMPILE-COMMAND is a command to be used in creating a \`standard' object file -from the given SOURCEFILE. - -The output file name is determined by removing the directory component from -SOURCEFILE, then substituting the C source code suffix \`.c' with the -library object suffix, \`.lo'." - ;; - -execute) - $echo \ -"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]... - -Automatically set library path, then run a program. - -This mode accepts the following additional options: - - -dlopen FILE add the directory containing FILE to the library path - -This mode sets the library path environment variable according to \`-dlopen' -flags. - -If any of the ARGS are libtool executable wrappers, then they are translated -into their corresponding uninstalled binary, and any of their required library -directories are added to the library path. - -Then, COMMAND is executed, with ARGS as arguments." - ;; - -finish) - $echo \ -"Usage: $modename [OPTION]... --mode=finish [LIBDIR]... - -Complete the installation of libtool libraries. - -Each LIBDIR is a directory that contains libtool libraries. - -The commands that this mode executes may require superuser privileges. Use -the \`--dry-run' option if you just want to see what would be executed." - ;; - -install) - $echo \ -"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND... - -Install executables or libraries. - -INSTALL-COMMAND is the installation command. The first component should be -either the \`install' or \`cp' program. - -The rest of the components are interpreted as arguments to that command (only -BSD-compatible install options are recognized)." - ;; - -link) - $echo \ -"Usage: $modename [OPTION]... --mode=link LINK-COMMAND... - -Link object files or libraries together to form another library, or to -create an executable program. - -LINK-COMMAND is a command using the C compiler that you would use to create -a program from several object files. - -The following components of LINK-COMMAND are treated specially: - - -all-static do not do any dynamic linking at all - -avoid-version do not add a version suffix if possible - -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime - -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols - -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) - -export-symbols SYMFILE - try to export only the symbols listed in SYMFILE - -export-symbols-regex REGEX - try to export only the symbols matching REGEX - -LLIBDIR search LIBDIR for required installed libraries - -lNAME OUTPUT-FILE requires the installed library libNAME - -module build a library that can dlopened - -no-undefined declare that a library does not refer to external symbols - -o OUTPUT-FILE create OUTPUT-FILE from the specified objects - -release RELEASE specify package release information - -rpath LIBDIR the created library will eventually be installed in LIBDIR - -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries - -static do not do any dynamic linking of libtool libraries - -version-info CURRENT[:REVISION[:AGE]] - specify library version info [each variable defaults to 0] - -All other options (arguments beginning with \`-') are ignored. - -Every other argument is treated as a filename. Files ending in \`.la' are -treated as uninstalled libtool libraries, other files are standard or library -object files. - -If the OUTPUT-FILE ends in \`.la', then a libtool library is created, -only library objects (\`.lo' files) may be specified, and \`-rpath' is -required, except when creating a convenience library. - -If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created -using \`ar' and \`ranlib', or on Windows using \`lib'. - -If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file -is created, otherwise an executable program is created." - ;; - -uninstall) - $echo \ -"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... - -Remove libraries from an installation directory. - -RM is the name of the program to use to delete files associated with each FILE -(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed -to RM. - -If FILE is a libtool library, all the files associated with it are deleted. -Otherwise, only FILE itself is deleted using RM." - ;; - -*) - $echo "$modename: invalid operation mode \`$mode'" 1>&2 - $echo "$help" 1>&2 - exit 1 - ;; -esac - -echo -$echo "Try \`$modename --help' for more information about other modes." - -exit 0 - -# Local Variables: -# mode:shell-script -# sh-indentation:2 -# End: diff --git a/saslauthd/config/missing b/saslauthd/config/missing deleted file mode 100755 index 6a37006e..00000000 --- a/saslauthd/config/missing +++ /dev/null @@ -1,336 +0,0 @@ -#! /bin/sh -# Common stub for a few missing GNU programs while installing. -# Copyright (C) 1996, 1997, 1999, 2000, 2002 Free Software Foundation, Inc. -# Originally by Fran,cois Pinard , 1996. - -# 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 2, 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -if test $# -eq 0; then - echo 1>&2 "Try \`$0 --help' for more information" - exit 1 -fi - -run=: - -# In the cases where this matters, `missing' is being run in the -# srcdir already. -if test -f configure.ac; then - configure_ac=configure.ac -else - configure_ac=configure.in -fi - -case "$1" in ---run) - # Try to run requested program, and just exit if it succeeds. - run= - shift - "$@" && exit 0 - ;; -esac - -# If it does not exist, or fails to run (possibly an outdated version), -# try to emulate it. -case "$1" in - - -h|--h|--he|--hel|--help) - echo "\ -$0 [OPTION]... PROGRAM [ARGUMENT]... - -Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an -error status if there is no known handling for PROGRAM. - -Options: - -h, --help display this help and exit - -v, --version output version information and exit - --run try to run the given command, and emulate it if it fails - -Supported PROGRAM values: - aclocal touch file \`aclocal.m4' - autoconf touch file \`configure' - autoheader touch file \`config.h.in' - automake touch all \`Makefile.in' files - bison create \`y.tab.[ch]', if possible, from existing .[ch] - flex create \`lex.yy.c', if possible, from existing .c - help2man touch the output file - lex create \`lex.yy.c', if possible, from existing .c - makeinfo touch the output file - tar try tar, gnutar, gtar, then tar without non-portable flags - yacc create \`y.tab.[ch]', if possible, from existing .[ch]" - ;; - - -v|--v|--ve|--ver|--vers|--versi|--versio|--version) - echo "missing 0.4 - GNU automake" - ;; - - -*) - echo 1>&2 "$0: Unknown \`$1' option" - echo 1>&2 "Try \`$0 --help' for more information" - exit 1 - ;; - - aclocal*) - if test -z "$run" && ($1 --version) > /dev/null 2>&1; then - # We have it, but it failed. - exit 1 - fi - - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified \`acinclude.m4' or \`${configure_ac}'. You might want - to install the \`Automake' and \`Perl' packages. Grab them from - any GNU archive site." - touch aclocal.m4 - ;; - - autoconf) - if test -z "$run" && ($1 --version) > /dev/null 2>&1; then - # We have it, but it failed. - exit 1 - fi - - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified \`${configure_ac}'. You might want to install the - \`Autoconf' and \`GNU m4' packages. Grab them from any GNU - archive site." - touch configure - ;; - - autoheader) - if test -z "$run" && ($1 --version) > /dev/null 2>&1; then - # We have it, but it failed. - exit 1 - fi - - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified \`acconfig.h' or \`${configure_ac}'. You might want - to install the \`Autoconf' and \`GNU m4' packages. Grab them - from any GNU archive site." - files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` - test -z "$files" && files="config.h" - touch_files= - for f in $files; do - case "$f" in - *:*) touch_files="$touch_files "`echo "$f" | - sed -e 's/^[^:]*://' -e 's/:.*//'`;; - *) touch_files="$touch_files $f.in";; - esac - done - touch $touch_files - ;; - - automake*) - if test -z "$run" && ($1 --version) > /dev/null 2>&1; then - # We have it, but it failed. - exit 1 - fi - - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. - You might want to install the \`Automake' and \`Perl' packages. - Grab them from any GNU archive site." - find . -type f -name Makefile.am -print | - sed 's/\.am$/.in/' | - while read f; do touch "$f"; done - ;; - - autom4te) - if test -z "$run" && ($1 --version) > /dev/null 2>&1; then - # We have it, but it failed. - exit 1 - fi - - echo 1>&2 "\ -WARNING: \`$1' is needed, and you do not seem to have it handy on your - system. You might have modified some files without having the - proper tools for further handling them. - You can get \`$1Help2man' as part of \`Autoconf' from any GNU - archive site." - - file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` - test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'` - if test -f "$file"; then - touch $file - else - test -z "$file" || exec >$file - echo "#! /bin/sh" - echo "# Created by GNU Automake missing as a replacement of" - echo "# $ $@" - echo "exit 0" - chmod +x $file - exit 1 - fi - ;; - - bison|yacc) - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified a \`.y' file. You may need the \`Bison' package - in order for those modifications to take effect. You can get - \`Bison' from any GNU archive site." - rm -f y.tab.c y.tab.h - if [ $# -ne 1 ]; then - eval LASTARG="\${$#}" - case "$LASTARG" in - *.y) - SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` - if [ -f "$SRCFILE" ]; then - cp "$SRCFILE" y.tab.c - fi - SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` - if [ -f "$SRCFILE" ]; then - cp "$SRCFILE" y.tab.h - fi - ;; - esac - fi - if [ ! -f y.tab.h ]; then - echo >y.tab.h - fi - if [ ! -f y.tab.c ]; then - echo 'main() { return 0; }' >y.tab.c - fi - ;; - - lex|flex) - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified a \`.l' file. You may need the \`Flex' package - in order for those modifications to take effect. You can get - \`Flex' from any GNU archive site." - rm -f lex.yy.c - if [ $# -ne 1 ]; then - eval LASTARG="\${$#}" - case "$LASTARG" in - *.l) - SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` - if [ -f "$SRCFILE" ]; then - cp "$SRCFILE" lex.yy.c - fi - ;; - esac - fi - if [ ! -f lex.yy.c ]; then - echo 'main() { return 0; }' >lex.yy.c - fi - ;; - - help2man) - if test -z "$run" && ($1 --version) > /dev/null 2>&1; then - # We have it, but it failed. - exit 1 - fi - - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified a dependency of a manual page. You may need the - \`Help2man' package in order for those modifications to take - effect. You can get \`Help2man' from any GNU archive site." - - file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` - if test -z "$file"; then - file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` - fi - if [ -f "$file" ]; then - touch $file - else - test -z "$file" || exec >$file - echo ".ab help2man is required to generate this page" - exit 1 - fi - ;; - - makeinfo) - if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then - # We have makeinfo, but it failed. - exit 1 - fi - - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified a \`.texi' or \`.texinfo' file, or any other file - indirectly affecting the aspect of the manual. The spurious - call might also be the consequence of using a buggy \`make' (AIX, - DU, IRIX). You might want to install the \`Texinfo' package or - the \`GNU make' package. Grab either from any GNU archive site." - file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` - if test -z "$file"; then - file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` - file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` - fi - touch $file - ;; - - tar) - shift - if test -n "$run"; then - echo 1>&2 "ERROR: \`tar' requires --run" - exit 1 - fi - - # We have already tried tar in the generic part. - # Look for gnutar/gtar before invocation to avoid ugly error - # messages. - if (gnutar --version > /dev/null 2>&1); then - gnutar "$@" && exit 0 - fi - if (gtar --version > /dev/null 2>&1); then - gtar "$@" && exit 0 - fi - firstarg="$1" - if shift; then - case "$firstarg" in - *o*) - firstarg=`echo "$firstarg" | sed s/o//` - tar "$firstarg" "$@" && exit 0 - ;; - esac - case "$firstarg" in - *h*) - firstarg=`echo "$firstarg" | sed s/h//` - tar "$firstarg" "$@" && exit 0 - ;; - esac - fi - - echo 1>&2 "\ -WARNING: I can't seem to be able to run \`tar' with the given arguments. - You may want to install GNU tar or Free paxutils, or check the - command line arguments." - exit 1 - ;; - - *) - echo 1>&2 "\ -WARNING: \`$1' is needed, and you do not seem to have it handy on your - system. You might have modified some files without having the - proper tools for further handling them. Check the \`README' file, - it often tells you about the needed prerequirements for installing - this package. You may also peek at any GNU archive site, in case - some other package would contain this missing \`$1' program." - exit 1 - ;; -esac - -exit 0 diff --git a/saslauthd/config/mkinstalldirs b/saslauthd/config/mkinstalldirs deleted file mode 100755 index d2d5f21b..00000000 --- a/saslauthd/config/mkinstalldirs +++ /dev/null @@ -1,111 +0,0 @@ -#! /bin/sh -# mkinstalldirs --- make directory hierarchy -# Author: Noah Friedman -# Created: 1993-05-16 -# Public domain - -errstatus=0 -dirmode="" - -usage="\ -Usage: mkinstalldirs [-h] [--help] [-m mode] dir ..." - -# process command line arguments -while test $# -gt 0 ; do - case $1 in - -h | --help | --h*) # -h for help - echo "$usage" 1>&2 - exit 0 - ;; - -m) # -m PERM arg - shift - test $# -eq 0 && { echo "$usage" 1>&2; exit 1; } - dirmode=$1 - shift - ;; - --) # stop option processing - shift - break - ;; - -*) # unknown option - echo "$usage" 1>&2 - exit 1 - ;; - *) # first non-opt arg - break - ;; - esac -done - -for file -do - if test -d "$file"; then - shift - else - break - fi -done - -case $# in - 0) exit 0 ;; -esac - -case $dirmode in - '') - if mkdir -p -- . 2>/dev/null; then - echo "mkdir -p -- $*" - exec mkdir -p -- "$@" - fi - ;; - *) - if mkdir -m "$dirmode" -p -- . 2>/dev/null; then - echo "mkdir -m $dirmode -p -- $*" - exec mkdir -m "$dirmode" -p -- "$@" - fi - ;; -esac - -for file -do - set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` - shift - - pathcomp= - for d - do - pathcomp="$pathcomp$d" - case $pathcomp in - -*) pathcomp=./$pathcomp ;; - esac - - if test ! -d "$pathcomp"; then - echo "mkdir $pathcomp" - - mkdir "$pathcomp" || lasterr=$? - - if test ! -d "$pathcomp"; then - errstatus=$lasterr - else - if test ! -z "$dirmode"; then - echo "chmod $dirmode $pathcomp" - lasterr="" - chmod "$dirmode" "$pathcomp" || lasterr=$? - - if test ! -z "$lasterr"; then - errstatus=$lasterr - fi - fi - fi - fi - - pathcomp="$pathcomp/" - done -done - -exit $errstatus - -# Local Variables: -# mode: shell-script -# sh-indentation: 2 -# End: -# mkinstalldirs ends here diff --git a/saslauthd/configure.in b/saslauthd/configure.in index 0addcf41..f4bc3b56 100644 --- a/saslauthd/configure.in +++ b/saslauthd/configure.in @@ -163,30 +163,30 @@ AC_SUBST(LTLIBOBJS) dnl Checks for which function macros exist AC_MSG_CHECKING(whether $CC implements __func__) -AC_CACHE_VAL(have_func, +AC_CACHE_VAL(cyrus_cv_have_func, [AC_TRY_LINK([#include ],[printf("%s", __func__);], -have_func=yes, -have_func=no)]) -AC_MSG_RESULT($have_func) -if test "$have_func" = yes; then +cyrus_cv_have_func=yes, +cyrus_cv_have_func=no)]) +AC_MSG_RESULT($cyrus_cv_have_func) +if test "$cyrus_cv_have_func" = yes; then AC_DEFINE(HAVE_FUNC,[],[Does the compiler understand __func__]) else AC_MSG_CHECKING(whether $CC implements __PRETTY_FUNCTION__) - AC_CACHE_VAL(have_pretty_function, + AC_CACHE_VAL(cyrus_cv_have_pretty_function, [AC_TRY_LINK([#include ],[printf("%s", __PRETTY_FUNCTION__);], - have_pretty_function=yes, - have_pretty_function=no)]) - AC_MSG_RESULT($have_pretty_function) - if test "$have_pretty_function" = yes; then + cyrus_cv_have_pretty_function=yes, + cyrus_cv_have_pretty_function=no)]) + AC_MSG_RESULT($cyrus_cv_have_pretty_function) + if test "$cyrus_cv_have_pretty_function" = yes; then AC_DEFINE(HAVE_PRETTY_FUNCTION,[],[Does compiler understand __PRETTY_FUNCTION__]) else AC_MSG_CHECKING(whether $CC implements __FUNCTION__) - AC_CACHE_VAL(have_function, + AC_CACHE_VAL(cyrus_cv_have_function, [AC_TRY_LINK([#include ],[printf("%s", __FUNCTION__);], - have_function=yes, - have_function=no)]) - AC_MSG_RESULT($have_function) - if test "$have_function" = yes; then + cyrus_cv_have_function=yes, + cyrus_cv_have_function=no)]) + AC_MSG_RESULT($cyrus_cv_have_function) + if test "$cyrus_cv_have_function" = yes; then AC_DEFINE(HAVE_FUNCTION,[],[Does compiler understand __FUNCTION__]) fi fi From fbfae51552f2972799a4cc8d1c25c5626a510ca6 Mon Sep 17 00:00:00 2001 From: Ken Murchison Date: Wed, 10 Jun 2015 12:06:47 -0400 Subject: [PATCH 188/796] More build fixes --- .cvsignore => .gitignore | 4 ++-- SMakefile | 2 +- config/.gitignore | 4 ++++ configure.in => configure.ac | 0 include/{.cvsignore => .gitignore} | 1 + lib/{.cvsignore => .gitignore} | 0 plugins/{.cvsignore => .gitignore} | 0 saslauthd/.cvsignore | 19 ------------------- saslauthd/.gitignore | 11 +++++++++++ saslauthd/config/.gitignore | 4 ++++ saslauthd/{configure.in => configure.ac} | 0 sasldb/{.cvsignore => .gitignore} | 1 + utils/{.cvsignore => .gitignore} | 1 + 13 files changed, 25 insertions(+), 22 deletions(-) rename .cvsignore => .gitignore (84%) create mode 100644 config/.gitignore rename configure.in => configure.ac (100%) rename include/{.cvsignore => .gitignore} (93%) rename lib/{.cvsignore => .gitignore} (100%) rename plugins/{.cvsignore => .gitignore} (100%) delete mode 100644 saslauthd/.cvsignore create mode 100644 saslauthd/.gitignore create mode 100644 saslauthd/config/.gitignore rename saslauthd/{configure.in => configure.ac} (100%) rename sasldb/{.cvsignore => .gitignore} (91%) rename utils/{.cvsignore => .gitignore} (97%) diff --git a/.cvsignore b/.gitignore similarity index 84% rename from .cvsignore rename to .gitignore index c256a089..0a0a1cb7 100644 --- a/.cvsignore +++ b/.gitignore @@ -1,6 +1,6 @@ autom4te*.cache stamp-h.in -config.h.in +config.h.in* Makefile.in aclocal.m4 configure @@ -9,5 +9,5 @@ config.h config.cache libtool config.status -stamp-h +stamp-h1 Makefile diff --git a/SMakefile b/SMakefile index 87038a94..deef8aee 100644 --- a/SMakefile +++ b/SMakefile @@ -14,7 +14,7 @@ if test ! -x configure; then automake --add-missing --include-deps echo cd saslauthd cd saslauthd - echo aclocal -I ../cmulocal -I config + echo aclocal -I ../cmulocal -I config -I ../config aclocal -I ../cmulocal -I config -I ../config echo autoheader autoheader diff --git a/config/.gitignore b/config/.gitignore new file mode 100644 index 00000000..5e7d2734 --- /dev/null +++ b/config/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore diff --git a/configure.in b/configure.ac similarity index 100% rename from configure.in rename to configure.ac diff --git a/include/.cvsignore b/include/.gitignore similarity index 93% rename from include/.cvsignore rename to include/.gitignore index 79aa245f..a6fab3cd 100644 --- a/include/.cvsignore +++ b/include/.gitignore @@ -3,5 +3,6 @@ Makefile .deps .libs *.l[ao] +*.o makemd5 md5global.h diff --git a/lib/.cvsignore b/lib/.gitignore similarity index 100% rename from lib/.cvsignore rename to lib/.gitignore diff --git a/plugins/.cvsignore b/plugins/.gitignore similarity index 100% rename from plugins/.cvsignore rename to plugins/.gitignore diff --git a/saslauthd/.cvsignore b/saslauthd/.cvsignore deleted file mode 100644 index 1a810f0f..00000000 --- a/saslauthd/.cvsignore +++ /dev/null @@ -1,19 +0,0 @@ -autom4te*.cache -configure -aclocal.m4 -stamp-h -stamp-h.in -Makefile.in -Makefile -saslauthd.h -saslauthd.h.in -config.log -config.status -config.cache -.deps -.libs -*.l[ao] -saslauthd -saslauthd.8 -testsaslauthd -saslcache diff --git a/saslauthd/.gitignore b/saslauthd/.gitignore new file mode 100644 index 00000000..65a4d7e2 --- /dev/null +++ b/saslauthd/.gitignore @@ -0,0 +1,11 @@ +Makefile.in +Makefile +.deps +.libs +*.l[ao] +*.o +saslauthd +saslauthd.8 +saslauthd.h* +stamp-h1 +testsaslauthd diff --git a/saslauthd/config/.gitignore b/saslauthd/config/.gitignore new file mode 100644 index 00000000..5e7d2734 --- /dev/null +++ b/saslauthd/config/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore diff --git a/saslauthd/configure.in b/saslauthd/configure.ac similarity index 100% rename from saslauthd/configure.in rename to saslauthd/configure.ac diff --git a/sasldb/.cvsignore b/sasldb/.gitignore similarity index 91% rename from sasldb/.cvsignore rename to sasldb/.gitignore index 13bb78db..78659548 100644 --- a/sasldb/.cvsignore +++ b/sasldb/.gitignore @@ -3,3 +3,4 @@ Makefile .deps .libs *.l[ao] +*.o diff --git a/utils/.cvsignore b/utils/.gitignore similarity index 97% rename from utils/.cvsignore rename to utils/.gitignore index 7d4844fe..cd6b27ce 100644 --- a/utils/.cvsignore +++ b/utils/.gitignore @@ -3,6 +3,7 @@ Makefile .deps .libs *.l[ao] +*.o smtptest testsuite testsuitestatic From 9553a596a877cd18a4fe88052c1ae5063c74e37f Mon Sep 17 00:00:00 2001 From: Ken Murchison Date: Fri, 17 Jul 2015 14:27:04 -0400 Subject: [PATCH 189/796] auth_krb5.c: added krb5_conv_krb4_instance option to allow user-specified instances bastardized by Cyrus IMAP auth_pts/afskrb to be converted back to krb5 form --- saslauthd/auth_krb5.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/saslauthd/auth_krb5.c b/saslauthd/auth_krb5.c index 0648a291..7e14e78d 100644 --- a/saslauthd/auth_krb5.c +++ b/saslauthd/auth_krb5.c @@ -127,6 +127,15 @@ form_principal_name ( const char *forced_instance = 0; int plen; + plen = strlcpy(pname, user, pnamelen); + user = pname; + + if (config && cfile_getswitch(config, "krb5_conv_krb4_instance", 0)) { + char *krb4_instance; + + if ((krb4_instance = strchr(pname, '.'))) *krb4_instance = '/'; + } + if (config) { char keyname[1024]; @@ -149,8 +158,7 @@ form_principal_name ( } /* form user[/instance][@realm] */ - plen = snprintf(pname, pnamelen, "%s%s%s%s%s", - user, + plen += snprintf(pname+plen, pnamelen-plen, "%s%s%s%s", (forced_instance ? "/" : ""), (forced_instance ? forced_instance : ""), ((realm && realm[0]) ? "@" : ""), From 6bca701e6849bc7568f2cab4a032cb020ae940a1 Mon Sep 17 00:00:00 2001 From: Ignacio Casal Quinteiro Date: Mon, 28 Sep 2015 16:36:18 +0200 Subject: [PATCH 190/796] Create missing directory before running aclocal --- SMakefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/SMakefile b/SMakefile index deef8aee..4c73a25e 100644 --- a/SMakefile +++ b/SMakefile @@ -14,8 +14,9 @@ if test ! -x configure; then automake --add-missing --include-deps echo cd saslauthd cd saslauthd - echo aclocal -I ../cmulocal -I config -I ../config - aclocal -I ../cmulocal -I config -I ../config + mkdir config + echo aclocal -I ../cmulocal -I ../config -I config + aclocal -I ../cmulocal -I ../config -I config echo autoheader autoheader echo autoconf From d1654b71ce6a1e4c6dc9c929dd9795bb9167130f Mon Sep 17 00:00:00 2001 From: Ignacio Casal Quinteiro Date: Mon, 28 Sep 2015 16:39:38 +0200 Subject: [PATCH 191/796] Rename configure.in to configure.ac This is the new name for configure files --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 06d41d7d..e9ff537e 100644 --- a/configure.ac +++ b/configure.ac @@ -1,7 +1,7 @@ -dnl configure.in for the SASL library +dnl configure.ac for the SASL library dnl Rob Siemborski dnl Rob Earhart -dnl $Id: configure.in,v 1.224 2011/09/22 14:44:15 mel Exp $ +dnl $Id: configure.ac,v 1.224 2011/09/22 14:44:15 mel Exp $ dnl dnl Copyright (c) 2001 Carnegie Mellon University. All rights reserved. dnl From 6b2dddb732643fa741101832c4fc0411c694b545 Mon Sep 17 00:00:00 2001 From: Kazuo Ito Date: Mon, 28 Sep 2015 16:46:07 +0200 Subject: [PATCH 192/796] Support for LDAP_OPT_TIMEOUT OpenLDAP since 2.4 implements support for this option in ldap_result(), among other things. --- saslauthd/lak.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/saslauthd/lak.c b/saslauthd/lak.c index 419a6584..f6670736 100644 --- a/saslauthd/lak.c +++ b/saslauthd/lak.c @@ -838,6 +838,11 @@ static int lak_connect( syslog(LOG_WARNING|LOG_AUTH, "Unable to set LDAP_OPT_NETWORK_TIMEOUT %d.%d.", lak->conf->timeout.tv_sec, lak->conf->timeout.tv_usec); } + rc = ldap_set_option(lak->ld, LDAP_OPT_TIMEOUT, &(lak->conf->timeout)); + if (rc != LDAP_OPT_SUCCESS) { + syslog(LOG_WARNING|LOG_AUTH, "Unable to set LDAP_OPT_TIMEOUT %d.%d.", lak->conf->timeout.tv_sec, lak->conf->timeout.tv_usec); + } + rc = ldap_set_option(lak->ld, LDAP_OPT_TIMELIMIT, &(lak->conf->time_limit)); if (rc != LDAP_OPT_SUCCESS) { syslog(LOG_WARNING|LOG_AUTH, "Unable to set LDAP_OPT_TIMELIMIT %d.", lak->conf->time_limit); From ecd32058bee9305eb497d70a86a9657ea0e8319e Mon Sep 17 00:00:00 2001 From: Ignacio Casal Quinteiro Date: Mon, 28 Sep 2015 16:51:52 +0200 Subject: [PATCH 193/796] Do not use obsolete macro --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index e9ff537e..967d0f4b 100644 --- a/configure.ac +++ b/configure.ac @@ -1413,7 +1413,7 @@ inline static unsigned int sleep(unsigned int seconds) { #endif /* CONFIG_H */ ]) -AM_CONFIG_HEADER(config.h) +AC_CONFIG_HEADERS(config.h) AC_OUTPUT(Makefile libsasl2.pc From 4ef931745667b7439a55bf6f0827484241ff7482 Mon Sep 17 00:00:00 2001 From: Ken Murchison Date: Wed, 14 Oct 2015 09:09:45 -0400 Subject: [PATCH 194/796] Revert "Create missing directory before running aclocal" This reverts commit 6bca701e6849bc7568f2cab4a032cb020ae940a1. --- SMakefile | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/SMakefile b/SMakefile index 4c73a25e..deef8aee 100644 --- a/SMakefile +++ b/SMakefile @@ -14,9 +14,8 @@ if test ! -x configure; then automake --add-missing --include-deps echo cd saslauthd cd saslauthd - mkdir config - echo aclocal -I ../cmulocal -I ../config -I config - aclocal -I ../cmulocal -I ../config -I config + echo aclocal -I ../cmulocal -I config -I ../config + aclocal -I ../cmulocal -I config -I ../config echo autoheader autoheader echo autoconf From dfb6140de18336e9268b932639a7412cb9006d89 Mon Sep 17 00:00:00 2001 From: Ignacio Casal Quinteiro Date: Mon, 28 Sep 2015 16:55:56 +0200 Subject: [PATCH 195/796] Fix memory leak in sample --- sample/server.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sample/server.c b/sample/server.c index f5aff680..01dd7ba1 100644 --- a/sample/server.c +++ b/sample/server.c @@ -227,6 +227,8 @@ int mysasl_negotiate(FILE *in, FILE *out, sasl_conn_t *conn) /* send capability list to client */ send_string(out, data, len); + if (mech) + free(data); dprintf(1, "waiting for client mechanism...\n"); len = recv_string(in, chosenmech, sizeof chosenmech); From 506d660f1dcca185c07ba27fb9ed22473e734a59 Mon Sep 17 00:00:00 2001 From: Ignacio Casal Quinteiro Date: Mon, 28 Sep 2015 17:12:40 +0200 Subject: [PATCH 196/796] Release the server credentials that are no longer needed --- plugins/gssapi.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/plugins/gssapi.c b/plugins/gssapi.c index 2fd1b3b7..da3fd7d7 100644 --- a/plugins/gssapi.c +++ b/plugins/gssapi.c @@ -945,6 +945,12 @@ gssapi_server_mech_authneg(context_t *text, } cleanup: + if (text->server_creds != GSS_C_NO_CREDENTIAL) { + GSS_LOCK_MUTEX(params->utils); + maj_stat = gss_release_cred(&min_stat, &text->server_creds); + GSS_UNLOCK_MUTEX(params->utils); + text->server_creds = GSS_C_NO_CREDENTIAL; + } if (client_name_MN) { GSS_LOCK_MUTEX(params->utils); gss_release_name(&min_stat, &client_name_MN); From 740d6cf9a58d597e6e15d970eaa105650ada6f99 Mon Sep 17 00:00:00 2001 From: Ignacio Casal Quinteiro Date: Mon, 28 Sep 2015 17:19:53 +0200 Subject: [PATCH 197/796] Define error for when parsing the config file --- include/sasl.h | 1 + lib/common.c | 1 + lib/config.c | 4 ++-- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/include/sasl.h b/include/sasl.h index 8b8a63fb..82f7a171 100755 --- a/include/sasl.h +++ b/include/sasl.h @@ -179,6 +179,7 @@ because of some constrains/policy violation */ #define SASL_BADBINDING -32 /* channel binding failure */ +#define SASL_CONFIGERR -100 /* error when parsing configuration file */ /* max size of a sasl mechanism name */ #define SASL_MECHNAMEMAX 20 diff --git a/lib/common.c b/lib/common.c index 672fe2ff..de0adfdd 100644 --- a/lib/common.c +++ b/lib/common.c @@ -1362,6 +1362,7 @@ const char *sasl_errstring(int saslerr, case SASL_CONSTRAINT_VIOLAT: return "sasl_setpass can't store a property because " "of a constraint violation"; case SASL_BADBINDING: return "channel binding failure"; + case SASL_CONFIGERR: return "error when parsing configuration file"; default: return "undefined error!"; } diff --git a/lib/config.c b/lib/config.c index 7cae3020..fde3757c 100644 --- a/lib/config.c +++ b/lib/config.c @@ -91,7 +91,7 @@ int sasl_config_init(const char *filename) } if (*p != ':') { fclose(infile); - return SASL_FAIL; + return SASL_CONFIGERR; } *p++ = '\0'; @@ -99,7 +99,7 @@ int sasl_config_init(const char *filename) if (!*p) { fclose(infile); - return SASL_FAIL; + return SASL_CONFIGERR; } /* Now strip trailing spaces, if any */ From dfcbce9490199a82a75c3a2a591be4ae690b4395 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Thu, 22 Oct 2015 10:13:23 +0200 Subject: [PATCH 198/796] Allow more fine-grained logging from sql plugin Based on report in Red Hat bugzilla [1] and discussion in upstream mailing list [2] it is obvious, that there is no mechanism to stop logging some verbose messages. This patch is providing context to logger, which can involve application-defined callbacks and potentially reduce amount of logged messages. This commit resolves cyrus-sasl bug [3]. Original patch from Patrick Wagner [1] https://bugzilla.redhat.com/show_bug.cgi?id=1273580 [2] http://lists.andrew.cmu.edu/pipermail/cyrus-sasl/2015-October/002825.html [3] https://bugzilla.cyrusimap.org/show_bug.cgi?id=3906 --- plugins/sql.c | 102 ++++++++++++++++++++++++++------------------------ 1 file changed, 54 insertions(+), 48 deletions(-) diff --git a/plugins/sql.c b/plugins/sql.c index 3b89383a..615d3217 100644 --- a/plugins/sql.c +++ b/plugins/sql.c @@ -71,7 +71,7 @@ static void *_mysql_open(char *host, char *port, int usessl, MYSQL *mysql; if (!(mysql = mysql_init(NULL))) { - utils->log(NULL, SASL_LOG_ERR, + utils->log(utils->conn, SASL_LOG_ERR, "sql plugin: could not execute mysql_init()"); return NULL; } @@ -108,7 +108,7 @@ static int _mysql_exec(void *conn, const char *cmd, char *value, size_t size, (void)mysql_real_query(conn, cmd, len); if(mysql_errno(conn)) { - utils->log(NULL, SASL_LOG_ERR, "sql query failed: %s", + utils->log(utils->conn, SASL_LOG_ERR, "sql query failed: %s", mysql_error(conn)); return -1; } @@ -123,7 +123,7 @@ static int _mysql_exec(void *conn, const char *cmd, char *value, size_t size, result = mysql_store_result(conn); if (!result) { /* umm nothing found */ - utils->log(NULL, SASL_LOG_NOTE, "sql plugin: no result found"); + utils->log(utils->conn, SASL_LOG_NOTE, "sql plugin: no result found"); return -1; } @@ -132,11 +132,11 @@ static int _mysql_exec(void *conn, const char *cmd, char *value, size_t size, if (!row_count) { /* umm nothing found */ mysql_free_result(result); - utils->log(NULL, SASL_LOG_NOTE, "sql plugin: no result found"); + utils->log(utils->conn, SASL_LOG_NOTE, "sql plugin: no result found"); return -1; } if (row_count > 1) { - utils->log(NULL, SASL_LOG_WARN, + utils->log(utils->conn, SASL_LOG_WARN, "sql plugin: found duplicate row for query %s", cmd); } @@ -145,7 +145,7 @@ static int _mysql_exec(void *conn, const char *cmd, char *value, size_t size, row = mysql_fetch_row(result); if (!row || !row[0]) { /* umm nothing found */ - utils->log(NULL, SASL_LOG_NOTE, "sql plugin: no result found"); + utils->log(utils->conn, SASL_LOG_NOTE, "sql plugin: no result found"); mysql_free_result(result); return -1; } @@ -257,7 +257,8 @@ static void *_pgsql_open(char *host, char *port, int usessl, free(conninfo); if ((PQstatus(conn) != CONNECTION_OK)) { - utils->log(NULL, SASL_LOG_ERR, "sql plugin: %s", PQerrorMessage(conn)); + utils->log(utils->conn, SASL_LOG_ERR, "sql plugin: %s", + PQerrorMessage(conn)); return NULL; } @@ -288,7 +289,7 @@ static int _pgsql_exec(void *conn, const char *cmd, char *value, size_t size, } else if (status != PGRES_TUPLES_OK) { /* error */ - utils->log(NULL, SASL_LOG_DEBUG, "sql plugin: %s ", + utils->log(utils->conn, SASL_LOG_DEBUG, "sql plugin: %s ", PQresStatus(status)); PQclear(result); return -1; @@ -298,12 +299,12 @@ static int _pgsql_exec(void *conn, const char *cmd, char *value, size_t size, row_count = PQntuples(result); if (!row_count) { /* umm nothing found */ - utils->log(NULL, SASL_LOG_NOTE, "sql plugin: no result found"); + utils->log(utils->conn, SASL_LOG_NOTE, "sql plugin: no result found"); PQclear(result); return -1; } if (row_count > 1) { - utils->log(NULL, SASL_LOG_WARN, + utils->log(utils->conn, SASL_LOG_WARN, "sql plugin: found duplicate row for query %s", cmd); } @@ -357,14 +358,14 @@ static void *_sqlite_open(char *host __attribute__((unused)), db = sqlite_open(database, 0, &zErrMsg); if (db == NULL) { - utils->log(NULL, SASL_LOG_ERR, "sql plugin: %s", zErrMsg); + utils->log(utils->conn, SASL_LOG_ERR, "sql plugin: %s", zErrMsg); sqlite_freemem (zErrMsg); return NULL; } rc = sqlite_exec(db, "PRAGMA empty_result_callbacks = ON", NULL, NULL, &zErrMsg); if (rc != SQLITE_OK) { - utils->log(NULL, SASL_LOG_ERR, "sql plugin: %s", zErrMsg); + utils->log(utils->conn, SASL_LOG_ERR, "sql plugin: %s", zErrMsg); sqlite_freemem (zErrMsg); sqlite_close(db); return NULL; @@ -414,7 +415,7 @@ static int _sqlite_exec(void *db, const char *cmd, char *value, size_t size, rc = sqlite_exec((sqlite*)db, cmd, sqlite_my_callback, (void*)&result, &zErrMsg); if (rc != SQLITE_OK && rc != SQLITE_ABORT) { - utils->log(NULL, SASL_LOG_DEBUG, "sql plugin: %s ", zErrMsg); + utils->log(utils->conn, SASL_LOG_DEBUG, "sql plugin: %s ", zErrMsg); sqlite_freemem (zErrMsg); return -1; } @@ -426,7 +427,7 @@ static int _sqlite_exec(void *db, const char *cmd, char *value, size_t size, if (result == NULL) { /* umm nothing found */ - utils->log(NULL, SASL_LOG_NOTE, "sql plugin: no result found"); + utils->log(utils->conn, SASL_LOG_NOTE, "sql plugin: no result found"); return -1; } @@ -485,9 +486,10 @@ static void *_sqlite3_open(char *host __attribute__((unused)), rc = sqlite3_open(database, &db); if (SQLITE_OK != rc) { if (db) - utils->log(NULL, SASL_LOG_ERR, "sql plugin: %s", sqlite3_errmsg(db)); + utils->log(utils->conn, SASL_LOG_ERR, "sql plugin: %s", + sqlite3_errmsg(db)); else - utils->log(NULL, SASL_LOG_ERR, "sql plugin: %d", rc); + utils->log(utils->conn, SASL_LOG_ERR, "sql plugin: %d", rc); sqlite3_close(db); return NULL; } @@ -495,10 +497,11 @@ static void *_sqlite3_open(char *host __attribute__((unused)), rc = sqlite3_exec(db, "PRAGMA empty_result_callbacks = ON", NULL, NULL, &zErrMsg); if (rc != SQLITE_OK) { if (zErrMsg) { - utils->log(NULL, SASL_LOG_ERR, "sql plugin: %s", zErrMsg); + utils->log(utils->conn, SASL_LOG_ERR, "sql plugin: %s", + zErrMsg); sqlite3_free(zErrMsg); } else - utils->log(NULL, SASL_LOG_DEBUG, "sql plugin: %d", rc); + utils->log(utils->conn, SASL_LOG_DEBUG, "sql plugin: %d", rc); sqlite3_close(db); return NULL; } @@ -552,10 +555,10 @@ static int _sqlite3_exec(void *db, rc = sqlite3_exec((sqlite3*)db, cmd, sqlite3_my_callback, (void*)&result, &zErrMsg); if (rc != SQLITE_OK) { if (zErrMsg) { - utils->log(NULL, SASL_LOG_DEBUG, "sql plugin: %s", zErrMsg); + utils->log(utils->conn, SASL_LOG_DEBUG, "sql plugin: %s", zErrMsg); sqlite3_free(zErrMsg); } else { - utils->log(NULL, SASL_LOG_DEBUG, "sql plugin: %d", rc); + utils->log(utils->conn, SASL_LOG_DEBUG, "sql plugin: %d", rc); } return -1; } @@ -567,7 +570,7 @@ static int _sqlite3_exec(void *db, if (result == NULL) { /* umm nothing found */ - utils->log(NULL, SASL_LOG_NOTE, "sql plugin: no result found"); + utils->log(utils->conn, SASL_LOG_NOTE, "sql plugin: no result found"); return -1; } @@ -719,7 +722,7 @@ static char *sql_create_statement(const char *statement, const char *prop, buf_ptr += vlen; } else { - utils->log(NULL, SASL_LOG_ERR, + utils->log(utils->conn, SASL_LOG_ERR, "'%%v' shouldn't be in a SELECT or DELETE"); } break; @@ -769,7 +772,7 @@ static void sql_get_settings(const sasl_utils_t *utils, void *glob_context) } if (!e->name) { - utils->log(NULL, SASL_LOG_ERR, "SQL engine '%s' not supported", + utils->log(utils->conn, SASL_LOG_ERR, "SQL engine '%s' not supported", engine_name); } @@ -845,7 +848,7 @@ static void *sql_connect(sql_settings_t *settings, const sasl_utils_t *utils) * it should probably save the connection but for * now we will just disconnect everytime */ - utils->log(NULL, SASL_LOG_DEBUG, + utils->log(utils->conn, SASL_LOG_DEBUG, "sql plugin try and connect to a host\n"); /* create a working version of the hostnames */ @@ -861,7 +864,7 @@ static void *sql_connect(sql_settings_t *settings, const sasl_utils_t *utils) while (!isalnum(db_host[0])) db_host++; } - utils->log(NULL, SASL_LOG_DEBUG, + utils->log(utils->conn, SASL_LOG_DEBUG, "sql plugin trying to open db '%s' on host '%s'%s\n", settings->sql_database, cur_host, settings->sql_usessl ? " using SSL" : ""); @@ -877,7 +880,7 @@ static void *sql_connect(sql_settings_t *settings, const sasl_utils_t *utils) utils); if (conn) break; - utils->log(NULL, SASL_LOG_ERR, + utils->log(utils->conn, SASL_LOG_ERR, "sql plugin could not connect to host %s", cur_host); cur_host = db_host; @@ -917,7 +920,7 @@ static int sql_auxprop_lookup(void *glob_context, /* setup the settings */ settings = (sql_settings_t *) glob_context; - sparams->utils->log(NULL, SASL_LOG_DEBUG, + sparams->utils->log(sparams->utils->conn, SASL_LOG_DEBUG, "sql plugin Parse the username %s\n", user); user_buf = sparams->utils->malloc(ulen + 1); @@ -966,7 +969,7 @@ static int sql_auxprop_lookup(void *glob_context, conn = sql_connect(settings, sparams->utils); if (!conn) { - sparams->utils->log(NULL, SASL_LOG_ERR, + sparams->utils->log(sparams->utils->conn, SASL_LOG_ERR, "sql plugin couldn't connect to any host\n"); /* TODO: in the future we might want to extend the internal SQL driver API to return a more detailed error */ @@ -1014,14 +1017,15 @@ static int sql_auxprop_lookup(void *glob_context, if (!do_txn) { do_txn = 1; - sparams->utils->log(NULL, SASL_LOG_DEBUG, "begin transaction"); + sparams->utils->log(sparams->utils->conn, SASL_LOG_DEBUG, + "begin transaction"); if (settings->sql_engine->sql_begin_txn(conn, sparams->utils)) { - sparams->utils->log(NULL, SASL_LOG_ERR, + sparams->utils->log(sparams->utils->conn, SASL_LOG_ERR, "Unable to begin transaction\n"); } } - sparams->utils->log(NULL, SASL_LOG_DEBUG, + sparams->utils->log(sparams->utils->conn, SASL_LOG_DEBUG, "sql plugin create statement from %s %s %s\n", realname, escap_userid, escap_realm); @@ -1035,7 +1039,7 @@ static int sql_auxprop_lookup(void *glob_context, break; } - sparams->utils->log(NULL, SASL_LOG_DEBUG, + sparams->utils->log(sparams->utils->conn, SASL_LOG_DEBUG, "sql plugin doing query %s\n", query); value[0] = '\0'; @@ -1065,14 +1069,15 @@ static int sql_auxprop_lookup(void *glob_context, the userPassword attribute */ if (!do_txn) { do_txn = 1; - sparams->utils->log(NULL, SASL_LOG_DEBUG, "begin transaction"); + sparams->utils->log(sparams->utils->conn, SASL_LOG_DEBUG, + "begin transaction"); if (settings->sql_engine->sql_begin_txn(conn, sparams->utils)) { - sparams->utils->log(NULL, SASL_LOG_ERR, + sparams->utils->log(sparams->utils->conn, SASL_LOG_ERR, "Unable to begin transaction\n"); } } - sparams->utils->log(NULL, SASL_LOG_DEBUG, + sparams->utils->log(sparams->utils->conn, SASL_LOG_DEBUG, "sql plugin create statement from %s %s %s\n", SASL_AUX_PASSWORD_PROP, escap_userid, @@ -1088,7 +1093,7 @@ static int sql_auxprop_lookup(void *glob_context, if (query == NULL) { ret = SASL_NOMEM; } else { - sparams->utils->log(NULL, SASL_LOG_DEBUG, + sparams->utils->log(sparams->utils->conn, SASL_LOG_DEBUG, "sql plugin doing query %s\n", query); value[0] = '\0'; @@ -1110,9 +1115,10 @@ static int sql_auxprop_lookup(void *glob_context, if (do_txn) { - sparams->utils->log(NULL, SASL_LOG_DEBUG, "commit transaction"); + sparams->utils->log(sparams->utils->conn, SASL_LOG_DEBUG, + "commit transaction"); if (settings->sql_engine->sql_commit_txn(conn, sparams->utils)) { - sparams->utils->log(NULL, SASL_LOG_ERR, + sparams->utils->log(sparams->utils->conn, SASL_LOG_ERR, "Unable to commit transaction\n"); /* Failure of the commit is non fatal when reading values */ } @@ -1160,7 +1166,7 @@ static int sql_auxprop_store(void *glob_context, /* make sure our input is okay */ if (!glob_context || !sparams || !user) return SASL_BADPARAM; - sparams->utils->log(NULL, SASL_LOG_DEBUG, + sparams->utils->log(sparams->utils->conn, SASL_LOG_DEBUG, "sql plugin Parse the username %s\n", user); user_buf = sparams->utils->malloc(ulen + 1); @@ -1203,7 +1209,7 @@ static int sql_auxprop_store(void *glob_context, conn = sql_connect(settings, sparams->utils); if (!conn) { - sparams->utils->log(NULL, SASL_LOG_ERR, + sparams->utils->log(sparams->utils->conn, SASL_LOG_ERR, "sql plugin couldn't connect to any host\n"); goto done; } @@ -1212,7 +1218,7 @@ static int sql_auxprop_store(void *glob_context, settings->sql_engine->sql_escape_str(escap_realm, realm); if (settings->sql_engine->sql_begin_txn(conn, sparams->utils)) { - sparams->utils->log(NULL, SASL_LOG_ERR, + sparams->utils->log(sparams->utils->conn, SASL_LOG_ERR, "Unable to begin transaction\n"); } for (cur = to_store; ret == SASL_OK && cur->name; cur++) { @@ -1252,7 +1258,7 @@ static int sql_auxprop_store(void *glob_context, cur->values && cur->values[0] ? "" : SQL_NULL_VALUE, sparams->utils); - sparams->utils->log(NULL, SASL_LOG_DEBUG, + sparams->utils->log(sparams->utils->conn, SASL_LOG_DEBUG, "sql plugin doing statement %s\n", log_statement); sparams->utils->free(log_statement); @@ -1267,15 +1273,15 @@ static int sql_auxprop_store(void *glob_context, sparams->utils->free(statement); } if (ret != SASL_OK) { - sparams->utils->log(NULL, SASL_LOG_ERR, + sparams->utils->log(sparams->utils->conn, SASL_LOG_ERR, "Failed to store auxprop; aborting transaction\n"); if (settings->sql_engine->sql_rollback_txn(conn, sparams->utils)) { - sparams->utils->log(NULL, SASL_LOG_ERR, + sparams->utils->log(sparams->utils->conn, SASL_LOG_ERR, "Unable to rollback transaction\n"); } } else if (settings->sql_engine->sql_commit_txn(conn, sparams->utils)) { - sparams->utils->log(NULL, SASL_LOG_ERR, + sparams->utils->log(sparams->utils->conn, SASL_LOG_ERR, "Unable to commit transaction\n"); } @@ -1301,7 +1307,7 @@ static void sql_auxprop_free(void *glob_context, const sasl_utils_t *utils) if (!settings) return; - utils->log(NULL, SASL_LOG_DEBUG, "sql freeing memory\n"); + utils->log(utils->conn, SASL_LOG_DEBUG, "sql freeing memory\n"); utils->free(settings); } @@ -1344,12 +1350,12 @@ int sql_auxprop_plug_init(const sasl_utils_t *utils, if (!settings->sql_engine->name) return SASL_NOMECH; if (!sql_exists(settings->sql_select)) { - utils->log(NULL, SASL_LOG_ERR, "sql_select option missing"); + utils->log(utils->conn, SASL_LOG_ERR, "sql_select option missing"); utils->free(settings); return SASL_NOMECH; } - utils->log(NULL, SASL_LOG_DEBUG, + utils->log(utils->conn, SASL_LOG_DEBUG, "sql auxprop plugin using %s engine\n", settings->sql_engine->name); From 1cd61a21b3b34f1b26f0c5e92b66267ebc0c8738 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Mon, 19 Oct 2015 17:45:49 +0200 Subject: [PATCH 199/796] Allow more fine-grained logging from gssapi plugin Based on report in Red Hat bugzilla [2] and discussion in upstream mailing list [2] it is obvious, that there is no mechanism to stop logging of some verbose messages. This patch is providing context to logger, which can involve application-defined callbacks and potentially reduce amount of logged messages. [1] https://bugzilla.redhat.com/show_bug.cgi?id=1187097 [2] http://lists.andrew.cmu.edu/pipermail/cyrus-sasl/2015-January/002785.html --- plugins/gssapi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/gssapi.c b/plugins/gssapi.c index da3fd7d7..60cc38c5 100644 --- a/plugins/gssapi.c +++ b/plugins/gssapi.c @@ -1264,7 +1264,7 @@ gssapi_server_mech_step(void *conn_context, if (text == NULL) return SASL_BADPROT; - params->utils->log(NULL, SASL_LOG_DEBUG, + params->utils->log(params->utils->conn, SASL_LOG_DEBUG, "GSSAPI server step %d\n", text->state); switch (text->state) { @@ -1290,7 +1290,7 @@ gssapi_server_mech_step(void *conn_context, break; default: - params->utils->log(NULL, SASL_LOG_ERR, + params->utils->log(params->utils->conn, SASL_LOG_ERR, "Invalid GSSAPI server step %d\n", text->state); return SASL_FAIL; } @@ -1496,7 +1496,7 @@ static int gssapi_client_mech_step(void *conn_context, *clientout = NULL; *clientoutlen = 0; - params->utils->log(NULL, SASL_LOG_DEBUG, + params->utils->log(params->utils->conn, SASL_LOG_DEBUG, "GSSAPI client step %d", text->state); switch (text->state) { @@ -1989,7 +1989,7 @@ static int gssapi_client_mech_step(void *conn_context, } default: - params->utils->log(NULL, SASL_LOG_ERR, + params->utils->log(params->utils->conn, SASL_LOG_ERR, "Invalid GSSAPI client step %d\n", text->state); return SASL_FAIL; } From 35b1303f392b05b4f40ae7a33becf6d94eceaef9 Mon Sep 17 00:00:00 2001 From: Ignacio Casal Quinteiro Date: Thu, 15 Oct 2015 16:18:56 +0200 Subject: [PATCH 200/796] Rename mdb to lmdb This seems to have changed upstream --- cmulocal/sasldb.m4 | 18 +++++++++--------- configure.ac | 4 ++-- doc/options.html | 10 +++++----- sasldb/Makefile.am | 2 +- sasldb/{db_mdb.c => db_lmdb.c} | 8 ++++---- 5 files changed, 21 insertions(+), 21 deletions(-) rename sasldb/{db_mdb.c => db_lmdb.c} (98%) diff --git a/cmulocal/sasldb.m4 b/cmulocal/sasldb.m4 index e3c9016b..b43eb84e 100644 --- a/cmulocal/sasldb.m4 +++ b/cmulocal/sasldb.m4 @@ -6,7 +6,7 @@ dnl Figure out what database type we're using AC_DEFUN([SASL_DB_CHECK], [ cmu_save_LIBS="$LIBS" AC_ARG_WITH(dblib, - [AC_HELP_STRING([--with-dblib={berkeley|gdbm|mdb|ndbm|none|auto_detect}], + [AC_HELP_STRING([--with-dblib={berkeley|gdbm|lmdb|ndbm|none|auto_detect}], [set the DB library to use [[berkeley]]])], dblib=$withval, dblib=auto_detect) @@ -45,9 +45,9 @@ dnl named. arg. fi esac ;; - mdb) - AC_CHECK_HEADER(mdb.h, [ - AC_CHECK_LIB(mdb, mdb_env_create, SASL_DB_LIB="-lmdb"; enable_keep_db_open=yes, dblib="no")], + lmdb) + AC_CHECK_HEADER(lmdb.h, [ + AC_CHECK_LIB(lmdb, mdb_env_create, SASL_DB_LIB="-llmdb"; enable_keep_db_open=yes, dblib="no")], dblib="no") ;; ndbm) @@ -63,8 +63,8 @@ dnl named. arg. CYRUS_BERKELEY_DB_CHK() if test "$dblib" = no; then dnl How about OpenLDAP's mdb? - AC_CHECK_HEADER(mdb.h, [ - AC_CHECK_LIB(mdb, mdb_env_create, SASL_DB_LIB="-lmdb"; enable_keep_db_open=yes, dblib="no")], + AC_CHECK_HEADER(lmdb.h, [ + AC_CHECK_LIB(lmdb, mdb_env_create, SASL_DB_LIB="-llmdb"; enable_keep_db_open=yes, dblib="no")], dblib="no") fi if test "$dblib" = no; then @@ -99,7 +99,7 @@ dnl named. arg. ;; *) AC_MSG_WARN([Bad DB library implementation specified;]) - AC_ERROR([Use either \"berkeley\", \"gdbm\", \"mdb\", \"ndbm\" or \"none\"]) + AC_ERROR([Use either \"berkeley\", \"gdbm\", \"lmdb\", \"ndbm\" or \"none\"]) dblib=no ;; esac @@ -119,9 +119,9 @@ case "$dblib" in SASL_MECHS="$SASL_MECHS libsasldb.la" AC_DEFINE(SASL_GDBM,[],[Use GDBM for SASLdb]) ;; - mdb) + lmdb) SASL_MECHS="$SASL_MECHS libsasldb.la" - AC_DEFINE(SASL_MDB,[],[Use MDB for SASLdb]) + AC_DEFINE(SASL_LMDB,[],[Use LMDB for SASLdb]) ;; ndbm) SASL_MECHS="$SASL_MECHS libsasldb.la" diff --git a/configure.ac b/configure.ac index 967d0f4b..eddfc854 100644 --- a/configure.ac +++ b/configure.ac @@ -205,8 +205,8 @@ AC_ARG_ENABLE(keep_db_open, [ --enable-keep-db-open keep handle to DB open fo keep_db_open=$enableval, keep_db_open=no) -# Disable if Berkeley DB and MDB are not used -if test "$dblib" != berkeley -a "$dblib" != mdb; then +# Disable if Berkeley DB and LMDB are not used +if test "$dblib" != berkeley -a "$dblib" != lmdb; then keep_db_open=no fi diff --git a/doc/options.html b/doc/options.html index 66db5f69..beb76ae7 100644 --- a/doc/options.html +++ b/doc/options.html @@ -150,14 +150,14 @@

    Options for Cyrus SASL

    Path to sasldb file/etc/sasldb2 (system dependant) -sasldb_mapsizesasldb with MDB +sasldb_mapsizesasldb with LMDB Size of the memory map used by the DB. This is also the maximum possible size of the database, so it must be set to a value large enough to contain all the desired user records. 1048576 bytes -sasldb_maxreaderssasldb with MDB +sasldb_maxreaderssasldb with LMDB Maximum number of threads (or processes) that may concurrently read the database. 126 @@ -356,17 +356,17 @@

    Examples:

    -

    Notes on sasldb with MDB

    +

    Notes on sasldb with LMDB

    -

    The OpenLDAP MDB library is an extremely compact, extremely high performance +

    The OpenLDAP LMDB library is an extremely compact, extremely high performance B+tree database. The code for it is available in the regular OpenLDAP source distributions and it is distributed under the terms of the OpenLDAP Public License.

    Full documentation, plus papers and presentations are available on -the MDB page.

    +the LMDB page.


    Back to the index diff --git a/sasldb/Makefile.am b/sasldb/Makefile.am index e1e3f568..dd40bbca 100644 --- a/sasldb/Makefile.am +++ b/sasldb/Makefile.am @@ -46,7 +46,7 @@ sasl_version = 1:25:0 INCLUDES=-I$(top_srcdir)/include -I$(top_builddir)/include @SASL_DB_INC@ -extra_common_sources = db_none.c db_mdb.c db_ndbm.c db_gdbm.c db_berkeley.c +extra_common_sources = db_none.c db_lmdb.c db_ndbm.c db_gdbm.c db_berkeley.c EXTRA_DIST = NTMakefile diff --git a/sasldb/db_mdb.c b/sasldb/db_lmdb.c similarity index 98% rename from sasldb/db_mdb.c rename to sasldb/db_lmdb.c index 2e2577f5..4c0b5b10 100644 --- a/sasldb/db_mdb.c +++ b/sasldb/db_lmdb.c @@ -1,4 +1,4 @@ -/* db_mdb.c--SASL OpenLDAP MDB interface +/* db_lmdb.c--SASL OpenLDAP LMDB interface * Howard Chu * $Id$ */ @@ -44,7 +44,7 @@ #include -#include +#include #include #include @@ -211,7 +211,7 @@ int _sasldb_getdata(const sasl_utils_t *utils, /* check parameters */ if (!auth_identity || !realm || !propName || !out || !max_out) { utils->seterror(context, 0, - "Bad parameter in db_mdb.c: _sasldb_getdata"); + "Bad parameter in db_lmdb.c: _sasldb_getdata"); return SASL_BADPARAM; } @@ -300,7 +300,7 @@ int _sasldb_putdata(const sasl_utils_t *utils, if (!authid || !realm || !propName) { utils->seterror(context, 0, - "Bad parameter in db_mdb.c: _sasldb_putdata"); + "Bad parameter in db_lmdb.c: _sasldb_putdata"); return SASL_BADPARAM; } From 68da70600946f46979fbfea735489218a938da7c Mon Sep 17 00:00:00 2001 From: Ignacio Casal Quinteiro Date: Thu, 15 Oct 2015 17:00:12 +0200 Subject: [PATCH 201/796] lmdb: add missing ifdef --- sasldb/db_lmdb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sasldb/db_lmdb.c b/sasldb/db_lmdb.c index 4c0b5b10..ca54b46f 100644 --- a/sasldb/db_lmdb.c +++ b/sasldb/db_lmdb.c @@ -418,11 +418,13 @@ int _sasl_check_db(const sasl_utils_t *utils, } } +#if defined(KEEP_DB_OPEN) void sasldb_auxprop_free (void *glob_context, const sasl_utils_t *utils) { do_close(); } +#endif sasldb_handle _sasldb_getkeyhandle(const sasl_utils_t *utils, sasl_conn_t *conn) From 3ea310f668e80ce12587c993808ba0d5446bc4e5 Mon Sep 17 00:00:00 2001 From: Ignacio Casal Quinteiro Date: Thu, 15 Oct 2015 16:15:19 +0200 Subject: [PATCH 202/796] win32: allow to build the lmdb backend --- plugins/NTMakefile | 21 +++++++++++++++++---- win32/common.mak | 14 ++++++++++++++ 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/plugins/NTMakefile b/plugins/NTMakefile index 32dc58eb..7417f0f9 100755 --- a/plugins/NTMakefile +++ b/plugins/NTMakefile @@ -125,15 +125,25 @@ GSS_LIBS=/libpath:$(GSSAPI_LIBPATH) gssapi32.lib !ELSE GSS_FLAGS= GSS_LIBS= -!ENDIF +!ENDIF -CRAM_FLAGS=/DOBSOLETE_CRAM_ATTR=1 +!IF "$(SASLDB)" == "LMDB" +DB_LIBS=/libpath:$(LMDB_LIBPATH) lmdb.lib -DIGEST_FLAGS=/D "WITH_RC4" +# Auxprop Plugin +libsasldb_sources = allockey.c db_lmdb.c +libsasldb_objs = allockey.obj db_lmdb.obj +!ELSE +DB_LIBS=/libpath:$(DB_LIBPATH) $(DB_LIB) # Auxprop Plugin libsasldb_sources = allockey.c db_berkeley.c libsasldb_objs = allockey.obj db_berkeley.obj +!ENDIF + +CRAM_FLAGS=/DOBSOLETE_CRAM_ATTR=1 + +DIGEST_FLAGS=/D "WITH_RC4" saslSASLDB_sources = sasldb.c sasldb_init.c $(libsasldb_sources) $(common_sources) saslSASLDB_objs = sasldb.obj sasldb_init.obj $(libsasldb_objs) $(common_objs) @@ -152,7 +162,6 @@ EXTRA_FLAGS = /D TARGET_WIN_SYSTEM=$(TARGET_WIN_SYSTEM) $(EXTRA_FLAGS) EXTRA_FLAGS=$(EXTRA_FLAGS) $(DB_FLAGS) $(OPENSSL_FLAGS) $(GSS_FLAGS) $(SRP_FLAGS) $(SQL_FLAGS) $(DIGEST_FLAGS) $(CRAM_FLAGS) $(LDAP_FLAGS) CPPFLAGS = /I "..\win32\include" /I "." /I "..\include" $(EXTRA_FLAGS) /D "WIN32" /D "_WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" -DB_LIBS=/libpath:$(DB_LIBPATH) $(DB_LIB) OPENSSL_LIBS=/libpath:$(OPENSSL_LIBPATH) libeay32.lib ssleay32.lib # Where to install files from this directory @@ -188,6 +197,9 @@ allockey.c: ..\sasldb\allockey.c db_berkeley.c: ..\sasldb\db_berkeley.c xcopy /D /Y ..\sasldb\db_berkeley.c . +db_lmdb.c: ..\sasldb\db_lmdb.c + xcopy /D /Y ..\sasldb\db_lmdb.c . + #Add /pdb: option? saslANONYMOUS.dll: $(saslANONYMOUS_objs) saslANONYMOUS.res @@ -263,6 +275,7 @@ CLEAN : -@erase getaddrinfo.c -@erase allockey.c -@erase db_berkeley.c + -@erase db_lmdb.c -@erase getnameinfo.c -@erase $(generated_rc) -@erase "*.res" diff --git a/win32/common.mak b/win32/common.mak index c2a9338b..480de13f 100644 --- a/win32/common.mak +++ b/win32/common.mak @@ -79,6 +79,20 @@ DB_LIBPATH=c:\work\isode\db\build_win32\Release_static !ENDIF !ENDIF +!IF "$(LMDB_INCLUDE)" == "" +DB_INCLUDE=c:\work\isode\lmdb\libraries\liblmdb +!IF "$(VERBOSE)" != "0" +!MESSAGE Defaulting LMDB include path to $(LMDB_INCLUDE). +!ENDIF +!ENDIF + +!IF "$(LMDB_LIBPATH)" == "" +DB_LIBPATH=c:\work\isode\lmdb\libraries\liblmdb\Release +!IF "$(VERBOSE)" != "0" +!MESSAGE Defaulting LMDB library path to $(LMDB_LIBPATH). +!ENDIF +!ENDIF + !IF "$(OPENSSL_INCLUDE)" == "" OPENSSL_INCLUDE="D:\openssl\engine-0.9.6g-md3\include" !IF "$(VERBOSE)" != "0" From 2e9f03cfa927ac8062f3e60ebbc119dbe0aae34e Mon Sep 17 00:00:00 2001 From: Ignacio Casal Quinteiro Date: Tue, 17 Nov 2015 16:14:01 +0100 Subject: [PATCH 203/796] 'INCLUDES' is the old name for 'AM_CPPFLAGS' --- java/CyrusSasl/Makefile.am | 2 +- lib/Makefile.am | 2 +- plugins/Makefile.am | 2 +- pwcheck/Makefile.am | 2 +- sample/Makefile.am | 2 +- saslauthd/Makefile.am | 2 +- sasldb/Makefile.am | 2 +- utils/Makefile.am | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/java/CyrusSasl/Makefile.am b/java/CyrusSasl/Makefile.am index be1ffc14..1ce772aa 100644 --- a/java/CyrusSasl/Makefile.am +++ b/java/CyrusSasl/Makefile.am @@ -28,7 +28,7 @@ javasasl_version = 1:0:0 javasasldir = $(prefix)/lib/java/classes/sasl/CyrusSasl javahtmldir = $(prefix)/html/sasl -INCLUDES=-I$(top_srcdir)/include $(JAVA_INCLUDES) +AM_CPPFLAGS=-I$(top_srcdir)/include $(JAVA_INCLUDES) javasasl_JAVA = Sasl.java GenericClient.java \ ClientFactory.java \ diff --git a/lib/Makefile.am b/lib/Makefile.am index b8964a87..0467220d 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -45,7 +45,7 @@ # CURRENT:REVISION:AGE sasl_version = 3:0:0 -INCLUDES=-DLIBSASL_EXPORTS=1 -I$(top_srcdir)/include -I$(top_srcdir)/plugins -I$(top_builddir)/include -I$(top_srcdir)/sasldb +AM_CPPFLAGS=-DLIBSASL_EXPORTS=1 -I$(top_srcdir)/include -I$(top_srcdir)/plugins -I$(top_builddir)/include -I$(top_srcdir)/sasldb EXTRA_DIST = windlopen.c staticopen.h NTMakefile EXTRA_LIBRARIES = libsasl2.a diff --git a/plugins/Makefile.am b/plugins/Makefile.am index d570de1c..d75d2401 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -49,7 +49,7 @@ # CURRENT:REVISION:AGE plugin_version = 3:0:0 -INCLUDES=-I$(top_srcdir)/include -I$(top_srcdir)/lib -I$(top_srcdir)/sasldb -I$(top_builddir)/include +AM_CPPFLAGS=-I$(top_srcdir)/include -I$(top_srcdir)/lib -I$(top_srcdir)/sasldb -I$(top_builddir)/include AM_LDFLAGS = -module -export-dynamic -rpath $(plugindir) -version-info $(plugin_version) COMPAT_OBJS = @LTGETADDRINFOOBJS@ @LTGETNAMEINFOOBJS@ @LTSNPRINTFOBJS@ diff --git a/pwcheck/Makefile.am b/pwcheck/Makefile.am index 8c9fc09c..b6ed1d48 100644 --- a/pwcheck/Makefile.am +++ b/pwcheck/Makefile.am @@ -24,7 +24,7 @@ sbin_PROGRAMS = pwcheck -INCLUDES = -I../include -I../lib +AM_CPPFLAGS = -I../include -I../lib pwcheck_SOURCES = pwcheck.c EXTRA_pwcheck_SOURCES = pwcheck_getpwnam.c pwcheck_getspnam.c diff --git a/sample/Makefile.am b/sample/Makefile.am index f00579db..5eef380a 100644 --- a/sample/Makefile.am +++ b/sample/Makefile.am @@ -42,7 +42,7 @@ # ################################################################ -INCLUDES=-I$(top_srcdir)/include +AM_CPPFLAGS=-I$(top_srcdir)/include noinst_PROGRAMS = client server EXTRA_PROGRAMS = sample-client sample-server diff --git a/saslauthd/Makefile.am b/saslauthd/Makefile.am index 894322a4..b55fe369 100644 --- a/saslauthd/Makefile.am +++ b/saslauthd/Makefile.am @@ -25,7 +25,7 @@ saslcache_SOURCES = saslcache.c EXTRA_DIST = saslauthd.8 saslauthd.mdoc config include \ getnameinfo.c getaddrinfo.c LDAP_SASLAUTHD -INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include -I$(top_srcdir)/../include +AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include -I$(top_srcdir)/../include DEFS = @DEFS@ -DSASLAUTHD_CONF_FILE_DEFAULT=\"@sysconfdir@/saslauthd.conf\" -I. -I$(srcdir) -I.. diff --git a/sasldb/Makefile.am b/sasldb/Makefile.am index dd40bbca..eddc5464 100644 --- a/sasldb/Makefile.am +++ b/sasldb/Makefile.am @@ -44,7 +44,7 @@ # Note that this doesn't necessaraly follow the libsasl2 verison info sasl_version = 1:25:0 -INCLUDES=-I$(top_srcdir)/include -I$(top_builddir)/include @SASL_DB_INC@ +AM_CPPFLAGS=-I$(top_srcdir)/include -I$(top_builddir)/include @SASL_DB_INC@ extra_common_sources = db_none.c db_lmdb.c db_ndbm.c db_gdbm.c db_berkeley.c diff --git a/utils/Makefile.am b/utils/Makefile.am index 7e2f983d..cce413bb 100644 --- a/utils/Makefile.am +++ b/utils/Makefile.am @@ -89,7 +89,7 @@ libsfsasl2_la_SOURCES = libsfsasl2_la_LIBADD = sfsasl.lo libsfsasl2_la_LDFLAGS = -version-info 1:0:0 -export-dynamic -rpath $(libdir) -INCLUDES=-I$(top_srcdir)/include -I$(top_builddir)/include @SASL_DB_INC@ +AM_CPPFLAGS=-I$(top_srcdir)/include -I$(top_builddir)/include @SASL_DB_INC@ EXTRA_DIST = saslpasswd2.8 sasldblistusers2.8 pluginviewer.8 sfsasl.h sfsasl.c smtptest.c testsuite.c pluginviewer.c NTMakefile sfsasl.lo: sfsasl.c From 513d25cc6829c216dcafb2ffb31ff2d5a5744c4e Mon Sep 17 00:00:00 2001 From: Ignacio Casal Quinteiro Date: Tue, 17 Nov 2015 16:50:53 +0100 Subject: [PATCH 204/796] Fix relocation error when compiling --- sasldb/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sasldb/Makefile.am b/sasldb/Makefile.am index eddc5464..f166488c 100644 --- a/sasldb/Makefile.am +++ b/sasldb/Makefile.am @@ -44,7 +44,7 @@ # Note that this doesn't necessaraly follow the libsasl2 verison info sasl_version = 1:25:0 -AM_CPPFLAGS=-I$(top_srcdir)/include -I$(top_builddir)/include @SASL_DB_INC@ +AM_CPPFLAGS=-fPIC -I$(top_srcdir)/include -I$(top_builddir)/include @SASL_DB_INC@ extra_common_sources = db_none.c db_lmdb.c db_ndbm.c db_gdbm.c db_berkeley.c From bc4bada1146477996aa25c2149c5fea9a8c98aaa Mon Sep 17 00:00:00 2001 From: Ignacio Casal Quinteiro Date: Wed, 18 Nov 2015 09:44:34 +0100 Subject: [PATCH 205/796] Missing NTMakefile in EXTRA_DIST --- sample/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/sample/Makefile.am b/sample/Makefile.am index 5eef380a..6bc77aff 100644 --- a/sample/Makefile.am +++ b/sample/Makefile.am @@ -46,6 +46,7 @@ AM_CPPFLAGS=-I$(top_srcdir)/include noinst_PROGRAMS = client server EXTRA_PROGRAMS = sample-client sample-server +EXTRA_DIST = NTMakefile CLEANFILES=sample-client sample-server ./.libs/*sample-client ./.libs/*sample-server sample_client_SOURCES = sample-client.c From e75a84dc19216f37f9f083665b3556a391c08518 Mon Sep 17 00:00:00 2001 From: Ignacio Casal Quinteiro Date: Wed, 18 Nov 2015 10:21:34 +0100 Subject: [PATCH 206/796] win32: fix typo on default variables --- win32/common.mak | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/win32/common.mak b/win32/common.mak index 480de13f..b3dae197 100644 --- a/win32/common.mak +++ b/win32/common.mak @@ -80,14 +80,14 @@ DB_LIBPATH=c:\work\isode\db\build_win32\Release_static !ENDIF !IF "$(LMDB_INCLUDE)" == "" -DB_INCLUDE=c:\work\isode\lmdb\libraries\liblmdb +LMDB_INCLUDE=c:\work\isode\lmdb\libraries\liblmdb !IF "$(VERBOSE)" != "0" !MESSAGE Defaulting LMDB include path to $(LMDB_INCLUDE). !ENDIF !ENDIF !IF "$(LMDB_LIBPATH)" == "" -DB_LIBPATH=c:\work\isode\lmdb\libraries\liblmdb\Release +LMDB_LIBPATH=c:\work\isode\lmdb\libraries\liblmdb\Release !IF "$(VERBOSE)" != "0" !MESSAGE Defaulting LMDB library path to $(LMDB_LIBPATH). !ENDIF From 424e7fedd0a32cfe66ee6aac412ab901dbfcfd8a Mon Sep 17 00:00:00 2001 From: Ignacio Casal Quinteiro Date: Thu, 19 Nov 2015 15:06:52 +0100 Subject: [PATCH 207/796] Merge AUTHORS in one single file --- AUTHORS | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/AUTHORS b/AUTHORS index 3e00420b..aaff3075 100644 --- a/AUTHORS +++ b/AUTHORS @@ -44,3 +44,15 @@ and both Larry Greenfield and Alexey Melnikov have done more work on it. getaddrinfo.c was written by Hajimu UMEMOTO which is based on the IPv6 code written by KIKUCHI Takahiro + +Igor Brezac has done a good deal of work on the saslauthd +LDAP module. + +Jeremy Rumpf implemented the credential cache, unified +the different IPC methods under a common framework. + +Fabian Knittel wrote auth_pam plugin, based on +Debian's pwcheck_pam daemon by Michael-John Turner . + +saslauthd was originally contributed by Lyndon Nerenberg on +behalf of MessagingDirect Ltd. From 1cbb299fd90097c10a4608119f3fb567d757e8be Mon Sep 17 00:00:00 2001 From: Ignacio Casal Quinteiro Date: Thu, 19 Nov 2015 15:08:13 +0100 Subject: [PATCH 208/796] Remove configure magic from saslauthd --- SMakefile | 10 -- configure.ac | 105 ++++++++++- saslauthd/AUTHORS | 23 --- saslauthd/INSTALL | 3 - saslauthd/Makefile.am | 7 +- saslauthd/NEWS | 3 - saslauthd/README | 4 - saslauthd/auth_httpform.c | 3 + saslauthd/auth_shadow.c | 2 + saslauthd/cache.c | 2 +- saslauthd/cache.h | 2 +- saslauthd/config/.gitignore | 4 - saslauthd/configure.ac | 340 ------------------------------------ saslauthd/mechanisms.h | 2 +- saslauthd/saslauthd-main.h | 3 +- saslauthd/testsaslauthd.c | 2 +- saslauthd/utils.h | 3 +- 17 files changed, 115 insertions(+), 403 deletions(-) delete mode 100644 saslauthd/AUTHORS delete mode 100644 saslauthd/INSTALL delete mode 100644 saslauthd/NEWS delete mode 100644 saslauthd/README delete mode 100644 saslauthd/config/.gitignore delete mode 100644 saslauthd/configure.ac diff --git a/SMakefile b/SMakefile index deef8aee..8b2abf22 100644 --- a/SMakefile +++ b/SMakefile @@ -12,16 +12,6 @@ if test ! -x configure; then autoconf echo automake --add-missing --include-deps automake --add-missing --include-deps - echo cd saslauthd - cd saslauthd - echo aclocal -I ../cmulocal -I config -I ../config - aclocal -I ../cmulocal -I config -I ../config - echo autoheader - autoheader - echo autoconf - autoconf - echo automake --add-missing --include-deps - automake --add-missing --include-deps fi LIBS="" diff --git a/configure.ac b/configure.ac index eddfc854..4ca34d87 100644 --- a/configure.ac +++ b/configure.ac @@ -580,6 +580,68 @@ if test "$gssapi" != "no"; then AC_MSG_RESULT($use_gss_mutexes) fi +SASL2_CRYPT_CHK + +AC_ARG_ENABLE(sia, [ --enable-sia enable SIA authentication [no] ], + sia=$enableval, + sia=no) +LIB_SIA="" +if test "$sia" != no; then + if test -f /etc/sia/matrix.conf; then + AC_DEFINE(HAVE_SIA,[],[Include SIA Support]) + LIB_SIA="-lsecurity -ldb -lm -laud" + else + AC_ERROR([No support for SIA found]) + fi +fi +AC_SUBST(LIB_SIA) + +AC_ARG_ENABLE(auth-sasldb, [ --enable-auth-sasldb enable experimental SASLdb authentication module [no] ], + authsasldb=$enableval, + authsasldb=no) +if test "$authsasldb" != no; then + if test ! -d "../sasldb"; then + echo "ERROR: Cannot build sasldb module outside of the full SASL source tree." + exit 0; + fi + AC_DEFINE(AUTH_SASLDB,[],[Include SASLdb Support]) + SASL_DB_PATH_CHECK() + SASL_DB_CHECK() + SASL_DB_LIB="$SASL_DB_LIB ../sasldb/.libs/libsasldb.al" +fi + +AC_ARG_ENABLE(httpform, [ --enable-httpform enable HTTP form authentication [[no]] ], + httpform=$enableval, + httpform=no) +if test "$httpform" != no; then + AC_DEFINE(HAVE_HTTPFORM,[],[Include HTTP form Support]) +fi + +AC_ARG_WITH(pam, [ --with-pam=DIR use PAM (rooted in DIR) [yes] ], + with_pam=$withval, + with_pam=yes) +if test "$with_pam" != no; then + if test -d $with_pam; then + CPPFLAGS="$CPPFLAGS -I${with_pam}/include" + LDFLAGS="$LDFLAGS -L${with_pam}/lib" + fi + cmu_save_LIBS="$LIBS" + AC_CHECK_LIB(pam, pam_start, [ + AC_CHECK_HEADER(security/pam_appl.h,, + with_pam=no)], + with_pam=no, $SASL_DL_LIB) + LIBS="$cmu_save_LIBS" +fi + +AC_MSG_CHECKING(for PAM support) +AC_MSG_RESULT($with_pam) +LIB_PAM="" +if test "$with_pam" != no; then + AC_DEFINE(HAVE_PAM,[],[Support for PAM?]) + LIB_PAM="-lpam" +fi +AC_SUBST(LIB_PAM) + dnl PLAIN SASL_PLAIN_CHK @@ -672,9 +734,26 @@ else fi -# make the option show up so people don't whine that it is only in the -# saslauthd configure script --help -AC_ARG_WITH(ldap, [ --with-ldap=DIR use LDAP (in DIR) for saslauthd [no] ],,with_ldap=no) +AC_MSG_CHECKING(to include LDAP support) +AC_ARG_WITH(ldap, [ --with-ldap=DIR use LDAP (in DIR) for saslauthd [no] ], + with_ldap=$withval, + with_ldap=no) +AC_MSG_RESULT($with_ldap) + +if test -d $with_ldap; then + CPPFLAGS="$CPPFLAGS -I${with_ldap}/include" + CMU_ADD_LIBPATH(${with_ldap}/lib) +fi + +LDAP_LIBS="" +if test "$with_ldap" != no; then + AC_CHECK_LIB(ldap, ldap_initialize, [ AC_DEFINE(HAVE_LDAP,[],[Support for LDAP?]) + LDAP_LIBS="-lldap -llber" + if test "$with_openssl" != "no"; then + LDAP_LIBS="$LDAP_LIBS -lcrypto $LIB_RSAREF" + fi],,-llber) +fi +AC_SUBST(LDAP_LIBS) dnl SQL @@ -1196,7 +1275,7 @@ AC_HEADER_TIME AC_HEADER_STDC AC_HEADER_DIRENT AC_HEADER_SYS_WAIT -AC_CHECK_HEADERS(des.h dlfcn.h fcntl.h limits.h malloc.h paths.h strings.h sys/file.h sys/time.h syslog.h unistd.h inttypes.h sys/uio.h sys/param.h sysexits.h stdarg.h varargs.h) +AC_CHECK_HEADERS(crypt.h des.h dlfcn.h fcntl.h limits.h malloc.h paths.h strings.h sys/file.h sys/time.h syslog.h unistd.h inttypes.h sys/uio.h sys/param.h sysexits.h stdarg.h varargs.h) IPv6_CHECK_SS_FAMILY() IPv6_CHECK_SA_LEN() @@ -1204,7 +1283,7 @@ IPv6_CHECK_SOCKLEN_T() #AC_FUNC_MEMCMP #AC_FUNC_VPRINTF -AC_CHECK_FUNCS(gethostname getdomainname getpwnam getspnam gettimeofday inet_aton memcpy mkdir select socket strchr strdup strerror strspn strstr strtol jrand48 getpassphrase) +AC_CHECK_FUNCS(gethostname getdomainname getpwnam getspnam gettimeofday inet_aton memcpy mkdir select socket strchr strdup strerror strspn strstr strtol jrand48 getpassphrase asprintf strlcat strlcpy) if test $enable_cmulocal = yes; then AC_WARN([enabling CMU local kludges]) @@ -1217,8 +1296,6 @@ AC_EGREP_HEADER(sockaddr_storage, sys/socket.h, [ AC_SUBST(DIRS) -AC_CONFIG_SUBDIRS(saslauthd) - AH_TOP([ /* acconfig.h - autoheader configuration input */ /* @@ -1410,6 +1487,19 @@ inline static unsigned int sleep(unsigned int seconds) { } #endif +/* handy string manipulation functions */ +#ifndef HAVE_STRLCPY +extern size_t saslauthd_strlcpy(char *dst, const char *src, size_t len); +#define strlcpy(x,y,z) saslauthd_strlcpy((x),(y),(z)) +#endif +#ifndef HAVE_STRLCAT +extern size_t saslauthd_strlcat(char *dst, const char *src, size_t len); +#define strlcat(x,y,z) saslauthd_strlcat((x),(y),(z)) +#endif +#ifndef HAVE_ASPRINTF +extern int asprintf(char **str, const char *fmt, ...); +#endif + #endif /* CONFIG_H */ ]) @@ -1418,6 +1508,7 @@ AC_CONFIG_HEADERS(config.h) AC_OUTPUT(Makefile libsasl2.pc include/Makefile +saslauthd/Makefile sasldb/Makefile plugins/Makefile lib/Makefile diff --git a/saslauthd/AUTHORS b/saslauthd/AUTHORS deleted file mode 100644 index ecb1bec8..00000000 --- a/saslauthd/AUTHORS +++ /dev/null @@ -1,23 +0,0 @@ -Tim Martin wrote, debugged, and tested most of the -code. - -Rob Siemborski wrote the self-contained autoconf system. - -Larry Greenfield talked a lot. - -Igor Brezac has done a good deal of work on the saslauthd -LDAP module. - -Jeremy Rumpf implemented the credential cache, unified -the different IPC methods under a common framework. - -Fabian Knittel wrote auth_pam plugin, based on -Debian's pwcheck_pam daemon by Michael-John Turner . - -saslauthd was originally contributed by Lyndon Nerenberg on -behalf of MessagingDirect Ltd. - -getaddrinfo.c was written by Hajimu UMEMOTO -which is based on the IPv6 code written by KIKUCHI Takahiro - - diff --git a/saslauthd/INSTALL b/saslauthd/INSTALL deleted file mode 100644 index ed6ed2ca..00000000 --- a/saslauthd/INSTALL +++ /dev/null @@ -1,3 +0,0 @@ -Follow the install documentation for SASL. (saslauthd will install as -a part of the regular Cyrus SASL distribution as long as you configure -SASL with --with-saslauthd) diff --git a/saslauthd/Makefile.am b/saslauthd/Makefile.am index b55fe369..2b45fc1b 100644 --- a/saslauthd/Makefile.am +++ b/saslauthd/Makefile.am @@ -2,6 +2,9 @@ AUTOMAKE_OPTIONS = 1.7 sbin_PROGRAMS = saslauthd testsaslauthd EXTRA_PROGRAMS = saslcache +LTLIBOBJS = @LTLIBOBJS@ +LTLIBOBJS_FULL = $(addprefix ${top_srcdir}/lib/,${LTLIBOBJS}) + saslauthd_SOURCES = mechanisms.c globals.h \ mechanisms.h auth_dce.c auth_dce.h auth_getpwent.c \ auth_getpwent.h auth_krb5.c auth_krb5.h auth_krb4.c \ @@ -13,10 +16,10 @@ saslauthd_SOURCES = mechanisms.c globals.h \ ipc_unix.c ipc_doors.c saslauthd-main.c saslauthd-main.h \ md5.c saslauthd_md5.h md5global.h EXTRA_saslauthd_sources = getaddrinfo.c getnameinfo.c -saslauthd_DEPENDENCIES = saslauthd-main.o @LTLIBOBJS@ +saslauthd_DEPENDENCIES = saslauthd-main.o $(LTLIBOBJS_FULL) saslauthd_LDADD = @SASL_KRB_LIB@ \ @GSSAPIBASE_LIBS@ @LIB_CRYPT@ @LIB_SIA@ \ - @LIB_SOCKET@ @SASL_DB_LIB@ @LIB_PAM@ @LDAP_LIBS@ @LTLIBOBJS@ + @LIB_SOCKET@ @SASL_DB_LIB@ @LIB_PAM@ @LDAP_LIBS@ $(LTLIBOBJS_FULL) testsaslauthd_SOURCES = testsaslauthd.c utils.c testsaslauthd_LDADD = @LIB_SOCKET@ diff --git a/saslauthd/NEWS b/saslauthd/NEWS deleted file mode 100644 index 79b9a364..00000000 --- a/saslauthd/NEWS +++ /dev/null @@ -1,3 +0,0 @@ -New in v1.1.0 ------------------ -- saslauthd now configures as a separate package. diff --git a/saslauthd/README b/saslauthd/README deleted file mode 100644 index f3184b6f..00000000 --- a/saslauthd/README +++ /dev/null @@ -1,4 +0,0 @@ -This directory contains the saslauthd daemon. Similar to pwcheck, it -allows password verification from a separate process. - -For more information, consult the main Cyrus SASL documentation. diff --git a/saslauthd/auth_httpform.c b/saslauthd/auth_httpform.c index 8dbf5518..b8e555ab 100644 --- a/saslauthd/auth_httpform.c +++ b/saslauthd/auth_httpform.c @@ -57,6 +57,8 @@ #ident "$Id: auth_httpform.c,v 1.2 2006/04/19 19:51:04 murch Exp $" #endif +#include + /* PUBLIC DEPENDENCIES */ #include #include @@ -73,6 +75,7 @@ #include #include #include +#include #include "mechanisms.h" #include "utils.h" diff --git a/saslauthd/auth_shadow.c b/saslauthd/auth_shadow.c index 1988afdf..9bb0187a 100644 --- a/saslauthd/auth_shadow.c +++ b/saslauthd/auth_shadow.c @@ -31,6 +31,8 @@ #ident "$Id: auth_shadow.c,v 1.12 2009/08/14 14:58:38 mel Exp $" #endif +#include + /* PUBLIC DEPENDENCIES */ #include "mechanisms.h" diff --git a/saslauthd/cache.c b/saslauthd/cache.c index 2b784647..543e1766 100644 --- a/saslauthd/cache.c +++ b/saslauthd/cache.c @@ -37,7 +37,7 @@ /**************************************** * includes *****************************************/ -#include "saslauthd.h" +#include #include #include diff --git a/saslauthd/cache.h b/saslauthd/cache.h index 6a5707e2..b8c88382 100644 --- a/saslauthd/cache.h +++ b/saslauthd/cache.h @@ -41,7 +41,7 @@ /* constant includes */ -#include "saslauthd.h" +#include /**************************************************************** diff --git a/saslauthd/config/.gitignore b/saslauthd/config/.gitignore deleted file mode 100644 index 5e7d2734..00000000 --- a/saslauthd/config/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# Ignore everything in this directory -* -# Except this file -!.gitignore diff --git a/saslauthd/configure.ac b/saslauthd/configure.ac deleted file mode 100644 index f4bc3b56..00000000 --- a/saslauthd/configure.ac +++ /dev/null @@ -1,340 +0,0 @@ -AC_INIT(mechanisms.h) -AC_PREREQ([2.54]) - -AC_CONFIG_AUX_DIR(config) -AC_CANONICAL_HOST - -dnl Should we enable SASLAUTHd at all? -AC_ARG_WITH(saslauthd, [ --with-saslauthd=DIR enable use of the saslauth daemon using state dir DIR ], - with_saslauthd=$withval, - with_saslauthd=yes) - if test "$with_saslauthd" = yes; then - with_saslauthd="/var/state/saslauthd" - fi - AC_DEFINE(HAVE_SASLAUTHD,[],[Include support for saslauthd?]) - AC_DEFINE_UNQUOTED(PATH_SASLAUTHD_RUNDIR, "$with_saslauthd",[Location of saslauthd socket]) -AM_CONDITIONAL(SASLAUTHD, test "$with_saslauthd" != no) - -AM_INIT_AUTOMAKE(saslauthd,2.1.26) -CMU_INIT_AUTOMAKE - -dnl Checks for programs. -AC_PROG_CC -AC_PROG_CPP -AC_PROG_AWK -AC_PROG_MAKE_SET -AC_PROG_LN_S -AC_PROG_INSTALL - -dnl Checks for build foo -CMU_C___ATTRIBUTE__ -CMU_GUESS_RUNPATH_SWITCH - -dnl Checks for libraries. -CMU_SOCKETS - -CMU_HAVE_OPENSSL -AC_MSG_CHECKING(for OpenSSL) -AC_MSG_RESULT($with_openssl) - -SASL_DES_CHK - -dnl mechanism-related checking -SASL_KERBEROS_V4_CHK -SASL_GSSAPI_CHK - -if test "$gssapi" != no; then - if test "$gss_impl" = "heimdal"; then - AC_DEFINE(KRB5_HEIMDAL,[],[Using Heimdal]) - fi - AC_DEFINE(HAVE_GSSAPI,[],[Include GSSAPI/Kerberos 5 Support]) -fi - -SASL2_CRYPT_CHK - -AC_ARG_ENABLE(sia, [ --enable-sia enable SIA authentication [no] ], - sia=$enableval, - sia=no) -LIB_SIA="" -if test "$sia" != no; then - if test -f /etc/sia/matrix.conf; then - AC_DEFINE(HAVE_SIA,[],[Include SIA Support]) - LIB_SIA="-lsecurity -ldb -lm -laud" - else - AC_ERROR([No support for SIA found]) - fi -fi -AC_SUBST(LIB_SIA) - -AC_ARG_ENABLE(auth-sasldb, [ --enable-auth-sasldb enable experimental SASLdb authentication module [no] ], - authsasldb=$enableval, - authsasldb=no) -if test "$authsasldb" != no; then - if test ! -d "../sasldb"; then - echo "ERROR: Cannot build sasldb module outside of the full SASL source tree." - exit 0; - fi - AC_DEFINE(AUTH_SASLDB,[],[Include SASLdb Support]) - SASL_DB_PATH_CHECK() - SASL_DB_CHECK() - SASL_DB_LIB="$SASL_DB_LIB ../sasldb/.libs/libsasldb.al" -fi - -AC_ARG_ENABLE(httpform, [ --enable-httpform enable HTTP form authentication [[no]] ], - httpform=$enableval, - httpform=no) -if test "$httpform" != no; then - AC_DEFINE(HAVE_HTTPFORM,[],[Include HTTP form Support]) -fi - -AC_ARG_WITH(pam, [ --with-pam=DIR use PAM (rooted in DIR) [yes] ], - with_pam=$withval, - with_pam=yes) -if test "$with_pam" != no; then - if test -d $with_pam; then - CPPFLAGS="$CPPFLAGS -I${with_pam}/include" - LDFLAGS="$LDFLAGS -L${with_pam}/lib" - fi - cmu_save_LIBS="$LIBS" - AC_CHECK_LIB(pam, pam_start, [ - AC_CHECK_HEADER(security/pam_appl.h,, - with_pam=no)], - with_pam=no, $SASL_DL_LIB) - LIBS="$cmu_save_LIBS" -fi - -AC_ARG_WITH(ipctype, [ --with-ipctype={unix,doors} use ipctype [unix] ], - with_ipctype=$withval, - with_ipctype="unix") -MAIN_COMPAT_OBJ="saslauthd-${with_ipctype}.o" -AC_SUBST(MAIN_COMPAT_OBJ) -if test "$with_ipctype" = "doors"; then - AC_DEFINE(USE_DOORS,[],[Use the doors IPC API]) - AC_DEFINE(SASLAUTHD_THREADED,[],[Saslauthd runs threaded?]) - LIBS="$LIBS -ldoor -lpthread" -fi - -AC_MSG_CHECKING(for PAM support) -AC_MSG_RESULT($with_pam) -LIB_PAM="" -if test "$with_pam" != no; then - AC_DEFINE(HAVE_PAM,[],[Support for PAM?]) - LIB_PAM="-lpam" -fi -AC_SUBST(LIB_PAM) - -AC_CHECK_LIB(resolv, inet_aton) - -AC_MSG_CHECKING(to include LDAP support) -AC_ARG_WITH(ldap, [ --with-ldap=DIR use LDAP (in DIR) [no] ], - with_ldap=$withval, - with_ldap=no) -AC_MSG_RESULT($with_ldap) - -if test -d $with_ldap; then - CPPFLAGS="$CPPFLAGS -I${with_ldap}/include" - CMU_ADD_LIBPATH(${with_ldap}/lib) -fi - -LDAP_LIBS="" -if test "$with_ldap" != no; then - AC_CHECK_LIB(ldap, ldap_initialize, [ AC_DEFINE(HAVE_LDAP,[],[Support for LDAP?]) - LDAP_LIBS="-lldap -llber" - if test "$with_openssl" != "no"; then - LDAP_LIBS="$LDAP_LIBS -lcrypto $LIB_RSAREF" - fi],,-llber) - -fi -AC_SUBST(LDAP_LIBS) - - -dnl Checks for header files. -AC_HEADER_STDC -AC_HEADER_SYS_WAIT -AC_HEADER_TIME -AC_CHECK_HEADERS(crypt.h fcntl.h krb5.h strings.h syslog.h unistd.h sys/time.h sys/uio.h) - -dnl Checks for typedefs, structures, and compiler characteristics. -AC_C_CONST -AC_TYPE_PID_T - -LTLIBOBJS=`echo "$LIB@&t@OBJS" | sed 's,\.[[^.]]* ,.lo ,g;s,\.[[^.]]*$,.lo,'` -AC_SUBST(LTLIBOBJS) - -dnl Checks for which function macros exist -AC_MSG_CHECKING(whether $CC implements __func__) -AC_CACHE_VAL(cyrus_cv_have_func, -[AC_TRY_LINK([#include ],[printf("%s", __func__);], -cyrus_cv_have_func=yes, -cyrus_cv_have_func=no)]) -AC_MSG_RESULT($cyrus_cv_have_func) -if test "$cyrus_cv_have_func" = yes; then - AC_DEFINE(HAVE_FUNC,[],[Does the compiler understand __func__]) -else - AC_MSG_CHECKING(whether $CC implements __PRETTY_FUNCTION__) - AC_CACHE_VAL(cyrus_cv_have_pretty_function, - [AC_TRY_LINK([#include ],[printf("%s", __PRETTY_FUNCTION__);], - cyrus_cv_have_pretty_function=yes, - cyrus_cv_have_pretty_function=no)]) - AC_MSG_RESULT($cyrus_cv_have_pretty_function) - if test "$cyrus_cv_have_pretty_function" = yes; then - AC_DEFINE(HAVE_PRETTY_FUNCTION,[],[Does compiler understand __PRETTY_FUNCTION__]) - else - AC_MSG_CHECKING(whether $CC implements __FUNCTION__) - AC_CACHE_VAL(cyrus_cv_have_function, - [AC_TRY_LINK([#include ],[printf("%s", __FUNCTION__);], - cyrus_cv_have_function=yes, - cyrus_cv_have_function=no)]) - AC_MSG_RESULT($cyrus_cv_have_function) - if test "$cyrus_cv_have_function" = yes; then - AC_DEFINE(HAVE_FUNCTION,[],[Does compiler understand __FUNCTION__]) - fi - fi -fi - -dnl Checks for library functions. -AC_TYPE_SIGNAL -AC_CHECK_FUNCS(gethostname mkdir socket strdup) -dnl Only look for one or the other -AC_CHECK_FUNCS(getspnam getuserpw, break) -AC_CHECK_FUNCS(asprintf strlcat strlcpy) - -if test $ac_cv_func_getspnam = yes; then - AC_MSG_CHECKING(if getpwnam_r/getspnam_r take 5 arguments) - AC_TRY_COMPILE( - [ -#include -#include -#include - ], - [ -struct passwd *pw; -struct passwd pwbuf; -char pwdata[512]; -(void) getpwnam_r("bin", &pwbuf, pwdata, sizeof(pwdata), &pw); - ], - [AC_MSG_RESULT(yes) - AC_DEFINE(GETXXNAM_R_5ARG, 1, - [Define if your getpwnam_r()/getspnam_r() - functions take 5 arguments])], - [AC_MSG_RESULT(no)] - ) -fi - -dnl Check for getaddrinfo -GETADDRINFOOBJS="" -sasl_cv_getaddrinfo=no -IPv6_CHECK_FUNC(getaddrinfo, - [AC_DEFINE(HAVE_GETADDRINFO,[],[Do we have a getaddrinfo() function?])], [sasl_cv_getaddrinfo=yes]) -if test $sasl_cv_getaddrinfo = yes; then - AC_LIBOBJ(getaddrinfo) -fi - -dnl Check for getnameinfo -GETNAMEINFOOBJS="" -sasl_cv_getnameinfo=no -IPv6_CHECK_FUNC(getnameinfo, - [AC_DEFINE(HAVE_GETNAMEINFO,[],[Do we have a getnameinfo() function?])], [sasl_cv_getnameinfo=yes]) -if test $sasl_cv_getnameinfo = yes; then - AC_LIBOBJ(getnameinfo) -fi - -IPv6_CHECK_SS_FAMILY() -IPv6_CHECK_SA_LEN() -IPv6_CHECK_SOCKLEN_T() - -AC_EGREP_HEADER(sockaddr_storage, sys/socket.h, - AC_DEFINE(HAVE_STRUCT_SOCKADDR_STORAGE,[],[Do we have a sockaddr_storage struct?])) - -AH_TOP([ -#ifndef _SASLAUTHD_H -#define _SASLAUTHD_H - -#include -]) - -AH_BOTTOM([ - -#ifndef HAVE___ATTRIBUTE__ -/* Can't use attributes... */ -#define __attribute__(foo) -#endif - -#include -#include -#include -#ifndef WIN32 -# include -# include -#else /* WIN32 */ -# include -#endif /* WIN32 */ -#include - -#include - -#ifndef HAVE_SOCKLEN_T -typedef unsigned int socklen_t; -#endif /* HAVE_SOCKLEN_T */ - -#ifndef HAVE_STRUCT_SOCKADDR_STORAGE -#define _SS_MAXSIZE 128 /* Implementation specific max size */ -#define _SS_PADSIZE (_SS_MAXSIZE - sizeof (struct sockaddr)) - -struct sockaddr_storage { - struct sockaddr ss_sa; - char __ss_pad2[_SS_PADSIZE]; -}; -# define ss_family ss_sa.sa_family -#endif /* !HAVE_STRUCT_SOCKADDR_STORAGE */ - -#ifndef AF_INET6 -/* Define it to something that should never appear */ -#define AF_INET6 AF_MAX -#endif - -/* Create a struct iovec if we need one */ -#if !defined(HAVE_SYS_UIO_H) -struct iovec { - long iov_len; - char *iov_base; -}; -#else -#include -#include -#endif - -#ifndef HAVE_GETADDRINFO -#define getaddrinfo sasl_getaddrinfo -#define freeaddrinfo sasl_freeaddrinfo -#define getnameinfo sasl_getnameinfo -#define gai_strerror sasl_gai_strerror -#include "gai.h" -#endif - -#ifndef AI_NUMERICHOST /* support glibc 2.0.x */ -#define AI_NUMERICHOST 4 -#define NI_NUMERICHOST 2 -#define NI_NAMEREQD 4 -#define NI_NUMERICSERV 8 -#endif - -/* handy string manipulation functions */ -#ifndef HAVE_STRLCPY -extern size_t saslauthd_strlcpy(char *dst, const char *src, size_t len); -#define strlcpy(x,y,z) saslauthd_strlcpy((x),(y),(z)) -#endif -#ifndef HAVE_STRLCAT -extern size_t saslauthd_strlcat(char *dst, const char *src, size_t len); -#define strlcat(x,y,z) saslauthd_strlcat((x),(y),(z)) -#endif -#ifndef HAVE_ASPRINTF -extern int asprintf(char **str, const char *fmt, ...); -#endif - -#endif -]) - -AC_CONFIG_HEADERS(saslauthd.h) - -AC_OUTPUT(Makefile) diff --git a/saslauthd/mechanisms.h b/saslauthd/mechanisms.h index e2323bf5..3ed8d1c0 100644 --- a/saslauthd/mechanisms.h +++ b/saslauthd/mechanisms.h @@ -32,7 +32,7 @@ #ifndef _MECHANISMS_H #define _MECHANISMS_H -#include "saslauthd.h" +#include /* PUBLIC DEPENDENCIES */ /* Authentication mechanism dispatch table definition */ diff --git a/saslauthd/saslauthd-main.h b/saslauthd/saslauthd-main.h index 87d223b3..754626c6 100644 --- a/saslauthd/saslauthd-main.h +++ b/saslauthd/saslauthd-main.h @@ -45,8 +45,9 @@ #ifndef _SASLAUTHDMAIN_H #define _SASLAUTHDMAIN_H +#include + #include -#include "saslauthd.h" /**************************************************************** * Plug in some autoconf magic to determine what IPC method diff --git a/saslauthd/testsaslauthd.c b/saslauthd/testsaslauthd.c index f1e837a7..368af76d 100644 --- a/saslauthd/testsaslauthd.c +++ b/saslauthd/testsaslauthd.c @@ -41,7 +41,7 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include +#include #include #include diff --git a/saslauthd/utils.h b/saslauthd/utils.h index a2556c42..dc3a9a3e 100644 --- a/saslauthd/utils.h +++ b/saslauthd/utils.h @@ -45,12 +45,11 @@ #ifndef _UTILS_H #define _UTILS_H +#include #include #include #include -#include "saslauthd.h" - /* log prioities */ #define L_ERR LOG_ERR From 654ede3e4d931c63adbf6af23ad8fa5bdb6aecfe Mon Sep 17 00:00:00 2001 From: Ignacio Casal Quinteiro Date: Thu, 19 Nov 2015 16:13:27 +0100 Subject: [PATCH 209/796] configure: do not use the deprecated version of AM_INIT_AUTOMAKE Instead we pass all the parameters to AC_INIT and we improve the AM_INIT_AUTOMAKE to also create a tar.xz on distcheck which is the new standard --- configure.ac | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/configure.ac b/configure.ac index 4ca34d87..429189ec 100644 --- a/configure.ac +++ b/configure.ac @@ -41,8 +41,19 @@ dnl WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN dnl AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING dnl OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. dnl -AC_INIT(lib/saslint.h) -AC_PREREQ([2.54]) + +AC_PREREQ(2.63.2) + +dnl +dnl REMINDER: When changing the version number here, please also update +dnl the values in win32/include/config.h and include/sasl.h as well. +dnl +AC_INIT([cyrus-sasl], + [2.1.26], + [https://git.cyrus.foundation/maniphest/], + [cyrus-sasl], + [https://docs.cyrus.foundation]) + AC_CONFIG_MACRO_DIR([config]) dnl use ./config.cache as the default cache file. @@ -56,11 +67,7 @@ AC_CONFIG_AUX_DIR(config) AC_CANONICAL_HOST AC_CANONICAL_TARGET -dnl -dnl REMINDER: When changing the version number here, please also update -dnl the values in win32/include/config.h and include/sasl.h as well. -dnl -AM_INIT_AUTOMAKE(cyrus-sasl, 2.1.26) +AM_INIT_AUTOMAKE([1.11 tar-ustar dist-xz no-dist-gzip -Wno-portability subdir-objects]) CMU_INIT_AUTOMAKE # and include our config dir scripts From 3f42b7d7f3ef52056c79b31529d1a5be695c74c1 Mon Sep 17 00:00:00 2001 From: Ignacio Casal Quinteiro Date: Fri, 20 Nov 2015 11:16:31 +0100 Subject: [PATCH 210/796] Fix up pkgconfig pc file --- libsasl2.pc.in | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libsasl2.pc.in b/libsasl2.pc.in index 40bea37c..ddad76dc 100644 --- a/libsasl2.pc.in +++ b/libsasl2.pc.in @@ -1,8 +1,12 @@ -libdir = @libdir@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ Name: Cyrus SASL Description: Cyrus SASL implementation URL: http://www.cyrussasl.org/ Version: @VERSION@ +Cflags: -I${includedir} Libs: -L${libdir} -lsasl2 Libs.private: @LIB_DOOR@ @SASL_DL_LIB@ @LIBS@ From 3321e488019b6e0eebaa6c4b853dd5739e619909 Mon Sep 17 00:00:00 2001 From: Ignacio Casal Quinteiro Date: Fri, 20 Nov 2015 11:21:37 +0100 Subject: [PATCH 211/796] Pass -no-undefined flag. This is needed for mingw --- lib/Makefile.am | 2 +- plugins/Makefile.am | 2 +- sasldb/Makefile.am | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/Makefile.am b/lib/Makefile.am index 0467220d..17d155be 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -64,7 +64,7 @@ LIB_DOOR= @LIB_DOOR@ lib_LTLIBRARIES = libsasl2.la libsasl2_la_SOURCES = $(common_sources) $(common_headers) -libsasl2_la_LDFLAGS = -version-info $(sasl_version) +libsasl2_la_LDFLAGS = -version-info $(sasl_version) -no-undefined libsasl2_la_DEPENDENCIES = $(LTLIBOBJS) libsasl2_la_LIBADD = $(LTLIBOBJS) $(SASL_DL_LIB) $(LIB_SOCKET) $(LIB_DOOR) diff --git a/plugins/Makefile.am b/plugins/Makefile.am index d75d2401..8634f7e5 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -50,7 +50,7 @@ plugin_version = 3:0:0 AM_CPPFLAGS=-I$(top_srcdir)/include -I$(top_srcdir)/lib -I$(top_srcdir)/sasldb -I$(top_builddir)/include -AM_LDFLAGS = -module -export-dynamic -rpath $(plugindir) -version-info $(plugin_version) +AM_LDFLAGS = -module -export-dynamic -rpath $(plugindir) -version-info $(plugin_version) -no-undefined COMPAT_OBJS = @LTGETADDRINFOOBJS@ @LTGETNAMEINFOOBJS@ @LTSNPRINTFOBJS@ diff --git a/sasldb/Makefile.am b/sasldb/Makefile.am index f166488c..8ead7060 100644 --- a/sasldb/Makefile.am +++ b/sasldb/Makefile.am @@ -56,7 +56,8 @@ noinst_LIBRARIES = libsasldb.a libsasldb_la_SOURCES = allockey.c sasldb.h EXTRA_libsasldb_la_SOURCES = $(extra_common_sources) libsasldb_la_DEPENDENCIES = $(SASL_DB_BACKEND) -libsasldb_la_LIBADD = $(SASL_DB_BACKEND) +libsasldb_la_LIBADD = $(SASL_DB_BACKEND) +libsasldb_la_LDFLAGS = -no-undefined # Prevent make dist stupidity libsasldb_a_SOURCES = From d6bb516cfd4cb86cc3843aad78ea7c3240847e91 Mon Sep 17 00:00:00 2001 From: Ignacio Casal Quinteiro Date: Fri, 20 Nov 2015 11:27:09 +0100 Subject: [PATCH 212/796] Mingw already provides getopt --- lib/saslutil.c | 2 +- utils/sasldblistusers.c | 4 ++++ utils/saslpasswd.c | 5 ++++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/saslutil.c b/lib/saslutil.c index 61741246..bcdb1cad 100644 --- a/lib/saslutil.c +++ b/lib/saslutil.c @@ -607,7 +607,7 @@ int get_fqhostname( return (0); } -#ifdef WIN32 +#if defined(WIN32) && !defined(__MINGW64_VERSION_MAJOR) /***************************************************************************** * * MODULE NAME : GETOPT.C diff --git a/utils/sasldblistusers.c b/utils/sasldblistusers.c index 1b4d1e57..f755866a 100644 --- a/utils/sasldblistusers.c +++ b/utils/sasldblistusers.c @@ -57,9 +57,13 @@ #ifdef WIN32 #include +#if defined(__MINGW64_VERSION_MAJOR) +#include +#else __declspec(dllimport) char *optarg; __declspec(dllimport) int optind; #endif +#endif /* Cheating to make the utils work out right */ LIBSASL_VAR const sasl_utils_t *sasl_global_utils; diff --git a/utils/saslpasswd.c b/utils/saslpasswd.c index b3902f5f..b633f8f8 100644 --- a/utils/saslpasswd.c +++ b/utils/saslpasswd.c @@ -58,9 +58,12 @@ #include #include +#if defined(__MINGW64_VERSION_MAJOR) +#include +#else __declspec(dllimport) char *optarg; __declspec(dllimport) int optind; - +#endif /* perror can't be used on Windows system calls, so we define a new macro to underline this */ void p_oserror (const char *string); #endif /*WIN32*/ From c34ae6a35909e4ec50b4614628a598ae935c71c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 19 Nov 2015 19:40:52 +0100 Subject: [PATCH 213/796] Use AX_PROG_CC_FOR_BUILD for build generators This allows to call makemd5 in cross-compiled environments. --- configure.ac | 1 + include/Makefile.am | 15 ++++- m4/ax_prog_cc_for_build.m4 | 125 +++++++++++++++++++++++++++++++++++++ 3 files changed, 138 insertions(+), 3 deletions(-) create mode 100644 m4/ax_prog_cc_for_build.m4 diff --git a/configure.ac b/configure.ac index 429189ec..2abcc610 100644 --- a/configure.ac +++ b/configure.ac @@ -93,6 +93,7 @@ AC_ARG_ENABLE(obsolete_cram_attr, enable_obsolete_cram_attr=yes) AC_PROG_CC +AX_PROG_CC_FOR_BUILD AC_PROG_CPP AC_PROG_AWK AC_PROG_LN_S diff --git a/include/Makefile.am b/include/Makefile.am index 5ea5be23..c942efa9 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -51,9 +51,15 @@ noinst_PROGRAMS = makemd5 makemd5_SOURCES = makemd5.c -md5global.h: makemd5 - -rm -f md5global.h - ./makemd5 md5global.h +makemd5$(BUILD_EXEEXT) $(makemd5_OBJECTS): CC=$(CC_FOR_BUILD) +makemd5$(BUILD_EXEEXT) $(makemd5_OBJECTS): CFLAGS=$(CFLAGS_FOR_BUILD) +makemd5$(BUILD_EXEEXT): LDFLAGS=$(LDFLAGS_FOR_BUILD) + +md5global.h: makemd5$(BUILD_EXEEXT) Makefile + -rm -f $@ + ./$< $@ + +BUILT_SOURCES = md5global.h EXTRA_DIST = NTMakefile DISTCLEANFILES = md5global.h @@ -63,3 +69,6 @@ framedir = /Library/Frameworks/SASL2.framework frameheaderdir = $(framedir)/Versions/A/Headers frameheader_DATA = $(saslinclude_HEADERS) endif + +# TODO: automake, don't build it +makemd5$(EXEEXT): diff --git a/m4/ax_prog_cc_for_build.m4 b/m4/ax_prog_cc_for_build.m4 new file mode 100644 index 00000000..77fd346a --- /dev/null +++ b/m4/ax_prog_cc_for_build.m4 @@ -0,0 +1,125 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_prog_cc_for_build.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_PROG_CC_FOR_BUILD +# +# DESCRIPTION +# +# This macro searches for a C compiler that generates native executables, +# that is a C compiler that surely is not a cross-compiler. This can be +# useful if you have to generate source code at compile-time like for +# example GCC does. +# +# The macro sets the CC_FOR_BUILD and CPP_FOR_BUILD macros to anything +# needed to compile or link (CC_FOR_BUILD) and preprocess (CPP_FOR_BUILD). +# The value of these variables can be overridden by the user by specifying +# a compiler with an environment variable (like you do for standard CC). +# +# It also sets BUILD_EXEEXT and BUILD_OBJEXT to the executable and object +# file extensions for the build platform, and GCC_FOR_BUILD to `yes' if +# the compiler we found is GCC. All these variables but GCC_FOR_BUILD are +# substituted in the Makefile. +# +# LICENSE +# +# Copyright (c) 2008 Paolo Bonzini +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 8 + +AU_ALIAS([AC_PROG_CC_FOR_BUILD], [AX_PROG_CC_FOR_BUILD]) +AC_DEFUN([AX_PROG_CC_FOR_BUILD], [dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_CPP])dnl +AC_REQUIRE([AC_EXEEXT])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl + +dnl Use the standard macros, but make them use other variable names +dnl +pushdef([ac_cv_prog_CPP], ac_cv_build_prog_CPP)dnl +pushdef([ac_cv_prog_gcc], ac_cv_build_prog_gcc)dnl +pushdef([ac_cv_prog_cc_works], ac_cv_build_prog_cc_works)dnl +pushdef([ac_cv_prog_cc_cross], ac_cv_build_prog_cc_cross)dnl +pushdef([ac_cv_prog_cc_g], ac_cv_build_prog_cc_g)dnl +pushdef([ac_cv_exeext], ac_cv_build_exeext)dnl +pushdef([ac_cv_objext], ac_cv_build_objext)dnl +pushdef([ac_exeext], ac_build_exeext)dnl +pushdef([ac_objext], ac_build_objext)dnl +pushdef([CC], CC_FOR_BUILD)dnl +pushdef([CPP], CPP_FOR_BUILD)dnl +pushdef([CFLAGS], CFLAGS_FOR_BUILD)dnl +pushdef([CPPFLAGS], CPPFLAGS_FOR_BUILD)dnl +pushdef([LDFLAGS], LDFLAGS_FOR_BUILD)dnl +pushdef([host], build)dnl +pushdef([host_alias], build_alias)dnl +pushdef([host_cpu], build_cpu)dnl +pushdef([host_vendor], build_vendor)dnl +pushdef([host_os], build_os)dnl +pushdef([ac_cv_host], ac_cv_build)dnl +pushdef([ac_cv_host_alias], ac_cv_build_alias)dnl +pushdef([ac_cv_host_cpu], ac_cv_build_cpu)dnl +pushdef([ac_cv_host_vendor], ac_cv_build_vendor)dnl +pushdef([ac_cv_host_os], ac_cv_build_os)dnl +pushdef([ac_cpp], ac_build_cpp)dnl +pushdef([ac_compile], ac_build_compile)dnl +pushdef([ac_link], ac_build_link)dnl + +save_cross_compiling=$cross_compiling +save_ac_tool_prefix=$ac_tool_prefix +cross_compiling=no +ac_tool_prefix= + +AC_PROG_CC +AC_PROG_CPP +AC_EXEEXT + +ac_tool_prefix=$save_ac_tool_prefix +cross_compiling=$save_cross_compiling + +dnl Restore the old definitions +dnl +popdef([ac_link])dnl +popdef([ac_compile])dnl +popdef([ac_cpp])dnl +popdef([ac_cv_host_os])dnl +popdef([ac_cv_host_vendor])dnl +popdef([ac_cv_host_cpu])dnl +popdef([ac_cv_host_alias])dnl +popdef([ac_cv_host])dnl +popdef([host_os])dnl +popdef([host_vendor])dnl +popdef([host_cpu])dnl +popdef([host_alias])dnl +popdef([host])dnl +popdef([LDFLAGS])dnl +popdef([CPPFLAGS])dnl +popdef([CFLAGS])dnl +popdef([CPP])dnl +popdef([CC])dnl +popdef([ac_objext])dnl +popdef([ac_exeext])dnl +popdef([ac_cv_objext])dnl +popdef([ac_cv_exeext])dnl +popdef([ac_cv_prog_cc_g])dnl +popdef([ac_cv_prog_cc_cross])dnl +popdef([ac_cv_prog_cc_works])dnl +popdef([ac_cv_prog_gcc])dnl +popdef([ac_cv_prog_CPP])dnl + +dnl Finally, set Makefile variables +dnl +BUILD_EXEEXT=$ac_build_exeext +BUILD_OBJEXT=$ac_build_objext +AC_SUBST(BUILD_EXEEXT)dnl +AC_SUBST(BUILD_OBJEXT)dnl +AC_SUBST([CFLAGS_FOR_BUILD])dnl +AC_SUBST([CPPFLAGS_FOR_BUILD])dnl +AC_SUBST([LDFLAGS_FOR_BUILD])dnl +]) From 84f58aa8782829f5054109a67d65c9a198b8a2a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Fri, 20 Nov 2015 17:45:53 +0100 Subject: [PATCH 214/796] mingw: link with -lws2_32 --- cmulocal/bsd_sockets.m4 | 21 ++++++++++++++++++++- plugins/Makefile.am | 20 ++++++++++---------- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/cmulocal/bsd_sockets.m4 b/cmulocal/bsd_sockets.m4 index 42b3c7fa..9d75044d 100644 --- a/cmulocal/bsd_sockets.m4 +++ b/cmulocal/bsd_sockets.m4 @@ -7,7 +7,26 @@ dnl It now puts everything required for sockets into LIB_SOCKET AC_DEFUN([CMU_SOCKETS], [ save_LIBS="$LIBS" - LIB_SOCKET="" + AC_CHECK_HEADERS([sys/socket.h ws2tcpip.h]) + AC_CHECK_FUNC(socket, , [ + AC_CHECK_LIB(socket, socket, [LIB_SOCKET=-lsocket], [ + LIBS="$LIBS -lws2_32" + AC_LINK_IFELSE([ + AC_LANG_PROGRAM([[ + #ifdef HAVE_SYS_SOCKET_H + # include + #endif + #ifdef HAVE_WS2TCPIP_H + # include + #endif + ]], [[return socket(0, 0, 0);]]) + ], + [LIB_SOCKET=-lws2_32 + AC_MSG_RESULT(yes)], + [AC_MSG_ERROR([socket not found])]) + ]) + ]) + LIBS="$save_LIBS" AC_CHECK_FUNC(connect, :, [AC_CHECK_LIB(nsl, gethostbyname, LIB_SOCKET="-lnsl $LIB_SOCKET") diff --git a/plugins/Makefile.am b/plugins/Makefile.am index 8634f7e5..4c54bf84 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -71,11 +71,11 @@ EXTRA_LTLIBRARIES = libplain.la libanonymous.la libkerberos4.la libcrammd5.la \ libplain_la_SOURCES = plain.c plain_init.c $(common_sources) libplain_la_DEPENDENCIES = $(COMPAT_OBJS) -libplain_la_LIBADD = $(PLAIN_LIBS) $(COMPAT_OBJS) +libplain_la_LIBADD = $(PLAIN_LIBS) $(LIB_SOCKET) $(COMPAT_OBJS) libanonymous_la_SOURCES = anonymous.c anonymous_init.c $(common_sources) libanonymous_la_DEPENDENCIES = $(COMPAT_OBJS) -libanonymous_la_LIBADD = $(COMPAT_OBJS) +libanonymous_la_LIBADD = $(LIB_SOCKET) $(COMPAT_OBJS) libkerberos4_la_SOURCES = kerberos4.c kerberos4_init.c $(common_sources) libkerberos4_la_DEPENDENCIES = $(COMPAT_OBJS) @@ -91,7 +91,7 @@ libgssapiv2_la_LIBADD = $(GSSAPIBASE_LIBS) $(GSSAPI_LIBS) $(LIB_SOCKET) $(COMPAT libcrammd5_la_SOURCES = cram.c crammd5_init.c $(common_sources) libcrammd5_la_DEPENDENCIES = $(COMPAT_OBJS) -libcrammd5_la_LIBADD = $(COMPAT_OBJS) +libcrammd5_la_LIBADD = $(LIB_SOCKET) $(COMPAT_OBJS) libdigestmd5_la_SOURCES = digestmd5.c digestmd5_init.c $(common_sources) libdigestmd5_la_DEPENDENCIES = $(COMPAT_OBJS) @@ -99,32 +99,32 @@ libdigestmd5_la_LIBADD = $(LIB_DES) $(LIB_SOCKET) $(COMPAT_OBJS) libscram_la_SOURCES = scram.c scram_init.c $(common_sources) libscram_la_DEPENDENCIES = $(COMPAT_OBJS) -libscram_la_LIBADD = $(SCRAM_LIBS) $(COMPAT_OBJS) +libscram_la_LIBADD = $(SCRAM_LIBS) $(LIB_SOCKET) $(COMPAT_OBJS) liblogin_la_SOURCES = login.c login_init.c $(common_sources) liblogin_la_DEPENDENCIES = $(COMPAT_OBJS) -liblogin_la_LIBADD = $(PLAIN_LIBS) $(COMPAT_OBJS) +liblogin_la_LIBADD = $(PLAIN_LIBS) $(LIB_SOCKET) $(COMPAT_OBJS) libsrp_la_SOURCES = srp.c srp_init.c $(common_sources) libsrp_la_DEPENDENCIES = $(COMPAT_OBJS) -libsrp_la_LIBADD = $(SRP_LIBS) $(COMPAT_OBJS) +libsrp_la_LIBADD = $(SRP_LIBS) $(LIB_SOCKET) $(COMPAT_OBJS) libotp_la_SOURCES = otp.c otp_init.c otp.h $(common_sources) libotp_la_DEPENDENCIES = $(COMPAT_OBJS) -libotp_la_LIBADD = $(OTP_LIBS) $(COMPAT_OBJS) +libotp_la_LIBADD = $(OTP_LIBS) $(LIB_SOCKET) $(COMPAT_OBJS) libntlm_la_SOURCES = ntlm.c ntlm_init.c $(common_sources) libntlm_la_DEPENDENCIES = $(COMPAT_OBJS) -libntlm_la_LIBADD = $(NTLM_LIBS) $(COMPAT_OBJS) +libntlm_la_LIBADD = $(NTLM_LIBS) $(LIB_SOCKET) $(COMPAT_OBJS) libpassdss_la_SOURCES = passdss.c passdss_init.c $(common_sources) libpassdss_la_DEPENDENCIES = $(COMPAT_OBJS) -libpassdss_la_LIBADD = $(PASSDSS_LIBS) $(COMPAT_OBJS) +libpassdss_la_LIBADD = $(PASSDSS_LIBS) $(LIB_SOCKET) $(COMPAT_OBJS) # Auxprop Plugins libsasldb_la_SOURCES = sasldb.c sasldb_init.c $(common_sources) libsasldb_la_DEPENDENCIES = $(COMPAT_OBJS) -libsasldb_la_LIBADD = ../sasldb/libsasldb.la $(SASL_DB_LIB) $(COMPAT_OBJS) +libsasldb_la_LIBADD = ../sasldb/libsasldb.la $(SASL_DB_LIB) $(LIB_SOCKET) $(COMPAT_OBJS) libldapdb_la_SOURCES = ldapdb.c ldapdb_init.c $(common_sources) libldapdb_la_DEPENDENCIES = $(COMPAT_OBJS) From 3d727024eca92b1e9f04bfe321c25dd6846729ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Fri, 20 Nov 2015 17:59:13 +0100 Subject: [PATCH 215/796] mingw32: use windlopen.c not dlopen.c --- configure.ac | 1 + lib/Makefile.am | 10 ++++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 2abcc610..18f3fdda 100644 --- a/configure.ac +++ b/configure.ac @@ -1123,6 +1123,7 @@ AC_ARG_ENABLE(macos-framework, [ --disable-macos-framework disable buildi ;; esac AM_CONDITIONAL(MACOSX, test "$building_for_macosx" = yes) +AM_CONDITIONAL(WINDOWS, test "$host_os" = "mingw32") dnl dmalloc tests AC_MSG_CHECKING(for dmalloc library) diff --git a/lib/Makefile.am b/lib/Makefile.am index 17d155be..85d7b8aa 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -47,15 +47,21 @@ sasl_version = 3:0:0 AM_CPPFLAGS=-DLIBSASL_EXPORTS=1 -I$(top_srcdir)/include -I$(top_srcdir)/plugins -I$(top_builddir)/include -I$(top_srcdir)/sasldb -EXTRA_DIST = windlopen.c staticopen.h NTMakefile +EXTRA_DIST = windlopen.c dlopen.c staticopen.h NTMakefile EXTRA_LIBRARIES = libsasl2.a noinst_LIBRARIES = @SASL_STATIC_LIBS@ libsasl2_a_SOURCES= BUILT_SOURCES = $(SASL_STATIC_SRCS) +if WINDOWS +DLOPEN_C = windlopen.c +else +DLOPEN_C = dlopen.c +endif + common_headers = saslint.h -common_sources = auxprop.c canonusr.c checkpw.c client.c common.c config.c external.c md5.c saslutil.c server.c seterror.c dlopen.c ../plugins/plugin_common.c +common_sources = auxprop.c canonusr.c checkpw.c client.c common.c config.c external.c md5.c saslutil.c server.c seterror.c $(DLOPEN_C) ../plugins/plugin_common.c LTLIBOBJS = @LTLIBOBJS@ LIBOBJS = @LIBOBJS@ From ed8bd7643adf94b916a904b56a8f97a818798d58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Fri, 20 Nov 2015 18:48:20 +0100 Subject: [PATCH 216/796] lib: build an intermediate libobj library So other targets can reference it directly --- lib/Makefile.am | 8 +++++--- plugins/Makefile.am | 10 +--------- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/lib/Makefile.am b/lib/Makefile.am index 85d7b8aa..4e68e327 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -64,15 +64,17 @@ common_headers = saslint.h common_sources = auxprop.c canonusr.c checkpw.c client.c common.c config.c external.c md5.c saslutil.c server.c seterror.c $(DLOPEN_C) ../plugins/plugin_common.c LTLIBOBJS = @LTLIBOBJS@ -LIBOBJS = @LIBOBJS@ LIB_DOOR= @LIB_DOOR@ lib_LTLIBRARIES = libsasl2.la +noinst_LTLIBRARIES = libobj.la + +libobj_la_SOURCES = +libobj_la_LIBADD = $(LTLIBOBJS) libsasl2_la_SOURCES = $(common_sources) $(common_headers) libsasl2_la_LDFLAGS = -version-info $(sasl_version) -no-undefined -libsasl2_la_DEPENDENCIES = $(LTLIBOBJS) -libsasl2_la_LIBADD = $(LTLIBOBJS) $(SASL_DL_LIB) $(LIB_SOCKET) $(LIB_DOOR) +libsasl2_la_LIBADD = libobj.la $(SASL_DL_LIB) $(LIB_SOCKET) $(LIB_DOOR) if MACOSX framedir = /Library/Frameworks/SASL2.framework diff --git a/plugins/Makefile.am b/plugins/Makefile.am index 4c54bf84..452596e9 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -52,7 +52,7 @@ plugin_version = 3:0:0 AM_CPPFLAGS=-I$(top_srcdir)/include -I$(top_srcdir)/lib -I$(top_srcdir)/sasldb -I$(top_builddir)/include AM_LDFLAGS = -module -export-dynamic -rpath $(plugindir) -version-info $(plugin_version) -no-undefined -COMPAT_OBJS = @LTGETADDRINFOOBJS@ @LTGETNAMEINFOOBJS@ @LTSNPRINTFOBJS@ +COMPAT_OBJS = $(top_builddir)/lib/libobj.la EXTRA_DIST = makeinit.sh NTMakefile noinst_SCRIPTS = makeinit.sh @@ -148,11 +148,3 @@ CLEANFILES=$(init_src) ${init_src}: $(srcdir)/makeinit.sh $(SHELL) $(srcdir)/makeinit.sh - -# Compatibility function build rules (they build in lib/) -$(COMPAT_OBJS): - rm -f $(COMPAT_OBJS) - cd ../lib; $(MAKE) $(COMPAT_OBJS) - for file in $(COMPAT_OBJS); do ln -s ../lib/$$file .; done - - From ec87191343604e4a316a389d1f64a0f5809582a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Fri, 20 Nov 2015 19:51:39 +0100 Subject: [PATCH 217/796] configure: explicit return type --- configure.ac | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 18f3fdda..07dcad55 100644 --- a/configure.ac +++ b/configure.ac @@ -242,8 +242,8 @@ AC_CHECK_PROGS(NM, nm) AC_MSG_CHECKING(for underscore before symbols) AC_CACHE_VAL(sasl_cv_uscore,[ - echo "main(){int i=1;} - foo(){int i=6;}" > conftest.c + echo "void main(){int i=1;} + void foo(){int i=6;}" > conftest.c ${CC} -o a.out conftest.c > /dev/null if (${NM} a.out | grep _foo) > /dev/null; then sasl_cv_uscore=yes @@ -261,8 +261,8 @@ if test $sasl_cv_uscore = yes; then AC_CACHE_VAL(sasl_cv_dlsym_adds_uscore,AC_TRY_RUN( [ #include #include -foo() { int i=0;} -main() { void *self, *ptr1, *ptr2; self=dlopen(NULL,RTLD_LAZY); +void foo() { int i=0;} +void main() { void *self, *ptr1, *ptr2; self=dlopen(NULL,RTLD_LAZY); if(self) { ptr1=dlsym(self,"foo"); ptr2=dlsym(self,"_foo"); if(ptr1 && !ptr2) exit(0); } exit(1); } ], [sasl_cv_dlsym_adds_uscore=yes], sasl_cv_dlsym_adds_uscore=no From 0ef58694c7c6459f6a5f4255d857d20405cc75ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Fri, 20 Nov 2015 20:16:52 +0100 Subject: [PATCH 218/796] configure: add a userful summary --- configure.ac | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 07dcad55..0e43a715 100644 --- a/configure.ac +++ b/configure.ac @@ -1534,4 +1534,12 @@ java/javax/security/auth/callback/Makefile pwcheck/Makefile man/Makefile) -echo Configuration Complete. Type \'make\' to build. +AC_MSG_NOTICE([ + +cyrus-sasl - $VERSION + +• Prefix: $prefix +• Plugins: $SASL_MECHS + +Now type 'make' to build $PACKAGE +]) From 4a64c00dba4d35cadc71242f9f81336f46f72009 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Fri, 4 Dec 2015 17:59:26 +0100 Subject: [PATCH 219/796] GSSAPI: Use per-connection mutex where possible Original patch from Alexander Bokovoy --- plugins/gssapi.c | 225 ++++++++++++++++++++++++++--------------------- 1 file changed, 126 insertions(+), 99 deletions(-) diff --git a/plugins/gssapi.c b/plugins/gssapi.c index 60cc38c5..50e1217b 100644 --- a/plugins/gssapi.c +++ b/plugins/gssapi.c @@ -126,20 +126,29 @@ extern gss_OID gss_nt_service_name; */ #ifdef GSS_USE_MUTEXES -#define GSS_LOCK_MUTEX(utils) \ - if(((sasl_utils_t *)(utils))->mutex_lock(gss_mutex) != 0) { \ +#define GSS_LOCK_MUTEX_EXT(utils, mutex) \ + if(((sasl_utils_t *)(utils))->mutex_lock(mutex) != 0) { \ return SASL_FAIL; \ } -#define GSS_UNLOCK_MUTEX(utils) \ - if(((sasl_utils_t *)(utils))->mutex_unlock(gss_mutex) != 0) { \ +#define GSS_UNLOCK_MUTEX_EXT(utils, mutex) \ + if(((sasl_utils_t *)(utils))->mutex_unlock(mutex) != 0) { \ return SASL_FAIL; \ } +#define GSS_LOCK_MUTEX(utils) GSS_LOCK_MUTEX_EXT(utils, gss_mutex) +#define GSS_UNLOCK_MUTEX(utils) GSS_UNLOCK_MUTEX_EXT(utils, gss_mutex) + +#define GSS_LOCK_MUTEX_CTX(utils, ctx) GSS_LOCK_MUTEX_EXT(utils, (ctx)->ctx_mutex) +#define GSS_UNLOCK_MUTEX_CTX(utils, ctx) GSS_UNLOCK_MUTEX_EXT(utils, (ctx)->ctx_mutex) + + static void *gss_mutex = NULL; #else #define GSS_LOCK_MUTEX(utils) #define GSS_UNLOCK_MUTEX(utils) +#define GSS_LOCK_MUTEX_CTX(utils, ctx) +#define GSS_UNLOCK_MUTEX_CTX(utils, ctx) #endif typedef struct context { @@ -176,6 +185,7 @@ typedef struct context { char *authid; /* hold the authid between steps - server */ const char *user; /* hold the userid between steps - client */ + void *ctx_mutex; /* A per-context mutex */ } context_t; enum { @@ -355,7 +365,7 @@ sasl_gss_encode(void *context, const struct iovec *invec, unsigned numiov, output_token->value = NULL; output_token->length = 0; - GSS_LOCK_MUTEX(text->utils); + GSS_LOCK_MUTEX_CTX(text->utils, text); maj_stat = gss_wrap (&min_stat, text->gss_ctx, privacy, @@ -363,14 +373,14 @@ sasl_gss_encode(void *context, const struct iovec *invec, unsigned numiov, input_token, NULL, output_token); - GSS_UNLOCK_MUTEX(text->utils); + GSS_UNLOCK_MUTEX_CTX(text->utils, text); if (GSS_ERROR(maj_stat)) { sasl_gss_seterror(text->utils, maj_stat, min_stat); if (output_token->value) { - GSS_LOCK_MUTEX(text->utils); + GSS_LOCK_MUTEX_CTX(text->utils, text); gss_release_buffer(&min_stat, output_token); - GSS_UNLOCK_MUTEX(text->utils); + GSS_UNLOCK_MUTEX_CTX(text->utils, text); } return SASL_FAIL; } @@ -384,9 +394,9 @@ sasl_gss_encode(void *context, const struct iovec *invec, unsigned numiov, output_token->length + 4); if (ret != SASL_OK) { - GSS_LOCK_MUTEX(text->utils); + GSS_LOCK_MUTEX_CTX(text->utils, text); gss_release_buffer(&min_stat, output_token); - GSS_UNLOCK_MUTEX(text->utils); + GSS_UNLOCK_MUTEX_CTX(text->utils, text); return ret; } @@ -407,9 +417,9 @@ sasl_gss_encode(void *context, const struct iovec *invec, unsigned numiov, *output = text->encode_buf; if (output_token->value) { - GSS_LOCK_MUTEX(text->utils); + GSS_LOCK_MUTEX_CTX(text->utils, text); gss_release_buffer(&min_stat, output_token); - GSS_UNLOCK_MUTEX(text->utils); + GSS_UNLOCK_MUTEX_CTX(text->utils, text); } return SASL_OK; @@ -455,21 +465,21 @@ gssapi_decode_packet(void *context, output_token->value = NULL; output_token->length = 0; - GSS_LOCK_MUTEX(text->utils); + GSS_LOCK_MUTEX_CTX(text->utils, text); maj_stat = gss_unwrap (&min_stat, text->gss_ctx, input_token, output_token, NULL, NULL); - GSS_UNLOCK_MUTEX(text->utils); + GSS_UNLOCK_MUTEX_CTX(text->utils, text); if (GSS_ERROR(maj_stat)) { sasl_gss_seterror(text->utils,maj_stat,min_stat); if (output_token->value) { - GSS_LOCK_MUTEX(text->utils); + GSS_LOCK_MUTEX_CTX(text->utils, text); gss_release_buffer(&min_stat, output_token); - GSS_UNLOCK_MUTEX(text->utils); + GSS_UNLOCK_MUTEX_CTX(text->utils, text); } return SASL_FAIL; } @@ -484,17 +494,17 @@ gssapi_decode_packet(void *context, &text->decode_once_buf_len, *outputlen); if (result != SASL_OK) { - GSS_LOCK_MUTEX(text->utils); + GSS_LOCK_MUTEX_CTX(text->utils, text); gss_release_buffer(&min_stat, output_token); - GSS_UNLOCK_MUTEX(text->utils); + GSS_UNLOCK_MUTEX_CTX(text->utils, text); return result; } *output = text->decode_once_buf; memcpy(*output, output_token->value, *outputlen); } - GSS_LOCK_MUTEX(text->utils); + GSS_LOCK_MUTEX_CTX(text->utils, text); gss_release_buffer(&min_stat, output_token); - GSS_UNLOCK_MUTEX(text->utils); + GSS_UNLOCK_MUTEX_CTX(text->utils, text); } return SASL_OK; @@ -525,7 +535,14 @@ static context_t *sasl_gss_new_context(const sasl_utils_t *utils) memset(ret,0,sizeof(context_t)); ret->utils = utils; - +#ifdef GSS_USE_MUTEXES + ret->ctx_mutex = utils->mutex_alloc(); + if (!ret->ctx_mutex) { + utils->free(ret); + return NULL; + } +#endif + return ret; } @@ -535,7 +552,11 @@ static int sasl_gss_free_context_contents(context_t *text) if (!text) return SASL_OK; - GSS_LOCK_MUTEX(text->utils); +#ifdef GSS_USE_MUTEXES + if (text->ctx_mutex) { + GSS_LOCK_MUTEX_CTX(text->utils, text); + } +#endif if (text->gss_ctx != GSS_C_NO_CONTEXT) { maj_stat = gss_delete_sec_context(&min_stat,&text->gss_ctx, @@ -563,8 +584,6 @@ static int sasl_gss_free_context_contents(context_t *text) text->client_creds = GSS_C_NO_CREDENTIAL; } - GSS_UNLOCK_MUTEX(text->utils); - if (text->out_buf) { text->utils->free(text->out_buf); text->out_buf = NULL; @@ -598,6 +617,14 @@ static int sasl_gss_free_context_contents(context_t *text) text->authid = NULL; } +#ifdef GSS_USE_MUTEXES + if (text->ctx_mutex) { + GSS_UNLOCK_MUTEX_CTX(text->utils, text); + text->utils->mutex_free(text->ctx_mutex); + text->ctx_mutex = NULL; + } +#endif + return SASL_OK; } @@ -692,12 +719,12 @@ gssapi_server_mech_authneg(context_t *text, } sprintf(name_token.value,"%s@%s", params->service, params->serverFQDN); - GSS_LOCK_MUTEX(params->utils); + GSS_LOCK_MUTEX_CTX(params->utils, text); maj_stat = gss_import_name (&min_stat, &name_token, GSS_C_NT_HOSTBASED_SERVICE, &text->server_name); - GSS_UNLOCK_MUTEX(params->utils); + GSS_UNLOCK_MUTEX_CTX(params->utils, text); params->utils->free(name_token.value); name_token.value = NULL; @@ -709,15 +736,15 @@ gssapi_server_mech_authneg(context_t *text, } if ( text->server_creds != GSS_C_NO_CREDENTIAL) { - GSS_LOCK_MUTEX(params->utils); + GSS_LOCK_MUTEX_CTX(params->utils, text); maj_stat = gss_release_cred(&min_stat, &text->server_creds); - GSS_UNLOCK_MUTEX(params->utils); + GSS_UNLOCK_MUTEX_CTX(params->utils, text); text->server_creds = GSS_C_NO_CREDENTIAL; } /* If caller didn't provide creds already */ if ( server_creds == GSS_C_NO_CREDENTIAL) { - GSS_LOCK_MUTEX(params->utils); + GSS_LOCK_MUTEX_CTX(params->utils, text); maj_stat = gss_acquire_cred(&min_stat, text->server_name, GSS_C_INDEFINITE, @@ -726,7 +753,7 @@ gssapi_server_mech_authneg(context_t *text, &text->server_creds, NULL, NULL); - GSS_UNLOCK_MUTEX(params->utils); + GSS_UNLOCK_MUTEX_CTX(params->utils, text); if (GSS_ERROR(maj_stat)) { sasl_gss_seterror(text->utils, maj_stat, min_stat); @@ -743,7 +770,7 @@ gssapi_server_mech_authneg(context_t *text, } - GSS_LOCK_MUTEX(params->utils); + GSS_LOCK_MUTEX_CTX(params->utils, text); maj_stat = gss_accept_sec_context(&min_stat, &(text->gss_ctx), @@ -756,15 +783,15 @@ gssapi_server_mech_authneg(context_t *text, &out_flags, NULL, /* context validity period */ &(text->client_creds)); - GSS_UNLOCK_MUTEX(params->utils); + GSS_UNLOCK_MUTEX_CTX(params->utils, text); if (GSS_ERROR(maj_stat)) { sasl_gss_log(text->utils, maj_stat, min_stat); text->utils->seterror(text->utils->conn, SASL_NOLOG, "GSSAPI Failure: gss_accept_sec_context"); if (output_token->value) { - GSS_LOCK_MUTEX(params->utils); + GSS_LOCK_MUTEX_CTX(params->utils, text); gss_release_buffer(&min_stat, output_token); - GSS_UNLOCK_MUTEX(params->utils); + GSS_UNLOCK_MUTEX_CTX(params->utils, text); } sasl_gss_free_context_contents(text); return SASL_BADAUTH; @@ -778,18 +805,18 @@ gssapi_server_mech_authneg(context_t *text, ret = _plug_buf_alloc(text->utils, &(text->out_buf), &(text->out_buf_len), *serveroutlen); if(ret != SASL_OK) { - GSS_LOCK_MUTEX(params->utils); + GSS_LOCK_MUTEX_CTX(params->utils, text); gss_release_buffer(&min_stat, output_token); - GSS_UNLOCK_MUTEX(params->utils); + GSS_UNLOCK_MUTEX_CTX(params->utils, text); return ret; } memcpy(text->out_buf, output_token->value, *serveroutlen); *serverout = text->out_buf; } - GSS_LOCK_MUTEX(params->utils); + GSS_LOCK_MUTEX_CTX(params->utils, text); gss_release_buffer(&min_stat, output_token); - GSS_UNLOCK_MUTEX(params->utils); + GSS_UNLOCK_MUTEX_CTX(params->utils, text); } else { /* No output token, send an empty string */ *serverout = GSSAPI_BLANK_STRING; @@ -832,12 +859,12 @@ gssapi_server_mech_authneg(context_t *text, /* continue with authentication */ } - GSS_LOCK_MUTEX(params->utils); + GSS_LOCK_MUTEX_CTX(params->utils, text); maj_stat = gss_canonicalize_name(&min_stat, text->client_name, mech_type, &client_name_MN); - GSS_UNLOCK_MUTEX(params->utils); + GSS_UNLOCK_MUTEX_CTX(params->utils, text); if (GSS_ERROR(maj_stat)) { SETERROR(text->utils, "GSSAPI Failure: gss_canonicalize_name"); @@ -848,12 +875,12 @@ gssapi_server_mech_authneg(context_t *text, name_token.value = NULL; name_without_realm.value = NULL; - GSS_LOCK_MUTEX(params->utils); + GSS_LOCK_MUTEX_CTX(params->utils, text); maj_stat = gss_display_name (&min_stat, client_name_MN, &name_token, NULL); - GSS_UNLOCK_MUTEX(params->utils); + GSS_UNLOCK_MUTEX_CTX(params->utils, text); if (GSS_ERROR(maj_stat)) { SETERROR(text->utils, "GSSAPI Failure: gss_display_name"); @@ -883,7 +910,7 @@ gssapi_server_mech_authneg(context_t *text, name_without_realm.length = strlen( (char *) name_without_realm.value ); - GSS_LOCK_MUTEX(params->utils); + GSS_LOCK_MUTEX_CTX(params->utils, text); maj_stat = gss_import_name (&min_stat, &name_without_realm, /* Solaris 8/9 gss_import_name doesn't accept GSS_C_NULL_OID here, @@ -894,7 +921,7 @@ gssapi_server_mech_authneg(context_t *text, GSS_C_NULL_OID, #endif &without); - GSS_UNLOCK_MUTEX(params->utils); + GSS_UNLOCK_MUTEX_CTX(params->utils, text); if (GSS_ERROR(maj_stat)) { SETERROR(text->utils, "GSSAPI Failure: gss_import_name"); @@ -903,12 +930,12 @@ gssapi_server_mech_authneg(context_t *text, goto cleanup; } - GSS_LOCK_MUTEX(params->utils); + GSS_LOCK_MUTEX_CTX(params->utils, text); maj_stat = gss_compare_name(&min_stat, client_name_MN, without, &equal); - GSS_UNLOCK_MUTEX(params->utils); + GSS_UNLOCK_MUTEX_CTX(params->utils, text); if (GSS_ERROR(maj_stat)) { SETERROR(text->utils, "GSSAPI Failure: gss_compare_name"); @@ -1059,7 +1086,7 @@ gssapi_server_mech_ssfcap(context_t *text, real_input_token.value = (void *)sasldata; real_input_token.length = 4; - GSS_LOCK_MUTEX(params->utils); + GSS_LOCK_MUTEX_CTX(params->utils, text); maj_stat = gss_wrap(&min_stat, text->gss_ctx, 0, /* Just integrity checking here */ @@ -1067,14 +1094,14 @@ gssapi_server_mech_ssfcap(context_t *text, input_token, NULL, output_token); - GSS_UNLOCK_MUTEX(params->utils); + GSS_UNLOCK_MUTEX_CTX(params->utils, text); if (GSS_ERROR(maj_stat)) { sasl_gss_seterror(text->utils, maj_stat, min_stat); if (output_token->value) { - GSS_LOCK_MUTEX(params->utils); + GSS_LOCK_MUTEX_CTX(params->utils, text); gss_release_buffer(&min_stat, output_token); - GSS_UNLOCK_MUTEX(params->utils); + GSS_UNLOCK_MUTEX_CTX(params->utils, text); } sasl_gss_free_context_contents(text); return SASL_FAIL; @@ -1088,18 +1115,18 @@ gssapi_server_mech_ssfcap(context_t *text, ret = _plug_buf_alloc(text->utils, &(text->out_buf), &(text->out_buf_len), *serveroutlen); if(ret != SASL_OK) { - GSS_LOCK_MUTEX(params->utils); + GSS_LOCK_MUTEX_CTX(params->utils, text); gss_release_buffer(&min_stat, output_token); - GSS_UNLOCK_MUTEX(params->utils); + GSS_UNLOCK_MUTEX_CTX(params->utils, text); return ret; } memcpy(text->out_buf, output_token->value, *serveroutlen); *serverout = text->out_buf; } - GSS_LOCK_MUTEX(params->utils); + GSS_LOCK_MUTEX_CTX(params->utils, text); gss_release_buffer(&min_stat, output_token); - GSS_UNLOCK_MUTEX(params->utils); + GSS_UNLOCK_MUTEX_CTX(params->utils, text); } /* Wait for ssf request and authid */ @@ -1130,14 +1157,14 @@ gssapi_server_mech_ssfreq(context_t *text, real_input_token.value = (void *)clientin; real_input_token.length = clientinlen; - GSS_LOCK_MUTEX(params->utils); + GSS_LOCK_MUTEX_CTX(params->utils, text); maj_stat = gss_unwrap(&min_stat, text->gss_ctx, input_token, output_token, NULL, NULL); - GSS_UNLOCK_MUTEX(params->utils); + GSS_UNLOCK_MUTEX_CTX(params->utils, text); if (GSS_ERROR(maj_stat)) { sasl_gss_seterror(text->utils, maj_stat, min_stat); @@ -1148,9 +1175,9 @@ gssapi_server_mech_ssfreq(context_t *text, if (output_token->length < 4) { SETERROR(text->utils, "token too short"); - GSS_LOCK_MUTEX(params->utils); + GSS_LOCK_MUTEX_CTX(params->utils, text); gss_release_buffer(&min_stat, output_token); - GSS_UNLOCK_MUTEX(params->utils); + GSS_UNLOCK_MUTEX_CTX(params->utils, text); sasl_gss_free_context_contents(text); return SASL_FAIL; } @@ -1181,9 +1208,9 @@ gssapi_server_mech_ssfreq(context_t *text, /* Mark that we attempted negotiation */ oparams->mech_ssf = 2; if (output_token->value) { - GSS_LOCK_MUTEX(params->utils); + GSS_LOCK_MUTEX_CTX(params->utils, text); gss_release_buffer(&min_stat, output_token); - GSS_UNLOCK_MUTEX(params->utils); + GSS_UNLOCK_MUTEX_CTX(params->utils, text); } sasl_gss_free_context_contents(text); return SASL_FAIL; @@ -1227,9 +1254,9 @@ gssapi_server_mech_ssfreq(context_t *text, } } - GSS_LOCK_MUTEX(params->utils); + GSS_LOCK_MUTEX_CTX(params->utils, text); gss_release_buffer(&min_stat, output_token); - GSS_UNLOCK_MUTEX(params->utils); + GSS_UNLOCK_MUTEX_CTX(params->utils, text); text->state = SASL_GSSAPI_STATE_AUTHENTICATED; @@ -1553,12 +1580,12 @@ static int gssapi_client_mech_step(void *conn_context, sprintf(name_token.value,"%s@%s", params->service, params->serverFQDN); - GSS_LOCK_MUTEX(params->utils); + GSS_LOCK_MUTEX_CTX(params->utils, text); maj_stat = gss_import_name (&min_stat, &name_token, GSS_C_NT_HOSTBASED_SERVICE, &text->server_name); - GSS_UNLOCK_MUTEX(params->utils); + GSS_UNLOCK_MUTEX_CTX(params->utils, text); params->utils->free(name_token.value); name_token.value = NULL; @@ -1582,9 +1609,9 @@ static int gssapi_client_mech_step(void *conn_context, * and no input from the server. However, thanks to Imap, * which discards our first output, this happens all the time. * Throw away the context and try again. */ - GSS_LOCK_MUTEX(params->utils); + GSS_LOCK_MUTEX_CTX(params->utils, text); maj_stat = gss_delete_sec_context (&min_stat,&text->gss_ctx,GSS_C_NO_BUFFER); - GSS_UNLOCK_MUTEX(params->utils); + GSS_UNLOCK_MUTEX_CTX(params->utils, text); text->gss_ctx = GSS_C_NO_CONTEXT; } @@ -1606,7 +1633,7 @@ static int gssapi_client_mech_step(void *conn_context, req_flags = req_flags | GSS_C_DELEG_FLAG; } - GSS_LOCK_MUTEX(params->utils); + GSS_LOCK_MUTEX_CTX(params->utils, text); maj_stat = gss_init_sec_context(&min_stat, client_creds, /* GSS_C_NO_CREDENTIAL */ &text->gss_ctx, @@ -1620,14 +1647,14 @@ static int gssapi_client_mech_step(void *conn_context, output_token, &out_req_flags, NULL); - GSS_UNLOCK_MUTEX(params->utils); + GSS_UNLOCK_MUTEX_CTX(params->utils, text); if (GSS_ERROR(maj_stat)) { sasl_gss_seterror(text->utils, maj_stat, min_stat); if (output_token->value) { - GSS_LOCK_MUTEX(params->utils); + GSS_LOCK_MUTEX_CTX(params->utils, text); gss_release_buffer(&min_stat, output_token); - GSS_UNLOCK_MUTEX(params->utils); + GSS_UNLOCK_MUTEX_CTX(params->utils, text); } sasl_gss_free_context_contents(text); return SASL_FAIL; @@ -1658,22 +1685,22 @@ static int gssapi_client_mech_step(void *conn_context, ret = _plug_buf_alloc(text->utils, &(text->out_buf), &(text->out_buf_len), *clientoutlen); if(ret != SASL_OK) { - GSS_LOCK_MUTEX(params->utils); + GSS_LOCK_MUTEX_CTX(params->utils, text); gss_release_buffer(&min_stat, output_token); - GSS_UNLOCK_MUTEX(params->utils); + GSS_UNLOCK_MUTEX_CTX(params->utils, text); return ret; } memcpy(text->out_buf, output_token->value, *clientoutlen); *clientout = text->out_buf; } - GSS_LOCK_MUTEX(params->utils); + GSS_LOCK_MUTEX_CTX(params->utils, text); gss_release_buffer(&min_stat, output_token); - GSS_UNLOCK_MUTEX(params->utils); + GSS_UNLOCK_MUTEX_CTX(params->utils, text); } if (maj_stat == GSS_S_COMPLETE) { - GSS_LOCK_MUTEX(params->utils); + GSS_LOCK_MUTEX_CTX(params->utils, text); maj_stat = gss_inquire_context(&min_stat, text->gss_ctx, &text->client_name, @@ -1684,7 +1711,7 @@ static int gssapi_client_mech_step(void *conn_context, NULL, /* flags */ NULL, /* local init */ NULL); /* open */ - GSS_UNLOCK_MUTEX(params->utils); + GSS_UNLOCK_MUTEX_CTX(params->utils, text); if (GSS_ERROR(maj_stat)) { sasl_gss_seterror(text->utils, maj_stat, min_stat); @@ -1693,18 +1720,18 @@ static int gssapi_client_mech_step(void *conn_context, } name_token.length = 0; - GSS_LOCK_MUTEX(params->utils); + GSS_LOCK_MUTEX_CTX(params->utils, text); maj_stat = gss_display_name(&min_stat, text->client_name, &name_token, NULL); - GSS_UNLOCK_MUTEX(params->utils); + GSS_UNLOCK_MUTEX_CTX(params->utils, text); if (GSS_ERROR(maj_stat)) { if (name_token.value) { - GSS_LOCK_MUTEX(params->utils); + GSS_LOCK_MUTEX_CTX(params->utils, text); gss_release_buffer(&min_stat, &name_token); - GSS_UNLOCK_MUTEX(params->utils); + GSS_UNLOCK_MUTEX_CTX(params->utils, text); } SETERROR(text->utils, "GSSAPI Failure"); sasl_gss_free_context_contents(text); @@ -1725,9 +1752,9 @@ static int gssapi_client_mech_step(void *conn_context, SASL_CU_AUTHID | SASL_CU_AUTHZID, oparams); } - GSS_LOCK_MUTEX(params->utils); + GSS_LOCK_MUTEX_CTX(params->utils, text); gss_release_buffer(&min_stat, &name_token); - GSS_UNLOCK_MUTEX(params->utils); + GSS_UNLOCK_MUTEX_CTX(params->utils, text); if (ret != SASL_OK) return ret; @@ -1753,32 +1780,32 @@ static int gssapi_client_mech_step(void *conn_context, real_input_token.value = (void *) serverin; real_input_token.length = serverinlen; - GSS_LOCK_MUTEX(params->utils); + GSS_LOCK_MUTEX_CTX(params->utils, text); maj_stat = gss_unwrap(&min_stat, text->gss_ctx, input_token, output_token, NULL, NULL); - GSS_UNLOCK_MUTEX(params->utils); + GSS_UNLOCK_MUTEX_CTX(params->utils, text); if (GSS_ERROR(maj_stat)) { sasl_gss_seterror(text->utils, maj_stat, min_stat); - sasl_gss_free_context_contents(text); if (output_token->value) { - GSS_LOCK_MUTEX(params->utils); + GSS_LOCK_MUTEX_CTX(params->utils, text); gss_release_buffer(&min_stat, output_token); - GSS_UNLOCK_MUTEX(params->utils); + GSS_UNLOCK_MUTEX_CTX(params->utils, text); } + sasl_gss_free_context_contents(text); return SASL_FAIL; } if (output_token->length != 4) { SETERROR(text->utils, (output_token->length < 4) ? "token too short" : "token too long"); - GSS_LOCK_MUTEX(params->utils); + GSS_LOCK_MUTEX_CTX(params->utils, text); gss_release_buffer(&min_stat, output_token); - GSS_UNLOCK_MUTEX(params->utils); + GSS_UNLOCK_MUTEX_CTX(params->utils, text); sasl_gss_free_context_contents(text); return SASL_FAIL; } @@ -1879,9 +1906,9 @@ static int gssapi_client_mech_step(void *conn_context, } } - GSS_LOCK_MUTEX(params->utils); + GSS_LOCK_MUTEX_CTX(params->utils, text); gss_release_buffer(&min_stat, output_token); - GSS_UNLOCK_MUTEX(params->utils); + GSS_UNLOCK_MUTEX_CTX(params->utils, text); /* oparams->user is always set, due to canon_user requirements. * Make sure the client actually requested it though, by checking @@ -1927,7 +1954,7 @@ static int gssapi_client_mech_step(void *conn_context, } ((unsigned char *)input_token->value)[0] = mychoice; - GSS_LOCK_MUTEX(params->utils); + GSS_LOCK_MUTEX_CTX(params->utils, text); maj_stat = gss_wrap (&min_stat, text->gss_ctx, 0, /* Just integrity checking here */ @@ -1935,7 +1962,7 @@ static int gssapi_client_mech_step(void *conn_context, input_token, NULL, output_token); - GSS_UNLOCK_MUTEX(params->utils); + GSS_UNLOCK_MUTEX_CTX(params->utils, text); params->utils->free(input_token->value); input_token->value = NULL; @@ -1943,9 +1970,9 @@ static int gssapi_client_mech_step(void *conn_context, if (GSS_ERROR(maj_stat)) { sasl_gss_seterror(text->utils, maj_stat, min_stat); if (output_token->value) { - GSS_LOCK_MUTEX(params->utils); + GSS_LOCK_MUTEX_CTX(params->utils, text); gss_release_buffer(&min_stat, output_token); - GSS_UNLOCK_MUTEX(params->utils); + GSS_UNLOCK_MUTEX_CTX(params->utils, text); } sasl_gss_free_context_contents(text); return SASL_FAIL; @@ -1961,18 +1988,18 @@ static int gssapi_client_mech_step(void *conn_context, &(text->out_buf_len), *clientoutlen); if (ret != SASL_OK) { - GSS_LOCK_MUTEX(params->utils); + GSS_LOCK_MUTEX_CTX(params->utils, text); gss_release_buffer(&min_stat, output_token); - GSS_UNLOCK_MUTEX(params->utils); + GSS_UNLOCK_MUTEX_CTX(params->utils, text); return ret; } memcpy(text->out_buf, output_token->value, *clientoutlen); *clientout = text->out_buf; } - GSS_LOCK_MUTEX(params->utils); + GSS_LOCK_MUTEX_CTX(params->utils, text); gss_release_buffer(&min_stat, output_token); - GSS_UNLOCK_MUTEX(params->utils); + GSS_UNLOCK_MUTEX_CTX(params->utils, text); } From d66db428216f94c9c57d3693a5948226f3d37038 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Fri, 20 Nov 2015 11:28:58 +0100 Subject: [PATCH 220/796] Fix build warnings --- lib/server.c | 2 +- plugins/gssapi.c | 3 ++- plugins/ldapdb.c | 1 + plugins/plugin_common.c | 2 +- saslauthd/auth_httpform.c | 2 +- saslauthd/auth_shadow.c | 4 ++++ 6 files changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/server.c b/lib/server.c index 490b6521..51309d6d 100644 --- a/lib/server.c +++ b/lib/server.c @@ -650,7 +650,7 @@ static int load_config(const sasl_callback_t *verifyfile_cb) goto done; } - snprintf(config_filename, len, "%.*s%c%s.conf", path_len, path_to_config, + snprintf(config_filename, len, "%.*s%c%s.conf", (int)path_len, path_to_config, HIER_DELIMITER, global_callbacks.appname); /* Ask the application if it's safe to use this file */ diff --git a/plugins/gssapi.c b/plugins/gssapi.c index 50e1217b..87a2da2d 100644 --- a/plugins/gssapi.c +++ b/plugins/gssapi.c @@ -212,7 +212,8 @@ sasl_gss_seterror_(const sasl_utils_t *utils, OM_uint32 maj, OM_uint32 min, OM_uint32 msg_ctx; int ret; char *out = NULL; - size_t len, curlen = 0; + size_t len; + unsigned curlen = 0; const char prefix[] = "GSSAPI Error: "; if (!utils) return SASL_OK; diff --git a/plugins/ldapdb.c b/plugins/ldapdb.c index ddead7f3..20162102 100644 --- a/plugins/ldapdb.c +++ b/plugins/ldapdb.c @@ -22,6 +22,7 @@ #include "plugin_common.h" +#define LDAP_DEPRECATED 1 #include static char ldapdb[] = "ldapdb"; diff --git a/plugins/plugin_common.c b/plugins/plugin_common.c index 1d633eea..f2b26bdf 100644 --- a/plugins/plugin_common.c +++ b/plugins/plugin_common.c @@ -94,7 +94,7 @@ static void sockaddr_unmapped( if (!IN6_IS_ADDR_V4MAPPED((&sin6->sin6_addr))) return; sin4 = (struct sockaddr_in *)sa; - addr = *(uint32_t *)&sin6->sin6_addr.s6_addr[12]; + addr = *(uint32_t *)&sin6->sin6_addr.s6_addr32[3]; port = sin6->sin6_port; memset(sin4, 0, sizeof(struct sockaddr_in)); sin4->sin_addr.s_addr = addr; diff --git a/saslauthd/auth_httpform.c b/saslauthd/auth_httpform.c index b8e555ab..045a8b55 100644 --- a/saslauthd/auth_httpform.c +++ b/saslauthd/auth_httpform.c @@ -577,7 +577,7 @@ auth_httpform ( "Content-Type: application/x-www-form-urlencoded" CRLF "Content-Length: %d" TWO_CRLF "%s", - r_uri, r_host, r_port, strlen(req), req); + r_uri, r_host, r_port, (int)strlen(req), req); if (flags & VERBOSE) { syslog(LOG_DEBUG, "auth_httpform: sending %s %s %s", diff --git a/saslauthd/auth_shadow.c b/saslauthd/auth_shadow.c index 9bb0187a..b37af02f 100644 --- a/saslauthd/auth_shadow.c +++ b/saslauthd/auth_shadow.c @@ -72,6 +72,10 @@ # include # endif /* ! HAVE_GETUSERPW */ +# ifdef HAVE_CRYPT_H +# include +# endif + # include "auth_shadow.h" # include "globals.h" /* END PUBLIC DEPENDENCIES */ From f134d168c0ac761ce2403591bf0a1bc4a0160897 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Fri, 20 Nov 2015 12:29:38 +0100 Subject: [PATCH 221/796] release the GSSAPI server credential handle immediately after the GSSAPI security context is established --- plugins/gssapi.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/plugins/gssapi.c b/plugins/gssapi.c index 87a2da2d..e5ffdaff 100644 --- a/plugins/gssapi.c +++ b/plugins/gssapi.c @@ -972,6 +972,12 @@ gssapi_server_mech_authneg(context_t *text, ret = SASL_CONTINUE; } + /* Release server creds which are no longer needed */ + if ( text->server_creds != GSS_C_NO_CREDENTIAL) { + maj_stat = gss_release_cred(&min_stat, &text->server_creds); + text->server_creds = GSS_C_NO_CREDENTIAL; + } + cleanup: if (text->server_creds != GSS_C_NO_CREDENTIAL) { GSS_LOCK_MUTEX(params->utils); From 2f740223fa1820dd71e6ab0e50d4964760789209 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Fri, 20 Nov 2015 12:41:07 +0100 Subject: [PATCH 222/796] missing size_t declaration (stddef.h empty on Linux) --- include/sasl.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/sasl.h b/include/sasl.h index 82f7a171..54afd9ca 100755 --- a/include/sasl.h +++ b/include/sasl.h @@ -226,6 +226,8 @@ extern "C" { * they must be called before all other SASL functions: */ +#include + /* memory allocation functions which may optionally be replaced: */ typedef void *sasl_malloc_t(size_t); From 5dc6ef971eb07b77dfe8c9c19c7a4844cf3f1de8 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Fri, 20 Nov 2015 12:47:19 +0100 Subject: [PATCH 223/796] gsskrb5_register_acceptor_identity macro Reported as https://bugzilla.redhat.com/show_bug.cgi?id=976538 --- cmulocal/sasl2.m4 | 12 ++++++++++++ plugins/gssapi.c | 2 ++ 2 files changed, 14 insertions(+) diff --git a/cmulocal/sasl2.m4 b/cmulocal/sasl2.m4 index 795d347b..dd0ec69a 100644 --- a/cmulocal/sasl2.m4 +++ b/cmulocal/sasl2.m4 @@ -266,6 +266,18 @@ if test "$gssapi" != no; then cmu_save_LIBS="$LIBS" LIBS="$LIBS $GSSAPIBASE_LIBS" AC_CHECK_FUNCS(gsskrb5_register_acceptor_identity) + if test "$ac_cv_func_gsskrb5_register_acceptor_identity" = no ; then + AC_CHECK_HEADERS(gssapi/gssapi_krb5.h) + if test "$ac_cv_header_gssapi_gssapi_krb5_h" = "yes"; then + AC_CHECK_DECL(gsskrb5_register_acceptor_identity, + [AC_DEFINE(HAVE_GSSKRB5_REGISTER_ACCEPTOR_IDENTITY,1, + [Define if your GSSAPI implementation defines gsskrb5_register_acceptor_identity])],, + [ + AC_INCLUDES_DEFAULT + #include + ]) + fi + fi AC_CHECK_FUNCS(gss_decapsulate_token) AC_CHECK_FUNCS(gss_encapsulate_token) AC_CHECK_FUNCS(gss_oid_equal) diff --git a/plugins/gssapi.c b/plugins/gssapi.c index e5ffdaff..c0240c81 100644 --- a/plugins/gssapi.c +++ b/plugins/gssapi.c @@ -51,6 +51,8 @@ #include #endif +#include + #ifdef WIN32 # include From a0d90e4aa95bf20a4218ce3171a9dc4bef797fba Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Mon, 23 Nov 2015 17:17:33 +0100 Subject: [PATCH 224/796] improve sql libraries detection --- configure.ac | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 0e43a715..818bd8b2 100644 --- a/configure.ac +++ b/configure.ac @@ -817,7 +817,18 @@ LIB_MYSQL="" case "$with_mysql" in no) true;; - notfound) AC_WARN([MySQL Library not found]); true;; + notfound) + save_LDFLAGS=$LDFLAGS + LIB_MYSQL=`mysql_config --libs` + LIB_MYSQL="-lmysqlclient" + LDFLAGS="$LDFLAGS $LIB_MYSQL" + # CPPFLAGS="${CPPFLAGS} `mysql_config --include`" + AC_CHECK_LIB(mysqlclient, mysql_select_db, + AC_DEFINE(HAVE_MYSQL, [], [Do we have mysql support?]), + [AC_WARN([MySQL library mysqlclient does not work]) + with_mysql=no]) + LDFLAGS=$save_LDFLAGS + ;; *) if test -d ${with_mysql}/lib/mysql; then CMU_ADD_LIBPATH_TO(${with_mysql}/lib/mysql, LIB_MYSQL) @@ -838,6 +849,8 @@ case "$with_mysql" in CPPFLAGS="${CPPFLAGS} -I${with_mysql}/mysql/include" elif test -d ${with_mysql}/include; then CPPFLAGS="${CPPFLAGS} -I${with_mysql}/include" + elif test -d ${prefix}/include/mysql; then + CPPFLAGS="${CPPFLAGS} -I${prefix}/include/mysql" else CPPFLAGS="${CPPFLAGS} -I${with_mysql}" fi @@ -881,7 +894,17 @@ LIB_PGSQL="" case "$with_pgsql" in no) true;; - notfound) AC_WARN([PostgreSQL Library not found]); true;; + notfound) + LIB_PGSQL="-lpq" + # CPPFLAGS="${CPPFLAGS} -I`pg_config --includedir`" + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS $LIB_PGSQL" + AC_CHECK_LIB(pq, PQsetdbLogin, AC_DEFINE(HAVE_PGSQL,[], + [Do we have Postgres support?]), + [AC_WARN([PostgreSQL Library pq does not work]) + with_pgsql=no]) + LDFLAGS=$save_LDFLAGS + ;; *) if test -d ${with_pgsql}/lib/pgsql; then CMU_ADD_LIBPATH_TO(${with_pgsql}/lib/pgsql, LIB_PGSQL) @@ -902,6 +925,8 @@ case "$with_pgsql" in CPPFLAGS="${CPPFLAGS} -I${with_pgsql}/pgsql/include" elif test -d ${with_pgsql}/include; then CPPFLAGS="${CPPFLAGS} -I${with_pgsql}/include" + elif test -d ${prefix}/include; then + CPPFLAGS="${CPPFLAGS} -I${prefix}/include" else CPPFLAGS="${CPPFLAGS} -I${with_pgsql}" fi From 91f766a668b921ccb687d10add35f91a5dfc7bcd Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Tue, 24 Nov 2015 18:59:48 +0100 Subject: [PATCH 225/796] Fix compiler warnings on latest Fedora --- configure.ac | 1 + lib/checkpw.c | 10 ++--- lib/common.c | 3 -- lib/saslutil.c | 2 - plugins/digestmd5.c | 6 +-- plugins/ntlm.c | 75 +++++++++++++++++++++----------------- plugins/sasldb.c | 2 +- plugins/scram.c | 61 +++++++++++++++++-------------- sample/client.c | 14 +++---- sample/server.c | 20 +++++----- saslauthd/auth_getpwent.c | 1 + saslauthd/auth_httpform.c | 1 - saslauthd/auth_krb5.c | 3 +- saslauthd/auth_ldap.c | 6 --- saslauthd/auth_shadow.c | 3 +- saslauthd/cfile.c | 1 - saslauthd/ipc_unix.c | 2 +- saslauthd/lak.c | 8 ++-- saslauthd/saslauthd-main.c | 2 - saslauthd/testsaslauthd.c | 8 +--- utils/dbconverter-2.c | 2 +- utils/pluginviewer.c | 6 +-- 22 files changed, 115 insertions(+), 122 deletions(-) diff --git a/configure.ac b/configure.ac index 818bd8b2..5eef61e6 100644 --- a/configure.ac +++ b/configure.ac @@ -99,6 +99,7 @@ AC_PROG_AWK AC_PROG_LN_S AC_PROG_MAKE_SET AC_PROG_INSTALL +AC_USE_SYSTEM_EXTENSIONS CMU_C___ATTRIBUTE__ dnl check for -R, etc. switch diff --git a/lib/checkpw.c b/lib/checkpw.c index d371f3f2..0fa483c9 100644 --- a/lib/checkpw.c +++ b/lib/checkpw.c @@ -116,9 +116,9 @@ static int _sasl_make_plain_secret(const char *salt, } _sasl_MD5Init(&ctx); - _sasl_MD5Update(&ctx, salt, 16); - _sasl_MD5Update(&ctx, "sasldb", 6); - _sasl_MD5Update(&ctx, passwd, (unsigned int) passlen); + _sasl_MD5Update(&ctx, (const unsigned char *) salt, 16); + _sasl_MD5Update(&ctx, (const unsigned char *) "sasldb", 6); + _sasl_MD5Update(&ctx, (const unsigned char *) passwd, (unsigned int) passlen); memcpy((*secret)->data, salt, 16); (*secret)->data[16] = '\0'; _sasl_MD5Final((*secret)->data + 17, &ctx); @@ -368,8 +368,8 @@ int _sasl_auxprop_verify_apop(sasl_conn_t *conn, } _sasl_MD5Init(&ctx); - _sasl_MD5Update(&ctx, challenge, strlen(challenge)); - _sasl_MD5Update(&ctx, auxprop_values[0].values[0], + _sasl_MD5Update(&ctx, (const unsigned char *) challenge, strlen(challenge)); + _sasl_MD5Update(&ctx, (const unsigned char *) auxprop_values[0].values[0], strlen(auxprop_values[0].values[0])); _sasl_MD5Final(digest, &ctx); diff --git a/lib/common.c b/lib/common.c index de0adfdd..4a24d74d 100644 --- a/lib/common.c +++ b/lib/common.c @@ -1526,12 +1526,9 @@ _sasl_getsimple(void *context, size_t *len) { const char *userid; - sasl_conn_t *conn; if (! context || ! result) return SASL_BADPARAM; - conn = (sasl_conn_t *)context; - switch(id) { case SASL_CB_AUTHNAME: userid = getenv("USER"); diff --git a/lib/saslutil.c b/lib/saslutil.c index bcdb1cad..f13478a4 100644 --- a/lib/saslutil.c +++ b/lib/saslutil.c @@ -131,7 +131,6 @@ int sasl_encode64(const char *_in, const unsigned char *in = (const unsigned char *)_in; unsigned char *out = (unsigned char *)_out; unsigned char oval; - char *blah; unsigned olen; /* check params */ @@ -147,7 +146,6 @@ int sasl_encode64(const char *_in, } /* Do the work... */ - blah = (char *) out; while (inlen >= 3) { /* user provided max buffer size; make sure we don't go over it */ *out++ = basis_64[in[0] >> 2]; diff --git a/plugins/digestmd5.c b/plugins/digestmd5.c index 2fb05508..39d8ef2d 100644 --- a/plugins/digestmd5.c +++ b/plugins/digestmd5.c @@ -3048,7 +3048,8 @@ static int digestmd5_server_mech_step(void *conn_context, memset(oparams, 0, sizeof(sasl_out_params_t)); if (text->nonce) sparams->utils->free(text->nonce); if (text->realm) sparams->utils->free(text->realm); - text->nonce = text->realm = NULL; + text->realm = NULL; + text->nonce = NULL; /* fall through and issue challenge */ } @@ -3650,7 +3651,6 @@ static int parse_server_challenge(client_context_t *ctext, int saw_qop = 0; int ciphers = 0; int maxbuf_count = 0; - bool IsUTF8 = FALSE; int algorithm_count = 0; int opaque_count = 0; @@ -3867,8 +3867,6 @@ static int parse_server_challenge(client_context_t *ctext, params->utils->seterror(params->utils->conn, 0, "Charset must be UTF-8"); goto FreeAllocatedMem; - } else { - IsUTF8 = TRUE; } } else if (strcasecmp(name,"algorithm")==0) { if (text->http_mode && strcasecmp(value, "md5") == 0) { diff --git a/plugins/ntlm.c b/plugins/ntlm.c index 79ea47ca..ba0288d4 100644 --- a/plugins/ntlm.c +++ b/plugins/ntlm.c @@ -275,7 +275,7 @@ static void load_buffer(u_char *buf, const u_char *str, uint16 len, { if (len) { if (unicode) { - to_unicode(base + *offset, str, len); + to_unicode(base + *offset, (const char *) str, len); len *= 2; } else { @@ -373,10 +373,10 @@ static unsigned char *P16_lm(unsigned char *P16, sasl_secret_t *passwd, char P14[14]; unsigned char S8[] = { 0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 }; - strncpy(P14, passwd->data, sizeof(P14)); + strncpy(P14, (const char *) passwd->data, sizeof(P14)); ucase(P14, sizeof(P14)); - E(P16, P14, sizeof(P14), S8, sizeof(S8)); + E(P16, (unsigned char *) P14, sizeof(P14), S8, sizeof(S8)); *result = SASL_OK; return P16; } @@ -390,8 +390,8 @@ static unsigned char *P16_nt(unsigned char *P16, sasl_secret_t *passwd, *result = SASL_NOMEM; } else { - to_unicode(*buf, passwd->data, passwd->len); - MD4(*buf, 2 * passwd->len, P16); + to_unicode((unsigned char *) *buf, (const char *) passwd->data, passwd->len); + MD4((unsigned char *) *buf, 2 * passwd->len, P16); *result = SASL_OK; } return P16; @@ -444,9 +444,9 @@ static unsigned char *V2(unsigned char *V2, sasl_secret_t *passwd, strcpy(upper, authid); if (target) strcat(upper, target); ucase(upper, len); - to_unicode(*buf, upper, len); + to_unicode((unsigned char *) *buf, upper, len); - HMAC(EVP_md5(), hash, MD4_DIGEST_LENGTH, *buf, 2 * len, hash, &len); + HMAC(EVP_md5(), hash, MD4_DIGEST_LENGTH, (unsigned char *) *buf, 2 * len, hash, &len); /* V2 = HMAC-MD5(NTLMv2hash, challenge + blob) + blob */ HMAC_Init(&ctx, hash, len, EVP_md5()); @@ -768,8 +768,8 @@ static void make_netbios_name(const char *in, unsigned char out[]) */ n = strcspn(in, "."); if (n > 16) n = 16; - strncpy(out+18, in, n); - in = out+18; + strncpy((char *) out+18, in, n); + in = (char *) out+18; ucase(in, n); out[j++] = 0x20; @@ -1033,7 +1033,7 @@ static int smb_negotiate_protocol(const sasl_utils_t *utils, "NTLM: error reading NEGPROT response"); return SASL_FAIL; } - p = text->out_buf; + p = (unsigned char *) text->out_buf; /* parse the header */ if (len < SMB_HDR_SIZE) { @@ -1115,7 +1115,7 @@ static int smb_negotiate_protocol(const sasl_utils_t *utils, return SASL_NOMEM; } memcpy(*domain, p, len); - from_unicode(*domain, *domain, len); + from_unicode(*domain, (unsigned char *) *domain, len); text->flags |= NTLM_TARGET_IS_DOMAIN; } @@ -1256,7 +1256,7 @@ static int smb_session_setup(const sasl_utils_t *utils, server_context_t *text, "NTLM: error reading SESSIONSETUP response"); return SASL_FAIL; } - p = text->out_buf; + p = (unsigned char *) text->out_buf; /* parse the header */ if (len < SMB_HDR_SIZE) { @@ -1343,12 +1343,12 @@ static int create_challenge(const sasl_utils_t *utils, return SASL_NOMEM; } - base = *buf; + base = (unsigned char *) *buf; memset(base, 0, *outlen); memcpy(base + NTLM_SIG_OFFSET, NTLM_SIGNATURE, sizeof(NTLM_SIGNATURE)); htoil(base + NTLM_TYPE_OFFSET, NTLM_TYPE_CHALLENGE); load_buffer(base + NTLM_TYPE2_TARGET_OFFSET, - ucase(target, 0), (uint16) xstrlen(target), flags & NTLM_USE_UNICODE, + (const unsigned char *) ucase(target, 0), (uint16) xstrlen(target), flags & NTLM_USE_UNICODE, base, &offset); htoil(base + NTLM_TYPE2_FLAGS_OFFSET, flags); memcpy(base + NTLM_TYPE2_CHALLENGE_OFFSET, nonce, NTLM_NONCE_LENGTH); @@ -1500,26 +1500,30 @@ static int ntlm_server_mech_step2(server_context_t *text, return SASL_BADPROT; } - result = unload_buffer(sparams->utils, clientin + NTLM_TYPE3_LMRESP_OFFSET, + result = unload_buffer(sparams->utils, + (const unsigned char *) clientin + NTLM_TYPE3_LMRESP_OFFSET, (u_char **) &lm_resp, &lm_resp_len, 0, - clientin, clientinlen); + (const unsigned char *) clientin, clientinlen); if (result != SASL_OK) goto cleanup; - result = unload_buffer(sparams->utils, clientin + NTLM_TYPE3_NTRESP_OFFSET, + result = unload_buffer(sparams->utils, + (const unsigned char *) clientin + NTLM_TYPE3_NTRESP_OFFSET, (u_char **) &nt_resp, &nt_resp_len, 0, - clientin, clientinlen); + (const unsigned char *) clientin, clientinlen); if (result != SASL_OK) goto cleanup; - result = unload_buffer(sparams->utils, clientin + NTLM_TYPE3_DOMAIN_OFFSET, + result = unload_buffer(sparams->utils, + (const unsigned char *) clientin + NTLM_TYPE3_DOMAIN_OFFSET, (u_char **) &domain, &domain_len, text->flags & NTLM_USE_UNICODE, - clientin, clientinlen); + (const unsigned char *) clientin, clientinlen); if (result != SASL_OK) goto cleanup; - result = unload_buffer(sparams->utils, clientin + NTLM_TYPE3_USER_OFFSET, + result = unload_buffer(sparams->utils, + (const unsigned char *) clientin + NTLM_TYPE3_USER_OFFSET, (u_char **) &authid, &authid_len, text->flags & NTLM_USE_UNICODE, - clientin, clientinlen); + (const unsigned char *) clientin, clientinlen); if (result != SASL_OK) goto cleanup; /* require at least one response and an authid */ @@ -1582,7 +1586,7 @@ static int ntlm_server_mech_step2(server_context_t *text, } password->len = (unsigned) pass_len; - strncpy(password->data, auxprop_values[0].values[0], pass_len + 1); + strncpy((char *) password->data, auxprop_values[0].values[0], pass_len + 1); /* erase the plaintext password */ sparams->utils->prop_erase(sparams->propctx, password_request[0]); @@ -1805,15 +1809,15 @@ static int create_request(const sasl_utils_t *utils, return SASL_NOMEM; } - base = *buf; + base = (unsigned char *) *buf; memset(base, 0, *outlen); memcpy(base + NTLM_SIG_OFFSET, NTLM_SIGNATURE, sizeof(NTLM_SIGNATURE)); htoil(base + NTLM_TYPE_OFFSET, NTLM_TYPE_REQUEST); htoil(base + NTLM_TYPE1_FLAGS_OFFSET, flags); load_buffer(base + NTLM_TYPE1_DOMAIN_OFFSET, - domain, (uint16) xstrlen(domain), 0, base, &offset); + (const unsigned char *) domain, (uint16) xstrlen(domain), 0, base, &offset); load_buffer(base + NTLM_TYPE1_WORKSTN_OFFSET, - wkstn, (uint16) xstrlen(wkstn), 0, base, &offset); + (const unsigned char *) wkstn, (uint16) xstrlen(wkstn), 0, base, &offset); return SASL_OK; } @@ -1858,7 +1862,7 @@ static int create_response(const sasl_utils_t *utils, return SASL_NOMEM; } - base = *buf; + base = (unsigned char *) *buf; memset(base, 0, *outlen); memcpy(base + NTLM_SIG_OFFSET, NTLM_SIGNATURE, sizeof(NTLM_SIGNATURE)); htoil(base + NTLM_TYPE_OFFSET, NTLM_TYPE_RESPONSE); @@ -1867,12 +1871,15 @@ static int create_response(const sasl_utils_t *utils, load_buffer(base + NTLM_TYPE3_NTRESP_OFFSET, nt_resp, nt_resp ? NTLM_RESP_LENGTH : 0, 0, base, &offset); load_buffer(base + NTLM_TYPE3_DOMAIN_OFFSET, - ucase(domain, 0), (uint16) xstrlen(domain), flags & NTLM_USE_UNICODE, + (const unsigned char *) ucase(domain, 0), (uint16) xstrlen(domain), + flags & NTLM_USE_UNICODE, base, &offset); load_buffer(base + NTLM_TYPE3_USER_OFFSET, - user, (uint16) xstrlen(user), flags & NTLM_USE_UNICODE, base, &offset); + (const unsigned char *) user, (uint16) xstrlen(user), + flags & NTLM_USE_UNICODE, base, &offset); load_buffer(base + NTLM_TYPE3_WORKSTN_OFFSET, - ucase(wkstn, 0), (uint16) xstrlen(wkstn), flags & NTLM_USE_UNICODE, + (const unsigned char *) ucase(wkstn, 0), (uint16) xstrlen(wkstn), + flags & NTLM_USE_UNICODE, base, &offset); load_buffer(base + NTLM_TYPE3_SESSIONKEY_OFFSET, key, key ? NTLM_SESSKEY_LENGTH : 0, 0, base, &offset); @@ -2011,7 +2018,8 @@ static int ntlm_client_mech_step2(client_context_t *text, flags &= NTLM_FLAGS_MASK; /* mask off the bits we don't support */ - result = unload_buffer(params->utils, serverin + NTLM_TYPE2_TARGET_OFFSET, + result = unload_buffer(params->utils, + (const unsigned char *) serverin + NTLM_TYPE2_TARGET_OFFSET, (u_char **) &domain, NULL, flags & NTLM_USE_UNICODE, (u_char *) serverin, serverinlen); @@ -2027,7 +2035,7 @@ static int ntlm_client_mech_step2(client_context_t *text, (sendv2[0] == 'o' && sendv2[1] == 'n') || sendv2[0] == 't')) { /* put the cnonce in place after the LMv2 HMAC */ - char *cnonce = resp + MD5_DIGEST_LENGTH; + char *cnonce = (char *) resp + MD5_DIGEST_LENGTH; params->utils->log(NULL, SASL_LOG_DEBUG, "calculating LMv2 response"); @@ -2035,7 +2043,8 @@ static int ntlm_client_mech_step2(client_context_t *text, params->utils->rand(params->utils->rpool, cnonce, NTLM_NONCE_LENGTH); V2(resp, password, oparams->authid, domain, - serverin + NTLM_TYPE2_CHALLENGE_OFFSET, cnonce, NTLM_NONCE_LENGTH, + (const unsigned char *) serverin + NTLM_TYPE2_CHALLENGE_OFFSET, + (const unsigned char *) cnonce, NTLM_NONCE_LENGTH, params->utils, &text->out_buf, &text->out_buf_len, &result); lm_resp = resp; diff --git a/plugins/sasldb.c b/plugins/sasldb.c index 1edbb8be..403a9ccb 100644 --- a/plugins/sasldb.c +++ b/plugins/sasldb.c @@ -248,7 +248,7 @@ static int sasldb_auxprop_store(void *glob_context __attribute__((unused)), ret = SASL_OK; for (cur = to_store; cur->name; cur++) { - char * value = (cur->values && cur->values[0]) ? cur->values[0] : NULL; + char * value = (char *) (cur->values && cur->values[0]) ? cur->values[0] : NULL; if (cur->name[0] == '*') { continue; diff --git a/plugins/scram.c b/plugins/scram.c index 62a101c9..b0681c4f 100644 --- a/plugins/scram.c +++ b/plugins/scram.c @@ -255,6 +255,7 @@ create_nonce(const sasl_utils_t * utils, return buffer; } +#ifdef SCRAM_DEBUG /* Useful for debugging interop issues */ static void print_hash (const char * func, const char * hash) @@ -267,6 +268,7 @@ print_hash (const char * func, const char * hash) } printf ("\n"); } +#endif /* The result variable need to point to a buffer big enough for the [SHA-1] hash */ @@ -299,7 +301,7 @@ Hi (const sasl_utils_t * utils, if (HMAC(EVP_sha1(), (const unsigned char *) str, (int)str_len, - initial_key, + (const unsigned char *) initial_key, (int)salt_len + 4, (unsigned char *)result, &hash_len) == NULL) { @@ -315,7 +317,7 @@ Hi (const sasl_utils_t * utils, if (HMAC(EVP_sha1(), (const unsigned char *) str, (int)str_len, - temp_result, + (const unsigned char *) temp_result, SCRAM_HASH_SIZE, (unsigned char *)temp_result, &hash_len) == NULL) { @@ -345,9 +347,10 @@ scram_server_user_salt(const sasl_utils_t * utils, size_t * p_salt_len) { char * result = utils->malloc(SCRAM_HASH_SIZE); - Hi(utils, username, strlen(username), g_salt_key, SALT_SIZE, 20 /* iterations */, result); + Hi(utils, username, strlen(username), (const char *) g_salt_key, SALT_SIZE, + 20 /* iterations */, result); *p_salt_len = SCRAM_HASH_SIZE; - return result; + return (unsigned char *) result; } static int @@ -386,7 +389,7 @@ GenerateScramSecrets (const sasl_utils_t * utils, /* SaltedPassword := Hi(password, salt) */ Hi (utils, - sec->data, + (const char *) sec->data, sec->len, salt, salt_len, @@ -397,7 +400,7 @@ GenerateScramSecrets (const sasl_utils_t * utils, if (HMAC(EVP_sha1(), (const unsigned char *) SaltedPassword, SCRAM_HASH_SIZE, - CLIENT_KEY_CONSTANT, + (const unsigned char *) CLIENT_KEY_CONSTANT, CLIENT_KEY_CONSTANT_LEN, (unsigned char *)ClientKey, &hash_len) == NULL) { @@ -407,7 +410,8 @@ GenerateScramSecrets (const sasl_utils_t * utils, } /* StoredKey := H(ClientKey) */ - if (SHA1(ClientKey, SCRAM_HASH_SIZE, StoredKey) == NULL) { + if (SHA1((const unsigned char *) ClientKey, SCRAM_HASH_SIZE, + (unsigned char *) StoredKey) == NULL) { *error_text = "SHA1 call failed"; result = SASL_SCRAM_INTERNAL; goto cleanup; @@ -418,7 +422,7 @@ GenerateScramSecrets (const sasl_utils_t * utils, if (HMAC(EVP_sha1(), (const unsigned char *) SaltedPassword, SCRAM_HASH_SIZE, - SERVER_KEY_CONSTANT, + (const unsigned char *) SERVER_KEY_CONSTANT, SERVER_KEY_CONSTANT_LEN, (unsigned char *)ServerKey, &hash_len) == NULL) { @@ -509,7 +513,6 @@ scram_server_mech_step1(server_context_t *text, NULL }; int canon_flags; struct propval auxprop_values[3]; - unsigned int hash_len = 0; int result; if (clientinlen == 0) { @@ -783,13 +786,13 @@ scram_server_mech_step1(server_context_t *text, char * s_iteration_count; char * end; - text->salt = scram_server_user_salt(sparams->utils, text->authentication_id, &text->salt_len); + text->salt = (char *) scram_server_user_salt(sparams->utils, text->authentication_id, &text->salt_len); sparams->utils->getopt(sparams->utils->getopt_context, /* Different SCRAM hashes can have different strengh */ SCRAM_SASL_MECH, "scram_iteration_counter", - &s_iteration_count, + (const char **) &s_iteration_count, NULL); if (s_iteration_count != NULL) { @@ -899,7 +902,7 @@ scram_server_mech_step1(server_context_t *text, (unsigned int)base64_salt_len, text->salt, (unsigned int)base64_salt_len, - &text->salt_len) != SASL_OK) { + (unsigned int *) &text->salt_len) != SASL_OK) { SETERROR(sparams->utils, "Invalid base64 encoding of the salt in " SCRAM_SASL_MECH " stored value"); continue; } @@ -1304,7 +1307,7 @@ scram_server_mech_step2(server_context_t *text, if (HMAC(EVP_sha1(), (const unsigned char *) text->StoredKey, SCRAM_HASH_SIZE, - text->auth_message, + (const unsigned char *)text->auth_message, (int)text->auth_message_len, (unsigned char *)ClientSignature, &hash_len) == NULL) { @@ -1336,7 +1339,8 @@ scram_server_mech_step2(server_context_t *text, } /* StoredKey := H(ClientKey) */ - if (SHA1(ReceivedClientKey, SCRAM_HASH_SIZE, CalculatedStoredKey) == NULL) { + if (SHA1((const unsigned char *) ReceivedClientKey, SCRAM_HASH_SIZE, + (unsigned char *) CalculatedStoredKey) == NULL) { sparams->utils->seterror(sparams->utils->conn,0, "SHA1 call failed"); result = SASL_SCRAM_INTERNAL; @@ -1355,7 +1359,7 @@ scram_server_mech_step2(server_context_t *text, if (HMAC(EVP_sha1(), (const unsigned char *) text->ServerKey, SCRAM_HASH_SIZE, - text->auth_message, + (unsigned char *) text->auth_message, (int)text->auth_message_len, (unsigned char *)ServerSignature, &hash_len) == NULL) { @@ -1572,7 +1576,7 @@ static int scram_setpass(void *glob_context __attribute__((unused)), /* Different SCRAM hashes can have different strengh */ SCRAM_SASL_MECH, "scram_iteration_counter", - &s_iteration_count, + (const char **) &s_iteration_count, NULL); if (s_iteration_count != NULL) { @@ -1663,14 +1667,14 @@ static int scram_setpass(void *glob_context __attribute__((unused)), goto cleanup; } - sprintf(sec->data, + sprintf((char *) sec->data, "%s$%u:%s$%s:%s", SCRAM_SASL_MECH, iteration_count, base64_salt, base64_StoredKey, base64_ServerKey); - sec->len = (unsigned int) strlen(sec->data); + sec->len = (unsigned int) strlen((const char *) sec->data); } /* do the store */ @@ -1684,7 +1688,7 @@ static int scram_setpass(void *glob_context __attribute__((unused)), if (!r) { r = sparams->utils->prop_set(propctx, "authPassword", - (sec ? sec->data : NULL), + (const char *) (sec ? sec->data : NULL), (sec ? sec->len : 0)); } if (!r) { @@ -1989,7 +1993,7 @@ scram_client_mech_step1(client_context_t *text, if (userid != NULL && *userid != '\0') { result = encode_saslname (oparams->user, - &encoded_authorization_id, + (const char **) &encoded_authorization_id, &freeme2); if (result != SASL_OK) { @@ -2000,7 +2004,7 @@ scram_client_mech_step1(client_context_t *text, } result = encode_saslname (oparams->authid, - &encoded_authcid, + (const char **) &encoded_authcid, &freeme); if (result != SASL_OK) { MEMERROR( params->utils ); @@ -2277,7 +2281,7 @@ scram_client_mech_step2(client_context_t *text, goto cleanup; } - channel_binding_data = params->cbinding->data; + channel_binding_data = (const char *) params->cbinding->data; channel_binding_data_len = params->cbinding->len; } @@ -2368,7 +2372,7 @@ scram_client_mech_step2(client_context_t *text, /* SaltedPassword := Hi(password, salt) */ Hi (params->utils, - text->password->data, + (const char *) text->password->data, text->password->len, text->salt, text->salt_len, @@ -2381,7 +2385,7 @@ scram_client_mech_step2(client_context_t *text, if (HMAC(EVP_sha1(), (const unsigned char *) text->SaltedPassword, SCRAM_HASH_SIZE, - CLIENT_KEY_CONSTANT, + (const unsigned char *) CLIENT_KEY_CONSTANT, CLIENT_KEY_CONSTANT_LEN, (unsigned char *)ClientKey, &hash_len) == NULL) { @@ -2394,7 +2398,8 @@ scram_client_mech_step2(client_context_t *text, PRINT_HASH ("ClientKey", ClientKey); /* StoredKey := H(ClientKey) */ - if (SHA1(ClientKey, SCRAM_HASH_SIZE, StoredKey) == NULL) { + if (SHA1((const unsigned char *) ClientKey, SCRAM_HASH_SIZE, + (unsigned char *) StoredKey) == NULL) { params->utils->seterror(params->utils->conn,0, "SHA1 call failed"); result = SASL_SCRAM_INTERNAL; @@ -2407,7 +2412,7 @@ scram_client_mech_step2(client_context_t *text, if (HMAC(EVP_sha1(), (const unsigned char *)StoredKey, SCRAM_HASH_SIZE, - text->auth_message, + (const unsigned char *) text->auth_message, (int)text->auth_message_len, (unsigned char *)ClientSignature, &hash_len) == NULL) { @@ -2535,7 +2540,7 @@ scram_client_mech_step3(client_context_t *text, if (HMAC(EVP_sha1(), (const unsigned char *)text->SaltedPassword, SCRAM_HASH_SIZE, - SERVER_KEY_CONSTANT, + (const unsigned char *) SERVER_KEY_CONSTANT, SERVER_KEY_CONSTANT_LEN, (unsigned char *)ServerKey, &hash_len) == NULL) { @@ -2549,7 +2554,7 @@ scram_client_mech_step3(client_context_t *text, if (HMAC(EVP_sha1(), (const unsigned char *)ServerKey, SCRAM_HASH_SIZE, - text->auth_message, + (const unsigned char *) text->auth_message, (int)text->auth_message_len, (unsigned char *)ServerSignature, &hash_len) == NULL) { diff --git a/sample/client.c b/sample/client.c index d568be53..aee8eacc 100644 --- a/sample/client.c +++ b/sample/client.c @@ -174,7 +174,7 @@ getsecret(sasl_conn_t *conn, } x->len = len; - strcpy(x->data, password); + strcpy((char *)x->data, password); memset(password, 0, len); *psecret = x; @@ -255,7 +255,7 @@ int mysasl_negotiate(FILE *in, FILE *out, sasl_conn_t *conn) mech = buf; } - r = sasl_client_start(conn, mech, NULL, &data, &len, &chosenmech); + r = sasl_client_start(conn, mech, NULL, &data, (unsigned int *) &len, &chosenmech); if (r != SASL_OK && r != SASL_CONTINUE) { saslerr(r, "starting SASL negotiation"); printf("\n%s\n", sasl_errdetail(conn)); @@ -295,7 +295,7 @@ int mysasl_negotiate(FILE *in, FILE *out, sasl_conn_t *conn) } len = recv_string(in, buf, sizeof buf); - r = sasl_client_step(conn, buf, len, NULL, &data, &len); + r = sasl_client_step(conn, buf, len, NULL, &data, (unsigned int *) &len); if (r != SASL_OK && r != SASL_CONTINUE) { saslerr(r, "performing SASL negotiation"); printf("\n%s\n", sasl_errdetail(conn)); @@ -389,7 +389,7 @@ int main(int argc, char *argv[]) /* set ip addresses */ salen = sizeof(local_ip); - if (getsockname(fd, (struct sockaddr *)&local_ip, &salen) < 0) { + if (getsockname(fd, (struct sockaddr *)&local_ip, (unsigned int*) &salen) < 0) { perror("getsockname"); } @@ -408,7 +408,7 @@ int main(int argc, char *argv[]) snprintf(localaddr, sizeof(localaddr), "%s;%s", hbuf, pbuf); salen = sizeof(remote_ip); - if (getpeername(fd, (struct sockaddr *)&remote_ip, &salen) < 0) { + if (getpeername(fd, (struct sockaddr *)&remote_ip, (unsigned int *) &salen) < 0) { perror("getpeername"); } @@ -433,8 +433,8 @@ int main(int argc, char *argv[]) if (cb_flag) { cb.name = "sasl-sample"; cb.critical = cb_flag > 1; - cb.data = "this is a test of channel binding"; - cb.len = strlen(cb.data); + cb.data = (unsigned char *) "this is a test of channel binding"; + cb.len = (unsigned int) strlen((const char *) cb.data); sasl_setprop(conn, SASL_CHANNEL_BINDING, &cb); } diff --git a/sample/server.c b/sample/server.c index 01dd7ba1..2a9c0ef7 100644 --- a/sample/server.c +++ b/sample/server.c @@ -220,7 +220,7 @@ int mysasl_negotiate(FILE *in, FILE *out, sasl_conn_t *conn) dprintf(1, "generating client mechanism list... "); r = sasl_listmech(conn, NULL, NULL, " ", NULL, - &data, &len, &count); + &data, (unsigned int *) &len, &count); if (r != SASL_OK) saslfail(r, "generating mechanism list"); dprintf(1, "%d mechanisms\n", count); } @@ -228,7 +228,7 @@ int mysasl_negotiate(FILE *in, FILE *out, sasl_conn_t *conn) /* send capability list to client */ send_string(out, data, len); if (mech) - free(data); + free((void *) data); dprintf(1, "waiting for client mechanism...\n"); len = recv_string(in, chosenmech, sizeof chosenmech); @@ -260,10 +260,10 @@ int mysasl_negotiate(FILE *in, FILE *out, sasl_conn_t *conn) /* start libsasl negotiation */ r = sasl_server_start(conn, chosenmech, buf, len, - &data, &len); + &data, (unsigned int *) &len); } else { r = sasl_server_start(conn, chosenmech, NULL, 0, - &data, &len); + &data, (unsigned int *) &len); } if (r != SASL_OK && r != SASL_CONTINUE) { @@ -291,7 +291,7 @@ int mysasl_negotiate(FILE *in, FILE *out, sasl_conn_t *conn) return -1; } - r = sasl_server_step(conn, buf, len, &data, &len); + r = sasl_server_step(conn, buf, len, &data, (unsigned int *) &len); if (r != SASL_OK && r != SASL_CONTINUE) { saslerr(r, "performing SASL negotiation"); fputc('N', out); /* send NO to client */ @@ -422,7 +422,7 @@ int main(int argc, char *argv[]) /* set ip addresses */ salen = sizeof(local_ip); - if (getsockname(fd, (struct sockaddr *)&local_ip, &salen) < 0) { + if (getsockname(fd, (struct sockaddr *)&local_ip, (unsigned int *) &salen) < 0) { perror("getsockname"); } niflags = (NI_NUMERICHOST | NI_NUMERICSERV); @@ -440,7 +440,7 @@ int main(int argc, char *argv[]) snprintf(localaddr, sizeof(localaddr), "%s;%s", hbuf, pbuf); salen = sizeof(remote_ip); - if (getpeername(fd, (struct sockaddr *)&remote_ip, &salen) < 0) { + if (getpeername(fd, (struct sockaddr *)&remote_ip, (unsigned int *) &salen) < 0) { perror("getpeername"); } @@ -470,8 +470,8 @@ int main(int argc, char *argv[]) cb.name = "sasl-sample"; cb.critical = cb_flag > 1; - cb.data = "this is a test of channel binding"; - cb.len = strlen(cb.data); + cb.data = (const unsigned char *) "this is a test of channel binding"; + cb.len = (unsigned int) strlen((const char *) cb.data); if (cb_flag) { sasl_setprop(conn, SASL_CHANNEL_BINDING, &cb); @@ -518,7 +518,7 @@ static void displayStatus_1(m, code, type) maj_stat = gss_display_status(&min_stat, code, type, GSS_C_NULL_OID, &msg_ctx, &msg); - fprintf(stderr, "%s: %s\n", m, (char *)msg.value); + fprintf(stderr, "%s (%u): %s\n", m, maj_stat, (char *)msg.value); (void) gss_release_buffer(&min_stat, &msg); if (!msg_ctx) diff --git a/saslauthd/auth_getpwent.c b/saslauthd/auth_getpwent.c index d4ebe542..84e1cc2c 100644 --- a/saslauthd/auth_getpwent.c +++ b/saslauthd/auth_getpwent.c @@ -42,6 +42,7 @@ #include #include #include +#include #ifdef HAVE_CRYPT_H #include diff --git a/saslauthd/auth_httpform.c b/saslauthd/auth_httpform.c index 045a8b55..aacf9888 100644 --- a/saslauthd/auth_httpform.c +++ b/saslauthd/auth_httpform.c @@ -505,7 +505,6 @@ auth_httpform ( int s=-1; /* socket to remote auth host */ struct addrinfo *r; /* remote socket address info */ char *req; /* request, with user and pw */ - char *c; /* scratch pointer */ int rc; /* return code scratch area */ char postbuf[RESP_LEN]; /* request buffer */ int postlen; /* length of post request */ diff --git a/saslauthd/auth_krb5.c b/saslauthd/auth_krb5.c index 7e14e78d..354e9700 100644 --- a/saslauthd/auth_krb5.c +++ b/saslauthd/auth_krb5.c @@ -79,7 +79,6 @@ auth_krb5_init ( ) { #ifdef AUTH_KRB5 - int rc; char *configname = 0; if (krbtf_init() == -1) { @@ -102,7 +101,7 @@ auth_krb5_init ( } if (config) { - keytabname = cfile_getstring(config, "krb5_keytab", keytabname); + keytabname = (char *) cfile_getstring(config, "krb5_keytab", keytabname); verify_principal = cfile_getstring(config, "krb5_verify_principal", verify_principal); } diff --git a/saslauthd/auth_ldap.c b/saslauthd/auth_ldap.c index c8d2878d..2cd50f37 100644 --- a/saslauthd/auth_ldap.c +++ b/saslauthd/auth_ldap.c @@ -96,12 +96,6 @@ auth_ldap_init ( /* END PARAMETERS */ ) { - /* VARIABLES */ - struct addrinfo hints; - int err; - char *c; /* scratch pointer */ - /* END VARIABLES */ - if (mech_option != NULL) { SASLAUTHD_CONF_FILE = mech_option; } diff --git a/saslauthd/auth_shadow.c b/saslauthd/auth_shadow.c index b37af02f..d69e380f 100644 --- a/saslauthd/auth_shadow.c +++ b/saslauthd/auth_shadow.c @@ -35,6 +35,7 @@ /* PUBLIC DEPENDENCIES */ #include "mechanisms.h" +#include #ifdef AUTH_SHADOW @@ -239,7 +240,7 @@ auth_shadow ( if ((sp->sp_expire != -1) && (today > sp->sp_expire)) { if (flags & VERBOSE) { - syslog(LOG_DEBUG, "DEBUG: auth_shadow: account expired: %dl > %dl", + syslog(LOG_DEBUG, "DEBUG: auth_shadow: account expired: %ld > %ld", today, sp->sp_expire); } RETURN("NO Account expired"); diff --git a/saslauthd/cfile.c b/saslauthd/cfile.c index 5c87d022..386b07a6 100644 --- a/saslauthd/cfile.c +++ b/saslauthd/cfile.c @@ -76,7 +76,6 @@ cfile cfile_read(const char *filename, char *complaint, int complaint_len) int alloced = 0; char buf[BIG_ENOUGH]; char *p, *key; - int result; struct cfile *cf; if (complaint) diff --git a/saslauthd/ipc_unix.c b/saslauthd/ipc_unix.c index f82a2452..58a1fa68 100644 --- a/saslauthd/ipc_unix.c +++ b/saslauthd/ipc_unix.c @@ -232,7 +232,7 @@ void ipc_loop() { continue; } - conn_fd = accept(sock_fd, (struct sockaddr *)&client, &len); + conn_fd = accept(sock_fd, (struct sockaddr *)&client, (unsigned int *) &len); rc = errno; rel_accept_lock(); diff --git a/saslauthd/lak.c b/saslauthd/lak.c index f6670736..17f58baf 100644 --- a/saslauthd/lak.c +++ b/saslauthd/lak.c @@ -835,12 +835,12 @@ static int lak_connect( rc = ldap_set_option(lak->ld, LDAP_OPT_NETWORK_TIMEOUT, &(lak->conf->timeout)); if (rc != LDAP_OPT_SUCCESS) { - syslog(LOG_WARNING|LOG_AUTH, "Unable to set LDAP_OPT_NETWORK_TIMEOUT %d.%d.", lak->conf->timeout.tv_sec, lak->conf->timeout.tv_usec); + syslog(LOG_WARNING|LOG_AUTH, "Unable to set LDAP_OPT_NETWORK_TIMEOUT %ld.%ld.", lak->conf->timeout.tv_sec, lak->conf->timeout.tv_usec); } rc = ldap_set_option(lak->ld, LDAP_OPT_TIMEOUT, &(lak->conf->timeout)); if (rc != LDAP_OPT_SUCCESS) { - syslog(LOG_WARNING|LOG_AUTH, "Unable to set LDAP_OPT_TIMEOUT %d.%d.", lak->conf->timeout.tv_sec, lak->conf->timeout.tv_usec); + syslog(LOG_WARNING|LOG_AUTH, "Unable to set LDAP_OPT_TIMEOUT %ld.%ld.", lak->conf->timeout.tv_sec, lak->conf->timeout.tv_usec); } rc = ldap_set_option(lak->ld, LDAP_OPT_TIMELIMIT, &(lak->conf->time_limit)); @@ -1727,13 +1727,13 @@ static int lak_base64_decode( return LAK_NOMEM; EVP_DecodeInit(&EVP_ctx); - rc = EVP_DecodeUpdate(&EVP_ctx, text, &i, (char *)src, strlen(src)); + rc = EVP_DecodeUpdate(&EVP_ctx, (unsigned char *) text, &i, (const unsigned char *)src, strlen(src)); if (rc < 0) { free(text); return LAK_FAIL; } tlen += i; - EVP_DecodeFinal(&EVP_ctx, text, &i); + EVP_DecodeFinal(&EVP_ctx, (unsigned char *) text, &i); *ret = text; if (rlen != NULL) diff --git a/saslauthd/saslauthd-main.c b/saslauthd/saslauthd-main.c index 5d9ca8a3..e869eb33 100644 --- a/saslauthd/saslauthd-main.c +++ b/saslauthd/saslauthd-main.c @@ -631,7 +631,6 @@ void detach_tty() { int null_fd; int exit_result; pid_t pid; - char pid_buf[100]; struct flock lockinfo; /************************************************************** @@ -893,7 +892,6 @@ void handle_sigchld() { * Do some final cleanup here. **************************************************************/ void server_exit() { - struct flock lock_st; /********************************************************* * If we're not the master process, don't do anything diff --git a/saslauthd/testsaslauthd.c b/saslauthd/testsaslauthd.c index 368af76d..5de666e7 100644 --- a/saslauthd/testsaslauthd.c +++ b/saslauthd/testsaslauthd.c @@ -105,9 +105,7 @@ static int saslauthd_verify_password(const char *saslauthd_path, struct sockaddr_un srvaddr; int r; unsigned short count; - void *context; char pwpath[sizeof(srvaddr.sun_path)]; - const char *p = NULL; #ifdef USE_DOORS door_arg_t arg; #endif @@ -133,7 +131,6 @@ static int saslauthd_verify_password(const char *saslauthd_path, */ { unsigned short u_len, p_len, s_len, r_len; - struct iovec iov[8]; u_len = htons(strlen(userid)); p_len = htons(strlen(passwd)); @@ -253,10 +250,7 @@ main(int argc, char *argv[]) const char *realm = NULL, *service = NULL, *path = NULL; int c; int flag_error = 0; - unsigned passlen, verifylen; - const char *errstr = NULL; - int result; - char *user_domain = NULL; + int result = 0; int repeat = 0; while ((c = getopt(argc, argv, "p:u:r:s:f:R:")) != EOF) diff --git a/utils/dbconverter-2.c b/utils/dbconverter-2.c index 04df2cba..33e18fb2 100644 --- a/utils/dbconverter-2.c +++ b/utils/dbconverter-2.c @@ -376,7 +376,7 @@ int good_getopt(void *context __attribute__((unused)), } static struct sasl_callback goodsasl_cb[] = { - { SASL_CB_GETOPT, &good_getopt, NULL }, + { SASL_CB_GETOPT, (int (*)(void))&good_getopt, NULL }, { SASL_CB_LIST_END, NULL, NULL } }; diff --git a/utils/pluginviewer.c b/utils/pluginviewer.c index 3164acdc..15c2b0e0 100644 --- a/utils/pluginviewer.c +++ b/utils/pluginviewer.c @@ -422,7 +422,7 @@ main(int argc, char *argv[]) case 'b': options = optarg; while (*options != '\0') { - switch(getsubopt(&options, (const char * const *)bit_subopts, &value)) { + switch(getsubopt(&options, (char * const *)bit_subopts, &value)) { case OPT_MIN: if (! value) { errflag = 1; @@ -447,7 +447,7 @@ main(int argc, char *argv[]) case 'e': options = optarg; while (*options != '\0') { - switch(getsubopt(&options, (const char * const *)ext_subopts, &value)) { + switch(getsubopt(&options, (char * const *)ext_subopts, &value)) { case OPT_EXT_SSF: if (! value) { errflag = 1; @@ -476,7 +476,7 @@ main(int argc, char *argv[]) case 'f': options = optarg; while (*options != '\0') { - switch(getsubopt(&options, (const char * const *)flag_subopts, &value)) { + switch(getsubopt(&options, (char * const *)flag_subopts, &value)) { case OPT_NOPLAIN: secprops.security_flags |= SASL_SEC_NOPLAINTEXT; break; From 68cb8626ca6919e3e9378be1e1b52186d8066870 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Fri, 4 Dec 2015 17:58:07 +0100 Subject: [PATCH 226/796] Support AIX SASL GSSAPI When choosing protection layer in gssapi_server_mech_ssfreq(), we are acceptor already and this means SentByAcceptor bit is cleared. If acceptor receives a token with SentByAcceptor bit set, this is wrong and therefore must cause SASL negotiation to fail. Original code used LAYER_NONE constant (equal to 1) wrongly here. Original patch from Alexander Bokovoy --- plugins/gssapi.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/plugins/gssapi.c b/plugins/gssapi.c index c0240c81..d23a0d10 100644 --- a/plugins/gssapi.c +++ b/plugins/gssapi.c @@ -1192,19 +1192,18 @@ gssapi_server_mech_ssfreq(context_t *text, } layerchoice = (int)(((char *)(output_token->value))[0]); - if (layerchoice == LAYER_NONE && + if (!(layerchoice & (LAYER_INTEGRITY | LAYER_CONFIDENTIALITY)) && (text->qop & LAYER_NONE)) { /* no encryption */ oparams->encode = NULL; oparams->decode = NULL; oparams->mech_ssf = 0; - } else if (layerchoice == LAYER_INTEGRITY && + } else if ((layerchoice & LAYER_INTEGRITY) && (text->qop & LAYER_INTEGRITY)) { /* integrity */ oparams->encode = &gssapi_integrity_encode; oparams->decode = &gssapi_decode; oparams->mech_ssf = 1; - } else if ((layerchoice == LAYER_CONFIDENTIALITY || - /* For compatibility with broken clients setting both bits */ - layerchoice == (LAYER_CONFIDENTIALITY|LAYER_INTEGRITY)) && + } else if (/* For compatibility with broken clients setting both bits */ + (layerchoice & (LAYER_CONFIDENTIALITY | LAYER_INTEGRITY)) && (text->qop & LAYER_CONFIDENTIALITY)) { /* privacy */ oparams->encode = &gssapi_privacy_encode; oparams->decode = &gssapi_decode; From 1c94516858fcc9042edeb1682da5e031c6eb3e84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Fri, 20 Nov 2015 18:50:58 +0100 Subject: [PATCH 227/796] sasld: remove unused libsasldb.a rule --- sasldb/Makefile.am | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/sasldb/Makefile.am b/sasldb/Makefile.am index 8ead7060..497ee251 100644 --- a/sasldb/Makefile.am +++ b/sasldb/Makefile.am @@ -51,19 +51,9 @@ extra_common_sources = db_none.c db_lmdb.c db_ndbm.c db_gdbm.c db_berkeley.c EXTRA_DIST = NTMakefile noinst_LTLIBRARIES = libsasldb.la -noinst_LIBRARIES = libsasldb.a libsasldb_la_SOURCES = allockey.c sasldb.h EXTRA_libsasldb_la_SOURCES = $(extra_common_sources) libsasldb_la_DEPENDENCIES = $(SASL_DB_BACKEND) libsasldb_la_LIBADD = $(SASL_DB_BACKEND) libsasldb_la_LDFLAGS = -no-undefined - -# Prevent make dist stupidity -libsasldb_a_SOURCES = -EXTRA_libsasldb_a_SOURCES = - -libsasldb.a: libsasldb.la $(SASL_DB_BACKEND_STATIC) - $(AR) cru .libs/$@ $(SASL_DB_BACKEND_STATIC) - - From 1518b84c1a1adb1fce4c28da7bfce6bf69064016 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Fri, 20 Nov 2015 18:54:54 +0100 Subject: [PATCH 228/796] Remove LIBSASL_API to sasldb It's build as a static library, and thus do not use exported symbols. --- sasldb/sasldb.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sasldb/sasldb.h b/sasldb/sasldb.h index 0cef3b44..06183ebd 100644 --- a/sasldb/sasldb.h +++ b/sasldb/sasldb.h @@ -73,7 +73,7 @@ int _sasldb_putdata(const sasl_utils_t *utils, const char *data, size_t data_len); /* Should be run before any db access is attempted */ -LIBSASL_API int _sasl_check_db(const sasl_utils_t *utils, +int _sasl_check_db(const sasl_utils_t *utils, sasl_conn_t *conn); /* These allow iterating through the keys of the database */ @@ -84,15 +84,15 @@ typedef int (* sasldb_list_callback_t) (const char *authid, const char *property, void *rock); -LIBSASL_API sasldb_handle _sasldb_getkeyhandle(const sasl_utils_t *utils, +sasldb_handle _sasldb_getkeyhandle(const sasl_utils_t *utils, sasl_conn_t *conn); -LIBSASL_API int _sasldb_getnextkey(const sasl_utils_t *utils, +int _sasldb_getnextkey(const sasl_utils_t *utils, sasldb_handle handle, char *out, const size_t max_out, size_t *out_len); -LIBSASL_API int _sasldb_releasekeyhandle(const sasl_utils_t *utils, +int _sasldb_releasekeyhandle(const sasl_utils_t *utils, sasldb_handle handle); -LIBSASL_API int _sasldb_listusers(const sasl_utils_t *utils, +int _sasldb_listusers(const sasl_utils_t *utils, sasl_conn_t *context, sasldb_list_callback_t callback, void *callback_rock); From 8625eb2ad3cda13f25246b7940dd1add2ad80474 Mon Sep 17 00:00:00 2001 From: Ignacio Casal Quinteiro Date: Fri, 20 Nov 2015 17:35:25 +0100 Subject: [PATCH 229/796] Provide a more standard autogen script Also moved the macros to a more standard m4 directory --- Makefile.am | 4 +-- SMakefile | 45 --------------------------------- autogen.sh | 37 +++++++++++++++++++++++++++ cmulocal/init_automake.m4 | 7 ----- configure.ac | 6 +---- {cmulocal => m4}/berkdb.m4 | 0 {cmulocal => m4}/bsd_sockets.m4 | 0 {cmulocal => m4}/c-attribute.m4 | 0 {cmulocal => m4}/common.m4 | 0 {cmulocal => m4}/cyrus.m4 | 0 {cmulocal => m4}/ipv6.m4 | 0 {cmulocal => m4}/kerberos_v4.m4 | 0 {cmulocal => m4}/openldap.m4 | 0 {cmulocal => m4}/openssl.m4 | 0 {cmulocal => m4}/plain.m4 | 0 {cmulocal => m4}/sasl2.m4 | 0 {cmulocal => m4}/sasldb.m4 | 0 17 files changed, 40 insertions(+), 59 deletions(-) delete mode 100644 SMakefile create mode 100755 autogen.sh delete mode 100644 cmulocal/init_automake.m4 rename {cmulocal => m4}/berkdb.m4 (100%) rename {cmulocal => m4}/bsd_sockets.m4 (100%) rename {cmulocal => m4}/c-attribute.m4 (100%) rename {cmulocal => m4}/common.m4 (100%) rename {cmulocal => m4}/cyrus.m4 (100%) rename {cmulocal => m4}/ipv6.m4 (100%) rename {cmulocal => m4}/kerberos_v4.m4 (100%) rename {cmulocal => m4}/openldap.m4 (100%) rename {cmulocal => m4}/openssl.m4 (100%) rename {cmulocal => m4}/plain.m4 (100%) rename {cmulocal => m4}/sasl2.m4 (100%) rename {cmulocal => m4}/sasldb.m4 (100%) diff --git a/Makefile.am b/Makefile.am index bd12837a..f72bb26b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,5 @@ AUTOMAKE_OPTIONS = 1.7 -ACLOCAL_AMFLAGS = -I config +ACLOCAL_AMFLAGS = -I m4 # Top-level Makefile.am for SASL # Rob Earhart # @@ -71,7 +71,7 @@ INSTALLOSX = endif SUBDIRS=include sasldb lib plugins utils doc man $(PWC) $(SAM) $(JAV) $(SAD) -EXTRA_DIST=config cmulocal win32 mac dlcompat-20010505 NTMakefile INSTALL.TXT \ +EXTRA_DIST=config win32 mac dlcompat-20010505 NTMakefile INSTALL.TXT \ libsasl2.pc.in pkgconfigdir = $(libdir)/pkgconfig diff --git a/SMakefile b/SMakefile deleted file mode 100644 index 8b2abf22..00000000 --- a/SMakefile +++ /dev/null @@ -1,45 +0,0 @@ -NEW_AUTOTOOLS=yes -export NEW_AUTOTOOLS - -if test ! -x configure; then - echo libtoolize - libtoolize - echo aclocal -I cmulocal -I config - aclocal -I cmulocal -I config - echo autoheader - autoheader - echo autoconf - autoconf - echo automake --add-missing --include-deps - automake --add-missing --include-deps -fi - -LIBS="" -case `uname` in - Linux) CFLAGS="${CFLAGS} -O2 -g" - LNEXTRA=" --with-javabase=/usr/local/lib/java" - ;; - - SunOS) CC="gcc" - CFLAGS="${CFLAGS} -O2 -g" - LNEXTRA=" --with-javabase=/usr/java --with-ipctype=doors" -# CC="cc" -# if test "${WASH_CYRUS_DEBUG}" = "t"; then -# CFLAGS="${CFLAGS} -xs -g" -# else -# CFLAGS="${CFLAGS} -xO3 -xdepend" -# fi - ;; -esac - -LD_LIBRARY_PATH=/usr/local/lib -MAKE=gmake -LNCOMMAND="${SRCDIR}/configure --with-staticsasl --prefix=/usr/local --enable-cmulocal --with-sfio=/usr/local --enable-java ${LNEXTRA} --with-saslauthd=/var/run/saslauthd --enable-login --enable-srp --disable-otp --disable-checkapop --enable-krb4 --with-dblib=none --with-authdaemond" -INSTCOMMAND="rm -rf ${DESTDIR}/*; \ - ${MAKE} DESTDIR=${DESTDIR} install; \ - echo 'usr/local /' > ${DESTDIR}/depot.conf; \ - echo '~delete sbin/smtptest' >> ${DESTDIR}/depot.conf; \ - mkdir ${DESTDIR}/usr/local/lib/java/lib; \ - jar cf ${DESTDIR}/usr/local/lib/java/lib/sasl.jar -C ${DESTDIR}/usr/local/lib/java/classes/sasl ." - -export CC CFLAGS CPPFLAGS LIBS LD_LIBRARY_PATH diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 00000000..38e3be29 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,37 @@ +#!/bin/sh +# Run this to generate all the initial makefiles, etc. +test -n "$srcdir" || srcdir=`dirname "$0"` +test -n "$srcdir" || srcdir=. + +olddir=`pwd` + +cd $srcdir + +(test -f configure.ac) || { + echo "*** ERROR: Directory "\`$srcdir\'" does not look like the top-level project directory ***" + exit 1 +} + +PKG_NAME=`autoconf --trace 'AC_INIT:$1' configure.ac` + +if [ "$#" = 0 -a "x$NOCONFIGURE" = "x" ]; then + echo "*** WARNING: I am going to run \`configure' with no arguments." >&2 + echo "*** If you wish to pass any to it, please specify them on the" >&2 + echo "*** \`$0\' command line." >&2 + echo "" >&2 +fi + +aclocal --install || exit 1 +autoreconf --verbose --force --install -Wno-portability || exit 1 + +cd $olddir +if [ "$NOCONFIGURE" = "" ]; then + $srcdir/configure "$@" || exit 1 + + if [ "$1" = "--help" ]; then exit 0 else + echo "Now type \`make\' to compile $PKG_NAME" || exit 1 + fi +else + echo "Skipping configure process." +fi + diff --git a/cmulocal/init_automake.m4 b/cmulocal/init_automake.m4 deleted file mode 100644 index fb2aff15..00000000 --- a/cmulocal/init_automake.m4 +++ /dev/null @@ -1,7 +0,0 @@ -dnl init_automake.m4--cmulocal automake setup macro -dnl Rob Earhart - -AC_DEFUN([CMU_INIT_AUTOMAKE], [ - AC_REQUIRE([AM_INIT_AUTOMAKE]) - ACLOCAL="$ACLOCAL -I \$(top_srcdir)/cmulocal" - ]) diff --git a/configure.ac b/configure.ac index 5eef61e6..76eb3b94 100644 --- a/configure.ac +++ b/configure.ac @@ -54,7 +54,7 @@ AC_INIT([cyrus-sasl], [cyrus-sasl], [https://docs.cyrus.foundation]) -AC_CONFIG_MACRO_DIR([config]) +AC_CONFIG_MACRO_DIR([m4]) dnl use ./config.cache as the default cache file. dnl we require a cache file to successfully configure our build. @@ -68,10 +68,6 @@ AC_CANONICAL_HOST AC_CANONICAL_TARGET AM_INIT_AUTOMAKE([1.11 tar-ustar dist-xz no-dist-gzip -Wno-portability subdir-objects]) -CMU_INIT_AUTOMAKE - -# and include our config dir scripts -ACLOCAL="$ACLOCAL -I \$(top_srcdir)/config" DIRS="" diff --git a/cmulocal/berkdb.m4 b/m4/berkdb.m4 similarity index 100% rename from cmulocal/berkdb.m4 rename to m4/berkdb.m4 diff --git a/cmulocal/bsd_sockets.m4 b/m4/bsd_sockets.m4 similarity index 100% rename from cmulocal/bsd_sockets.m4 rename to m4/bsd_sockets.m4 diff --git a/cmulocal/c-attribute.m4 b/m4/c-attribute.m4 similarity index 100% rename from cmulocal/c-attribute.m4 rename to m4/c-attribute.m4 diff --git a/cmulocal/common.m4 b/m4/common.m4 similarity index 100% rename from cmulocal/common.m4 rename to m4/common.m4 diff --git a/cmulocal/cyrus.m4 b/m4/cyrus.m4 similarity index 100% rename from cmulocal/cyrus.m4 rename to m4/cyrus.m4 diff --git a/cmulocal/ipv6.m4 b/m4/ipv6.m4 similarity index 100% rename from cmulocal/ipv6.m4 rename to m4/ipv6.m4 diff --git a/cmulocal/kerberos_v4.m4 b/m4/kerberos_v4.m4 similarity index 100% rename from cmulocal/kerberos_v4.m4 rename to m4/kerberos_v4.m4 diff --git a/cmulocal/openldap.m4 b/m4/openldap.m4 similarity index 100% rename from cmulocal/openldap.m4 rename to m4/openldap.m4 diff --git a/cmulocal/openssl.m4 b/m4/openssl.m4 similarity index 100% rename from cmulocal/openssl.m4 rename to m4/openssl.m4 diff --git a/cmulocal/plain.m4 b/m4/plain.m4 similarity index 100% rename from cmulocal/plain.m4 rename to m4/plain.m4 diff --git a/cmulocal/sasl2.m4 b/m4/sasl2.m4 similarity index 100% rename from cmulocal/sasl2.m4 rename to m4/sasl2.m4 diff --git a/cmulocal/sasldb.m4 b/m4/sasldb.m4 similarity index 100% rename from cmulocal/sasldb.m4 rename to m4/sasldb.m4 From 9c9fd1dbf632ee3b0a29493fb2d71acce998aaa3 Mon Sep 17 00:00:00 2001 From: Ken Murchison Date: Fri, 29 Jan 2016 16:35:51 -0500 Subject: [PATCH 230/796] configure.ac: we need to define HAVE_GSSAPI and KRB5_HEIMDAL --- configure.ac | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/configure.ac b/configure.ac index 76eb3b94..a31256b6 100644 --- a/configure.ac +++ b/configure.ac @@ -571,10 +571,15 @@ SASL_GSSAPI_CHK if test "$gssapi" != "no"; then AC_DEFINE(STATIC_GSSAPIV2,[],[Link GSSAPI Statically]) + AC_DEFINE(HAVE_GSSAPI,[],[Include GSSAPI/Kerberos 5 Support]) + mutex_default="no" if test "$gss_impl" = "mit"; then mutex_default="yes" + elif test "$gss_impl" = "heimdal"; then + AC_DEFINE(KRB5_HEIMDAL,[],[Using Heimdal]) fi + AC_MSG_CHECKING(to use mutexes aroung GSS calls) AC_ARG_ENABLE(gss_mutexes, [ --enable-gss_mutexes use mutexes around calls to the GSS library], use_gss_mutexes=$enableval, From 97ef5be66bee9c9d4db6dbbd3428bb7432a6f269 Mon Sep 17 00:00:00 2001 From: Ignacio Casal Quinteiro Date: Fri, 29 Jan 2016 22:53:03 +0100 Subject: [PATCH 231/796] configure: check for the kerberos header as well --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index a31256b6..d3f38af7 100644 --- a/configure.ac +++ b/configure.ac @@ -1311,7 +1311,7 @@ AC_HEADER_TIME AC_HEADER_STDC AC_HEADER_DIRENT AC_HEADER_SYS_WAIT -AC_CHECK_HEADERS(crypt.h des.h dlfcn.h fcntl.h limits.h malloc.h paths.h strings.h sys/file.h sys/time.h syslog.h unistd.h inttypes.h sys/uio.h sys/param.h sysexits.h stdarg.h varargs.h) +AC_CHECK_HEADERS(crypt.h des.h dlfcn.h fcntl.h limits.h malloc.h paths.h strings.h sys/file.h sys/time.h syslog.h unistd.h inttypes.h sys/uio.h sys/param.h sysexits.h stdarg.h varargs.h krb5.h) IPv6_CHECK_SS_FAMILY() IPv6_CHECK_SA_LEN() From f607d99bf6e3e2074ab925f96765488f29b821ec Mon Sep 17 00:00:00 2001 From: Ken Murchison Date: Sat, 30 Jan 2016 10:00:02 -0500 Subject: [PATCH 232/796] squashed a ton of compiler warnings --- lib/checkpw.c | 4 +-- lib/common.c | 4 +-- plugins/gs2.c | 2 +- plugins/gssapi.c | 14 +++++------ plugins/otp.c | 51 ++++++++++++++++++------------------- plugins/sasldb.c | 2 +- saslauthd/auth_httpform.c | 53 ++++++++++++++++----------------------- saslauthd/auth_krb5.c | 10 ++++---- saslauthd/krbtf.c | 3 ++- utils/pluginviewer.c | 4 +-- 10 files changed, 69 insertions(+), 78 deletions(-) diff --git a/lib/checkpw.c b/lib/checkpw.c index 0fa483c9..829ab9be 100644 --- a/lib/checkpw.c +++ b/lib/checkpw.c @@ -659,7 +659,7 @@ static int saslauthd_verify_password(sasl_conn_t *conn, #endif /* check to see if the user configured a rundir */ - if (_sasl_getcallback(conn, SASL_CB_GETOPT, &getopt, &context) == SASL_OK) { + if (_sasl_getcallback(conn, SASL_CB_GETOPT, (sasl_callback_ft *)&getopt, &context) == SASL_OK) { getopt(context, NULL, "saslauthd_path", &p, NULL); } if (p) { @@ -1041,7 +1041,7 @@ static int authdaemon_verify_password(sasl_conn_t *conn, int sock = -1; /* check to see if the user configured a rundir */ - if (_sasl_getcallback(conn, SASL_CB_GETOPT, &getopt, &context) == SASL_OK) { + if (_sasl_getcallback(conn, SASL_CB_GETOPT, (sasl_callback_ft *)&getopt, &context) == SASL_OK) { getopt(context, NULL, "authdaemond_path", &p, NULL); } if (!p) { diff --git a/lib/common.c b/lib/common.c index 4a24d74d..91ba4af4 100644 --- a/lib/common.c +++ b/lib/common.c @@ -1045,10 +1045,10 @@ int sasl_getprop(sasl_conn_t *conn, int propnum, const void **pvalue) break; case SASL_GSS_CREDS: if(conn->type == SASL_CONN_CLIENT) - *(void **)pvalue = + *(const void **)pvalue = ((sasl_client_conn_t *)conn)->cparams->gss_creds; else - *(void **)pvalue = + *(const void **)pvalue = ((sasl_server_conn_t *)conn)->sparams->gss_creds; break; case SASL_HTTP_REQUEST: { diff --git a/plugins/gs2.c b/plugins/gs2.c index 42d29c97..996aab82 100644 --- a/plugins/gs2.c +++ b/plugins/gs2.c @@ -275,7 +275,7 @@ gs2_common_mech_dispose(void *conn_context, const sasl_utils_t *utils) static void gs2_common_mech_free(void *global_context __attribute__((unused)), - const sasl_utils_t *utils) + const sasl_utils_t *utils __attribute__((unused))) { OM_uint32 minor; diff --git a/plugins/gssapi.c b/plugins/gssapi.c index d23a0d10..5204e54b 100644 --- a/plugins/gssapi.c +++ b/plugins/gssapi.c @@ -551,7 +551,7 @@ static context_t *sasl_gss_new_context(const sasl_utils_t *utils) static int sasl_gss_free_context_contents(context_t *text) { - OM_uint32 maj_stat, min_stat; + OM_uint32 min_stat; if (!text) return SASL_OK; @@ -562,28 +562,28 @@ static int sasl_gss_free_context_contents(context_t *text) #endif if (text->gss_ctx != GSS_C_NO_CONTEXT) { - maj_stat = gss_delete_sec_context(&min_stat,&text->gss_ctx, - GSS_C_NO_BUFFER); + (void) gss_delete_sec_context(&min_stat,&text->gss_ctx, + GSS_C_NO_BUFFER); text->gss_ctx = GSS_C_NO_CONTEXT; } if (text->client_name != GSS_C_NO_NAME) { - maj_stat = gss_release_name(&min_stat,&text->client_name); + (void) gss_release_name(&min_stat,&text->client_name); text->client_name = GSS_C_NO_NAME; } if (text->server_name != GSS_C_NO_NAME) { - maj_stat = gss_release_name(&min_stat,&text->server_name); + (void) gss_release_name(&min_stat,&text->server_name); text->server_name = GSS_C_NO_NAME; } if ( text->server_creds != GSS_C_NO_CREDENTIAL) { - maj_stat = gss_release_cred(&min_stat, &text->server_creds); + (void) gss_release_cred(&min_stat, &text->server_creds); text->server_creds = GSS_C_NO_CREDENTIAL; } if ( text->client_creds != GSS_C_NO_CREDENTIAL) { - maj_stat = gss_release_cred(&min_stat, &text->client_creds); + (void) gss_release_cred(&min_stat, &text->client_creds); text->client_creds = GSS_C_NO_CREDENTIAL; } diff --git a/plugins/otp.c b/plugins/otp.c index dd730651..9a04d969 100644 --- a/plugins/otp.c +++ b/plugins/otp.c @@ -119,7 +119,7 @@ static void otp_hash(const EVP_MD *md, char *in, size_t inlen, unsigned char *out, int swab) { EVP_MD_CTX mdctx; - char hash[EVP_MAX_MD_SIZE]; + unsigned char hash[EVP_MAX_MD_SIZE]; unsigned int i; int j; unsigned hashlen; @@ -146,7 +146,8 @@ static void otp_hash(const EVP_MD *md, char *in, size_t inlen, static int generate_otp(const sasl_utils_t *utils, algorithm_option_t *alg, unsigned seq, char *seed, - char *secret, char *otp) + unsigned char *secret, unsigned secret_len, + unsigned char *otp) { const EVP_MD *md; char *key; @@ -157,19 +158,18 @@ static int generate_otp(const sasl_utils_t *utils, return SASL_FAIL; } - if ((key = utils->malloc(strlen(seed) + strlen(secret) + 1)) == NULL) { + if ((key = utils->malloc(strlen(seed) + secret_len + 1)) == NULL) { SETERROR(utils, "cannot allocate OTP key"); return SASL_NOMEM; } /* initial step */ - strcpy(key, seed); - strcat(key, secret); + sprintf(key, "%s%.*s", seed, secret_len, secret); otp_hash(md, key, strlen(key), otp, alg->swab); /* computation step */ while (seq-- > 0) - otp_hash(md, otp, OTP_HASH_SIZE, otp, alg->swab); + otp_hash(md, (char *) otp, OTP_HASH_SIZE, otp, alg->swab); utils->free(key); @@ -587,12 +587,12 @@ int hex2bin(char *hex, unsigned char *bin, int binlen) return (i < binlen) ? SASL_BADAUTH : SASL_OK; } -static int make_secret(const sasl_utils_t *utils, - const char *alg, unsigned seq, char *seed, char *otp, +static int make_secret(const sasl_utils_t *utils, const char *alg, + unsigned seq, char *seed, unsigned char *otp, time_t timeout, sasl_secret_t **secret) { size_t sec_len; - unsigned char *data; + char *data; char buf[2*OTP_HASH_SIZE+1]; /* @@ -610,7 +610,7 @@ static int make_secret(const sasl_utils_t *utils, } (*secret)->len = (unsigned) sec_len; - data = (*secret)->data; + data = (char *) (*secret)->data; bin2hex(otp, OTP_HASH_SIZE, buf); buf[2*OTP_HASH_SIZE] = '\0'; @@ -628,7 +628,7 @@ static int parse_secret(const sasl_utils_t *utils, time_t *timeout) { if (strlen(secret) < seclen) { - unsigned char *c; + char *c; /* * old-style (binary) secret is stored as: @@ -753,8 +753,8 @@ static int word2bin(const sasl_utils_t *utils, /* alternate dictionary */ if (alt_dict) { EVP_MD_CTX mdctx; - char hash[EVP_MAX_MD_SIZE]; - int hashlen; + unsigned char hash[EVP_MAX_MD_SIZE]; + unsigned hashlen; EVP_DigestInit(&mdctx, md); EVP_DigestUpdate(&mdctx, word, strlen(word)); @@ -850,7 +850,7 @@ static int verify_response(server_context_t *text, const sasl_utils_t *utils, if (r == SASL_OK) { /* do one more hash (previous otp) and compare to stored otp */ - otp_hash(md, cur_otp, OTP_HASH_SIZE, prev_otp, text->alg->swab); + otp_hash(md, (char *) cur_otp, OTP_HASH_SIZE, prev_otp, text->alg->swab); if (!memcmp(prev_otp, text->otp, OTP_HASH_SIZE)) { /* update the secret with this seq/otp */ @@ -1071,7 +1071,7 @@ static int otp_server_mech_step1(server_context_t *text, result = params->utils->prop_request(propctx, store_request); if (result == SASL_OK) result = params->utils->prop_set(propctx, "cmusaslsecretOTP", - sec->data, sec->len); + (char *) sec->data, sec->len); if (result == SASL_OK) result = params->utils->auxprop_store(params->utils->conn, propctx, text->authid); @@ -1153,7 +1153,7 @@ otp_server_mech_step2(server_context_t *text, result = params->utils->prop_request(propctx, store_request); if (result == SASL_OK) result = params->utils->prop_set(propctx, "cmusaslsecretOTP", - sec->data, sec->len); + (char *) sec->data, sec->len); if (result == SASL_OK) result = params->utils->auxprop_store(params->utils->conn, propctx, text->authid); @@ -1244,7 +1244,7 @@ static void otp_server_mech_dispose(void *conn_context, r = utils->prop_request(propctx, store_request); if (!r) r = utils->prop_set(propctx, "cmusaslsecretOTP", - (sec ? sec->data : NULL), + (sec ? (char *) sec->data : NULL), (sec ? sec->len : 0)); if (!r) r = utils->auxprop_store(utils->conn, propctx, text->authid); @@ -1269,8 +1269,7 @@ static void otp_server_mech_dispose(void *conn_context, static int otp_setpass(void *glob_context __attribute__((unused)), sasl_server_params_t *sparams, const char *userstr, - const char *pass, - unsigned passlen __attribute__((unused)), + const char *pass, unsigned passlen, const char *oldpass __attribute__((unused)), unsigned oldpasslen __attribute__((unused)), unsigned flags) @@ -1315,7 +1314,7 @@ static int otp_setpass(void *glob_context __attribute__((unused)), unsigned int len; unsigned short randnum; char seed[OTP_SEED_MAX+1]; - char otp[OTP_HASH_SIZE]; + unsigned char otp[OTP_HASH_SIZE]; sparams->utils->getopt(sparams->utils->getopt_context, "OTP", "otp_mda", &mda, &len); @@ -1342,7 +1341,7 @@ static int otp_setpass(void *glob_context __attribute__((unused)), sprintf(seed, "%.2s%04u", sparams->serverFQDN, (randnum % 9999) + 1); r = generate_otp(sparams->utils, algs, OTP_SEQUENCE_DEFAULT, - seed, (char*) pass, otp); + seed, (unsigned char *) pass, passlen, otp); if (r != SASL_OK) { /* generate_otp() takes care of error message */ goto cleanup; @@ -1364,7 +1363,7 @@ static int otp_setpass(void *glob_context __attribute__((unused)), r = sparams->utils->prop_request(propctx, store_request); if (!r) r = sparams->utils->prop_set(propctx, "cmusaslsecretOTP", - (sec ? sec->data : NULL), + (sec ? (char *) sec->data : NULL), (sec ? sec->len : 0)); if (!r) r = sparams->utils->auxprop_store(sparams->utils->conn, propctx, user); @@ -1670,7 +1669,7 @@ static int otp_client_mech_step2(client_context_t *text, algorithm_option_t *alg; unsigned seq; char seed[OTP_SEED_MAX+1]; - char otp[OTP_HASH_SIZE]; + unsigned char otp[OTP_HASH_SIZE]; int init_done = 0; /* parse challenge */ @@ -1694,7 +1693,7 @@ static int otp_client_mech_step2(client_context_t *text, /* generate otp */ result = generate_otp(params->utils, alg, seq, seed, - text->password->data, otp); + text->password->data, text->password->len, otp); if (result != SASL_OK) return result; result = _plug_buf_alloc(params->utils, &(text->out_buf), @@ -1704,7 +1703,7 @@ static int otp_client_mech_step2(client_context_t *text, if (seq < OTP_SEQUENCE_REINIT) { unsigned short randnum; char new_seed[OTP_SEED_MAX+1]; - char new_otp[OTP_HASH_SIZE]; + unsigned char new_otp[OTP_HASH_SIZE]; /* try to reinitialize */ @@ -1717,7 +1716,7 @@ static int otp_client_mech_step2(client_context_t *text, } while (!strcasecmp(seed, new_seed)); result = generate_otp(params->utils, alg, OTP_SEQUENCE_DEFAULT, - new_seed, text->password->data, new_otp); + new_seed, text->password->data, text->password->len, new_otp); if (result == SASL_OK) { /* create an init-hex response */ diff --git a/plugins/sasldb.c b/plugins/sasldb.c index 403a9ccb..51214d65 100644 --- a/plugins/sasldb.c +++ b/plugins/sasldb.c @@ -248,7 +248,7 @@ static int sasldb_auxprop_store(void *glob_context __attribute__((unused)), ret = SASL_OK; for (cur = to_store; cur->name; cur++) { - char * value = (char *) (cur->values && cur->values[0]) ? cur->values[0] : NULL; + const char *value = (cur->values && cur->values[0]) ? cur->values[0] : NULL; if (cur->name[0] == '*') { continue; diff --git a/saslauthd/auth_httpform.c b/saslauthd/auth_httpform.c index aacf9888..c5c1b826 100644 --- a/saslauthd/auth_httpform.c +++ b/saslauthd/auth_httpform.c @@ -171,7 +171,7 @@ static char *url_escape( size_t length = strlen(string); size_t alloc = length+50; /* add some reserve */ char *out; - int outidx=0, inidx=0; + size_t outidx=0, inidx=0; /* END VARIABLES */ out = malloc(alloc); @@ -237,7 +237,8 @@ static char *create_post_data( { /* VARIABLES */ const char *ptr, *line_ptr; - char *buf, *buf_ptr; + char *esc_user = NULL, *esc_password = NULL, *esc_realm = NULL; + char *buf = NULL, *buf_ptr; int filtersize; int ulen, plen, rlen; int numpercents=0; @@ -245,28 +246,12 @@ static char *create_post_data( size_t i; /* END VARIABLES */ - user = url_escape(user); - if (!user) { + user = esc_user = url_escape(user); + password = esc_password = url_escape(password); + realm = esc_realm = url_escape(realm); + if (!user || !password || !realm) { logger(LOG_ERR, "auth_httpform:create_post_data", "failed to allocate memory"); - return NULL; - } - - password = url_escape(password); - if (!password) { - memset(user, 0, strlen(user)); - free(user); - logger(LOG_ERR, "auth_httpform:create_post_data", "failed to allocate memory"); - return NULL; - } - - realm = url_escape(realm); - if (!realm) { - memset(user, 0, strlen(user)); - free(user); - memset(password, 0, strlen(password)); - free(password); - logger(LOG_ERR, "auth_httpform:create_post_data", "failed to allocate memory"); - return NULL; + goto CLEANUP; } /* calculate memory needed for creating the complete query string. */ @@ -335,12 +320,18 @@ static char *create_post_data( memcpy(buf_ptr, line_ptr, strlen(line_ptr)+1); CLEANUP: - memset(user, 0, strlen(user)); - memset(password, 0, strlen(password)); - memset(realm, 0, strlen(realm)); - free(user); - free(password); - free(realm); + if (esc_user) { + memset(esc_user, 0, strlen(esc_user)); + free(esc_user); + } + if (esc_password) { + memset(esc_password, 0, strlen(esc_password)); + free(esc_password); + } + if (esc_realm) { + memset(esc_realm, 0, strlen(realm)); + free(esc_realm); + } return buf; } @@ -496,8 +487,8 @@ auth_httpform ( /* PARAMETERS */ const char *user, /* I: plaintext authenticator */ const char *password, /* I: plaintext password */ - const char *service, - const char *realm + const char *service __attribute__((unused)), + const char *realm /* I: user's realm */ /* END PARAMETERS */ ) { diff --git a/saslauthd/auth_krb5.c b/saslauthd/auth_krb5.c index 354e9700..e3e068d3 100644 --- a/saslauthd/auth_krb5.c +++ b/saslauthd/auth_krb5.c @@ -102,7 +102,7 @@ auth_krb5_init ( if (config) { keytabname = (char *) cfile_getstring(config, "krb5_keytab", keytabname); - verify_principal = cfile_getstring(config, "krb5_verify_principal", verify_principal); + verify_principal = (char *) cfile_getstring(config, "krb5_verify_principal", verify_principal); } return 0; @@ -145,7 +145,7 @@ form_principal_name ( if (forced_instance) { char *user_specified; - if (user_specified = strchr(user, '/')) { + if ((user_specified = strchr(user, '/'))) { if (strcmp(user_specified + 1, forced_instance)) { /* user not allowed to override sysadmin */ return -1; @@ -424,9 +424,9 @@ auth_krb5 ( krb5_get_init_creds_opt_init(&opts); /* 15 min should be more than enough */ krb5_get_init_creds_opt_set_tkt_life(&opts, 900); - if (code = krb5_get_init_creds_password(context, &creds, - auth_user, password, NULL, NULL, - 0, NULL, &opts)) { + if ((code = krb5_get_init_creds_password(context, &creds, + auth_user, password, NULL, NULL, + 0, NULL, &opts))) { krb5_cc_destroy(context, ccache); krb5_free_principal(context, auth_user); krb5_free_context(context); diff --git a/saslauthd/krbtf.c b/saslauthd/krbtf.c index 9084c1ce..370850dc 100644 --- a/saslauthd/krbtf.c +++ b/saslauthd/krbtf.c @@ -56,6 +56,7 @@ /* PUBLIC DEPENDENCIES */ #include +#include #include #include @@ -90,7 +91,7 @@ static char tf_dir[] = PATH_SASLAUTHD_RUNDIR "/.tf"; static char *tfn_cookie = 0; static int tfn_cookie_len = 0; static char pidstring[80]; -int pidstring_len = 0; +size_t pidstring_len = 0; /* END PRIVATE DEPENDENCIES */ #endif /* WANT_KRBTF */ diff --git a/utils/pluginviewer.c b/utils/pluginviewer.c index 15c2b0e0..41b859de 100644 --- a/utils/pluginviewer.c +++ b/utils/pluginviewer.c @@ -209,8 +209,8 @@ getpath(void *context, static int plugview_sasl_getopt ( - void *context, - const char *plugin_name, + void *context __attribute__((unused)), + const char *plugin_name __attribute__((unused)), const char *option, const char **result, unsigned *len From 37c1cba4cd582f3a0b0e11f5ac2330277f456371 Mon Sep 17 00:00:00 2001 From: Ignacio Casal Quinteiro Date: Sat, 30 Jan 2016 10:03:51 -0500 Subject: [PATCH 233/796] saslauthd/Makefile.am: Fix make dist --- saslauthd/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/saslauthd/Makefile.am b/saslauthd/Makefile.am index 2b45fc1b..f38097cf 100644 --- a/saslauthd/Makefile.am +++ b/saslauthd/Makefile.am @@ -26,7 +26,7 @@ testsaslauthd_LDADD = @LIB_SOCKET@ saslcache_SOURCES = saslcache.c -EXTRA_DIST = saslauthd.8 saslauthd.mdoc config include \ +EXTRA_DIST = saslauthd.8 saslauthd.mdoc include \ getnameinfo.c getaddrinfo.c LDAP_SASLAUTHD AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include -I$(top_srcdir)/../include DEFS = @DEFS@ -DSASLAUTHD_CONF_FILE_DEFAULT=\"@sysconfdir@/saslauthd.conf\" -I. -I$(srcdir) -I.. From aacd3d02fbff0dbe0b228a321de0e7a2a1b636c8 Mon Sep 17 00:00:00 2001 From: Ken Murchison Date: Sat, 30 Jan 2016 10:06:22 -0500 Subject: [PATCH 234/796] checkpw.c: wrap long lines --- lib/checkpw.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/checkpw.c b/lib/checkpw.c index 829ab9be..c38dffc4 100644 --- a/lib/checkpw.c +++ b/lib/checkpw.c @@ -659,7 +659,8 @@ static int saslauthd_verify_password(sasl_conn_t *conn, #endif /* check to see if the user configured a rundir */ - if (_sasl_getcallback(conn, SASL_CB_GETOPT, (sasl_callback_ft *)&getopt, &context) == SASL_OK) { + if (_sasl_getcallback(conn, SASL_CB_GETOPT, + (sasl_callback_ft *)&getopt, &context) == SASL_OK) { getopt(context, NULL, "saslauthd_path", &p, NULL); } if (p) { @@ -1041,7 +1042,8 @@ static int authdaemon_verify_password(sasl_conn_t *conn, int sock = -1; /* check to see if the user configured a rundir */ - if (_sasl_getcallback(conn, SASL_CB_GETOPT, (sasl_callback_ft *)&getopt, &context) == SASL_OK) { + if (_sasl_getcallback(conn, SASL_CB_GETOPT, + (sasl_callback_ft *)&getopt, &context) == SASL_OK) { getopt(context, NULL, "authdaemond_path", &p, NULL); } if (!p) { From 76dd88987eb7a916cc56585ccf38232c646483d8 Mon Sep 17 00:00:00 2001 From: Jered Floyd Date: Thu, 24 Mar 2016 12:40:42 -0400 Subject: [PATCH 235/796] auth_rimap.c: Don't hang when IMAP server closes connection --- saslauthd/auth_rimap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/saslauthd/auth_rimap.c b/saslauthd/auth_rimap.c index 24ed3e93..bdf89b3f 100644 --- a/saslauthd/auth_rimap.c +++ b/saslauthd/auth_rimap.c @@ -393,7 +393,7 @@ auth_rimap ( while( select (fds, &perm, NULL, NULL, &timeout ) >0 ) { if ( FD_ISSET(s, &perm) ) { ret = read(s, rbuf+rc, sizeof(rbuf)-rc); - if ( ret<0 ) { + if ( ret<=0 ) { rc = ret; break; } else { @@ -506,7 +506,7 @@ auth_rimap ( while( select (fds, &perm, NULL, NULL, &timeout ) >0 ) { if ( FD_ISSET(s, &perm) ) { ret = read(s, rbuf+rc, sizeof(rbuf)-rc); - if ( ret<0 ) { + if ( ret<=0 ) { rc = ret; break; } else { From 1b85b07a52c3bdae1037e9767ef188e8f8ca9a75 Mon Sep 17 00:00:00 2001 From: Spencer Jackson Date: Tue, 14 Jun 2016 10:19:54 -0400 Subject: [PATCH 236/796] digestmd5.c: plug memory leak in client step 2 --- plugins/digestmd5.c | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/digestmd5.c b/plugins/digestmd5.c index 39d8ef2d..66903947 100644 --- a/plugins/digestmd5.c +++ b/plugins/digestmd5.c @@ -4330,6 +4330,7 @@ static int digestmd5_client_mech_step2(client_context_t *ctext, if (nrealm == 1) { /* only one choice! */ + if (text->realm) params->utils->free(text->realm); text->realm = realms[0]; /* free realms */ From 0b8dcb972a4f226cf24ef3493e75c479c38004e9 Mon Sep 17 00:00:00 2001 From: Ignacio Casal Quinteiro Date: Fri, 24 Jun 2016 09:21:26 -0400 Subject: [PATCH 237/796] win32: GZ is deprecated, use RTC1 instead --- win32/common.mak | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/win32/common.mak b/win32/common.mak index b3dae197..5c9c4b28 100644 --- a/win32/common.mak +++ b/win32/common.mak @@ -208,7 +208,7 @@ CODEGEN=/MDd !ENDIF !ENDIF -CPP_PROJ=$(CODEGEN) /W3 /Gm $(EXCEPTHANDLING) /ZI /Od /D "_DEBUG" /D _CRT_SECURE_NO_DEPRECATE=1 $(CPPFLAGS) /FD /GZ /c +CPP_PROJ=$(CODEGEN) /W3 /Gm $(EXCEPTHANDLING) /ZI /Od /D "_DEBUG" /D _CRT_SECURE_NO_DEPRECATE=1 $(CPPFLAGS) /FD /RTC1 /c incremental=yes From 4c8e3f24bb943386a67b4de65bb849f562499dd0 Mon Sep 17 00:00:00 2001 From: Ken Murchison Date: Thu, 30 Jun 2016 10:34:12 -0400 Subject: [PATCH 238/796] ntlm.c, otp.c: support OpenSSL 1.1 --- plugins/ntlm.c | 40 ++++++++++++++++--- plugins/otp.c | 105 +++++++++++++++++++++++++++++++++++-------------- 2 files changed, 110 insertions(+), 35 deletions(-) diff --git a/plugins/ntlm.c b/plugins/ntlm.c index ba0288d4..b5630d8c 100644 --- a/plugins/ntlm.c +++ b/plugins/ntlm.c @@ -417,6 +417,29 @@ static unsigned char *P24(unsigned char *P24, unsigned char *P21, return P24; } +static HMAC_CTX *_plug_HMAC_CTX_new(const sasl_utils_t *utils) +{ + utils->log(NULL, SASL_LOG_DEBUG, "_plug_HMAC_CTX_new()"); + +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + return HMAC_CTX_new(); +#else + return utils->malloc(sizeof(EVP_MD_CTX)); +#endif +} + +static void _plug_HMAC_CTX_free(HMAC_CTX *ctx, const sasl_utils_t *utils) +{ + utils->log(NULL, SASL_LOG_DEBUG, "_plug_HMAC_CTX_free()"); + +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + HMAC_CTX_free(ctx); +#else + HMAC_cleanup(ctx); + utils->free(ctx); +#endif +} + static unsigned char *V2(unsigned char *V2, sasl_secret_t *passwd, const char *authid, const char *target, const unsigned char *challenge, @@ -424,7 +447,7 @@ static unsigned char *V2(unsigned char *V2, sasl_secret_t *passwd, const sasl_utils_t *utils, char **buf, unsigned *buflen, int *result) { - HMAC_CTX ctx; + HMAC_CTX *ctx = NULL; unsigned char hash[EVP_MAX_MD_SIZE]; char *upper; unsigned int len; @@ -435,6 +458,10 @@ static unsigned char *V2(unsigned char *V2, sasl_secret_t *passwd, SETERROR(utils, "cannot allocate NTLMv2 hash"); *result = SASL_NOMEM; } + else if ((ctx = _plug_HMAC_CTX_new(utils)) == NULL) { + SETERROR(utils, "cannot allocate HMAC CTX"); + *result = SASL_NOMEM; + } else { /* NTLMv2hash = HMAC-MD5(NTLMhash, unicode(ucase(authid + domain))) */ P16_nt(hash, passwd, utils, buf, buflen, result); @@ -449,17 +476,18 @@ static unsigned char *V2(unsigned char *V2, sasl_secret_t *passwd, HMAC(EVP_md5(), hash, MD4_DIGEST_LENGTH, (unsigned char *) *buf, 2 * len, hash, &len); /* V2 = HMAC-MD5(NTLMv2hash, challenge + blob) + blob */ - HMAC_Init(&ctx, hash, len, EVP_md5()); - HMAC_Update(&ctx, challenge, NTLM_NONCE_LENGTH); - HMAC_Update(&ctx, blob, bloblen); - HMAC_Final(&ctx, V2, &len); - HMAC_cleanup(&ctx); + HMAC_Init_ex(ctx, hash, len, EVP_md5(), NULL); + HMAC_Update(ctx, challenge, NTLM_NONCE_LENGTH); + HMAC_Update(ctx, blob, bloblen); + HMAC_Final(ctx, V2, &len); /* the blob is concatenated outside of this function */ *result = SASL_OK; } + if (ctx) _plug_HMAC_CTX_free(ctx, utils); + return V2; } diff --git a/plugins/otp.c b/plugins/otp.c index 9a04d969..07a58f57 100644 --- a/plugins/otp.c +++ b/plugins/otp.c @@ -96,6 +96,28 @@ static algorithm_option_t algorithm_options[] = { {NULL, 0, NULL} }; +static EVP_MD_CTX *_plug_EVP_MD_CTX_new(const sasl_utils_t *utils) +{ + utils->log(NULL, SASL_LOG_DEBUG, "_plug_EVP_MD_CTX_new()"); + +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + return EVP_MD_CTX_new(); +#else + return utils->malloc(sizeof(EVP_MD_CTX)); +#endif +} + +static void _plug_EVP_MD_CTX_free(EVP_MD_CTX *ctx, const sasl_utils_t *utils) +{ + utils->log(NULL, SASL_LOG_DEBUG, "_plug_EVP_MD_CTX_free()"); + +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + EVP_MD_CTX_free(ctx); +#else + utils->free(ctx); +#endif +} + /* Convert the binary data into ASCII hex */ void bin2hex(unsigned char *bin, int binlen, char *hex) { @@ -116,17 +138,16 @@ void bin2hex(unsigned char *bin, int binlen, char *hex) * swabbing bytes if necessary. */ static void otp_hash(const EVP_MD *md, char *in, size_t inlen, - unsigned char *out, int swab) + unsigned char *out, int swab, EVP_MD_CTX *mdctx) { - EVP_MD_CTX mdctx; unsigned char hash[EVP_MAX_MD_SIZE]; unsigned int i; int j; unsigned hashlen; - EVP_DigestInit(&mdctx, md); - EVP_DigestUpdate(&mdctx, in, inlen); - EVP_DigestFinal(&mdctx, hash, &hashlen); + EVP_DigestInit(mdctx, md); + EVP_DigestUpdate(mdctx, in, inlen); + EVP_DigestFinal(mdctx, hash, &hashlen); /* Fold the result into 64 bits */ for (i = OTP_HASH_SIZE; i < hashlen; i++) { @@ -150,7 +171,9 @@ static int generate_otp(const sasl_utils_t *utils, unsigned char *otp) { const EVP_MD *md; - char *key; + EVP_MD_CTX *mdctx = NULL; + char *key = NULL; + int r = SASL_OK; if (!(md = EVP_get_digestbyname(alg->evp_name))) { utils->seterror(utils->conn, 0, @@ -158,22 +181,31 @@ static int generate_otp(const sasl_utils_t *utils, return SASL_FAIL; } + if ((mdctx = _plug_EVP_MD_CTX_new(utils)) == NULL) { + SETERROR(utils, "cannot allocate MD CTX"); + r = SASL_NOMEM; + goto done; + } + if ((key = utils->malloc(strlen(seed) + secret_len + 1)) == NULL) { SETERROR(utils, "cannot allocate OTP key"); - return SASL_NOMEM; + r = SASL_NOMEM; + goto done; } /* initial step */ sprintf(key, "%s%.*s", seed, secret_len, secret); - otp_hash(md, key, strlen(key), otp, alg->swab); + otp_hash(md, key, strlen(key), otp, alg->swab, mdctx); /* computation step */ while (seq-- > 0) - otp_hash(md, (char *) otp, OTP_HASH_SIZE, otp, alg->swab); - - utils->free(key); + otp_hash(md, (char *) otp, OTP_HASH_SIZE, otp, alg->swab, mdctx); + + done: + if (key) utils->free(key); + if (mdctx) _plug_EVP_MD_CTX_free(mdctx, utils); - return SASL_OK; + return r; } static int parse_challenge(const sasl_utils_t *utils, @@ -693,7 +725,8 @@ static int strptrcasecmp(const void *arg1, const void *arg2) /* Convert the 6 words into binary data */ static int word2bin(const sasl_utils_t *utils, - char *words, unsigned char *bin, const EVP_MD *md) + char *words, unsigned char *bin, const EVP_MD *md, + EVP_MD_CTX *mdctx) { int i, j; char *c, *word, buf[OTP_RESPONSE_MAX+1]; @@ -752,13 +785,12 @@ static int word2bin(const sasl_utils_t *utils, /* alternate dictionary */ if (alt_dict) { - EVP_MD_CTX mdctx; unsigned char hash[EVP_MAX_MD_SIZE]; unsigned hashlen; - EVP_DigestInit(&mdctx, md); - EVP_DigestUpdate(&mdctx, word, strlen(word)); - EVP_DigestFinal(&mdctx, hash, &hashlen); + EVP_DigestInit(mdctx, md); + EVP_DigestUpdate(mdctx, word, strlen(word)); + EVP_DigestFinal(mdctx, hash, &hashlen); /* use lowest 11 bits */ x = ((hash[hashlen-2] & 0x7) << 8) | hash[hashlen-1]; @@ -802,6 +834,7 @@ static int verify_response(server_context_t *text, const sasl_utils_t *utils, char *response) { const EVP_MD *md; + EVP_MD_CTX *mdctx = NULL; char *c; int do_init = 0; unsigned char cur_otp[OTP_HASH_SIZE], prev_otp[OTP_HASH_SIZE]; @@ -815,6 +848,11 @@ static int verify_response(server_context_t *text, const sasl_utils_t *utils, return SASL_FAIL; } + if ((mdctx = _plug_EVP_MD_CTX_new(utils)) == NULL) { + SETERROR(utils, "cannot allocate MD CTX"); + return SASL_NOMEM; + } + /* eat leading whitespace */ c = response; while (isspace((int) *c)) c++; @@ -824,7 +862,7 @@ static int verify_response(server_context_t *text, const sasl_utils_t *utils, r = hex2bin(c+strlen(OTP_HEX_TYPE), cur_otp, OTP_HASH_SIZE); } else if (!strncasecmp(c, OTP_WORD_TYPE, strlen(OTP_WORD_TYPE))) { - r = word2bin(utils, c+strlen(OTP_WORD_TYPE), cur_otp, md); + r = word2bin(utils, c+strlen(OTP_WORD_TYPE), cur_otp, md, mdctx); } else if (!strncasecmp(c, OTP_INIT_HEX_TYPE, strlen(OTP_INIT_HEX_TYPE))) { @@ -834,7 +872,7 @@ static int verify_response(server_context_t *text, const sasl_utils_t *utils, else if (!strncasecmp(c, OTP_INIT_WORD_TYPE, strlen(OTP_INIT_WORD_TYPE))) { do_init = 1; - r = word2bin(utils, c+strlen(OTP_INIT_WORD_TYPE), cur_otp, md); + r = word2bin(utils, c+strlen(OTP_INIT_WORD_TYPE), cur_otp, md, mdctx); } else { SETERROR(utils, "unknown OTP extended response type"); @@ -843,14 +881,15 @@ static int verify_response(server_context_t *text, const sasl_utils_t *utils, } else { /* standard response, try word first, and then hex */ - r = word2bin(utils, c, cur_otp, md); + r = word2bin(utils, c, cur_otp, md, mdctx); if (r != SASL_OK) r = hex2bin(c, cur_otp, OTP_HASH_SIZE); } if (r == SASL_OK) { /* do one more hash (previous otp) and compare to stored otp */ - otp_hash(md, (char *) cur_otp, OTP_HASH_SIZE, prev_otp, text->alg->swab); + otp_hash(md, (char *) cur_otp, OTP_HASH_SIZE, + prev_otp, text->alg->swab, mdctx); if (!memcmp(prev_otp, text->otp, OTP_HASH_SIZE)) { /* update the secret with this seq/otp */ @@ -879,23 +918,28 @@ static int verify_response(server_context_t *text, const sasl_utils_t *utils, *new_resp++ = '\0'; } - if (!(new_chal && new_resp)) - return SASL_BADAUTH; + if (!(new_chal && new_resp)) { + r = SASL_BADAUTH; + goto done; + } if ((r = parse_challenge(utils, new_chal, &alg, &seq, seed, 1)) != SASL_OK) { - return r; + goto done; } - if (seq < 1 || !strcasecmp(seed, text->seed)) - return SASL_BADAUTH; + if (seq < 1 || !strcasecmp(seed, text->seed)) { + r = SASL_BADAUTH; + goto done; + } /* find the MDA */ if (!(md = EVP_get_digestbyname(alg->evp_name))) { utils->seterror(utils->conn, 0, "OTP algorithm %s is not available", alg->evp_name); - return SASL_BADAUTH; + r = SASL_BADAUTH; + goto done; } if (!strncasecmp(c, OTP_INIT_HEX_TYPE, strlen(OTP_INIT_HEX_TYPE))) { @@ -903,7 +947,7 @@ static int verify_response(server_context_t *text, const sasl_utils_t *utils, } else if (!strncasecmp(c, OTP_INIT_WORD_TYPE, strlen(OTP_INIT_WORD_TYPE))) { - r = word2bin(utils, new_resp, new_otp, md); + r = word2bin(utils, new_resp, new_otp, md, mdctx); } if (r == SASL_OK) { @@ -914,7 +958,10 @@ static int verify_response(server_context_t *text, const sasl_utils_t *utils, memcpy(text->otp, new_otp, OTP_HASH_SIZE); } } - + + done: + if (mdctx) _plug_EVP_MD_CTX_free(mdctx, utils); + return r; } From aec13877ee0264b2003e7c2e5b76a42b050dd402 Mon Sep 17 00:00:00 2001 From: Jan Parcel Date: Tue, 18 Oct 2016 10:42:31 -0400 Subject: [PATCH 239/796] Fix for DoS attack from Oracle: We have found some issues in saslauthd. We contacted various members who maintain saslauthd and they suggested we report this to you so that you can help to coordinate this issue with the saslauthd and other consumers using this library. The details are below. TLP: AMBER Libsasl2: DOS attack possible on saslauthd deamon if configured with doors Problem Description: If "--with-ipctype=doors" is used, there are 2 types or stages of DOS possible for saslauthd. It may result in Segmentation Fault(core dump) led by SIGSEGV, also it may result in leaking reference count under certain circumstances. CONFIGURE_OPTIONS += --with-ipctype=doors The SIGSEGV can be triggered by running the PoC code as an unprivileged user. There might be a similar case that could be created for the other ipctype, this PoC only applies to the doors type. When reference count is leaked but the SIGSEGV is prevented, it is possible to lock up saslauthd daemon instead of killing it, which in a way is worse, if there is a re-starter available. The suggested fix addresses (1)the SIGSEGV, (2)the reference count problem, and also (3) a mis-declaration issue which prevented compiling the code on Solaris. Using the PoC code (open-close-w-null.c) it was possible to prove that: 1. The saslauthd can be DoS'ed by SIGSEGV. 2. If SIGSEGV is prevented but the reference count link issue is not fixed, it's possible to freeze saslauthd in a state where it has 1 or 0 threads and won't create any more because it thinks it already has the maximum number of threads (usually 5). There are a couple of curious things about the "simple-ugly" fix. The nice-complex fix keeps the thread count at maximum reference count, which probably means it is a superior solution. However, that is for upstream to ultimately decide. A. It's not clear why, with both fixes in (reference count and checking the arguments) the thread gets killed, but it does NOT get killed if any of the OTHER parameters that can be checked are done wrong. For those cases, the thread appears to simply loop. B. Sometimes saslauthd gets 1-off on the thread count, it shows 0 but still has 1 thread. But testing has not shown a way to get off by 2. Both of these seem mild compared to the other 2 problems, but the debugger didn't show exactly what is going on. Both the simple-ugly fix and the nice-complex fix have been tested for the core dump issue, and only the simple-ugly fix allows us to see the reference-count issue, because it does not create a new thread until there is a new connection request. Our preference is for the project to release the fix by September 19, 2016. TLP: AMBER --- saslauthd/ipc_doors.c | 50 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/saslauthd/ipc_doors.c b/saslauthd/ipc_doors.c index 92f403c0..4e459d7c 100644 --- a/saslauthd/ipc_doors.c +++ b/saslauthd/ipc_doors.c @@ -203,13 +203,42 @@ void ipc_cleanup() { logger(L_DEBUG, L_FUNC, "door file removed: %s", door_file); } +/************************************************************* + * It is very rare but not impossible to have door_return actually return. + * When it does, it leaks a reference count. Prevent that. + **************************************************************/ + +void +safe_door_return(char *data, size_t len) +{ + (void) door_return(data, len, NULL, 0); + /* + * If door_return() failed, and our response wasn't empty, try sending + * an empty response. If that still doesn't work, then we must exit + * this thread. + */ + if (len > 0) { + logger(L_ERR, L_FUNC, "door_return: %s", strerror(errno)); + (void) door_return(NULL, 0, NULL, 0); + } + logger(L_ERR, L_FUNC, "door_return: %s", strerror(errno)); + + pthread_mutex_lock(&num_lock); + if (num_procs > 0 && num_thr > 0) { + num_thr--; + } + pthread_mutex_unlock(&num_lock); + pthread_exit(NULL); +} + /************************************************************* * Handle the door data, pass the request off to * do_auth() back in saslauthd-main.c, then send the * result back through the door. **************************************************************/ -void do_request(void *cookie, char *data, size_t datasize, door_desc_t *dp, size_t ndesc) { +static void +do_request(void *cookie, char *data, size_t datasize, door_desc_t *dp, uint_t ndesc) { unsigned short count = 0; /* input/output data byte count */ char *response = NULL; /* response to send to the client */ char response_buff[1024]; /* temporary response buffer */ @@ -227,6 +256,12 @@ void do_request(void *cookie, char *data, size_t datasize, door_desc_t *dp, size **************************************************************/ dataend = data + datasize; + if (data == NULL || datasize < sizeof(unsigned short)) { + logger(L_ERR, L_FUNC, "Bad data"); + send_no(""); + return; + } + /* login id */ memcpy(&count, data, sizeof(unsigned short)); @@ -328,8 +363,7 @@ void do_request(void *cookie, char *data, size_t datasize, door_desc_t *dp, size if (flags & VERBOSE) logger(L_DEBUG, L_FUNC, "response: %s", response_buff); - if(door_return(response_buff, strlen(response_buff), NULL, 0) < 0) - logger(L_ERR, L_FUNC, "door_return: %s", strerror(errno)); + safe_door_return(response_buff, strlen(response_buff)); return; } @@ -353,14 +387,17 @@ void need_thread(door_info_t *di) { pthread_create(&newt, &thread_attr, &server_thread, NULL); } - + /************************************************************* * Start a new server thread. * Make it available for door invocations. **************************************************************/ void *server_thread(void *arg) { pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); - door_return(NULL, 0, NULL, 0); + + safe_door_return(NULL, 0); + + return (void *) NULL; } /************************************************************* @@ -382,8 +419,7 @@ void send_no(char *mesg) { if (flags & VERBOSE) logger(L_DEBUG, L_FUNC, "response: %s", buff); - if(door_return(buff, strlen(buff), NULL, 0) < 0) - logger(L_ERR, L_FUNC, "door_return: %s", strerror(errno)); + safe_door_return(buff, strlen(buff)); return; } From eddca2a6ed25027bf00126605cf213a2c4da03a6 Mon Sep 17 00:00:00 2001 From: Ken Murchison Date: Tue, 18 Oct 2016 13:13:41 -0400 Subject: [PATCH 240/796] updated --- ChangeLog | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/ChangeLog b/ChangeLog index c7be303c..6a547fa8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,53 @@ +2016-10-18 Ken Murchison + * Fixed potential DoS attack on saslauthd/doors (from Oracle) + +2016-06-30 Ken Murchison + * plugins/ntlm.c, otp.c: support OpenSSL 1.1 + +2016-06-14 Ken Murchison + * plugins/digestmd5.c: Fix memory leak in client step 2 + +2016-03-24 Ken Murchison + * auth_rimap.c: Don't hang when IMAP server closes connection + +2016-01-29 Ken Murchison + * Build fixes from Ignacio Casal Quinteiro + +2015-12-26 Ken Murchison + * Build fixes from Ignacio Casal Quinteiro + +2015-11-16 Ken Murchison + * Build fixes from Ignacio Casal Quinteiro + +2015-10-14 Ken Murchison + * Build fixes from Ignacio Casal Quinteiro + +2015-07-17 Ken Murchison + * auth_krb5.c: added krb5_conv_krb4_instance option + +2014-11-17 Ken Murchison + * plugins/digestmd5.c: Fix memory leaks + +2014-11-17 Ken Murchison + * plugins/digestmd5.c: prevent going from step 3 to step 2 + +2013-09-13 Alexey Melnikov + * Fix memory leaks in DIGEST + +2013-08-30 Ken Murchison + * plugins/digestmd5.c: only locate reauth cache when reauth is + enabled + +2013-07-11 Alexey Melnikov + * Treat SCRAM and DIGEST as more secure than PLAIN when selecting + client-side mechanism + +2013-07-11 Alexey Melnikov + * Handle NULL return from crypt() + +2012-11-20 Alexey Melnikov + * Added support for lmdb + 2012-11-19 Alexey Melnikov * Final 2.1.26 tagged and released by Ken. From 88d82a310f69ce5e0e77d7771aefaa5b912d49bb Mon Sep 17 00:00:00 2001 From: Ken Murchison Date: Tue, 18 Oct 2016 13:14:48 -0400 Subject: [PATCH 241/796] Getting ready for 2.1.27 --- configure.ac | 6 +++--- include/sasl.h | 2 +- win32/common.mak | 2 +- win32/include/config.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index d3f38af7..199d93e2 100644 --- a/configure.ac +++ b/configure.ac @@ -49,10 +49,10 @@ dnl REMINDER: When changing the version number here, please also update dnl the values in win32/include/config.h and include/sasl.h as well. dnl AC_INIT([cyrus-sasl], - [2.1.26], - [https://git.cyrus.foundation/maniphest/], + [2.1.27], + [https://github.com/cyrusimap/cyrus-sasl/issues], [cyrus-sasl], - [https://docs.cyrus.foundation]) + [http://cyrusimap.org]) AC_CONFIG_MACRO_DIR([m4]) diff --git a/include/sasl.h b/include/sasl.h index 54afd9ca..eb001ecc 100755 --- a/include/sasl.h +++ b/include/sasl.h @@ -126,7 +126,7 @@ /* Keep in sync with win32/common.mak */ #define SASL_VERSION_MAJOR 2 #define SASL_VERSION_MINOR 1 -#define SASL_VERSION_STEP 26 +#define SASL_VERSION_STEP 27 /* A convenience macro: same as was defined in the OpenLDAP LDAPDB */ #define SASL_VERSION_FULL ((SASL_VERSION_MAJOR << 16) |\ diff --git a/win32/common.mak b/win32/common.mak index 5c9c4b28..194dfe95 100644 --- a/win32/common.mak +++ b/win32/common.mak @@ -2,7 +2,7 @@ #Keep in sync with include/sasl.h and win32/include/config.h SASL_VERSION_MAJOR=2 SASL_VERSION_MINOR=1 -SASL_VERSION_STEP=26 +SASL_VERSION_STEP=27 !IF "$(STATIC)" == "" STATIC=yes diff --git a/win32/include/config.h b/win32/include/config.h index 34408378..8d8548ea 100644 --- a/win32/include/config.h +++ b/win32/include/config.h @@ -55,7 +55,7 @@ #define PACKAGE "cyrus-sasl" /* Our version */ -#define VERSION "2.1.26" +#define VERSION "2.1.27" /* Visual Studio supports prototypes */ #define PROTOTYPES 1 From c813bf1f8b8179807bc2d4cd99c4246df98c35dd Mon Sep 17 00:00:00 2001 From: "Lorenzo M. Catucci" Date: Tue, 25 Oct 2016 11:42:02 +0200 Subject: [PATCH 242/796] New version of Enable PAM_RHOST patch Originally submitted as https://bugzilla.cyrusimap.org/show_bug.cgi?id=3468 The patch changes saslauthd's protocol ABI, and will require a soname change. The protocol as implemented in testsaslauthd has been updated too, this solves the issue Petr Lautrbach wrote about in https://bugzilla.redhat.com/show_bug.cgi?id=683797#c12 --- lib/checkpw.c | 25 ++++++++++++++++++++++--- saslauthd/auth_dce.c | 6 ++++-- saslauthd/auth_dce.h | 2 +- saslauthd/auth_getpwent.c | 3 ++- saslauthd/auth_getpwent.h | 2 +- saslauthd/auth_httpform.c | 3 ++- saslauthd/auth_httpform.h | 2 +- saslauthd/auth_krb4.c | 6 ++++-- saslauthd/auth_krb4.h | 2 +- saslauthd/auth_krb5.c | 9 ++++++--- saslauthd/auth_krb5.h | 2 +- saslauthd/auth_ldap.c | 6 ++++-- saslauthd/auth_ldap.h | 2 +- saslauthd/auth_pam.c | 14 ++++++++++++-- saslauthd/auth_pam.h | 2 +- saslauthd/auth_rimap.c | 3 ++- saslauthd/auth_rimap.h | 2 +- saslauthd/auth_sasldb.c | 5 +++-- saslauthd/auth_sasldb.h | 2 +- saslauthd/auth_shadow.c | 6 ++++-- saslauthd/auth_shadow.h | 2 +- saslauthd/auth_sia.c | 6 ++++-- saslauthd/auth_sia.h | 2 +- saslauthd/ipc_doors.c | 19 ++++++++++++++++++- saslauthd/ipc_unix.c | 20 +++++++++++++++++++- saslauthd/mechanisms.h | 4 ++-- saslauthd/saslauthd-main.c | 16 ++++++++-------- saslauthd/saslauthd-main.h | 3 ++- saslauthd/testsaslauthd.c | 20 +++++++++++++++----- 29 files changed, 144 insertions(+), 52 deletions(-) diff --git a/lib/checkpw.c b/lib/checkpw.c index c38dffc4..bfaad3b0 100644 --- a/lib/checkpw.c +++ b/lib/checkpw.c @@ -654,6 +654,8 @@ static int saslauthd_verify_password(sasl_conn_t *conn, char pwpath[sizeof(srvaddr.sun_path)]; const char *p = NULL; char *freeme = NULL; + char *freemetoo = NULL; + const char *client_addr = NULL; #ifdef USE_DOORS door_arg_t arg; #endif @@ -686,13 +688,19 @@ static int saslauthd_verify_password(sasl_conn_t *conn, user_realm = rtmp + 1; } + if (sasl_getprop(conn, SASL_IPREMOTEPORT, (const void **) & client_addr) == SASL_OK) { + if(_sasl_strdup(client_addr, &freemetoo, NULL) != SASL_OK) + goto fail; + client_addr = freemetoo; + } + /* * build request of the form: * - * count authid count password count service count realm + * count authid count password count service count realm client */ { - unsigned short max_len, req_len, u_len, p_len, s_len, r_len; + unsigned short max_len, req_len, u_len, p_len, s_len, r_len, c_len; max_len = (unsigned short) sizeof(query); @@ -700,7 +708,8 @@ static int saslauthd_verify_password(sasl_conn_t *conn, if ((strlen(userid) > USHRT_MAX) || (strlen(passwd) > USHRT_MAX) || (strlen(service) > USHRT_MAX) || - (user_realm && (strlen(user_realm) > USHRT_MAX))) { + (user_realm && (strlen(user_realm) > USHRT_MAX)) || + (client_addr && (strlen(client_addr) > USHRT_MAX))) { goto toobig; } @@ -708,6 +717,7 @@ static int saslauthd_verify_password(sasl_conn_t *conn, p_len = (strlen(passwd)); s_len = (strlen(service)); r_len = ((user_realm ? strlen(user_realm) : 0)); + c_len = ((client_addr ? strlen(client_addr): 0)); /* prevent buffer overflow */ req_len = 30; @@ -718,11 +728,14 @@ static int saslauthd_verify_password(sasl_conn_t *conn, if (max_len - req_len < s_len) goto toobig; req_len += s_len; if (max_len - req_len < r_len) goto toobig; + req_len += r_len; + if (max_len - req_len < c_len) goto toobig; u_len = htons(u_len); p_len = htons(p_len); s_len = htons(s_len); r_len = htons(r_len); + c_len = htons(c_len); memcpy(query_end, &u_len, sizeof(unsigned short)); query_end += sizeof(unsigned short); @@ -739,6 +752,10 @@ static int saslauthd_verify_password(sasl_conn_t *conn, memcpy(query_end, &r_len, sizeof(unsigned short)); query_end += sizeof(unsigned short); if (user_realm) while (*user_realm) *query_end++ = *user_realm++; + + memcpy(query_end, &c_len, sizeof(unsigned short)); + query_end += sizeof(unsigned short); + if(client_addr) while (*client_addr) *query_end++ = *client_addr++; } #ifdef USE_DOORS @@ -840,6 +857,7 @@ static int saslauthd_verify_password(sasl_conn_t *conn, #endif /* USE_DOORS */ if(freeme) free(freeme); + if(freemetoo) free(freemetoo); if (!strncmp(response, "OK", 2)) { return SASL_OK; @@ -854,6 +872,7 @@ static int saslauthd_verify_password(sasl_conn_t *conn, fail: if (freeme) free(freeme); + if (freemetoo) free(freemetoo); return SASL_FAIL; } diff --git a/saslauthd/auth_dce.c b/saslauthd/auth_dce.c index 42a2b600..6e7e93b1 100644 --- a/saslauthd/auth_dce.c +++ b/saslauthd/auth_dce.c @@ -56,7 +56,8 @@ auth_dce( const char *login, /* I: plaintext authenticator */ const char *password, /* I: plaintext password */ const char *service __attribute__((unused)), - const char *realm __attribute__((unused)) + const char *realm __attribute__((unused)), + const char *remote __attribute__((unused)) /* END PARAMETERS */ ) { @@ -104,7 +105,8 @@ auth_dce( const char *login __attribute__((unused)), const char *password __attribute__((unused)), const char *service __attribute__((unused)), - const char *realm __attribute__((unused)) + const char *realm __attribute__((unused)), + const char *remote __attribute__((unused)) ) { return NULL; diff --git a/saslauthd/auth_dce.h b/saslauthd/auth_dce.h index d96ee158..fb9c2441 100644 --- a/saslauthd/auth_dce.h +++ b/saslauthd/auth_dce.h @@ -26,4 +26,4 @@ * END COPYRIGHT */ -char *auth_dce(const char *, const char *, const char *, const char *); +char *auth_dce(const char *, const char *, const char *, const char *, const char *); diff --git a/saslauthd/auth_getpwent.c b/saslauthd/auth_getpwent.c index 84e1cc2c..7b2671bf 100644 --- a/saslauthd/auth_getpwent.c +++ b/saslauthd/auth_getpwent.c @@ -72,7 +72,8 @@ auth_getpwent ( const char *login, /* I: plaintext authenticator */ const char *password, /* I: plaintext password */ const char *service __attribute__((unused)), - const char *realm __attribute__((unused)) + const char *realm __attribute__((unused)), + const char *remote __attribute__((unused)) /* I: remote host address */ /* END PARAMETERS */ ) { diff --git a/saslauthd/auth_getpwent.h b/saslauthd/auth_getpwent.h index 0b25f0af..788c4991 100644 --- a/saslauthd/auth_getpwent.h +++ b/saslauthd/auth_getpwent.h @@ -25,4 +25,4 @@ * DAMAGE. * END COPYRIGHT */ -char *auth_getpwent(const char *, const char *, const char *, const char *); +char *auth_getpwent(const char *, const char *, const char *, const char *, const char *); diff --git a/saslauthd/auth_httpform.c b/saslauthd/auth_httpform.c index c5c1b826..107e605f 100644 --- a/saslauthd/auth_httpform.c +++ b/saslauthd/auth_httpform.c @@ -488,7 +488,8 @@ auth_httpform ( const char *user, /* I: plaintext authenticator */ const char *password, /* I: plaintext password */ const char *service __attribute__((unused)), - const char *realm /* I: user's realm */ + const char *realm, /* I: user's realm */ + const char *remote __attribute__((unused)) /* I: client address */ /* END PARAMETERS */ ) { diff --git a/saslauthd/auth_httpform.h b/saslauthd/auth_httpform.h index 2a95e9c9..b42e4455 100644 --- a/saslauthd/auth_httpform.h +++ b/saslauthd/auth_httpform.h @@ -25,5 +25,5 @@ * DAMAGE. * END COPYRIGHT */ -char *auth_httpform(const char *, const char *, const char *, const char *); +char *auth_httpform(const char *, const char *, const char *, const char *, const char *); int auth_httpform_init(void); diff --git a/saslauthd/auth_krb4.c b/saslauthd/auth_krb4.c index 39e2bd2a..6f8f2022 100644 --- a/saslauthd/auth_krb4.c +++ b/saslauthd/auth_krb4.c @@ -171,7 +171,8 @@ auth_krb4 ( const char *login, /* I: plaintext authenticator */ const char *password, /* I: plaintext password */ const char *service, - const char *realm_in + const char *realm_in, + const char *remote /* I: remote host address */ /* END PARAMETERS */ ) { @@ -282,7 +283,8 @@ auth_krb4 ( const char *login __attribute__((unused)), const char *password __attribute__((unused)), const char *service __attribute__((unused)), - const char *realm __attribute__((unused)) + const char *realm __attribute__((unused)), + const char *remote __attribute__((unused)) ) { return NULL; diff --git a/saslauthd/auth_krb4.h b/saslauthd/auth_krb4.h index 7de941e0..7ffa3902 100644 --- a/saslauthd/auth_krb4.h +++ b/saslauthd/auth_krb4.h @@ -25,5 +25,5 @@ * DAMAGE. * END COPYRIGHT */ -char *auth_krb4(const char *, const char *, const char *, const char *); +char *auth_krb4(const char *, const char *, const char *, const char *, const char *); int auth_krb4_init(void); diff --git a/saslauthd/auth_krb5.c b/saslauthd/auth_krb5.c index e3e068d3..ce8fb6d9 100644 --- a/saslauthd/auth_krb5.c +++ b/saslauthd/auth_krb5.c @@ -179,7 +179,8 @@ auth_krb5 ( const char *user, /* I: plaintext authenticator */ const char *password, /* I: plaintext password */ const char *service, /* I: service authenticating to */ - const char *realm /* I: user's realm */ + const char *realm, /* I: user's realm */ + const char *remote /* I: remote host address */ /* END PARAMETERS */ ) { @@ -365,7 +366,8 @@ auth_krb5 ( const char *user, /* I: plaintext authenticator */ const char *password, /* I: plaintext password */ const char *service, /* I: service authenticating to */ - const char *realm /* I: user's realm */ + const char *realm, /* I: user's realm */ + const char *remote /* I: remote host address */ /* END PARAMETERS */ ) { @@ -473,7 +475,8 @@ auth_krb5 ( const char *login __attribute__((unused)), const char *password __attribute__((unused)), const char *service __attribute__((unused)), - const char *realm __attribute__((unused)) + const char *realm __attribute__((unused)), + const char *remote __attribute__((unused)) ) { return NULL; diff --git a/saslauthd/auth_krb5.h b/saslauthd/auth_krb5.h index 39a3a882..fac35c35 100644 --- a/saslauthd/auth_krb5.h +++ b/saslauthd/auth_krb5.h @@ -25,5 +25,5 @@ * DAMAGE. * END COPYRIGHT */ -char *auth_krb5(const char *, const char *, const char *, const char *); +char *auth_krb5(const char *, const char *, const char *, const char *, const char *); int auth_krb5_init(void); diff --git a/saslauthd/auth_ldap.c b/saslauthd/auth_ldap.c index 2cd50f37..d10c945f 100644 --- a/saslauthd/auth_ldap.c +++ b/saslauthd/auth_ldap.c @@ -60,7 +60,8 @@ auth_ldap( const char *login, /* I: plaintext authenticator */ const char *password, /* I: plaintext password */ const char *service, - const char *realm + const char *realm, + const char *remote /* I: remote host address */ /* END PARAMETERS */ ) { @@ -110,7 +111,8 @@ auth_ldap( const char *login __attribute__((unused)), const char *password __attribute__((unused)), const char *service __attribute__((unused)), - const char *realm __attribute__((unused)) + const char *realm __attribute__((unused)), + const char *remote __attribute__((unused)) ) { return NULL; diff --git a/saslauthd/auth_ldap.h b/saslauthd/auth_ldap.h index 983a6fca..fdc72789 100644 --- a/saslauthd/auth_ldap.h +++ b/saslauthd/auth_ldap.h @@ -25,5 +25,5 @@ * DAMAGE. * END COPYRIGHT */ -char *auth_ldap(const char *, const char *, const char *, const char *); +char *auth_ldap(const char *, const char *, const char *, const char *, const char *); int auth_ldap_init(void); diff --git a/saslauthd/auth_pam.c b/saslauthd/auth_pam.c index 5af938f2..23862850 100644 --- a/saslauthd/auth_pam.c +++ b/saslauthd/auth_pam.c @@ -186,7 +186,8 @@ auth_pam ( const char *login, /* I: plaintext authenticator */ const char *password, /* I: plaintext password */ const char *service, /* I: service name */ - const char *realm __attribute__((unused)) + const char *realm __attribute__((unused)), + const char *remote /* I: remote host address */ /* END PARAMETERS */ ) { @@ -213,6 +214,14 @@ auth_pam ( my_appdata.pamh = pamh; + char * remote_host = strdup(remote); + if (remote_host) { + char * semicol = strchr(remote_host, ';'); + if (semicol) * semicol = NULL; /* truncate remote_host at the ';' port separator */ + pam_set_item(pamh, PAM_RHOST, remote_host); + free (remote_host); + } + rc = pam_authenticate(pamh, PAM_SILENT); if (rc != PAM_SUCCESS) { syslog(LOG_DEBUG, "DEBUG: auth_pam: pam_authenticate failed: %s", @@ -242,7 +251,8 @@ auth_pam( const char *login __attribute__((unused)), const char *password __attribute__((unused)), const char *service __attribute__((unused)), - const char *realm __attribute__((unused)) + const char *realm __attribute__((unused)), + const char *remote __attribute__((unused)) ) { return NULL; diff --git a/saslauthd/auth_pam.h b/saslauthd/auth_pam.h index 4f57e8d7..d15cb462 100644 --- a/saslauthd/auth_pam.h +++ b/saslauthd/auth_pam.h @@ -32,4 +32,4 @@ * DAMAGE. * END COPYRIGHT */ -char *auth_pam(const char *, const char *, const char *, const char *); +char *auth_pam(const char *, const char *, const char *, const char *, const char *); diff --git a/saslauthd/auth_rimap.c b/saslauthd/auth_rimap.c index bdf89b3f..a2aa05e6 100644 --- a/saslauthd/auth_rimap.c +++ b/saslauthd/auth_rimap.c @@ -309,7 +309,8 @@ auth_rimap ( const char *login, /* I: plaintext authenticator */ const char *password, /* I: plaintext password */ const char *service __attribute__((unused)), - const char *realm __attribute__((unused)) + const char *realm __attribute__((unused)), + const char *remote __attribute__((unused)) /* I: remote host address */ /* END PARAMETERS */ ) { diff --git a/saslauthd/auth_rimap.h b/saslauthd/auth_rimap.h index 8eb101aa..760c9b35 100644 --- a/saslauthd/auth_rimap.h +++ b/saslauthd/auth_rimap.h @@ -25,5 +25,5 @@ * DAMAGE. * END COPYRIGHT */ -char *auth_rimap(const char *, const char *, const char *, const char *); +char *auth_rimap(const char *, const char *, const char *, const char *, const char *); int auth_rimap_init(void); diff --git a/saslauthd/auth_sasldb.c b/saslauthd/auth_sasldb.c index 720d339a..88906280 100644 --- a/saslauthd/auth_sasldb.c +++ b/saslauthd/auth_sasldb.c @@ -118,13 +118,14 @@ auth_sasldb ( const char *login, /* I: plaintext authenticator */ const char *password, /* I: plaintext password */ const char *service __attribute__((unused)), - const char *realm + const char *realm, #else const char *login __attribute__((unused)),/* I: plaintext authenticator */ const char *password __attribute__((unused)), /* I: plaintext password */ const char *service __attribute__((unused)), - const char *realm __attribute__((unused)) + const char *realm __attribute__((unused)), #endif + const char *remote __attribute__((unused)) /* I: remote host address */ /* END PARAMETERS */ ) { diff --git a/saslauthd/auth_sasldb.h b/saslauthd/auth_sasldb.h index 633c360f..4d225fe3 100644 --- a/saslauthd/auth_sasldb.h +++ b/saslauthd/auth_sasldb.h @@ -25,4 +25,4 @@ * DAMAGE. * END COPYRIGHT */ -char *auth_sasldb(const char *, const char *, const char *, const char *); +char *auth_sasldb(const char *, const char *, const char *, const char *, const char *); diff --git a/saslauthd/auth_shadow.c b/saslauthd/auth_shadow.c index d69e380f..d35892bb 100644 --- a/saslauthd/auth_shadow.c +++ b/saslauthd/auth_shadow.c @@ -95,7 +95,8 @@ auth_shadow ( const char *login, /* I: plaintext authenticator */ const char *password, /* I: plaintext password */ const char *service __attribute__((unused)), - const char *realm __attribute__((unused)) + const char *realm __attribute__((unused)), + const char *remote __attribute__((unused)) /* I: remote host address */ /* END PARAMETERS */ ) { @@ -315,7 +316,8 @@ auth_shadow ( const char *login __attribute__((unused)), const char *passwd __attribute__((unused)), const char *service __attribute__((unused)), - const char *realm __attribute__((unused)) + const char *realm __attribute__((unused)), + const char *remote __attribute__((unused)) ) { return NULL; diff --git a/saslauthd/auth_shadow.h b/saslauthd/auth_shadow.h index b08c06e5..7e96a594 100644 --- a/saslauthd/auth_shadow.h +++ b/saslauthd/auth_shadow.h @@ -25,4 +25,4 @@ * DAMAGE. * END COPYRIGHT */ -char *auth_shadow(const char *, const char *, const char *, const char *); +char *auth_shadow(const char *, const char *, const char *, const char *, const char *); diff --git a/saslauthd/auth_sia.c b/saslauthd/auth_sia.c index 72268b2e..4f8d5a4f 100644 --- a/saslauthd/auth_sia.c +++ b/saslauthd/auth_sia.c @@ -56,7 +56,8 @@ auth_sia ( const char *login, /* I: plaintext authenticator */ const char *password, /* I: plaintext password */ const char *service __attribute__((unused)), - const char *realm __attribute__((unused)) + const char *realm __attribute__((unused)), + const char *remote __attribute__((unused)) /* I: remote host address */ /* END PARAMETERS */ ) { @@ -84,7 +85,8 @@ auth_sia( const char *login __attribute__((unused)), const char *password __attribute__((unused)), const char *service __attribute__((unused)), - const char *realm __attribute__((unused)) + const char *realm __attribute__((unused)), + const char *remote __attribute__((unused)) ) { return NULL; diff --git a/saslauthd/auth_sia.h b/saslauthd/auth_sia.h index 56a328b4..932a4fbb 100644 --- a/saslauthd/auth_sia.h +++ b/saslauthd/auth_sia.h @@ -25,4 +25,4 @@ * DAMAGE. * END COPYRIGHT */ -char *auth_sia(const char *, const char *, const char *, const char *); +char *auth_sia(const char *, const char *, const char *, const char *, const char *); diff --git a/saslauthd/ipc_doors.c b/saslauthd/ipc_doors.c index 4e459d7c..cea37ed9 100644 --- a/saslauthd/ipc_doors.c +++ b/saslauthd/ipc_doors.c @@ -247,6 +247,7 @@ do_request(void *cookie, char *data, size_t datasize, door_desc_t *dp, uint_t nd char password[MAX_REQ_LEN + 1]; /* password for authentication */ char service[MAX_REQ_LEN + 1]; /* service name for authentication */ char realm[MAX_REQ_LEN + 1]; /* user realm for authentication */ + char client_addr[MAX_REQ_LEN + 1]; /* client address and port */ /************************************************************** @@ -329,6 +330,22 @@ do_request(void *cookie, char *data, size_t datasize, door_desc_t *dp, uint_t nd memcpy(realm, data, count); realm[count] = '\0'; + /* client_addr */ + memcpy(&count, data, sizeof(unsigned short)); + + count = ntohs(count); + data += sizeof(unsigned short); + + if (count > MAX_REQ_LEN || data + count > dataend) { + logger(L_ERR, L_FUNC, "client_addr exceeds MAX_REQ_LEN: %d", + MAX_REQ_LEN); + send_no(""); + return; + } + + memcpy(client_addr, data, count); + client_addr[count] = '\0'; + /************************************************************** * We don't allow NULL passwords or login names **************************************************************/ @@ -347,7 +364,7 @@ do_request(void *cookie, char *data, size_t datasize, door_desc_t *dp, uint_t nd /************************************************************** * Get the mechanism response from do_auth() and send it back. **************************************************************/ - response = do_auth(login, password, service, realm); + response = do_auth(login, password, service, realm, client_addr); memset(password, 0, strlen(password)); diff --git a/saslauthd/ipc_unix.c b/saslauthd/ipc_unix.c index 58a1fa68..d0d15118 100644 --- a/saslauthd/ipc_unix.c +++ b/saslauthd/ipc_unix.c @@ -329,6 +329,7 @@ void do_request(int conn_fd) { char password[MAX_REQ_LEN + 1]; /* password for authentication */ char service[MAX_REQ_LEN + 1]; /* service name for authentication */ char realm[MAX_REQ_LEN + 1]; /* user realm for authentication */ + char client_addr[MAX_REQ_LEN + 1]; /* client address and port */ /************************************************************** @@ -405,6 +406,23 @@ void do_request(int conn_fd) { realm[count] = '\0'; + /* client_addr */ + if (rx_rec(conn_fd, (void *)&count, (size_t)sizeof(count)) != (ssize_t)sizeof(count)) + return; + + count = ntohs(count); + + if (count > MAX_REQ_LEN) { + logger(L_ERR, L_FUNC, "client address exceeded MAX_REQ_LEN: %d", MAX_REQ_LEN); + send_no(conn_fd, ""); + return; + } + + if (rx_rec(conn_fd, (void *)&client_addr, (size_t)count) != (ssize_t)count) + return; + + client_addr[count] = '\0'; + /************************************************************** * We don't allow NULL passwords or login names **************************************************************/ @@ -423,7 +441,7 @@ void do_request(int conn_fd) { /************************************************************** * Get the mechanism response from do_auth() and send it back. **************************************************************/ - response = do_auth(login, password, service, realm); + response = do_auth(login, password, service, realm, client_addr); memset(password, 0, strlen(password)); diff --git a/saslauthd/mechanisms.h b/saslauthd/mechanisms.h index 3ed8d1c0..326adb95 100644 --- a/saslauthd/mechanisms.h +++ b/saslauthd/mechanisms.h @@ -40,8 +40,8 @@ typedef struct { char *name; /* name of the mechanism */ int (*initialize)(void); /* initialization function */ char *(*authenticate)(const char *, const char *, - const char *, const char *); /* authentication - function */ + const char *, const char *, + const char *); /* authentication function */ } authmech_t; extern authmech_t mechanisms[]; /* array of supported auth mechs */ diff --git a/saslauthd/saslauthd-main.c b/saslauthd/saslauthd-main.c index e869eb33..c3446f81 100644 --- a/saslauthd/saslauthd-main.c +++ b/saslauthd/saslauthd-main.c @@ -378,7 +378,7 @@ int main(int argc, char **argv) { * return a pointer to a string to send back to the client. * The caller is responsible for freeing the pointer. **************************************************************/ -char *do_auth(const char *_login, const char *password, const char *service, const char *realm) { +char *do_auth(const char *_login, const char *password, const char *service, const char *realm, const char *remote) { struct cache_result lkup_result; char *response; @@ -407,7 +407,7 @@ char *do_auth(const char *_login, const char *password, const char *service, con response = strdup("OK"); cached = 1; } else { - response = auth_mech->authenticate(login, password, service, realm); + response = auth_mech->authenticate(login, password, service, realm, remote); if (response == NULL) { logger(L_ERR, L_FUNC, "internal mechanism failure: %s", auth_mech->name); @@ -420,18 +420,18 @@ char *do_auth(const char *_login, const char *password, const char *service, con if (flags & VERBOSE) { if (cached) - logger(L_DEBUG, L_FUNC, "auth success (cached): [user=%s] [service=%s] [realm=%s]", \ - login, service, realm); + logger(L_DEBUG, L_FUNC, "auth success (cached): [user=%s] [service=%s] [realm=%s] [remote=%s]", \ + login, service, realm, remote); else - logger(L_DEBUG, L_FUNC, "auth success: [user=%s] [service=%s] [realm=%s] [mech=%s]", \ - login, service, realm, auth_mech->name); + logger(L_DEBUG, L_FUNC, "auth success: [user=%s] [service=%s] [realm=%s] [remote=%s] [mech=%s]", \ + login, service, realm, remote, auth_mech->name); } return response; } if (strncmp(response, "NO", 2) == 0) { - logger(L_INFO, L_FUNC, "auth failure: [user=%s] [service=%s] [realm=%s] [mech=%s] [reason=%s]", \ - login, service, realm, auth_mech->name, + logger(L_INFO, L_FUNC, "auth failure: [user=%s] [service=%s] [realm=%s] [remote=%s] [mech=%s] [reason=%s]", \ + login, service, realm, remote, auth_mech->name, strlen(response) >= 4 ? response+3 : "Unknown"); return response; diff --git a/saslauthd/saslauthd-main.h b/saslauthd/saslauthd-main.h index 754626c6..e6956b56 100644 --- a/saslauthd/saslauthd-main.h +++ b/saslauthd/saslauthd-main.h @@ -89,7 +89,8 @@ /* saslauthd-main.c */ extern char *do_auth(const char *, const char *, - const char *, const char *); + const char *, const char *, + const char *); extern void set_auth_mech(const char *); extern void set_max_procs(const char *); extern void set_mech_option(const char *); diff --git a/saslauthd/testsaslauthd.c b/saslauthd/testsaslauthd.c index 5de666e7..0047ae7d 100644 --- a/saslauthd/testsaslauthd.c +++ b/saslauthd/testsaslauthd.c @@ -96,7 +96,8 @@ static int saslauthd_verify_password(const char *saslauthd_path, const char *userid, const char *passwd, const char *service, - const char *user_realm) + const char *user_realm, + const char *client_addr) { char response[1024]; char query[8192]; @@ -130,12 +131,13 @@ static int saslauthd_verify_password(const char *saslauthd_path, * count authid count password count service count realm */ { - unsigned short u_len, p_len, s_len, r_len; + unsigned short u_len, p_len, s_len, r_len, c_len; u_len = htons(strlen(userid)); p_len = htons(strlen(passwd)); s_len = htons(strlen(service)); r_len = htons((user_realm ? strlen(user_realm) : 0)); + c_len = htons(((client_addr ? strlen(client_addr): 0))); memcpy(query_end, &u_len, sizeof(unsigned short)); query_end += sizeof(unsigned short); @@ -152,6 +154,10 @@ static int saslauthd_verify_password(const char *saslauthd_path, memcpy(query_end, &r_len, sizeof(unsigned short)); query_end += sizeof(unsigned short); if (user_realm) while (*user_realm) *query_end++ = *user_realm++; + + memcpy(query_end, &c_len, sizeof(unsigned short)); + query_end += sizeof(unsigned short); + if (client_addr) while (*client_addr) *query_end++ = *client_addr++; } #ifdef USE_DOORS @@ -248,13 +254,17 @@ main(int argc, char *argv[]) { const char *user = NULL, *password = NULL; const char *realm = NULL, *service = NULL, *path = NULL; + const char *client_addr = NULL; int c; int flag_error = 0; int result = 0; int repeat = 0; - while ((c = getopt(argc, argv, "p:u:r:s:f:R:")) != EOF) + while ((c = getopt(argc, argv, "p:u:r:s:f:R:a:")) != EOF) switch (c) { + case 'a': + client_addr = optarg; + break; case 'R': repeat = atoi(optarg); break; @@ -284,7 +294,7 @@ main(int argc, char *argv[]) if (flag_error) { (void)fprintf(stderr, "%s: usage: %s -u username -p password\n" - " [-r realm] [-s servicename]\n" + " [-r realm] [-s servicename] [-a clientaddr]\n" " [-f socket path] [-R repeatnum]\n", argv[0], argv[0]); exit(1); @@ -294,7 +304,7 @@ main(int argc, char *argv[]) for (c = 0; c < repeat; c++) { /* saslauthd-authenticated login */ printf("%d: ", c); - result = saslauthd_verify_password(path, user, password, service, realm); + result = saslauthd_verify_password(path, user, password, service, realm, client_addr); } return result; } From 46d149b4b889bd5c71241cc30cfac9174005f860 Mon Sep 17 00:00:00 2001 From: Jan Parcel Date: Tue, 18 Oct 2016 10:42:31 -0400 Subject: [PATCH 243/796] Fix for DoS attack DOS attack possible on saslauthd deamon if configured with doors. Requires local login. --- saslauthd/ipc_doors.c | 50 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/saslauthd/ipc_doors.c b/saslauthd/ipc_doors.c index 92f403c0..4e459d7c 100644 --- a/saslauthd/ipc_doors.c +++ b/saslauthd/ipc_doors.c @@ -203,13 +203,42 @@ void ipc_cleanup() { logger(L_DEBUG, L_FUNC, "door file removed: %s", door_file); } +/************************************************************* + * It is very rare but not impossible to have door_return actually return. + * When it does, it leaks a reference count. Prevent that. + **************************************************************/ + +void +safe_door_return(char *data, size_t len) +{ + (void) door_return(data, len, NULL, 0); + /* + * If door_return() failed, and our response wasn't empty, try sending + * an empty response. If that still doesn't work, then we must exit + * this thread. + */ + if (len > 0) { + logger(L_ERR, L_FUNC, "door_return: %s", strerror(errno)); + (void) door_return(NULL, 0, NULL, 0); + } + logger(L_ERR, L_FUNC, "door_return: %s", strerror(errno)); + + pthread_mutex_lock(&num_lock); + if (num_procs > 0 && num_thr > 0) { + num_thr--; + } + pthread_mutex_unlock(&num_lock); + pthread_exit(NULL); +} + /************************************************************* * Handle the door data, pass the request off to * do_auth() back in saslauthd-main.c, then send the * result back through the door. **************************************************************/ -void do_request(void *cookie, char *data, size_t datasize, door_desc_t *dp, size_t ndesc) { +static void +do_request(void *cookie, char *data, size_t datasize, door_desc_t *dp, uint_t ndesc) { unsigned short count = 0; /* input/output data byte count */ char *response = NULL; /* response to send to the client */ char response_buff[1024]; /* temporary response buffer */ @@ -227,6 +256,12 @@ void do_request(void *cookie, char *data, size_t datasize, door_desc_t *dp, size **************************************************************/ dataend = data + datasize; + if (data == NULL || datasize < sizeof(unsigned short)) { + logger(L_ERR, L_FUNC, "Bad data"); + send_no(""); + return; + } + /* login id */ memcpy(&count, data, sizeof(unsigned short)); @@ -328,8 +363,7 @@ void do_request(void *cookie, char *data, size_t datasize, door_desc_t *dp, size if (flags & VERBOSE) logger(L_DEBUG, L_FUNC, "response: %s", response_buff); - if(door_return(response_buff, strlen(response_buff), NULL, 0) < 0) - logger(L_ERR, L_FUNC, "door_return: %s", strerror(errno)); + safe_door_return(response_buff, strlen(response_buff)); return; } @@ -353,14 +387,17 @@ void need_thread(door_info_t *di) { pthread_create(&newt, &thread_attr, &server_thread, NULL); } - + /************************************************************* * Start a new server thread. * Make it available for door invocations. **************************************************************/ void *server_thread(void *arg) { pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); - door_return(NULL, 0, NULL, 0); + + safe_door_return(NULL, 0); + + return (void *) NULL; } /************************************************************* @@ -382,8 +419,7 @@ void send_no(char *mesg) { if (flags & VERBOSE) logger(L_DEBUG, L_FUNC, "response: %s", buff); - if(door_return(buff, strlen(buff), NULL, 0) < 0) - logger(L_ERR, L_FUNC, "door_return: %s", strerror(errno)); + safe_door_return(buff, strlen(buff)); return; } From 4463082b13eeff70841461387a8c3e994c2e5eaf Mon Sep 17 00:00:00 2001 From: Ken Murchison Date: Tue, 18 Oct 2016 13:13:41 -0400 Subject: [PATCH 244/796] updated --- ChangeLog | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/ChangeLog b/ChangeLog index c7be303c..6a547fa8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,53 @@ +2016-10-18 Ken Murchison + * Fixed potential DoS attack on saslauthd/doors (from Oracle) + +2016-06-30 Ken Murchison + * plugins/ntlm.c, otp.c: support OpenSSL 1.1 + +2016-06-14 Ken Murchison + * plugins/digestmd5.c: Fix memory leak in client step 2 + +2016-03-24 Ken Murchison + * auth_rimap.c: Don't hang when IMAP server closes connection + +2016-01-29 Ken Murchison + * Build fixes from Ignacio Casal Quinteiro + +2015-12-26 Ken Murchison + * Build fixes from Ignacio Casal Quinteiro + +2015-11-16 Ken Murchison + * Build fixes from Ignacio Casal Quinteiro + +2015-10-14 Ken Murchison + * Build fixes from Ignacio Casal Quinteiro + +2015-07-17 Ken Murchison + * auth_krb5.c: added krb5_conv_krb4_instance option + +2014-11-17 Ken Murchison + * plugins/digestmd5.c: Fix memory leaks + +2014-11-17 Ken Murchison + * plugins/digestmd5.c: prevent going from step 3 to step 2 + +2013-09-13 Alexey Melnikov + * Fix memory leaks in DIGEST + +2013-08-30 Ken Murchison + * plugins/digestmd5.c: only locate reauth cache when reauth is + enabled + +2013-07-11 Alexey Melnikov + * Treat SCRAM and DIGEST as more secure than PLAIN when selecting + client-side mechanism + +2013-07-11 Alexey Melnikov + * Handle NULL return from crypt() + +2012-11-20 Alexey Melnikov + * Added support for lmdb + 2012-11-19 Alexey Melnikov * Final 2.1.26 tagged and released by Ken. From de0ec5c0599551e9ccb63d29f61a30827b45ba22 Mon Sep 17 00:00:00 2001 From: Ken Murchison Date: Tue, 18 Oct 2016 13:14:48 -0400 Subject: [PATCH 245/796] Getting ready for 2.1.27 --- configure.ac | 6 +++--- include/sasl.h | 2 +- win32/common.mak | 2 +- win32/include/config.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index d3f38af7..199d93e2 100644 --- a/configure.ac +++ b/configure.ac @@ -49,10 +49,10 @@ dnl REMINDER: When changing the version number here, please also update dnl the values in win32/include/config.h and include/sasl.h as well. dnl AC_INIT([cyrus-sasl], - [2.1.26], - [https://git.cyrus.foundation/maniphest/], + [2.1.27], + [https://github.com/cyrusimap/cyrus-sasl/issues], [cyrus-sasl], - [https://docs.cyrus.foundation]) + [http://cyrusimap.org]) AC_CONFIG_MACRO_DIR([m4]) diff --git a/include/sasl.h b/include/sasl.h index 54afd9ca..eb001ecc 100755 --- a/include/sasl.h +++ b/include/sasl.h @@ -126,7 +126,7 @@ /* Keep in sync with win32/common.mak */ #define SASL_VERSION_MAJOR 2 #define SASL_VERSION_MINOR 1 -#define SASL_VERSION_STEP 26 +#define SASL_VERSION_STEP 27 /* A convenience macro: same as was defined in the OpenLDAP LDAPDB */ #define SASL_VERSION_FULL ((SASL_VERSION_MAJOR << 16) |\ diff --git a/win32/common.mak b/win32/common.mak index 5c9c4b28..194dfe95 100644 --- a/win32/common.mak +++ b/win32/common.mak @@ -2,7 +2,7 @@ #Keep in sync with include/sasl.h and win32/include/config.h SASL_VERSION_MAJOR=2 SASL_VERSION_MINOR=1 -SASL_VERSION_STEP=26 +SASL_VERSION_STEP=27 !IF "$(STATIC)" == "" STATIC=yes diff --git a/win32/include/config.h b/win32/include/config.h index 34408378..8d8548ea 100644 --- a/win32/include/config.h +++ b/win32/include/config.h @@ -55,7 +55,7 @@ #define PACKAGE "cyrus-sasl" /* Our version */ -#define VERSION "2.1.26" +#define VERSION "2.1.27" /* Visual Studio supports prototypes */ #define PROTOTYPES 1 From aed6632272eca00aeb0e024f05f2f62fe8554b8f Mon Sep 17 00:00:00 2001 From: Nicola Nye Date: Fri, 4 Nov 2016 11:51:25 +1100 Subject: [PATCH 246/796] [Docs] Migrating html docs into rst for display online. --- .gitignore | 3 + docsrc/_static/cyrus.css | 224 ++++ .../event_notifications/AclChange.json | 12 + .../event_notifications/ApplePushService.json | 9 + .../event_notifications/CalendarAlarm.json | 22 + .../event_notifications/FlagsClear.json | 18 + .../_static/event_notifications/FlagsSet.json | 18 + docsrc/_static/event_notifications/Login.json | 13 + .../_static/event_notifications/Logout.json | 13 + .../event_notifications/MailboxCreate.json | 10 + .../event_notifications/MailboxDelete.json | 10 + .../event_notifications/MailboxRename.json | 11 + .../event_notifications/MailboxSubscribe.json | 9 + .../MailboxUnSubscribe.json | 9 + .../event_notifications/MessageAppend.json | 19 + .../event_notifications/MessageCopy.json | 19 + .../event_notifications/MessageExpunge.json | 17 + .../event_notifications/MessageMove.json | 19 + .../event_notifications/MessageNew.json | 46 + .../event_notifications/MessageRead.json | 17 + .../event_notifications/MessageTrash.json | 17 + .../event_notifications/QuotaChange.json | 13 + .../event_notifications/QuotaExceed.json | 13 + .../event_notifications/QuotaWithin.json | 13 + docsrc/_static/favicon.ico | Bin 0 -> 1406 bytes docsrc/_static/headimg.gif | Bin 0 -> 83976 bytes docsrc/_static/logo.gif | Bin 0 -> 2927 bytes docsrc/_templates/layout.html | 25 + docsrc/conf.py | 397 ++++++ docsrc/contribute.rst | 33 + docsrc/developers.rst | 10 + docsrc/download.rst | 8 + docsrc/exts/sphinxlocal/__init__.py | 10 + docsrc/exts/sphinxlocal/builders/__init__.py | 10 + docsrc/exts/sphinxlocal/builders/manpage.py | 97 ++ docsrc/exts/sphinxlocal/roles/__init__.py | 10 + docsrc/exts/sphinxlocal/writers/__init__.py | 10 + docsrc/exts/sphinxlocal/writers/manpage.py | 92 ++ docsrc/exts/themes/cyrus/__init__.py | 17 + docsrc/exts/themes/cyrus/breadcrumbs.html | 23 + docsrc/exts/themes/cyrus/footer.html | 36 + docsrc/exts/themes/cyrus/layout.html | 188 +++ docsrc/exts/themes/cyrus/layout_old.html | 205 +++ docsrc/exts/themes/cyrus/search.html | 50 + docsrc/exts/themes/cyrus/searchbox.html | 9 + .../themes/cyrus/static/css/badge_only.css | 2 + docsrc/exts/themes/cyrus/static/css/theme.css | 5 + .../cyrus/static/fonts/Inconsolata-Bold.ttf | Bin 0 -> 47064 bytes .../themes/cyrus/static/fonts/Inconsolata.ttf | Bin 0 -> 63184 bytes .../themes/cyrus/static/fonts/Lato-Bold.ttf | Bin 0 -> 82368 bytes .../cyrus/static/fonts/Lato-Regular.ttf | Bin 0 -> 81980 bytes .../cyrus/static/fonts/RobotoSlab-Bold.ttf | Bin 0 -> 36596 bytes .../cyrus/static/fonts/RobotoSlab-Regular.ttf | Bin 0 -> 36276 bytes .../static/fonts/fontawesome-webfont.eot | Bin 0 -> 38205 bytes .../static/fonts/fontawesome-webfont.svg | 414 +++++++ .../static/fonts/fontawesome-webfont.ttf | Bin 0 -> 80652 bytes .../static/fonts/fontawesome-webfont.woff | Bin 0 -> 44432 bytes .../themes/cyrus/static/js/modernizr.min.js | 4 + docsrc/exts/themes/cyrus/static/js/theme.js | 113 ++ docsrc/exts/themes/cyrus/theme.conf | 9 + docsrc/exts/themes/cyrus/versions.html | 37 + .../exts/themes/sphinx_rtd_theme/__init__.py | 17 + .../themes/sphinx_rtd_theme/breadcrumbs.html | 23 + .../exts/themes/sphinx_rtd_theme/footer.html | 36 + .../exts/themes/sphinx_rtd_theme/layout.html | 181 +++ .../themes/sphinx_rtd_theme/layout_old.html | 205 +++ .../exts/themes/sphinx_rtd_theme/search.html | 50 + .../themes/sphinx_rtd_theme/searchbox.html | 9 + .../static/css/badge_only.css | 2 + .../sphinx_rtd_theme/static/css/theme.css | 5 + .../static/fonts/Inconsolata-Bold.ttf | Bin 0 -> 47064 bytes .../static/fonts/Inconsolata.ttf | Bin 0 -> 63184 bytes .../static/fonts/Lato-Bold.ttf | Bin 0 -> 82368 bytes .../static/fonts/Lato-Regular.ttf | Bin 0 -> 81980 bytes .../static/fonts/RobotoSlab-Bold.ttf | Bin 0 -> 36596 bytes .../static/fonts/RobotoSlab-Regular.ttf | Bin 0 -> 36276 bytes .../static/fonts/fontawesome-webfont.eot | Bin 0 -> 38205 bytes .../static/fonts/fontawesome-webfont.svg | 414 +++++++ .../static/fonts/fontawesome-webfont.ttf | Bin 0 -> 80652 bytes .../static/fonts/fontawesome-webfont.woff | Bin 0 -> 44432 bytes .../static/js/modernizr.min.js | 4 + .../sphinx_rtd_theme/static/js/theme.js | 113 ++ .../exts/themes/sphinx_rtd_theme/theme.conf | 9 + .../themes/sphinx_rtd_theme/versions.html | 37 + docsrc/index.rst | 86 ++ docsrc/sasl/advanced.rst | 34 + docsrc/sasl/appconvert.rst | 101 ++ docsrc/sasl/authentication_mechanisms.rst | 152 +++ docsrc/sasl/auxiliary_properties.rst | 40 + docsrc/sasl/components.rst | 184 +++ docsrc/sasl/concepts.rst | 63 + docsrc/sasl/developer/installation.rst | 81 ++ docsrc/sasl/developer/plugprog.rst | 347 ++++++ docsrc/sasl/developer/programming.rst | 1101 +++++++++++++++++ docsrc/sasl/developer/testing.rst | 95 ++ docsrc/sasl/faq.rst | 12 + .../sasl/faqs/authorize-vs-authenticate.rst | 38 + docsrc/sasl/faqs/crammd5-digestmd5.rst | 14 + docsrc/sasl/faqs/openldap-sasl-gssapi.rst | 81 ++ docsrc/sasl/faqs/plaintextpasswords.rst | 20 + docsrc/sasl/faqs/rfcs.rst | 35 + docsrc/sasl/faqs/upgrade-saslv2.rst | 22 + docsrc/sasl/gssapi.rst | 203 +++ docsrc/sasl/installation.rst | 235 ++++ docsrc/sasl/macosx.rst | 211 ++++ docsrc/sasl/options.rst | 422 +++++++ docsrc/sasl/os390.rst | 56 + docsrc/sasl/pwcheck.rst | 174 +++ docsrc/sasl/quickstart.rst | 94 ++ docsrc/sasl/resources.rst | 15 + docsrc/sasl/sasl_migration.rst | 20 + docsrc/sasl/sysadmin.rst | 455 +++++++ docsrc/sasl/upgrading.rst | 92 ++ docsrc/sasl/windows.rst | 170 +++ 114 files changed, 8146 insertions(+) create mode 100644 docsrc/_static/cyrus.css create mode 100644 docsrc/_static/event_notifications/AclChange.json create mode 100644 docsrc/_static/event_notifications/ApplePushService.json create mode 100644 docsrc/_static/event_notifications/CalendarAlarm.json create mode 100644 docsrc/_static/event_notifications/FlagsClear.json create mode 100644 docsrc/_static/event_notifications/FlagsSet.json create mode 100644 docsrc/_static/event_notifications/Login.json create mode 100644 docsrc/_static/event_notifications/Logout.json create mode 100644 docsrc/_static/event_notifications/MailboxCreate.json create mode 100644 docsrc/_static/event_notifications/MailboxDelete.json create mode 100644 docsrc/_static/event_notifications/MailboxRename.json create mode 100644 docsrc/_static/event_notifications/MailboxSubscribe.json create mode 100644 docsrc/_static/event_notifications/MailboxUnSubscribe.json create mode 100644 docsrc/_static/event_notifications/MessageAppend.json create mode 100644 docsrc/_static/event_notifications/MessageCopy.json create mode 100644 docsrc/_static/event_notifications/MessageExpunge.json create mode 100644 docsrc/_static/event_notifications/MessageMove.json create mode 100644 docsrc/_static/event_notifications/MessageNew.json create mode 100644 docsrc/_static/event_notifications/MessageRead.json create mode 100644 docsrc/_static/event_notifications/MessageTrash.json create mode 100644 docsrc/_static/event_notifications/QuotaChange.json create mode 100644 docsrc/_static/event_notifications/QuotaExceed.json create mode 100644 docsrc/_static/event_notifications/QuotaWithin.json create mode 100644 docsrc/_static/favicon.ico create mode 100644 docsrc/_static/headimg.gif create mode 100644 docsrc/_static/logo.gif create mode 100644 docsrc/_templates/layout.html create mode 100644 docsrc/conf.py create mode 100644 docsrc/contribute.rst create mode 100644 docsrc/developers.rst create mode 100644 docsrc/download.rst create mode 100644 docsrc/exts/sphinxlocal/__init__.py create mode 100644 docsrc/exts/sphinxlocal/builders/__init__.py create mode 100644 docsrc/exts/sphinxlocal/builders/manpage.py create mode 100644 docsrc/exts/sphinxlocal/roles/__init__.py create mode 100644 docsrc/exts/sphinxlocal/writers/__init__.py create mode 100644 docsrc/exts/sphinxlocal/writers/manpage.py create mode 100644 docsrc/exts/themes/cyrus/__init__.py create mode 100644 docsrc/exts/themes/cyrus/breadcrumbs.html create mode 100644 docsrc/exts/themes/cyrus/footer.html create mode 100644 docsrc/exts/themes/cyrus/layout.html create mode 100644 docsrc/exts/themes/cyrus/layout_old.html create mode 100644 docsrc/exts/themes/cyrus/search.html create mode 100644 docsrc/exts/themes/cyrus/searchbox.html create mode 100644 docsrc/exts/themes/cyrus/static/css/badge_only.css create mode 100644 docsrc/exts/themes/cyrus/static/css/theme.css create mode 100644 docsrc/exts/themes/cyrus/static/fonts/Inconsolata-Bold.ttf create mode 100644 docsrc/exts/themes/cyrus/static/fonts/Inconsolata.ttf create mode 100644 docsrc/exts/themes/cyrus/static/fonts/Lato-Bold.ttf create mode 100644 docsrc/exts/themes/cyrus/static/fonts/Lato-Regular.ttf create mode 100644 docsrc/exts/themes/cyrus/static/fonts/RobotoSlab-Bold.ttf create mode 100644 docsrc/exts/themes/cyrus/static/fonts/RobotoSlab-Regular.ttf create mode 100644 docsrc/exts/themes/cyrus/static/fonts/fontawesome-webfont.eot create mode 100644 docsrc/exts/themes/cyrus/static/fonts/fontawesome-webfont.svg create mode 100644 docsrc/exts/themes/cyrus/static/fonts/fontawesome-webfont.ttf create mode 100644 docsrc/exts/themes/cyrus/static/fonts/fontawesome-webfont.woff create mode 100644 docsrc/exts/themes/cyrus/static/js/modernizr.min.js create mode 100644 docsrc/exts/themes/cyrus/static/js/theme.js create mode 100644 docsrc/exts/themes/cyrus/theme.conf create mode 100644 docsrc/exts/themes/cyrus/versions.html create mode 100644 docsrc/exts/themes/sphinx_rtd_theme/__init__.py create mode 100644 docsrc/exts/themes/sphinx_rtd_theme/breadcrumbs.html create mode 100644 docsrc/exts/themes/sphinx_rtd_theme/footer.html create mode 100644 docsrc/exts/themes/sphinx_rtd_theme/layout.html create mode 100644 docsrc/exts/themes/sphinx_rtd_theme/layout_old.html create mode 100644 docsrc/exts/themes/sphinx_rtd_theme/search.html create mode 100644 docsrc/exts/themes/sphinx_rtd_theme/searchbox.html create mode 100644 docsrc/exts/themes/sphinx_rtd_theme/static/css/badge_only.css create mode 100644 docsrc/exts/themes/sphinx_rtd_theme/static/css/theme.css create mode 100644 docsrc/exts/themes/sphinx_rtd_theme/static/fonts/Inconsolata-Bold.ttf create mode 100644 docsrc/exts/themes/sphinx_rtd_theme/static/fonts/Inconsolata.ttf create mode 100644 docsrc/exts/themes/sphinx_rtd_theme/static/fonts/Lato-Bold.ttf create mode 100644 docsrc/exts/themes/sphinx_rtd_theme/static/fonts/Lato-Regular.ttf create mode 100644 docsrc/exts/themes/sphinx_rtd_theme/static/fonts/RobotoSlab-Bold.ttf create mode 100644 docsrc/exts/themes/sphinx_rtd_theme/static/fonts/RobotoSlab-Regular.ttf create mode 100644 docsrc/exts/themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.eot create mode 100644 docsrc/exts/themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.svg create mode 100644 docsrc/exts/themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.ttf create mode 100644 docsrc/exts/themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.woff create mode 100644 docsrc/exts/themes/sphinx_rtd_theme/static/js/modernizr.min.js create mode 100644 docsrc/exts/themes/sphinx_rtd_theme/static/js/theme.js create mode 100644 docsrc/exts/themes/sphinx_rtd_theme/theme.conf create mode 100644 docsrc/exts/themes/sphinx_rtd_theme/versions.html create mode 100644 docsrc/index.rst create mode 100644 docsrc/sasl/advanced.rst create mode 100644 docsrc/sasl/appconvert.rst create mode 100644 docsrc/sasl/authentication_mechanisms.rst create mode 100644 docsrc/sasl/auxiliary_properties.rst create mode 100644 docsrc/sasl/components.rst create mode 100644 docsrc/sasl/concepts.rst create mode 100644 docsrc/sasl/developer/installation.rst create mode 100644 docsrc/sasl/developer/plugprog.rst create mode 100644 docsrc/sasl/developer/programming.rst create mode 100644 docsrc/sasl/developer/testing.rst create mode 100644 docsrc/sasl/faq.rst create mode 100644 docsrc/sasl/faqs/authorize-vs-authenticate.rst create mode 100644 docsrc/sasl/faqs/crammd5-digestmd5.rst create mode 100644 docsrc/sasl/faqs/openldap-sasl-gssapi.rst create mode 100644 docsrc/sasl/faqs/plaintextpasswords.rst create mode 100644 docsrc/sasl/faqs/rfcs.rst create mode 100644 docsrc/sasl/faqs/upgrade-saslv2.rst create mode 100644 docsrc/sasl/gssapi.rst create mode 100644 docsrc/sasl/installation.rst create mode 100644 docsrc/sasl/macosx.rst create mode 100644 docsrc/sasl/options.rst create mode 100644 docsrc/sasl/os390.rst create mode 100644 docsrc/sasl/pwcheck.rst create mode 100644 docsrc/sasl/quickstart.rst create mode 100644 docsrc/sasl/resources.rst create mode 100644 docsrc/sasl/sasl_migration.rst create mode 100644 docsrc/sasl/sysadmin.rst create mode 100644 docsrc/sasl/upgrading.rst create mode 100644 docsrc/sasl/windows.rst diff --git a/.gitignore b/.gitignore index 0a0a1cb7..1ad3eef0 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,6 @@ libtool config.status stamp-h1 Makefile +*.pyc +docsrc/.doctrees/ +docsrc/build/ diff --git a/docsrc/_static/cyrus.css b/docsrc/_static/cyrus.css new file mode 100644 index 00000000..7ec3d497 --- /dev/null +++ b/docsrc/_static/cyrus.css @@ -0,0 +1,224 @@ +a { + color: #1f8fc0; +} + +a tt { + color: #1f8fc0; +} + +a.internal em { + font-style: normal; +} + +blockquote.epigraph div p { + font-style: italic; +} + +body { + font-family: sans-serif; + letter-spacing: 0; +} + +cite, code, pre, tt { + font-family: "Liberation Mono", "Consolas","Deja Vu Sans Mono","Bitstream Vera Sans Mono", monospace; +} + +div.admonition { + border-left: 0.5em solid #59bc00; + border-top: none; + border-right: none; + border-bottom: none; + margin-bottom: 1em; + padding-bottom: 0.5em; + padding-left: 1.5em; + padding-top: 0.5em; +} + +div.admonition > div:last-child > *:last-child { + margin-bottom: 0; +} + +div.admonition p { + margin: 1em 0 0.5em 0.5em; + padding: 0; +} + +div.admonition p.admonition-title { + color: black; + margin: 1em 0 0.5em 0.5em; + padding: 0; + font-weight: bold; + display: block; + background-color: inherit; + border-bottom: none; +} + +/* Green 'note' box */ +div.admonition.note { + border-left: 0.5em solid #59bc00; +} + +div.admonition.important { + border-color: #ffc200; +} + +div.admonition.warning { + border-color: #ff0000; +} + +div.admonition.tip { + border-color: #1e90ff; +} + +div.admonition-todo { + border-color: #cccccc; +} + +div.admonition.caution { + border-color: #950000; +} + +div.body a { + text-decoration: none; + color: #1F8FC0; +} + +div.body h1, div.body h2, div.body h3 { + color: #002e50; +} + +div.highlight { +/* border-left: 0.5em solid #666666; */ + padding: 0; + margin: 1em 0 0.5em 0; +} + +.highlight { + background: #eeeeee; +} + +div.highlight pre { + border: 0px solid; + margin: 1em 0.5em 0.5em 0.5em; + padding-bottom: 0.5em; + padding-left: 1.5em; + padding-top: 0.5em; +} + +div.linenodiv pre { + padding: 0.5em 0 0; +} + +div.related { + background-color: #1F8FC0; +} + +div.related ul li a { + color: white; +} + + +div.sphinxsidebar h3, div.sphinxsidebar h4 { + background-color: #002e50; + border: 1px solid white; + color: white; +} + +div.sphinxsidebar h3 a { + color: white; +} + +ol.arabic li { + margin-top: 0.5em; + line-height: 110% +} + +p.caption { + font-style: italic; +} + +.caption-text { + font-size: 60% +} + +nav.wy-nav-side p.caption { + font-size: 150% +} + +/* For bold-italic and italic inside other formatting styles */ +/* ``command line `` :italic:`with italics` + */ + +.bolditalic { + font-weight: bold; + font-style: italic; +} + +.italic { + font-style: italic; +} + +.pageheader { + background-image: url(headimg.gif); + text-align: left; + padding: 10px 15px; +} + +.pageheader ul { + float: right; + color: white; + list-style-type: none; + padding-left: 0; + margin-top: 30px; + margin-right: 10px; +} + +.pageheader li { + float: left; + margin: 0 0 0 10px; +} + +.pageheader li a { + border-radius: 1px; + padding: 8px 12px; + color: #f9f9f0; + text-shadow: 0 0 5px rgba(0, 0, 0, 0.5); +} + +.pageheader li a:hover { + background-color: #f9f9f0; + color: #0a507a; + text-shadow: none; +} + +.wy-nav-content { + max-width: 100% +} + +.wy-nav-side { + background-color: #2d9dcb; + color: white; +} + +.wy-nav-side li a { + color: white; +} + +.wy-side-nav-search { + background-color: #2d9dcb; +} + +.wy-side-nav-search a img { + margin-bottom: 0px; +} + +.wy-side-nav-search a:hover { + background-color: #2d9dcb; +} + +.wy-side-nav-search img { + border-radius: initial; + width: 100%; + height: 100%; + background-color: #2d9dcb; +} \ No newline at end of file diff --git a/docsrc/_static/event_notifications/AclChange.json b/docsrc/_static/event_notifications/AclChange.json new file mode 100644 index 00000000..474e3243 --- /dev/null +++ b/docsrc/_static/event_notifications/AclChange.json @@ -0,0 +1,12 @@ +{ + "aclRights": "lrs", + "aclSubject": "jane@example.org", + "event": "AclChange", + "mailboxID": "imap://john@example.org@imap.example.org/Testfolder_renamed;UIDVALIDITY=1424699807", + "pid": 8048, + "service": "imap", + "timestamp": "2015-02-23T14:57:59.736+01:00", + "uri": "imap://john@example.org@imap.example.org/Testfolder_renamed;UIDVALIDITY=1424699807", + "user": "john@example.org", + "vnd.cmu.sessionId": "imap.example.org-8048-1424699879-1-8051832424702584527" +} diff --git a/docsrc/_static/event_notifications/ApplePushService.json b/docsrc/_static/event_notifications/ApplePushService.json new file mode 100644 index 00000000..8c1f084e --- /dev/null +++ b/docsrc/_static/event_notifications/ApplePushService.json @@ -0,0 +1,9 @@ +{ + "event":"ApplePushService", + "user": "john@example.org", + "apsVersion": "", + "apsAccountId": "", + "apsDeviceToken": "", + "apsSubtopic": "", + "mailboxes": "[array of mailboxIDs]" +} diff --git a/docsrc/_static/event_notifications/CalendarAlarm.json b/docsrc/_static/event_notifications/CalendarAlarm.json new file mode 100644 index 00000000..706e5447 --- /dev/null +++ b/docsrc/_static/event_notifications/CalendarAlarm.json @@ -0,0 +1,22 @@ +{ + "event":"CalendarAlarm", + "pid":3164225, + "serverFQDN":"sloti30t15", + "alarmTime":"20151119T063000Z", + "alarmRecipients":["mailto:mary@example.org"], + "userId":"mary@example.org", + "calendarName":"Calendar", + "uid":"49ba20f5-cb44-4863-aea7-255f37ffc2e7", + "action":"email", + "summary":"Here's a lovely event. Remind me", + "description":"", + "location":"", + "timezone":"Australia/Melbourne", + "start":"20151119T073000Z", + "end":"20151119T083000Z", + "allDay":0, + "attendeeNames":[], + "attendeeEmails":[], + "attendeeStatus":[], + "organizer":"" +} \ No newline at end of file diff --git a/docsrc/_static/event_notifications/FlagsClear.json b/docsrc/_static/event_notifications/FlagsClear.json new file mode 100644 index 00000000..4a7691b1 --- /dev/null +++ b/docsrc/_static/event_notifications/FlagsClear.json @@ -0,0 +1,18 @@ +{ + "event": "FlagsClear", + "flagNames": "\\Flagged", + "messages": 1, + "modseq": 43, + "pid": 7721, + "service": "imap", + "timestamp": "2015-02-23T14:50:43.640+01:00", + "uidnext": 4, + "uidset": "3", + "uri": "imap://john@example.org@imap.example.org/INBOX;UIDVALIDITY=1424683682", + "user": "john@example.org", + "vnd.cmu.midset": [ + "<4d9618acd0aea6b33683766358351459@example.org>" + ], + "vnd.cmu.sessionId": "imap.example.org-7721-1424699443-1-8479002111695998134", + "vnd.cmu.unseenMessages": 0 +} diff --git a/docsrc/_static/event_notifications/FlagsSet.json b/docsrc/_static/event_notifications/FlagsSet.json new file mode 100644 index 00000000..97d76a2e --- /dev/null +++ b/docsrc/_static/event_notifications/FlagsSet.json @@ -0,0 +1,18 @@ +{ + "event": "FlagsSet", + "flagNames": "\\Flagged", + "messages": 1, + "modseq": 42, + "pid": 7649, + "service": "imap", + "timestamp": "2015-02-23T14:50:21.858+01:00", + "uidnext": 4, + "uidset": "3", + "uri": "imap://john@example.org@imap.example.org/INBOX;UIDVALIDITY=1424683682", + "user": "john@example.org", + "vnd.cmu.midset": [ + "<4d9618acd0aea6b33683766358351459@example.org>" + ], + "vnd.cmu.sessionId": "imap.example.org-7649-1424699421-1-11813528620713894618", + "vnd.cmu.unseenMessages": 0 +} diff --git a/docsrc/_static/event_notifications/Login.json b/docsrc/_static/event_notifications/Login.json new file mode 100644 index 00000000..2a955951 --- /dev/null +++ b/docsrc/_static/event_notifications/Login.json @@ -0,0 +1,13 @@ +{ + "clientIP": "::1", + "clientPort": 46461, + "event": "Login", + "pid": 7629, + "serverDomain": "::1", + "serverPort": 143, + "service": "imap", + "timestamp": "2015-02-23T14:47:36.097+01:00", + "uri": "imap://imap.example.org", + "user": "john@example.org", + "vnd.cmu.sessionId": "imap.example.org-7629-1424699256-1-3981462903180119079" +} diff --git a/docsrc/_static/event_notifications/Logout.json b/docsrc/_static/event_notifications/Logout.json new file mode 100644 index 00000000..7d897137 --- /dev/null +++ b/docsrc/_static/event_notifications/Logout.json @@ -0,0 +1,13 @@ +{ + "clientIP": "::1", + "clientPort": 46461, + "event": "Logout", + "pid": 7629, + "serverDomain": "::1", + "serverPort": 143, + "service": "imap", + "timestamp": "2015-02-23T14:47:36.183+01:00", + "uri": "imap://imap.example.org", + "user": "john@example.org", + "vnd.cmu.sessionId": "imap.example.org-7629-1424699256-1-3981462903180119079" +} diff --git a/docsrc/_static/event_notifications/MailboxCreate.json b/docsrc/_static/event_notifications/MailboxCreate.json new file mode 100644 index 00000000..f4b8f79d --- /dev/null +++ b/docsrc/_static/event_notifications/MailboxCreate.json @@ -0,0 +1,10 @@ +{ + "event": "MailboxCreate", + "mailboxID": "imap://john@example.org@imap.example.org/Testfolder;UIDVALIDITY=1424690388", + "pid": 7721, + "service": "imap", + "timestamp": "2015-02-23T14:55:57.621+01:00", + "uri": "imap://john@example.org@imap.example.org/Testfolder;UIDVALIDITY=1424690388", + "user": "john@example.org", + "vnd.cmu.sessionId": "imap.example.org-7721-1424699757-1-18345110432907898457" +} diff --git a/docsrc/_static/event_notifications/MailboxDelete.json b/docsrc/_static/event_notifications/MailboxDelete.json new file mode 100644 index 00000000..8dc5d2e6 --- /dev/null +++ b/docsrc/_static/event_notifications/MailboxDelete.json @@ -0,0 +1,10 @@ +{ + "event": "MailboxDelete", + "mailboxID": "imap://john@example.org@imap.example.org/Testfolder_renamed;UIDVALIDITY=1424699807", + "pid": 8070, + "service": "imap", + "timestamp": "2015-02-23T14:58:37.145+01:00", + "uri": "imap://john@example.org@imap.example.org/Testfolder_renamed;UIDVALIDITY=1424699807", + "user": "john@example.org", + "vnd.cmu.sessionId": "imap.example.org-8070-1424699917-1-11277155374959916506" +} diff --git a/docsrc/_static/event_notifications/MailboxRename.json b/docsrc/_static/event_notifications/MailboxRename.json new file mode 100644 index 00000000..1d954eea --- /dev/null +++ b/docsrc/_static/event_notifications/MailboxRename.json @@ -0,0 +1,11 @@ +{ + "event": "MailboxRename", + "mailboxID": "imap://john@example.org@imap.example.org/Testfolder_renamed;UIDVALIDITY=1424699807", + "oldMailboxID": "imap://john@example.org@imap.example.org/Testfolder;UIDVALIDITY=1424690388", + "pid": 8026, + "service": "imap", + "timestamp": "2015-02-23T14:56:47.466+01:00", + "uri": "imap://john@example.org@imap.example.org/Testfolder_renamed;UIDVALIDITY=1424699807", + "user": "john@example.org", + "vnd.cmu.sessionId": "imap.example.org-8026-1424699807-1-3097981731339369225" +} diff --git a/docsrc/_static/event_notifications/MailboxSubscribe.json b/docsrc/_static/event_notifications/MailboxSubscribe.json new file mode 100644 index 00000000..2bfd014c --- /dev/null +++ b/docsrc/_static/event_notifications/MailboxSubscribe.json @@ -0,0 +1,9 @@ +{ + "event": "MailboxSubscribe", + "pid": 3004, + "service": "imap", + "timestamp": "2015-02-23T18:37:02.344+01:00", + "uri": "imap://john@example.org@imap.example.org/Archive", + "user": "john@example.org", + "vnd.cmu.sessionId": "imap.example.org-3004-1424713022-1-7149274646509524617" +} diff --git a/docsrc/_static/event_notifications/MailboxUnSubscribe.json b/docsrc/_static/event_notifications/MailboxUnSubscribe.json new file mode 100644 index 00000000..31fc9a57 --- /dev/null +++ b/docsrc/_static/event_notifications/MailboxUnSubscribe.json @@ -0,0 +1,9 @@ +{ + "event": "MailboxUnSubscribe", + "pid": 3003, + "service": "imap", + "timestamp": "2015-02-23T18:37:19.482+01:00", + "uri": "imap://john@example.org@imap.example.org/Testfolder_renamed", + "user": "john@example.org", + "vnd.cmu.sessionId": "imap.example.org-3003-1424713039-1-2806700531460584176" +} diff --git a/docsrc/_static/event_notifications/MessageAppend.json b/docsrc/_static/event_notifications/MessageAppend.json new file mode 100644 index 00000000..e6e01511 --- /dev/null +++ b/docsrc/_static/event_notifications/MessageAppend.json @@ -0,0 +1,19 @@ +{ + "bodyStructure": "((\"TEXT\" \"PLAIN\" (\"CHARSET\" \"ISO-8859-1\") NIL NIL \"QUOTED-PRINTABLE\" 206 4 NIL NIL NIL NIL)(\"APPLICATION\" \"CALENDAR+XML\" (\"CHARSET\" \"UTF-8\" \"NAME\" \"kolab.xml\") NIL NIL \"8BIT\" 2030 NIL (\"ATTACHMENT\" (\"FILENAME\" \"kolab.xml\" \"SIZE\" \"2030\")) NIL NIL) \"MIXED\" (\"BOUNDARY\" \"=_d9aa3c2dd73a9166113254d4ebe07bc8\") NIL NIL NIL)", + "event": "MessageAppend", + "messageSize": 2992, + "messages": 3, + "modseq": 12, + "pid": 7721, + "service": "imap", + "timestamp": "2015-02-23T14:51:29.008+01:00", + "uidnext": 6, + "uri": "imap://john@example.org@imap.example.org/Calendar;UIDVALIDITY=1424683684/;UID=5", + "user": "john@example.org", + "vnd.cmu.envelope": "(\"Mon, 23 Feb 2015 13:51:28 +0000\" \"BBA47B13E4839F49AB1C8047EE7B4FDB-A4BF5BBB9FEAA271\" ((NIL NIL \"john\" \"example.org\")) ((NIL NIL \"john\" \"example.org\")) ((NIL NIL \"john\" \"example.org\")) ((NIL NIL \"john\" \"example.org\")) NIL NIL NIL NIL)", + "vnd.cmu.midset": [ + "NIL" + ], + "vnd.cmu.sessionId": "imap.example.org-7721-1424699488-1-10167054345787041319", + "vnd.cmu.unseenMessages": 3 +} diff --git a/docsrc/_static/event_notifications/MessageCopy.json b/docsrc/_static/event_notifications/MessageCopy.json new file mode 100644 index 00000000..7bf3e539 --- /dev/null +++ b/docsrc/_static/event_notifications/MessageCopy.json @@ -0,0 +1,19 @@ +{ + "event": "vnd.cmu.MessageCopy", + "messages": 1, + "modseq": 9, + "oldMailboxID": "imap://john@example.org@imap.example.org/Sent;UIDVALIDITY=1424683683", + "pid": 8107, + "service": "imap", + "timestamp": "2015-02-23T14:59:49.717+01:00", + "uidnext": 5, + "uidset": "4", + "uri": "imap://john@example.org@imap.example.org/Archive;UIDVALIDITY=1424683684", + "user": "john@example.org", + "vnd.cmu.midset": [ + "<4d9618acd0aea6b33683766358351459@example.org>" + ], + "vnd.cmu.oldUidset": "2", + "vnd.cmu.sessionId": "imap.example.org-8107-1424699989-1-8439907626481649843", + "vnd.cmu.unseenMessages": 0 +} diff --git a/docsrc/_static/event_notifications/MessageExpunge.json b/docsrc/_static/event_notifications/MessageExpunge.json new file mode 100644 index 00000000..bf189e06 --- /dev/null +++ b/docsrc/_static/event_notifications/MessageExpunge.json @@ -0,0 +1,17 @@ +{ + "event": "MessageExpunge", + "messages": 0, + "modseq": 53, + "pid": 7813, + "service": "imap", + "timestamp": "2015-02-23T14:55:20.562+01:00", + "uidnext": 5, + "uidset": "4", + "uri": "imap://john@example.org@imap.example.org/INBOX;UIDVALIDITY=1424683682", + "user": "john@example.org", + "vnd.cmu.midset": [ + "<4d9618acd0aea6b33683766358351459@example.org>" + ], + "vnd.cmu.sessionId": "imap.example.org-7813-1424699720-1-13590468293654033744", + "vnd.cmu.unseenMessages": 0 +} diff --git a/docsrc/_static/event_notifications/MessageMove.json b/docsrc/_static/event_notifications/MessageMove.json new file mode 100644 index 00000000..9961afcc --- /dev/null +++ b/docsrc/_static/event_notifications/MessageMove.json @@ -0,0 +1,19 @@ +{ + "event": "vnd.cmu.MessageMove", + "messages": 2, + "modseq": 5, + "oldMailboxID": "imap://john@example.org@imap.example.org/INBOX;UIDVALIDITY=1424683682", + "pid": 7685, + "service": "imap", + "timestamp": "2015-02-23T14:52:41.676+01:00", + "uidnext": 4, + "uidset": "3", + "uri": "imap://john@example.org@imap.example.org/Archive;UIDVALIDITY=1424683684", + "user": "john@example.org", + "vnd.cmu.midset": [ + "<4d9618acd0aea6b33683766358351459@example.org>" + ], + "vnd.cmu.oldUidset": "3", + "vnd.cmu.sessionId": "imap.example.org-7685-1424699561-1-7444588115769591371", + "vnd.cmu.unseenMessages": 0 +} diff --git a/docsrc/_static/event_notifications/MessageNew.json b/docsrc/_static/event_notifications/MessageNew.json new file mode 100644 index 00000000..4d4d400b --- /dev/null +++ b/docsrc/_static/event_notifications/MessageNew.json @@ -0,0 +1,46 @@ +{ + "event": "MessageNew", + "messageContent": { + "6": "Return-Path: \r\nReceived: from imap.example.org ([unix socket])\r\n\t by imap.example.org (Cyrus git2.5+0-Kolab-2.5-67.el6.kolab_3.4) with LMTPA;\r\n\t Mon, 20 Oct 2014 13:34:14 +0200\r\nX-Sieve: CMU Sieve 2.4\r\nX-Virus-Scanned: amavisd-new at example.org\r\nX-Spam-Flag: NO\r\nX-Spam-Score: -0.002\r\nX-Spam-Level: \r\nX-Spam-Status: No, score=-0.002 tagged_above=-10 required=6.2\r\n\ttests=[NO_RECEIVED=-0.001, NO_RELAYS=-0.001] autolearn=ham\r\nMIME-Version: 1.0\r\nContent-Type: text/plain; charset=US-ASCII;\r\n format=flowed\r\nContent-Transfer-Encoding: 7bit\r\nDate: Mon, 20 Oct 2014 13:32:41 +0200\r\nFrom: =?UTF-8?Q?Br=C3=BCederli=2C_Thomas?= \r\nTo: \"Doe, John\" \r\nSubject: MessageNew event test\r\nMessage-ID: \r\nX-Sender: john@example.org\r\n\r\nThis message should trigger the MessageNew event for john...\r\n...and MessageAppend to /Sent for the sender.\r\n" + }, + "messageHeaders": { + "6": { + "Content-Transfer-Encoding": "7bit", + "Content-Type": "text/plain", + "Date": "2014-10-20T11:32:41Z", + "From": [ + "Br\u00fcederli, Thomas " + ], + "MIME-Version": "1.0", + "Message-ID": "", + "Received": "from imap.example.org ([unix socket])\r\n\t by imap.example.org (Cyrus git2.5+0-Kolab-2.5-67.el6.kolab_3.4) with LMTPA;\r\n\t Mon, 20 Oct 2014 13:34:14 +0200", + "Return-Path": "", + "Subject": "MessageNew event test", + "To": [ + "Doe, John " + ], + "X-Sender": "john@example.org", + "X-Sieve": "CMU Sieve 2.4", + "X-Spam-Flag": "NO", + "X-Spam-Level": "", + "X-Spam-Score": "-0.002", + "X-Spam-Status": "No, score=-0.002 tagged_above=-10 required=6.2\r\n\ttests=[NO_RECEIVED=-0.001, NO_RELAYS=-0.001] autolearn=ham", + "X-Virus-Scanned": "amavisd-new at example.org" + } + }, + "messageSize": 976, + "messages": 6, + "modseq": 20, + "pid": 2340, + "service": "lmtpunix", + "timestamp": "2014-10-20T13:34:14.966+02:00", + "uidnext": 7, + "uidset": "6", + "uri": "imap://john@example.org@imap.example.org/INBOX;UIDVALIDITY=1411487714/;UID=6", + "user": "john@example.org", + "vnd.cmu.midset": [ + "" + ], + "vnd.cmu.sessionId": "imap.example.org-2340-1413804854-1", + "vnd.cmu.unseenMessages": 3 +} diff --git a/docsrc/_static/event_notifications/MessageRead.json b/docsrc/_static/event_notifications/MessageRead.json new file mode 100644 index 00000000..b6139a78 --- /dev/null +++ b/docsrc/_static/event_notifications/MessageRead.json @@ -0,0 +1,17 @@ +{ + "event": "MessageRead", + "messages": 1, + "modseq": 47, + "pid": 7685, + "service": "imap", + "timestamp": "2015-02-23T14:53:44.476+01:00", + "uidnext": 5, + "uidset": "4", + "uri": "imap://john@example.org@imap.example.org/INBOX;UIDVALIDITY=1424683682", + "user": "john@example.org", + "vnd.cmu.midset": [ + "<4d9618acd0aea6b33683766358351459@example.org>" + ], + "vnd.cmu.sessionId": "imap.example.org-7685-1424699624-1-9701853636551497828", + "vnd.cmu.unseenMessages": 0 +} diff --git a/docsrc/_static/event_notifications/MessageTrash.json b/docsrc/_static/event_notifications/MessageTrash.json new file mode 100644 index 00000000..1dc14928 --- /dev/null +++ b/docsrc/_static/event_notifications/MessageTrash.json @@ -0,0 +1,17 @@ +{ + "event": "MessageTrash", + "messages": 1, + "modseq": 48, + "pid": 7809, + "service": "imap", + "timestamp": "2015-02-23T14:54:02.616+01:00", + "uidnext": 5, + "uidset": "4", + "uri": "imap://john@example.org@imap.example.org/INBOX;UIDVALIDITY=1424683682", + "user": "john@example.org", + "vnd.cmu.midset": [ + "<4d9618acd0aea6b33683766358351459@example.org>" + ], + "vnd.cmu.sessionId": "imap.example.org-7809-1424699642-1-2896189896878960640", + "vnd.cmu.unseenMessages": 0 +} diff --git a/docsrc/_static/event_notifications/QuotaChange.json b/docsrc/_static/event_notifications/QuotaChange.json new file mode 100644 index 00000000..d000b58a --- /dev/null +++ b/docsrc/_static/event_notifications/QuotaChange.json @@ -0,0 +1,13 @@ +{ + "diskQuota": 123456789, + "diskUsed": 2, + "event": "QuotaChange", + "maxMessages": -1, + "messages": 3, + "pid": 8140, + "service": "imaps", + "timestamp": "2015-03-10T16:16:19.255+01:00", + "uri": "imap://john.doe@example.org@kolab.example.org/INBOX", + "user": "john.doe@example.org", + "vnd.cmu.sessionId": "kolab.example.org-8140-1426000578-1-14068443041501787710" +} diff --git a/docsrc/_static/event_notifications/QuotaExceed.json b/docsrc/_static/event_notifications/QuotaExceed.json new file mode 100644 index 00000000..654023ea --- /dev/null +++ b/docsrc/_static/event_notifications/QuotaExceed.json @@ -0,0 +1,13 @@ +{ + "diskQuota": 2, + "diskUsed": 2, + "event": "QuotaExceed", + "maxMessages": -1, + "messages": 3, + "pid": 8210, + "service": "lmtpunix", + "timestamp": "2015-03-10T16:13:40.218+01:00", + "uri": "imap://john.doe@example.org@kolab.example.org/INBOX", + "user": "john.doe@example.org", + "vnd.cmu.sessionId": "kolab.example.org-8210-1426000420-4-9494635035963533515" +} diff --git a/docsrc/_static/event_notifications/QuotaWithin.json b/docsrc/_static/event_notifications/QuotaWithin.json new file mode 100644 index 00000000..de643273 --- /dev/null +++ b/docsrc/_static/event_notifications/QuotaWithin.json @@ -0,0 +1,13 @@ +{ + "diskQuota": 123456789, + "diskUsed": 2, + "event": "QuotaWithin", + "maxMessages": -1, + "messages": 3, + "pid": 8140, + "service": "imaps", + "timestamp": "2015-03-10T16:16:19.255+01:00", + "uri": "imap://john.doe@example.org@kolab.example.org/INBOX", + "user": "john.doe@example.org", + "vnd.cmu.sessionId": "kolab.example.org-8140-1426000578-1-14068443041501787710" +} diff --git a/docsrc/_static/favicon.ico b/docsrc/_static/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..d1fb35c89f9a84468772607e0893ea568636949f GIT binary patch literal 1406 zcmeHHO-~b16g@+IP>_!f)1d>cGce*5WQwAleoNceiitZ2lDMnr!iBmtF|mLfU9{># zU1$>{JG3V5B!QB+z*YGJ5?FWDu3ebaOGjdtt_}C)+YFd zK{#rS5(GFYw}@Ta_};qRDwW=2dwU1(-j=Xm2CCIP6bdhp%iYGa`@odngT;jLGA_wi`F*fD~zK+Kr8kk2p9u#37+r ze2HizffynGcohrti!h8ytPuB8Z8RFFyat999|GnKf&n*bwHh*+IVg&k`d%bM1GtsD zg9kVNuIPlFY~X+2K!|g068_`}*ZnHfR8`fO#-MYqc?V?1AghdJhh)x~s`ISU)1!|E zCK)52F_|YEotJ$vM%rYmJasxMN&T7gGE>b7Rlm|DwW4E8XQnwm+$l*jK~IMyT^Q-+ zzDtAswoO-zGon*WJ0z(q945b4Ogn{BqH*jSp=m)7&h;MaK^IA(&q}7mlo*d&*2N=D l;TFaC**=@M@@U98+a}xSzrOF90DN=U_^AQElA!+%_zkL-b-(}s literal 0 HcmV?d00001 diff --git a/docsrc/_static/headimg.gif b/docsrc/_static/headimg.gif new file mode 100644 index 0000000000000000000000000000000000000000..deba4847b808447dccccf17646acabe1448fa971 GIT binary patch literal 83976 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 literal 0 HcmV?d00001 diff --git a/docsrc/_static/logo.gif b/docsrc/_static/logo.gif new file mode 100644 index 0000000000000000000000000000000000000000..25c0534d3dee8210f50ee6d5893b964140952176 GIT binary patch literal 2927 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 ZbRa^#Zl+tEAlcrwx654saqlJ|06YD4Z*l+t literal 0 HcmV?d00001 diff --git a/docsrc/_templates/layout.html b/docsrc/_templates/layout.html new file mode 100644 index 00000000..518c15ee --- /dev/null +++ b/docsrc/_templates/layout.html @@ -0,0 +1,25 @@ +{% extends "!layout.html" %} +{% set css_files = css_files + [ '_static/cyrus.css' ] %} + + +{% block header %} + +
    +{% endblock %} + + +{% block footer %} +{{ super() }} + +{% endblock %} diff --git a/docsrc/conf.py b/docsrc/conf.py new file mode 100644 index 00000000..e159ed0b --- /dev/null +++ b/docsrc/conf.py @@ -0,0 +1,397 @@ +# -*- coding: utf-8 -*- +# +# Cyrus SASL documentation build configuration file, created by +# sphinx-quickstart on Fri Jun 6 19:23:19 2014. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys +import os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.insert(0, os.path.abspath('.')) +sys.path.insert(0, os.path.abspath('exts')) + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +needs_sphinx = '1.2' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.coverage', + 'sphinx.ext.extlinks', + 'sphinx.ext.graphviz', + 'sphinx.ext.ifconfig', + 'sphinx.ext.mathjax', + 'sphinx.ext.todo', + 'sphinx.ext.intersphinx', +] + +extensions.append('sphinxlocal.builders.manpage') + +intersphinx_mapping = {'cyrusimap': ('https://www.cyrusimap.org/dev', None)} + +mathjax_path = 'https://cdn.mathjax.org/mathjax/latest/MathJax.js' + +todo_include_todos = False + +locale_dirs = [ 'locale/' ] +gettext_compact = False + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'Cyrus SASL' +copyright = u'1993-2016, The Cyrus Team' + + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# This is used in breadcrumbs.html to flag the version of the docs the user +# is on. It is NOT the latest version: it is the version of the branch this +# file is in. +# +# Needs to be kept in sync with the rst_prolog imap_*_version replacements +# below as branches increment version numbers. +# May need to also update toplevel index.rst to point to other versions. +# +# The short X.Y version. +version = '2.1.27' +# The full version, including alpha/beta/rc tags. +release = '2.1.27' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = [] + +# The reST default role (used for this markup: `text`) to use for all +# documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +show_authors = True + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +#keep_warnings = False + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. + +html_theme = 'cyrus' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + + +# Add any paths that contain custom themes here, relative to this directory. +html_theme_path = ["exts/themes"] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = "themes/images/logo.gif" + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +html_favicon = "_static/favicon.ico" + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +#html_extra_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +html_sidebars = {'**' : ['localtoc.html', 'searchbox.html']} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +html_show_sourcelink = False + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'Cyrusdoc' + + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + ('index', 'Cyrus.tex', u'Cyrus Documentation', + u'The Cyrus Team', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + ('index', 'SASL', u'Cyrus SASL Documentation', + u'The Cyrus Team', 'Cyrus', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +#texinfo_no_detailmenu = False + + +# -- Options for Epub output ---------------------------------------------- + +# Bibliographic Dublin Core info. +epub_title = u'Cyrus' +epub_author = u'The Cyrus Team' +epub_publisher = u'The Cyrus Team' +epub_copyright = u'2016, The Cyrus Team' + +# The basename for the epub file. It defaults to the project name. +epub_basename = u'Cyrus' + +# The HTML theme for the epub output. Since the default themes are not optimized +# for small screen space, using the same theme for HTML and epub output is +# usually not wise. This defaults to 'epub', a theme designed to save visual +# space. +#epub_theme = 'epub' + +# The language of the text. It defaults to the language option +# or en if the language is not set. +#epub_language = '' + +# The scheme of the identifier. Typical schemes are ISBN or URL. +#epub_scheme = '' + +# The unique identifier of the text. This can be a ISBN number +# or the project homepage. +#epub_identifier = '' + +# A unique identification for the text. +#epub_uid = '' + +# A tuple containing the cover image and cover page html template filenames. +#epub_cover = () + +# A sequence of (type, uri, title) tuples for the guide element of content.opf. +#epub_guide = () + +# HTML files that should be inserted before the pages created by sphinx. +# The format is a list of tuples containing the path and title. +#epub_pre_files = [] + +# HTML files shat should be inserted after the pages created by sphinx. +# The format is a list of tuples containing the path and title. +#epub_post_files = [] + +# A list of files that should not be packed into the epub file. +epub_exclude_files = ['search.html'] + +# The depth of the table of contents in toc.ncx. +#epub_tocdepth = 3 + +# Allow duplicate toc entries. +#epub_tocdup = True + +# Choose between 'default' and 'includehidden'. +#epub_tocscope = 'default' + +# Fix unsupported image types using the PIL. +#epub_fix_images = False + +# Scale large images. +#epub_max_image_width = 0 + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#epub_show_urls = 'inline' + +# If false, no index is generated. +#epub_use_index = True + + +# When this is updated, you may also need to update the version and release +# definitions listed above to stay up to date. +rst_prolog = """ +.. |imap_last_stable_version| replace:: 2.4.18 +.. |imap_last_stable_branch| replace:: `cyrus-imapd-2.4` +.. |imap_last_stable_next_version| replace:: 2.4.18 + patches +.. |imap_current_stable_version| replace:: 2.5.10 +.. |imap_current_stable_next_version| replace:: 2.5.10 + patches +.. |imap_current_stable_branch| replace:: `cyrus-imapd-2.5` +.. |imap_latest_development_version| replace:: 3.0.0-beta3 +.. |imap_latest_development_branch| replace:: master +.. |sasl_current_stable_version| replace:: 2.1.27 +.. |imap_stable_release_notes| raw:: html + + 2.5.10 + +.. |imap_development_release_notes| raw:: html + + 3.0.0-beta3 + +""" + +rst_prolog += """ +.. |git_cyrus_imapd_url| replace:: https://github.com/cyrusimap/cyrus-imapd.git +""" + +rst_prolog += """ +.. |AMS| replace:: :abbr:`AMS (Andrew Mail System)` +.. |CMU| replace:: :abbr:`CMU (Carnegie Mellon University)` +""" + +# Use this as :task:`18` +extlinks = { + 'task':('https://git.cyrus.foundation/T%s', 'Task #'), + 'issue':('https://github.com/cyrusimap/cyrus-imapd/issues/%s', 'Issue #'), + 'cyrus-stable':('http://www.cyrusimap.org/stable%s',None), + 'cyrus-dev':('http://www.cyrusimap.org/dev%s',None), + } diff --git a/docsrc/contribute.rst b/docsrc/contribute.rst new file mode 100644 index 00000000..f925de56 --- /dev/null +++ b/docsrc/contribute.rst @@ -0,0 +1,33 @@ +.. _contribute: + +=================== +Contributor Guide +=================== + +We want your help. No really, we do. In fact, it's bigger than that: we **need** your help. + +You might think that you're not ready; that you need to be an expert in mail systems, or learn another library, or have been involved with the mailing lists or be a professional tester or someone who writes perfectly designed code first time every time. You might think that your idea isn't useful, that nobody else experiences the bug you've noticed, that maybe it's just you that doesn't understand the documentation. + +We'd like to assure you that's not the case. + +All contributions are welcome, no matter how small. + +Cyrus has a :ref:`Contributor Guide ` that you can read. The contribution guidelines outline the process that you'll need to follow to get a code patch merged. By making expectations and process explicit, we hope to make it easier for you to contribute. + +And you don't just have to write code. You can help out by writing documentation, writing tests, lodging bug reports, or even by giving feedback about this work. (And yes, that includes giving feedback about the contribution guidelines.) + +Website Content Contributions +============================= + +Keeping documentation current alongside the code is a task in and of itself. :ref:`Join us! `. + + +Contribute Code +=============== + +The Cyrus Team always welcomes patches sent to the appropriate :ref:`Cyrus Mailing Lists `. + +IRC +=== + +Find us on **#cyrus** at **irc.freenode.net**. More information on clients at :ref:`Cyrus IMAPd IRC `. diff --git a/docsrc/developers.rst b/docsrc/developers.rst new file mode 100644 index 00000000..d7e42cec --- /dev/null +++ b/docsrc/developers.rst @@ -0,0 +1,10 @@ +========== +Developers +========== + + +.. toctree:: + :maxdepth: 2 + :glob: + + Contribute diff --git a/docsrc/download.rst b/docsrc/download.rst new file mode 100644 index 00000000..fa33c8be --- /dev/null +++ b/docsrc/download.rst @@ -0,0 +1,8 @@ +======== +Download +======== + + +.. toctree:: + + sasl/installation diff --git a/docsrc/exts/sphinxlocal/__init__.py b/docsrc/exts/sphinxlocal/__init__.py new file mode 100644 index 00000000..6d36d4bc --- /dev/null +++ b/docsrc/exts/sphinxlocal/__init__.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +""" + sphinxlocal + ~~~~~~~~~~~ + + Custom docutils components. + + :copyright: Copywrite 2015 by Nic Bernstein + :license: BSD, see LICENSE for details. +""" diff --git a/docsrc/exts/sphinxlocal/builders/__init__.py b/docsrc/exts/sphinxlocal/builders/__init__.py new file mode 100644 index 00000000..7297ea18 --- /dev/null +++ b/docsrc/exts/sphinxlocal/builders/__init__.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +""" + sphinxlocal.builders + ~~~~~~~~~~~~~~~ + + Custom docutils builders. + + :copyright: Copywrite 2015 by Nic Bernstein + :license: BSD, see LICENSE for details. +""" diff --git a/docsrc/exts/sphinxlocal/builders/manpage.py b/docsrc/exts/sphinxlocal/builders/manpage.py new file mode 100644 index 00000000..a6281f79 --- /dev/null +++ b/docsrc/exts/sphinxlocal/builders/manpage.py @@ -0,0 +1,97 @@ +# -*- coding: utf-8 -*- +""" + sphinxlocal.builders.manpage + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + A replacement for the manpage builder which come bundled with Sphinx. + + :version: 0.1 + :author: Nic Bernstein + + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +from os import path + +from six import string_types +from docutils.io import FileOutput +from docutils.frontend import OptionParser + +from sphinx import addnodes +from sphinx.errors import SphinxError +from sphinx.builders import Builder +from sphinx.environment import NoUri +from sphinx.util.nodes import inline_all_toctrees +from sphinx.util.console import bold, darkgreen +from sphinx.writers.manpage import ManualPageWriter +from sphinx.builders.manpage import ManualPageBuilder + +## +# Import our customized version of the stock Writer, which has the +# Translater in it. +from sphinxlocal.writers.manpage import CyrusManualPageWriter + +class CyrusManualPageBuilder(ManualPageBuilder): + """ + Builds groff output in manual page format. + """ + name = 'cyrman' + format = 'man' + supported_image_types = [] + + #settings_spec = (u'No options defined.', u'', ()) + #settings_defaults = {} + + def init(self): + if not self.config.man_pages: + self.warn('no "man_pages" config value found; no manual pages ' + 'will be written') + + def write(self, *ignored): + # overwritten -- use our own version of the Writer + docwriter = CyrusManualPageWriter(self) + docsettings = OptionParser( + defaults=self.env.settings, + components=(docwriter,), + read_config_files=True).get_default_values() + + self.info(bold('writing... '), nonl=True) + + for info in self.config.man_pages: + docname, name, description, authors, section = info + if isinstance(authors, string_types): + if authors: + authors = [authors] + else: + authors = [] + + targetname = '%s.%s' % (name, section) + self.info(darkgreen(targetname) + ' { ', nonl=True) + destination = FileOutput( + destination_path=path.join(self.outdir, targetname), + encoding='utf-8') + + tree = self.env.get_doctree(docname) + docnames = set() + largetree = inline_all_toctrees(self, docnames, docname, tree, + darkgreen, [docname]) + self.info('} ', nonl=True) + self.env.resolve_references(largetree, docname, self) + # remove pending_xref nodes + for pendingnode in largetree.traverse(addnodes.pending_xref): + pendingnode.replace_self(pendingnode.children) + + largetree.settings = docsettings + largetree.settings.title = name + largetree.settings.subtitle = description + largetree.settings.authors = authors + largetree.settings.section = section + + docwriter.write(largetree, destination) + self.info() + +def setup(app): + app.add_builder(CyrusManualPageBuilder) + + return {'version': '0.1'} diff --git a/docsrc/exts/sphinxlocal/roles/__init__.py b/docsrc/exts/sphinxlocal/roles/__init__.py new file mode 100644 index 00000000..6d36d4bc --- /dev/null +++ b/docsrc/exts/sphinxlocal/roles/__init__.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +""" + sphinxlocal + ~~~~~~~~~~~ + + Custom docutils components. + + :copyright: Copywrite 2015 by Nic Bernstein + :license: BSD, see LICENSE for details. +""" diff --git a/docsrc/exts/sphinxlocal/writers/__init__.py b/docsrc/exts/sphinxlocal/writers/__init__.py new file mode 100644 index 00000000..6de61d24 --- /dev/null +++ b/docsrc/exts/sphinxlocal/writers/__init__.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +""" + sphinxlocal.writers + ~~~~~~~~~~~~~~ + + Custom docutils writers. + + :copyright: Copyright 2015 by Nic Bernstein + :license: BSD, see LICENSE for details. +""" diff --git a/docsrc/exts/sphinxlocal/writers/manpage.py b/docsrc/exts/sphinxlocal/writers/manpage.py new file mode 100644 index 00000000..463524a4 --- /dev/null +++ b/docsrc/exts/sphinxlocal/writers/manpage.py @@ -0,0 +1,92 @@ +# -*- coding: utf-8 -*- +""" + sphinxlocal.writers.manpage + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + A replacement for the manpage builder which come bundled with Sphinx. + + :version: 0.1 + :author: Nic Bernstein + + :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +from docutils import nodes +from sphinx.writers.manpage import ( + MACRO_DEF, + ManualPageWriter, + ManualPageTranslator as BaseTranslator +) + + +from sphinx import addnodes +from sphinx.locale import admonitionlabels, _ +from sphinx.util.osutil import ustrftime +from sphinx.util.compat import docutils_version + +class CyrusManualPageWriter(ManualPageWriter): + + #settings_spec = (u'No options defined.', u'', ()) + #settings_defaults = {} + + def __init__(self, builder): + ManualPageWriter.__init__(self, builder) + self.builder = builder + + def translate(self): + visitor = CyrusManualPageTranslator(self.builder, self.document) + self.visitor = visitor + self.document.walkabout(visitor) + self.output = visitor.astext() + + +class CyrusManualPageTranslator(BaseTranslator): + """ + Custom translator. + """ + + def __init__(self, builder, *args, **kwds): + BaseTranslator.__init__(self, builder, *args, **kwds) + self.builder = builder + + self.in_productionlist = 0 + + # first title is the manpage title + self.section_level = -1 + + # docinfo set by man_pages config value + self._docinfo['title'] = self.document.settings.title + self._docinfo['subtitle'] = self.document.settings.subtitle + if self.document.settings.authors: + # don't set it if no author given + self._docinfo['author'] = self.document.settings.authors + self._docinfo['manual_section'] = self.document.settings.section + + # docinfo set by other config values + self._docinfo['title_upper'] = self._docinfo['title'].upper() + if builder.config.today: + self._docinfo['date'] = builder.config.today + else: + self._docinfo['date'] = ustrftime(builder.config.today_fmt + or _('%B %d, %Y')) + self._docinfo['copyright'] = builder.config.copyright + self._docinfo['version'] = builder.config.version + self._docinfo['manual_group'] = builder.config.project + + # since self.append_header() is never called, need to do this here + self.body.append(MACRO_DEF) + + # overwritten -- don't wrap literal_block with font calls + self.defs['literal_block'] = ('.sp\n.nf\n', '\n.fi\n') + + + # overwritten -- don't assume indentation + def visit_literal_block(self, node): + self.body.append(self.defs['literal_block'][0]) + self._in_literal = True + + + def depart_literal_block(self, node): + self._in_literal = False + self.body.append(self.defs['literal_block'][1]) diff --git a/docsrc/exts/themes/cyrus/__init__.py b/docsrc/exts/themes/cyrus/__init__.py new file mode 100644 index 00000000..95ddc52a --- /dev/null +++ b/docsrc/exts/themes/cyrus/__init__.py @@ -0,0 +1,17 @@ +"""Sphinx ReadTheDocs theme. + +From https://github.com/ryan-roemer/sphinx-bootstrap-theme. + +""" +import os + +VERSION = (0, 1, 8) + +__version__ = ".".join(str(v) for v in VERSION) +__version_full__ = __version__ + + +def get_html_theme_path(): + """Return list of HTML theme paths.""" + cur_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) + return cur_dir diff --git a/docsrc/exts/themes/cyrus/breadcrumbs.html b/docsrc/exts/themes/cyrus/breadcrumbs.html new file mode 100644 index 00000000..b0a43ef8 --- /dev/null +++ b/docsrc/exts/themes/cyrus/breadcrumbs.html @@ -0,0 +1,23 @@ +
    + +
    +
    diff --git a/docsrc/exts/themes/cyrus/footer.html b/docsrc/exts/themes/cyrus/footer.html new file mode 100644 index 00000000..8bd79145 --- /dev/null +++ b/docsrc/exts/themes/cyrus/footer.html @@ -0,0 +1,36 @@ +
    + {% if next or prev %} + + {% endif %} + +
    + +
    +

    + {%- if show_copyright %} + {%- if hasdoc('copyright') %} + {% trans path=pathto('copyright'), copyright=copyright|e %}© Copyright {{ copyright }}.{% endtrans %} + {%- else %} + {% trans copyright=copyright|e %}© Copyright {{ copyright }}.{% endtrans %} + {%- endif %} + {%- endif %} + + {%- if last_updated %} + {% trans last_updated=last_updated|e %}Last updated on {{ last_updated }}.{% endtrans %} + {%- endif %} +

    +
    + + {%- if show_sphinx %} + {% trans sphinx_version=sphinx_version|e %}Built with Sphinx {{ sphinx_version }} using a modified Read the Docs theme{% endtrans %}. + {%- endif %} + +
    + diff --git a/docsrc/exts/themes/cyrus/layout.html b/docsrc/exts/themes/cyrus/layout.html new file mode 100644 index 00000000..6181a42f --- /dev/null +++ b/docsrc/exts/themes/cyrus/layout.html @@ -0,0 +1,188 @@ +{# TEMPLATE VAR SETTINGS #} +{%- set url_root = pathto('', 1) %} +{%- if url_root == '#' %}{% set url_root = '' %}{% endif %} +{%- if not embedded and docstitle %} + {%- set titlesuffix = " — "|safe + docstitle|e %} +{%- else %} + {%- set titlesuffix = "" %} +{%- endif %} + + + + + + + {{ metatags }} + + {% block htmltitle %} + {{ title|striptags|e }}{{ titlesuffix }} + {% endblock %} + + {# FAVICON #} + {% if favicon %} + + {% endif %} + + {# CSS #} + + {# OPENSEARCH #} + {% if not embedded %} + {% if use_opensearch %} + + {% endif %} + + {% endif %} + + {# RTD hosts this file, so just load on non RTD builds #} + {% if not READTHEDOCS %} + + {% endif %} + + {% for cssfile in css_files %} + + {% endfor %} + + {% for cssfile in extra_css_files %} + + {% endfor %} + + {%- block linktags %} + {%- if hasdoc('about') %} + + {%- endif %} + {%- if hasdoc('genindex') %} + + {%- endif %} + {%- if hasdoc('search') %} + + {%- endif %} + {%- if hasdoc('copyright') %} + + {%- endif %} + + {%- if parents %} + + {%- endif %} + {%- if next %} + + {%- endif %} + {%- if prev %} + + {%- endif %} + {%- endblock %} + {%- block extrahead %} {% endblock %} + + {# Keep modernizr in head - http://modernizr.com/docs/#installing #} + {# I don't think this theme even uses modernizr, commenting out. NNye #} + {# #} + + + + + + + {% block header %} + {% endblock %} + +
    + + {# SIDE NAV, TOGGLES ON MOBILE #} + + +
    + + {# MOBILE NAV, TRIGGLES SIDE NAV ON TOGGLE #} + + + + {# PAGE CONTENT #} +
    +
    + + {% include "breadcrumbs.html" %} +
    + {% block body %}{% endblock %} +
    + {% include "footer.html" %} +
    +
    + +
    + +
    + {% include "versions.html" %} + + {% if not embedded %} + + + {%- for scriptfile in script_files %} + + {%- endfor %} + + {% endif %} + + {# RTD hosts this file, so just load on non RTD builds #} + {% if not READTHEDOCS %} + + {% endif %} + + {# STICKY NAVIGATION #} + {% if theme_sticky_navigation %} + + {% endif %} + + {%- block footer %} {% endblock %} + + + diff --git a/docsrc/exts/themes/cyrus/layout_old.html b/docsrc/exts/themes/cyrus/layout_old.html new file mode 100644 index 00000000..deb8df2a --- /dev/null +++ b/docsrc/exts/themes/cyrus/layout_old.html @@ -0,0 +1,205 @@ +{# + basic/layout.html + ~~~~~~~~~~~~~~~~~ + + Master layout template for Sphinx themes. + + :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +#} +{%- block doctype -%} + +{%- endblock %} +{%- set reldelim1 = reldelim1 is not defined and ' »' or reldelim1 %} +{%- set reldelim2 = reldelim2 is not defined and ' |' or reldelim2 %} +{%- set render_sidebar = (not embedded) and (not theme_nosidebar|tobool) and + (sidebars != []) %} +{%- set url_root = pathto('', 1) %} +{# XXX necessary? #} +{%- if url_root == '#' %}{% set url_root = '' %}{% endif %} +{%- if not embedded and docstitle %} + {%- set titlesuffix = " — "|safe + docstitle|e %} +{%- else %} + {%- set titlesuffix = "" %} +{%- endif %} + +{%- macro relbar() %} + +{%- endmacro %} + +{%- macro sidebar() %} + {%- if render_sidebar %} +
    +
    + {%- block sidebarlogo %} + {%- if logo %} + + {%- endif %} + {%- endblock %} + {%- if sidebars != None %} + {#- new style sidebar: explicitly include/exclude templates #} + {%- for sidebartemplate in sidebars %} + {%- include sidebartemplate %} + {%- endfor %} + {%- else %} + {#- old style sidebars: using blocks -- should be deprecated #} + {%- block sidebartoc %} + {%- include "localtoc.html" %} + {%- endblock %} + {%- block sidebarrel %} + {%- include "relations.html" %} + {%- endblock %} + {%- block sidebarsourcelink %} + {%- include "sourcelink.html" %} + {%- endblock %} + {%- if customsidebar %} + {%- include customsidebar %} + {%- endif %} + {%- block sidebarsearch %} + {%- include "searchbox.html" %} + {%- endblock %} + {%- endif %} +
    +
    + {%- endif %} +{%- endmacro %} + +{%- macro script() %} + + {%- for scriptfile in script_files %} + + {%- endfor %} +{%- endmacro %} + +{%- macro css() %} + + + {%- for cssfile in css_files %} + + {%- endfor %} +{%- endmacro %} + + + + + {{ metatags }} + {%- block htmltitle %} + {{ title|striptags|e }}{{ titlesuffix }} + {%- endblock %} + {{ css() }} + {%- if not embedded %} + {{ script() }} + {%- if use_opensearch %} + + {%- endif %} + {%- if favicon %} + + {%- endif %} + {%- endif %} +{%- block linktags %} + {%- if hasdoc('about') %} + + {%- endif %} + {%- if hasdoc('genindex') %} + + {%- endif %} + {%- if hasdoc('search') %} + + {%- endif %} + {%- if hasdoc('copyright') %} + + {%- endif %} + + {%- if parents %} + + {%- endif %} + {%- if next %} + + {%- endif %} + {%- if prev %} + + {%- endif %} +{%- endblock %} +{%- block extrahead %} {% endblock %} + + +{%- block header %}{% endblock %} + +{%- block relbar1 %}{{ relbar() }}{% endblock %} + +{%- block content %} + {%- block sidebar1 %} {# possible location for sidebar #} {% endblock %} + +
    + {%- block document %} +
    + {%- if render_sidebar %} +
    + {%- endif %} +
    + {% block body %} {% endblock %} +
    + {%- if render_sidebar %} +
    + {%- endif %} +
    + {%- endblock %} + + {%- block sidebar2 %}{{ sidebar() }}{% endblock %} +
    +
    +{%- endblock %} + +{%- block relbar2 %}{{ relbar() }}{% endblock %} + +{%- block footer %} + +

    asdf asdf asdf asdf 22

    +{%- endblock %} + + + diff --git a/docsrc/exts/themes/cyrus/search.html b/docsrc/exts/themes/cyrus/search.html new file mode 100644 index 00000000..e3aa9b5c --- /dev/null +++ b/docsrc/exts/themes/cyrus/search.html @@ -0,0 +1,50 @@ +{# + basic/search.html + ~~~~~~~~~~~~~~~~~ + + Template for the search page. + + :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +#} +{%- extends "layout.html" %} +{% set title = _('Search') %} +{% set script_files = script_files + ['_static/searchtools.js'] %} +{% block footer %} + + {# this is used when loading the search index using $.ajax fails, + such as on Chrome for documents on localhost #} + + {{ super() }} +{% endblock %} +{% block body %} + + + {% if search_performed %} +

    {{ _('Search Results') }}

    + {% if not search_results %} +

    {{ _('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.') }}

    + {% endif %} + {% endif %} +
    + {% if search_results %} +
      + {% for href, caption, context in search_results %} +
    • + {{ caption }} +

      {{ context|e }}

      +
    • + {% endfor %} +
    + {% endif %} +
    +{% endblock %} diff --git a/docsrc/exts/themes/cyrus/searchbox.html b/docsrc/exts/themes/cyrus/searchbox.html new file mode 100644 index 00000000..35ad52c5 --- /dev/null +++ b/docsrc/exts/themes/cyrus/searchbox.html @@ -0,0 +1,9 @@ +{%- if builder != 'singlehtml' %} +
    +
    + + + +
    +
    +{%- endif %} diff --git a/docsrc/exts/themes/cyrus/static/css/badge_only.css b/docsrc/exts/themes/cyrus/static/css/badge_only.css new file mode 100644 index 00000000..7e17fb14 --- /dev/null +++ b/docsrc/exts/themes/cyrus/static/css/badge_only.css @@ -0,0 +1,2 @@ +.fa:before{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-weight:normal;font-style:normal;src:url("../font/fontawesome_webfont.eot");src:url("../font/fontawesome_webfont.eot?#iefix") format("embedded-opentype"),url("../font/fontawesome_webfont.woff") format("woff"),url("../font/fontawesome_webfont.ttf") format("truetype"),url("../font/fontawesome_webfont.svg#FontAwesome") format("svg")}.fa:before{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;text-decoration:inherit}a .fa{display:inline-block;text-decoration:inherit}li .fa{display:inline-block}li .fa-large:before,li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-0.8em}ul.fas li .fa{width:0.8em}ul.fas li .fa-large:before,ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before{content:""}.icon-book:before{content:""}.fa-caret-down:before{content:""}.icon-caret-down:before{content:""}.fa-caret-up:before{content:""}.icon-caret-up:before{content:""}.fa-caret-left:before{content:""}.icon-caret-left:before{content:""}.fa-caret-right:before{content:""}.icon-caret-right:before{content:""}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;border-top:solid 10px #343131;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;z-index:400}.rst-versions a{color:#2980B9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27AE60;*zoom:1}.rst-versions .rst-current-version:before,.rst-versions .rst-current-version:after{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book{float:left}.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#E74C3C;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#F1C40F;color:#000}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:gray;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:solid 1px #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px}.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge .fa-book{float:none}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book{float:left}.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge .rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width: 768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}img{width:100%;height:auto}} +/*# sourceMappingURL=badge_only.css.map */ diff --git a/docsrc/exts/themes/cyrus/static/css/theme.css b/docsrc/exts/themes/cyrus/static/css/theme.css new file mode 100644 index 00000000..57b98fe6 --- /dev/null +++ b/docsrc/exts/themes/cyrus/static/css/theme.css @@ -0,0 +1,5 @@ +*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}[hidden]{display:none}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a:hover,a:active{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}blockquote{margin:0}dfn{font-style:italic}ins{background:#ff9;color:#000;text-decoration:none}mark{background:#ff0;color:#000;font-style:italic;font-weight:bold}pre,code,.rst-content tt,.rst-content code,kbd,samp{font-family:monospace,serif;_font-family:"courier new",monospace;font-size:1em}pre{white-space:pre}q{quotes:none}q:before,q:after{content:"";content:none}small{font-size:85%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}ul,ol,dl{margin:0;padding:0;list-style:none;list-style-image:none}li{list-style:none}dd{margin:0}img{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle;max-width:100%}svg:not(:root){overflow:hidden}figure{margin:0}form{margin:0}fieldset{border:0;margin:0;padding:0}label{cursor:pointer}legend{border:0;*margin-left:-7px;padding:0;white-space:normal}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button;*overflow:visible}button[disabled],input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0;*width:13px;*height:13px}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top;resize:vertical}table{border-collapse:collapse;border-spacing:0}td{vertical-align:top}.chromeframe{margin:0.2em 0;background:#ccc;color:#000;padding:0.2em 0}.ir{display:block;border:0;text-indent:-999em;overflow:hidden;background-color:transparent;background-repeat:no-repeat;text-align:left;direction:ltr;*line-height:0}.ir br{display:none}.hidden{display:none !important;visibility:hidden}.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.invisible{visibility:hidden}.relative{position:relative}big,small{font-size:100%}@media print{html,body,section{background:none !important}*{box-shadow:none !important;text-shadow:none !important;filter:none !important;-ms-filter:none !important}a,a:visited{text-decoration:underline}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,.rst-content p.caption,h3{orphans:3;widows:3}h2,.rst-content p.caption,h3{page-break-after:avoid}}.fa:before,.wy-menu-vertical li span.toctree-expand:before,.wy-menu-vertical li.on a span.toctree-expand:before,.wy-menu-vertical li.current>a span.toctree-expand:before,.rst-content .admonition-title:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content dl dt .headerlink:before,.rst-content tt.download span:first-child:before,.rst-content code.download span:first-child:before,.icon:before,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-alert,.rst-content .note,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .warning,.rst-content .seealso,.rst-content .admonition-todo,.btn,input[type="text"],input[type="password"],input[type="email"],input[type="url"],input[type="date"],input[type="month"],input[type="time"],input[type="datetime"],input[type="datetime-local"],input[type="week"],input[type="number"],input[type="search"],input[type="tel"],input[type="color"],select,textarea,.wy-menu-vertical li.on a,.wy-menu-vertical li.current>a,.wy-side-nav-search>a,.wy-side-nav-search .wy-dropdown>a,.wy-nav-top a{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}/*! + * Font Awesome 4.2.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */@font-face{font-family:'FontAwesome';src:url("../fonts/fontawesome-webfont.eot?v=4.2.0");src:url("../fonts/fontawesome-webfont.eot?#iefix&v=4.2.0") format("embedded-opentype"),url("../fonts/fontawesome-webfont.woff?v=4.2.0") format("woff"),url("../fonts/fontawesome-webfont.ttf?v=4.2.0") format("truetype"),url("../fonts/fontawesome-webfont.svg?v=4.2.0#fontawesomeregular") format("svg");font-weight:normal;font-style:normal}.fa,.wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.current>a span.toctree-expand,.rst-content .admonition-title,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content p.caption .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content dl dt .headerlink,.rst-content tt.download span:first-child,.rst-content code.download span:first-child,.icon{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333em;line-height:0.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14286em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14286em;width:2.14286em;top:0.14286em;text-align:center}.fa-li.fa-lg{left:-1.85714em}.fa-border{padding:.2em .25em .15em;border:solid 0.08em #eee;border-radius:.1em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left,.wy-menu-vertical li span.pull-left.toctree-expand,.wy-menu-vertical li.on a span.pull-left.toctree-expand,.wy-menu-vertical li.current>a span.pull-left.toctree-expand,.rst-content .pull-left.admonition-title,.rst-content h1 .pull-left.headerlink,.rst-content h2 .pull-left.headerlink,.rst-content p.caption .pull-left.headerlink,.rst-content h3 .pull-left.headerlink,.rst-content h4 .pull-left.headerlink,.rst-content h5 .pull-left.headerlink,.rst-content h6 .pull-left.headerlink,.rst-content dl dt .pull-left.headerlink,.rst-content tt.download span.pull-left:first-child,.rst-content code.download span.pull-left:first-child,.pull-left.icon{margin-right:.3em}.fa.pull-right,.wy-menu-vertical li span.pull-right.toctree-expand,.wy-menu-vertical li.on a span.pull-right.toctree-expand,.wy-menu-vertical li.current>a span.pull-right.toctree-expand,.rst-content .pull-right.admonition-title,.rst-content h1 .pull-right.headerlink,.rst-content h2 .pull-right.headerlink,.rst-content p.caption .pull-right.headerlink,.rst-content h3 .pull-right.headerlink,.rst-content h4 .pull-right.headerlink,.rst-content h5 .pull-right.headerlink,.rst-content h6 .pull-right.headerlink,.rst-content dl dt .pull-right.headerlink,.rst-content tt.download span.pull-right:first-child,.rst-content code.download span.pull-right:first-child,.pull-right.icon{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0);-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:""}.fa-music:before{content:""}.fa-search:before,.icon-search:before{content:""}.fa-envelope-o:before{content:""}.fa-heart:before{content:""}.fa-star:before{content:""}.fa-star-o:before{content:""}.fa-user:before{content:""}.fa-film:before{content:""}.fa-th-large:before{content:""}.fa-th:before{content:""}.fa-th-list:before{content:""}.fa-check:before{content:""}.fa-remove:before,.fa-close:before,.fa-times:before{content:""}.fa-search-plus:before{content:""}.fa-search-minus:before{content:""}.fa-power-off:before{content:""}.fa-signal:before{content:""}.fa-gear:before,.fa-cog:before{content:""}.fa-trash-o:before{content:""}.fa-home:before,.icon-home:before{content:""}.fa-file-o:before{content:""}.fa-clock-o:before{content:""}.fa-road:before{content:""}.fa-download:before,.rst-content tt.download span:first-child:before,.rst-content code.download span:first-child:before{content:""}.fa-arrow-circle-o-down:before{content:""}.fa-arrow-circle-o-up:before{content:""}.fa-inbox:before{content:""}.fa-play-circle-o:before{content:""}.fa-rotate-right:before,.fa-repeat:before{content:""}.fa-refresh:before{content:""}.fa-list-alt:before{content:""}.fa-lock:before{content:""}.fa-flag:before{content:""}.fa-headphones:before{content:""}.fa-volume-off:before{content:""}.fa-volume-down:before{content:""}.fa-volume-up:before{content:""}.fa-qrcode:before{content:""}.fa-barcode:before{content:""}.fa-tag:before{content:""}.fa-tags:before{content:""}.fa-book:before,.icon-book:before{content:""}.fa-bookmark:before{content:""}.fa-print:before{content:""}.fa-camera:before{content:""}.fa-font:before{content:""}.fa-bold:before{content:""}.fa-italic:before{content:""}.fa-text-height:before{content:""}.fa-text-width:before{content:""}.fa-align-left:before{content:""}.fa-align-center:before{content:""}.fa-align-right:before{content:""}.fa-align-justify:before{content:""}.fa-list:before{content:""}.fa-dedent:before,.fa-outdent:before{content:""}.fa-indent:before{content:""}.fa-video-camera:before{content:""}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:""}.fa-pencil:before{content:""}.fa-map-marker:before{content:""}.fa-adjust:before{content:""}.fa-tint:before{content:""}.fa-edit:before,.fa-pencil-square-o:before{content:""}.fa-share-square-o:before{content:""}.fa-check-square-o:before{content:""}.fa-arrows:before{content:""}.fa-step-backward:before{content:""}.fa-fast-backward:before{content:""}.fa-backward:before{content:""}.fa-play:before{content:""}.fa-pause:before{content:""}.fa-stop:before{content:""}.fa-forward:before{content:""}.fa-fast-forward:before{content:""}.fa-step-forward:before{content:""}.fa-eject:before{content:""}.fa-chevron-left:before{content:""}.fa-chevron-right:before{content:""}.fa-plus-circle:before{content:""}.fa-minus-circle:before{content:""}.fa-times-circle:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before{content:""}.fa-check-circle:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before{content:""}.fa-question-circle:before{content:""}.fa-info-circle:before{content:""}.fa-crosshairs:before{content:""}.fa-times-circle-o:before{content:""}.fa-check-circle-o:before{content:""}.fa-ban:before{content:""}.fa-arrow-left:before{content:""}.fa-arrow-right:before{content:""}.fa-arrow-up:before{content:""}.fa-arrow-down:before{content:""}.fa-mail-forward:before,.fa-share:before{content:""}.fa-expand:before{content:""}.fa-compress:before{content:""}.fa-plus:before{content:""}.fa-minus:before{content:""}.fa-asterisk:before{content:""}.fa-exclamation-circle:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.rst-content .admonition-title:before{content:""}.fa-gift:before{content:""}.fa-leaf:before{content:""}.fa-fire:before,.icon-fire:before{content:""}.fa-eye:before{content:""}.fa-eye-slash:before{content:""}.fa-warning:before,.fa-exclamation-triangle:before{content:""}.fa-plane:before{content:""}.fa-calendar:before{content:""}.fa-random:before{content:""}.fa-comment:before{content:""}.fa-magnet:before{content:""}.fa-chevron-up:before{content:""}.fa-chevron-down:before{content:""}.fa-retweet:before{content:""}.fa-shopping-cart:before{content:""}.fa-folder:before{content:""}.fa-folder-open:before{content:""}.fa-arrows-v:before{content:""}.fa-arrows-h:before{content:""}.fa-bar-chart-o:before,.fa-bar-chart:before{content:""}.fa-twitter-square:before{content:""}.fa-facebook-square:before{content:""}.fa-camera-retro:before{content:""}.fa-key:before{content:""}.fa-gears:before,.fa-cogs:before{content:""}.fa-comments:before{content:""}.fa-thumbs-o-up:before{content:""}.fa-thumbs-o-down:before{content:""}.fa-star-half:before{content:""}.fa-heart-o:before{content:""}.fa-sign-out:before{content:""}.fa-linkedin-square:before{content:""}.fa-thumb-tack:before{content:""}.fa-external-link:before{content:""}.fa-sign-in:before{content:""}.fa-trophy:before{content:""}.fa-github-square:before{content:""}.fa-upload:before{content:""}.fa-lemon-o:before{content:""}.fa-phone:before{content:""}.fa-square-o:before{content:""}.fa-bookmark-o:before{content:""}.fa-phone-square:before{content:""}.fa-twitter:before{content:""}.fa-facebook:before{content:""}.fa-github:before,.icon-github:before{content:""}.fa-unlock:before{content:""}.fa-credit-card:before{content:""}.fa-rss:before{content:""}.fa-hdd-o:before{content:""}.fa-bullhorn:before{content:""}.fa-bell:before{content:""}.fa-certificate:before{content:""}.fa-hand-o-right:before{content:""}.fa-hand-o-left:before{content:""}.fa-hand-o-up:before{content:""}.fa-hand-o-down:before{content:""}.fa-arrow-circle-left:before,.icon-circle-arrow-left:before{content:""}.fa-arrow-circle-right:before,.icon-circle-arrow-right:before{content:""}.fa-arrow-circle-up:before{content:""}.fa-arrow-circle-down:before{content:""}.fa-globe:before{content:""}.fa-wrench:before{content:""}.fa-tasks:before{content:""}.fa-filter:before{content:""}.fa-briefcase:before{content:""}.fa-arrows-alt:before{content:""}.fa-group:before,.fa-users:before{content:""}.fa-chain:before,.fa-link:before,.icon-link:before{content:""}.fa-cloud:before{content:""}.fa-flask:before{content:""}.fa-cut:before,.fa-scissors:before{content:""}.fa-copy:before,.fa-files-o:before{content:""}.fa-paperclip:before{content:""}.fa-save:before,.fa-floppy-o:before{content:""}.fa-square:before{content:""}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:""}.fa-list-ul:before{content:""}.fa-list-ol:before{content:""}.fa-strikethrough:before{content:""}.fa-underline:before{content:""}.fa-table:before{content:""}.fa-magic:before{content:""}.fa-truck:before{content:""}.fa-pinterest:before{content:""}.fa-pinterest-square:before{content:""}.fa-google-plus-square:before{content:""}.fa-google-plus:before{content:""}.fa-money:before{content:""}.fa-caret-down:before,.wy-dropdown .caret:before,.icon-caret-down:before{content:""}.fa-caret-up:before{content:""}.fa-caret-left:before{content:""}.fa-caret-right:before{content:""}.fa-columns:before{content:""}.fa-unsorted:before,.fa-sort:before{content:""}.fa-sort-down:before,.fa-sort-desc:before{content:""}.fa-sort-up:before,.fa-sort-asc:before{content:""}.fa-envelope:before{content:""}.fa-linkedin:before{content:""}.fa-rotate-left:before,.fa-undo:before{content:""}.fa-legal:before,.fa-gavel:before{content:""}.fa-dashboard:before,.fa-tachometer:before{content:""}.fa-comment-o:before{content:""}.fa-comments-o:before{content:""}.fa-flash:before,.fa-bolt:before{content:""}.fa-sitemap:before{content:""}.fa-umbrella:before{content:""}.fa-paste:before,.fa-clipboard:before{content:""}.fa-lightbulb-o:before{content:""}.fa-exchange:before{content:""}.fa-cloud-download:before{content:""}.fa-cloud-upload:before{content:""}.fa-user-md:before{content:""}.fa-stethoscope:before{content:""}.fa-suitcase:before{content:""}.fa-bell-o:before{content:""}.fa-coffee:before{content:""}.fa-cutlery:before{content:""}.fa-file-text-o:before{content:""}.fa-building-o:before{content:""}.fa-hospital-o:before{content:""}.fa-ambulance:before{content:""}.fa-medkit:before{content:""}.fa-fighter-jet:before{content:""}.fa-beer:before{content:""}.fa-h-square:before{content:""}.fa-plus-square:before{content:""}.fa-angle-double-left:before{content:""}.fa-angle-double-right:before{content:""}.fa-angle-double-up:before{content:""}.fa-angle-double-down:before{content:""}.fa-angle-left:before{content:""}.fa-angle-right:before{content:""}.fa-angle-up:before{content:""}.fa-angle-down:before{content:""}.fa-desktop:before{content:""}.fa-laptop:before{content:""}.fa-tablet:before{content:""}.fa-mobile-phone:before,.fa-mobile:before{content:""}.fa-circle-o:before{content:""}.fa-quote-left:before{content:""}.fa-quote-right:before{content:""}.fa-spinner:before{content:""}.fa-circle:before{content:""}.fa-mail-reply:before,.fa-reply:before{content:""}.fa-github-alt:before{content:""}.fa-folder-o:before{content:""}.fa-folder-open-o:before{content:""}.fa-smile-o:before{content:""}.fa-frown-o:before{content:""}.fa-meh-o:before{content:""}.fa-gamepad:before{content:""}.fa-keyboard-o:before{content:""}.fa-flag-o:before{content:""}.fa-flag-checkered:before{content:""}.fa-terminal:before{content:""}.fa-code:before{content:""}.fa-mail-reply-all:before,.fa-reply-all:before{content:""}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:""}.fa-location-arrow:before{content:""}.fa-crop:before{content:""}.fa-code-fork:before{content:""}.fa-unlink:before,.fa-chain-broken:before{content:""}.fa-question:before{content:""}.fa-info:before{content:""}.fa-exclamation:before{content:""}.fa-superscript:before{content:""}.fa-subscript:before{content:""}.fa-eraser:before{content:""}.fa-puzzle-piece:before{content:""}.fa-microphone:before{content:""}.fa-microphone-slash:before{content:""}.fa-shield:before{content:""}.fa-calendar-o:before{content:""}.fa-fire-extinguisher:before{content:""}.fa-rocket:before{content:""}.fa-maxcdn:before{content:""}.fa-chevron-circle-left:before{content:""}.fa-chevron-circle-right:before{content:""}.fa-chevron-circle-up:before{content:""}.fa-chevron-circle-down:before{content:""}.fa-html5:before{content:""}.fa-css3:before{content:""}.fa-anchor:before{content:""}.fa-unlock-alt:before{content:""}.fa-bullseye:before{content:""}.fa-ellipsis-h:before{content:""}.fa-ellipsis-v:before{content:""}.fa-rss-square:before{content:""}.fa-play-circle:before{content:""}.fa-ticket:before{content:""}.fa-minus-square:before{content:""}.fa-minus-square-o:before,.wy-menu-vertical li.on a span.toctree-expand:before,.wy-menu-vertical li.current>a span.toctree-expand:before{content:""}.fa-level-up:before{content:""}.fa-level-down:before{content:""}.fa-check-square:before{content:""}.fa-pencil-square:before{content:""}.fa-external-link-square:before{content:""}.fa-share-square:before{content:""}.fa-compass:before{content:""}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:""}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:""}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:""}.fa-euro:before,.fa-eur:before{content:""}.fa-gbp:before{content:""}.fa-dollar:before,.fa-usd:before{content:""}.fa-rupee:before,.fa-inr:before{content:""}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:""}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:""}.fa-won:before,.fa-krw:before{content:""}.fa-bitcoin:before,.fa-btc:before{content:""}.fa-file:before{content:""}.fa-file-text:before{content:""}.fa-sort-alpha-asc:before{content:""}.fa-sort-alpha-desc:before{content:""}.fa-sort-amount-asc:before{content:""}.fa-sort-amount-desc:before{content:""}.fa-sort-numeric-asc:before{content:""}.fa-sort-numeric-desc:before{content:""}.fa-thumbs-up:before{content:""}.fa-thumbs-down:before{content:""}.fa-youtube-square:before{content:""}.fa-youtube:before{content:""}.fa-xing:before{content:""}.fa-xing-square:before{content:""}.fa-youtube-play:before{content:""}.fa-dropbox:before{content:""}.fa-stack-overflow:before{content:""}.fa-instagram:before{content:""}.fa-flickr:before{content:""}.fa-adn:before{content:""}.fa-bitbucket:before,.icon-bitbucket:before{content:""}.fa-bitbucket-square:before{content:""}.fa-tumblr:before{content:""}.fa-tumblr-square:before{content:""}.fa-long-arrow-down:before{content:""}.fa-long-arrow-up:before{content:""}.fa-long-arrow-left:before{content:""}.fa-long-arrow-right:before{content:""}.fa-apple:before{content:""}.fa-windows:before{content:""}.fa-android:before{content:""}.fa-linux:before{content:""}.fa-dribbble:before{content:""}.fa-skype:before{content:""}.fa-foursquare:before{content:""}.fa-trello:before{content:""}.fa-female:before{content:""}.fa-male:before{content:""}.fa-gittip:before{content:""}.fa-sun-o:before{content:""}.fa-moon-o:before{content:""}.fa-archive:before{content:""}.fa-bug:before{content:""}.fa-vk:before{content:""}.fa-weibo:before{content:""}.fa-renren:before{content:""}.fa-pagelines:before{content:""}.fa-stack-exchange:before{content:""}.fa-arrow-circle-o-right:before{content:""}.fa-arrow-circle-o-left:before{content:""}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:""}.fa-dot-circle-o:before{content:""}.fa-wheelchair:before{content:""}.fa-vimeo-square:before{content:""}.fa-turkish-lira:before,.fa-try:before{content:""}.fa-plus-square-o:before,.wy-menu-vertical li span.toctree-expand:before{content:""}.fa-space-shuttle:before{content:""}.fa-slack:before{content:""}.fa-envelope-square:before{content:""}.fa-wordpress:before{content:""}.fa-openid:before{content:""}.fa-institution:before,.fa-bank:before,.fa-university:before{content:""}.fa-mortar-board:before,.fa-graduation-cap:before{content:""}.fa-yahoo:before{content:""}.fa-google:before{content:""}.fa-reddit:before{content:""}.fa-reddit-square:before{content:""}.fa-stumbleupon-circle:before{content:""}.fa-stumbleupon:before{content:""}.fa-delicious:before{content:""}.fa-digg:before{content:""}.fa-pied-piper:before{content:""}.fa-pied-piper-alt:before{content:""}.fa-drupal:before{content:""}.fa-joomla:before{content:""}.fa-language:before{content:""}.fa-fax:before{content:""}.fa-building:before{content:""}.fa-child:before{content:""}.fa-paw:before{content:""}.fa-spoon:before{content:""}.fa-cube:before{content:""}.fa-cubes:before{content:""}.fa-behance:before{content:""}.fa-behance-square:before{content:""}.fa-steam:before{content:""}.fa-steam-square:before{content:""}.fa-recycle:before{content:""}.fa-automobile:before,.fa-car:before{content:""}.fa-cab:before,.fa-taxi:before{content:""}.fa-tree:before{content:""}.fa-spotify:before{content:""}.fa-deviantart:before{content:""}.fa-soundcloud:before{content:""}.fa-database:before{content:""}.fa-file-pdf-o:before{content:""}.fa-file-word-o:before{content:""}.fa-file-excel-o:before{content:""}.fa-file-powerpoint-o:before{content:""}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:""}.fa-file-zip-o:before,.fa-file-archive-o:before{content:""}.fa-file-sound-o:before,.fa-file-audio-o:before{content:""}.fa-file-movie-o:before,.fa-file-video-o:before{content:""}.fa-file-code-o:before{content:""}.fa-vine:before{content:""}.fa-codepen:before{content:""}.fa-jsfiddle:before{content:""}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:""}.fa-circle-o-notch:before{content:""}.fa-ra:before,.fa-rebel:before{content:""}.fa-ge:before,.fa-empire:before{content:""}.fa-git-square:before{content:""}.fa-git:before{content:""}.fa-hacker-news:before{content:""}.fa-tencent-weibo:before{content:""}.fa-qq:before{content:""}.fa-wechat:before,.fa-weixin:before{content:""}.fa-send:before,.fa-paper-plane:before{content:""}.fa-send-o:before,.fa-paper-plane-o:before{content:""}.fa-history:before{content:""}.fa-circle-thin:before{content:""}.fa-header:before{content:""}.fa-paragraph:before{content:""}.fa-sliders:before{content:""}.fa-share-alt:before{content:""}.fa-share-alt-square:before{content:""}.fa-bomb:before{content:""}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:""}.fa-tty:before{content:""}.fa-binoculars:before{content:""}.fa-plug:before{content:""}.fa-slideshare:before{content:""}.fa-twitch:before{content:""}.fa-yelp:before{content:""}.fa-newspaper-o:before{content:""}.fa-wifi:before{content:""}.fa-calculator:before{content:""}.fa-paypal:before{content:""}.fa-google-wallet:before{content:""}.fa-cc-visa:before{content:""}.fa-cc-mastercard:before{content:""}.fa-cc-discover:before{content:""}.fa-cc-amex:before{content:""}.fa-cc-paypal:before{content:""}.fa-cc-stripe:before{content:""}.fa-bell-slash:before{content:""}.fa-bell-slash-o:before{content:""}.fa-trash:before{content:""}.fa-copyright:before{content:""}.fa-at:before{content:""}.fa-eyedropper:before{content:""}.fa-paint-brush:before{content:""}.fa-birthday-cake:before{content:""}.fa-area-chart:before{content:""}.fa-pie-chart:before{content:""}.fa-line-chart:before{content:""}.fa-lastfm:before{content:""}.fa-lastfm-square:before{content:""}.fa-toggle-off:before{content:""}.fa-toggle-on:before{content:""}.fa-bicycle:before{content:""}.fa-bus:before{content:""}.fa-ioxhost:before{content:""}.fa-angellist:before{content:""}.fa-cc:before{content:""}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:""}.fa-meanpath:before{content:""}.fa,.wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.current>a span.toctree-expand,.rst-content .admonition-title,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content p.caption .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content dl dt .headerlink,.rst-content tt.download span:first-child,.rst-content code.download span:first-child,.icon,.wy-dropdown .caret,.wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-inline-validate.wy-inline-validate-info .wy-input-context{font-family:inherit}.fa:before,.wy-menu-vertical li span.toctree-expand:before,.wy-menu-vertical li.on a span.toctree-expand:before,.wy-menu-vertical li.current>a span.toctree-expand:before,.rst-content .admonition-title:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content dl dt .headerlink:before,.rst-content tt.download span:first-child:before,.rst-content code.download span:first-child:before,.icon:before,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before{font-family:"FontAwesome";display:inline-block;font-style:normal;font-weight:normal;line-height:1;text-decoration:inherit}a .fa,a .wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li a span.toctree-expand,.wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.current>a span.toctree-expand,a .rst-content .admonition-title,.rst-content a .admonition-title,a .rst-content h1 .headerlink,.rst-content h1 a .headerlink,a .rst-content h2 .headerlink,.rst-content h2 a .headerlink,a .rst-content p.caption .headerlink,.rst-content p.caption a .headerlink,a .rst-content h3 .headerlink,.rst-content h3 a .headerlink,a .rst-content h4 .headerlink,.rst-content h4 a .headerlink,a .rst-content h5 .headerlink,.rst-content h5 a .headerlink,a .rst-content h6 .headerlink,.rst-content h6 a .headerlink,a .rst-content dl dt .headerlink,.rst-content dl dt a .headerlink,a .rst-content tt.download span:first-child,.rst-content tt.download a span:first-child,a .rst-content code.download span:first-child,.rst-content code.download a span:first-child,a .icon{display:inline-block;text-decoration:inherit}.btn .fa,.btn .wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li .btn span.toctree-expand,.btn .wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.on a .btn span.toctree-expand,.btn .wy-menu-vertical li.current>a span.toctree-expand,.wy-menu-vertical li.current>a .btn span.toctree-expand,.btn .rst-content .admonition-title,.rst-content .btn .admonition-title,.btn .rst-content h1 .headerlink,.rst-content h1 .btn .headerlink,.btn .rst-content h2 .headerlink,.rst-content h2 .btn .headerlink,.btn .rst-content p.caption .headerlink,.rst-content p.caption .btn .headerlink,.btn .rst-content h3 .headerlink,.rst-content h3 .btn .headerlink,.btn .rst-content h4 .headerlink,.rst-content h4 .btn .headerlink,.btn .rst-content h5 .headerlink,.rst-content h5 .btn .headerlink,.btn .rst-content h6 .headerlink,.rst-content h6 .btn .headerlink,.btn .rst-content dl dt .headerlink,.rst-content dl dt .btn .headerlink,.btn .rst-content tt.download span:first-child,.rst-content tt.download .btn span:first-child,.btn .rst-content code.download span:first-child,.rst-content code.download .btn span:first-child,.btn .icon,.nav .fa,.nav .wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li .nav span.toctree-expand,.nav .wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.on a .nav span.toctree-expand,.nav .wy-menu-vertical li.current>a span.toctree-expand,.wy-menu-vertical li.current>a .nav span.toctree-expand,.nav .rst-content .admonition-title,.rst-content .nav .admonition-title,.nav .rst-content h1 .headerlink,.rst-content h1 .nav .headerlink,.nav .rst-content h2 .headerlink,.rst-content h2 .nav .headerlink,.nav .rst-content p.caption .headerlink,.rst-content p.caption .nav .headerlink,.nav .rst-content h3 .headerlink,.rst-content h3 .nav .headerlink,.nav .rst-content h4 .headerlink,.rst-content h4 .nav .headerlink,.nav .rst-content h5 .headerlink,.rst-content h5 .nav .headerlink,.nav .rst-content h6 .headerlink,.rst-content h6 .nav .headerlink,.nav .rst-content dl dt .headerlink,.rst-content dl dt .nav .headerlink,.nav .rst-content tt.download span:first-child,.rst-content tt.download .nav span:first-child,.nav .rst-content code.download span:first-child,.rst-content code.download .nav span:first-child,.nav .icon{display:inline}.btn .fa.fa-large,.btn .wy-menu-vertical li span.fa-large.toctree-expand,.wy-menu-vertical li .btn span.fa-large.toctree-expand,.btn .rst-content .fa-large.admonition-title,.rst-content .btn .fa-large.admonition-title,.btn .rst-content h1 .fa-large.headerlink,.rst-content h1 .btn .fa-large.headerlink,.btn .rst-content h2 .fa-large.headerlink,.rst-content h2 .btn .fa-large.headerlink,.btn .rst-content p.caption .fa-large.headerlink,.rst-content p.caption .btn .fa-large.headerlink,.btn .rst-content h3 .fa-large.headerlink,.rst-content h3 .btn .fa-large.headerlink,.btn .rst-content h4 .fa-large.headerlink,.rst-content h4 .btn .fa-large.headerlink,.btn .rst-content h5 .fa-large.headerlink,.rst-content h5 .btn .fa-large.headerlink,.btn .rst-content h6 .fa-large.headerlink,.rst-content h6 .btn .fa-large.headerlink,.btn .rst-content dl dt .fa-large.headerlink,.rst-content dl dt .btn .fa-large.headerlink,.btn .rst-content tt.download span.fa-large:first-child,.rst-content tt.download .btn span.fa-large:first-child,.btn .rst-content code.download span.fa-large:first-child,.rst-content code.download .btn span.fa-large:first-child,.btn .fa-large.icon,.nav .fa.fa-large,.nav .wy-menu-vertical li span.fa-large.toctree-expand,.wy-menu-vertical li .nav span.fa-large.toctree-expand,.nav .rst-content .fa-large.admonition-title,.rst-content .nav .fa-large.admonition-title,.nav .rst-content h1 .fa-large.headerlink,.rst-content h1 .nav .fa-large.headerlink,.nav .rst-content h2 .fa-large.headerlink,.rst-content h2 .nav .fa-large.headerlink,.nav .rst-content p.caption .fa-large.headerlink,.rst-content p.caption .nav .fa-large.headerlink,.nav .rst-content h3 .fa-large.headerlink,.rst-content h3 .nav .fa-large.headerlink,.nav .rst-content h4 .fa-large.headerlink,.rst-content h4 .nav .fa-large.headerlink,.nav .rst-content h5 .fa-large.headerlink,.rst-content h5 .nav .fa-large.headerlink,.nav .rst-content h6 .fa-large.headerlink,.rst-content h6 .nav .fa-large.headerlink,.nav .rst-content dl dt .fa-large.headerlink,.rst-content dl dt .nav .fa-large.headerlink,.nav .rst-content tt.download span.fa-large:first-child,.rst-content tt.download .nav span.fa-large:first-child,.nav .rst-content code.download span.fa-large:first-child,.rst-content code.download .nav span.fa-large:first-child,.nav .fa-large.icon{line-height:0.9em}.btn .fa.fa-spin,.btn .wy-menu-vertical li span.fa-spin.toctree-expand,.wy-menu-vertical li .btn span.fa-spin.toctree-expand,.btn .rst-content .fa-spin.admonition-title,.rst-content .btn .fa-spin.admonition-title,.btn .rst-content h1 .fa-spin.headerlink,.rst-content h1 .btn .fa-spin.headerlink,.btn .rst-content h2 .fa-spin.headerlink,.rst-content h2 .btn .fa-spin.headerlink,.btn .rst-content p.caption .fa-spin.headerlink,.rst-content p.caption .btn .fa-spin.headerlink,.btn .rst-content h3 .fa-spin.headerlink,.rst-content h3 .btn .fa-spin.headerlink,.btn .rst-content h4 .fa-spin.headerlink,.rst-content h4 .btn .fa-spin.headerlink,.btn .rst-content h5 .fa-spin.headerlink,.rst-content h5 .btn .fa-spin.headerlink,.btn .rst-content h6 .fa-spin.headerlink,.rst-content h6 .btn .fa-spin.headerlink,.btn .rst-content dl dt .fa-spin.headerlink,.rst-content dl dt .btn .fa-spin.headerlink,.btn .rst-content tt.download span.fa-spin:first-child,.rst-content tt.download .btn span.fa-spin:first-child,.btn .rst-content code.download span.fa-spin:first-child,.rst-content code.download .btn span.fa-spin:first-child,.btn .fa-spin.icon,.nav .fa.fa-spin,.nav .wy-menu-vertical li span.fa-spin.toctree-expand,.wy-menu-vertical li .nav span.fa-spin.toctree-expand,.nav .rst-content .fa-spin.admonition-title,.rst-content .nav .fa-spin.admonition-title,.nav .rst-content h1 .fa-spin.headerlink,.rst-content h1 .nav .fa-spin.headerlink,.nav .rst-content h2 .fa-spin.headerlink,.rst-content h2 .nav .fa-spin.headerlink,.nav .rst-content p.caption .fa-spin.headerlink,.rst-content p.caption .nav .fa-spin.headerlink,.nav .rst-content h3 .fa-spin.headerlink,.rst-content h3 .nav .fa-spin.headerlink,.nav .rst-content h4 .fa-spin.headerlink,.rst-content h4 .nav .fa-spin.headerlink,.nav .rst-content h5 .fa-spin.headerlink,.rst-content h5 .nav .fa-spin.headerlink,.nav .rst-content h6 .fa-spin.headerlink,.rst-content h6 .nav .fa-spin.headerlink,.nav .rst-content dl dt .fa-spin.headerlink,.rst-content dl dt .nav .fa-spin.headerlink,.nav .rst-content tt.download span.fa-spin:first-child,.rst-content tt.download .nav span.fa-spin:first-child,.nav .rst-content code.download span.fa-spin:first-child,.rst-content code.download .nav span.fa-spin:first-child,.nav .fa-spin.icon{display:inline-block}.btn.fa:before,.wy-menu-vertical li span.btn.toctree-expand:before,.rst-content .btn.admonition-title:before,.rst-content h1 .btn.headerlink:before,.rst-content h2 .btn.headerlink:before,.rst-content p.caption .btn.headerlink:before,.rst-content h3 .btn.headerlink:before,.rst-content h4 .btn.headerlink:before,.rst-content h5 .btn.headerlink:before,.rst-content h6 .btn.headerlink:before,.rst-content dl dt .btn.headerlink:before,.rst-content tt.download span.btn:first-child:before,.rst-content code.download span.btn:first-child:before,.btn.icon:before{opacity:0.5;-webkit-transition:opacity 0.05s ease-in;-moz-transition:opacity 0.05s ease-in;transition:opacity 0.05s ease-in}.btn.fa:hover:before,.wy-menu-vertical li span.btn.toctree-expand:hover:before,.rst-content .btn.admonition-title:hover:before,.rst-content h1 .btn.headerlink:hover:before,.rst-content h2 .btn.headerlink:hover:before,.rst-content p.caption .btn.headerlink:hover:before,.rst-content h3 .btn.headerlink:hover:before,.rst-content h4 .btn.headerlink:hover:before,.rst-content h5 .btn.headerlink:hover:before,.rst-content h6 .btn.headerlink:hover:before,.rst-content dl dt .btn.headerlink:hover:before,.rst-content tt.download span.btn:first-child:hover:before,.rst-content code.download span.btn:first-child:hover:before,.btn.icon:hover:before{opacity:1}.btn-mini .fa:before,.btn-mini .wy-menu-vertical li span.toctree-expand:before,.wy-menu-vertical li .btn-mini span.toctree-expand:before,.btn-mini .rst-content .admonition-title:before,.rst-content .btn-mini .admonition-title:before,.btn-mini .rst-content h1 .headerlink:before,.rst-content h1 .btn-mini .headerlink:before,.btn-mini .rst-content h2 .headerlink:before,.rst-content h2 .btn-mini .headerlink:before,.btn-mini .rst-content p.caption .headerlink:before,.rst-content p.caption .btn-mini .headerlink:before,.btn-mini .rst-content h3 .headerlink:before,.rst-content h3 .btn-mini .headerlink:before,.btn-mini .rst-content h4 .headerlink:before,.rst-content h4 .btn-mini .headerlink:before,.btn-mini .rst-content h5 .headerlink:before,.rst-content h5 .btn-mini .headerlink:before,.btn-mini .rst-content h6 .headerlink:before,.rst-content h6 .btn-mini .headerlink:before,.btn-mini .rst-content dl dt .headerlink:before,.rst-content dl dt .btn-mini .headerlink:before,.btn-mini .rst-content tt.download span:first-child:before,.rst-content tt.download .btn-mini span:first-child:before,.btn-mini .rst-content code.download span:first-child:before,.rst-content code.download .btn-mini span:first-child:before,.btn-mini .icon:before{font-size:14px;vertical-align:-15%}.wy-alert,.rst-content .note,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .warning,.rst-content .seealso,.rst-content .admonition-todo{padding:12px;line-height:24px;margin-bottom:24px;background:#e7f2fa}.wy-alert-title,.rst-content .admonition-title{color:#fff;font-weight:bold;display:block;color:#fff;background:#6ab0de;margin:-12px;padding:6px 12px;margin-bottom:12px}.wy-alert.wy-alert-danger,.rst-content .wy-alert-danger.note,.rst-content .wy-alert-danger.attention,.rst-content .wy-alert-danger.caution,.rst-content .danger,.rst-content .error,.rst-content .wy-alert-danger.hint,.rst-content .wy-alert-danger.important,.rst-content .wy-alert-danger.tip,.rst-content .wy-alert-danger.warning,.rst-content .wy-alert-danger.seealso,.rst-content .wy-alert-danger.admonition-todo{background:#fdf3f2}.wy-alert.wy-alert-danger .wy-alert-title,.rst-content .wy-alert-danger.note .wy-alert-title,.rst-content .wy-alert-danger.attention .wy-alert-title,.rst-content .wy-alert-danger.caution .wy-alert-title,.rst-content .danger .wy-alert-title,.rst-content .error .wy-alert-title,.rst-content .wy-alert-danger.hint .wy-alert-title,.rst-content .wy-alert-danger.important .wy-alert-title,.rst-content .wy-alert-danger.tip .wy-alert-title,.rst-content .wy-alert-danger.warning .wy-alert-title,.rst-content .wy-alert-danger.seealso .wy-alert-title,.rst-content .wy-alert-danger.admonition-todo .wy-alert-title,.wy-alert.wy-alert-danger .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-danger .admonition-title,.rst-content .wy-alert-danger.note .admonition-title,.rst-content .wy-alert-danger.attention .admonition-title,.rst-content .wy-alert-danger.caution .admonition-title,.rst-content .danger .admonition-title,.rst-content .error .admonition-title,.rst-content .wy-alert-danger.hint .admonition-title,.rst-content .wy-alert-danger.important .admonition-title,.rst-content .wy-alert-danger.tip .admonition-title,.rst-content .wy-alert-danger.warning .admonition-title,.rst-content .wy-alert-danger.seealso .admonition-title,.rst-content .wy-alert-danger.admonition-todo .admonition-title{background:#f29f97}.wy-alert.wy-alert-warning,.rst-content .wy-alert-warning.note,.rst-content .attention,.rst-content .caution,.rst-content .wy-alert-warning.danger,.rst-content .wy-alert-warning.error,.rst-content .wy-alert-warning.hint,.rst-content .wy-alert-warning.important,.rst-content .wy-alert-warning.tip,.rst-content .warning,.rst-content .wy-alert-warning.seealso,.rst-content .admonition-todo{background:#ffedcc}.wy-alert.wy-alert-warning .wy-alert-title,.rst-content .wy-alert-warning.note .wy-alert-title,.rst-content .attention .wy-alert-title,.rst-content .caution .wy-alert-title,.rst-content .wy-alert-warning.danger .wy-alert-title,.rst-content .wy-alert-warning.error .wy-alert-title,.rst-content .wy-alert-warning.hint .wy-alert-title,.rst-content .wy-alert-warning.important .wy-alert-title,.rst-content .wy-alert-warning.tip .wy-alert-title,.rst-content .warning .wy-alert-title,.rst-content .wy-alert-warning.seealso .wy-alert-title,.rst-content .admonition-todo .wy-alert-title,.wy-alert.wy-alert-warning .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-warning .admonition-title,.rst-content .wy-alert-warning.note .admonition-title,.rst-content .attention .admonition-title,.rst-content .caution .admonition-title,.rst-content .wy-alert-warning.danger .admonition-title,.rst-content .wy-alert-warning.error .admonition-title,.rst-content .wy-alert-warning.hint .admonition-title,.rst-content .wy-alert-warning.important .admonition-title,.rst-content .wy-alert-warning.tip .admonition-title,.rst-content .warning .admonition-title,.rst-content .wy-alert-warning.seealso .admonition-title,.rst-content .admonition-todo .admonition-title{background:#f0b37e}.wy-alert.wy-alert-info,.rst-content .note,.rst-content .wy-alert-info.attention,.rst-content .wy-alert-info.caution,.rst-content .wy-alert-info.danger,.rst-content .wy-alert-info.error,.rst-content .wy-alert-info.hint,.rst-content .wy-alert-info.important,.rst-content .wy-alert-info.tip,.rst-content .wy-alert-info.warning,.rst-content .seealso,.rst-content .wy-alert-info.admonition-todo{background:#e7f2fa}.wy-alert.wy-alert-info .wy-alert-title,.rst-content .note .wy-alert-title,.rst-content .wy-alert-info.attention .wy-alert-title,.rst-content .wy-alert-info.caution .wy-alert-title,.rst-content .wy-alert-info.danger .wy-alert-title,.rst-content .wy-alert-info.error .wy-alert-title,.rst-content .wy-alert-info.hint .wy-alert-title,.rst-content .wy-alert-info.important .wy-alert-title,.rst-content .wy-alert-info.tip .wy-alert-title,.rst-content .wy-alert-info.warning .wy-alert-title,.rst-content .seealso .wy-alert-title,.rst-content .wy-alert-info.admonition-todo .wy-alert-title,.wy-alert.wy-alert-info .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-info .admonition-title,.rst-content .note .admonition-title,.rst-content .wy-alert-info.attention .admonition-title,.rst-content .wy-alert-info.caution .admonition-title,.rst-content .wy-alert-info.danger .admonition-title,.rst-content .wy-alert-info.error .admonition-title,.rst-content .wy-alert-info.hint .admonition-title,.rst-content .wy-alert-info.important .admonition-title,.rst-content .wy-alert-info.tip .admonition-title,.rst-content .wy-alert-info.warning .admonition-title,.rst-content .seealso .admonition-title,.rst-content .wy-alert-info.admonition-todo .admonition-title{background:#6ab0de}.wy-alert.wy-alert-success,.rst-content .wy-alert-success.note,.rst-content .wy-alert-success.attention,.rst-content .wy-alert-success.caution,.rst-content .wy-alert-success.danger,.rst-content .wy-alert-success.error,.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .wy-alert-success.warning,.rst-content .wy-alert-success.seealso,.rst-content .wy-alert-success.admonition-todo{background:#dbfaf4}.wy-alert.wy-alert-success .wy-alert-title,.rst-content .wy-alert-success.note .wy-alert-title,.rst-content .wy-alert-success.attention .wy-alert-title,.rst-content .wy-alert-success.caution .wy-alert-title,.rst-content .wy-alert-success.danger .wy-alert-title,.rst-content .wy-alert-success.error .wy-alert-title,.rst-content .hint .wy-alert-title,.rst-content .important .wy-alert-title,.rst-content .tip .wy-alert-title,.rst-content .wy-alert-success.warning .wy-alert-title,.rst-content .wy-alert-success.seealso .wy-alert-title,.rst-content .wy-alert-success.admonition-todo .wy-alert-title,.wy-alert.wy-alert-success .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-success .admonition-title,.rst-content .wy-alert-success.note .admonition-title,.rst-content .wy-alert-success.attention .admonition-title,.rst-content .wy-alert-success.caution .admonition-title,.rst-content .wy-alert-success.danger .admonition-title,.rst-content .wy-alert-success.error .admonition-title,.rst-content .hint .admonition-title,.rst-content .important .admonition-title,.rst-content .tip .admonition-title,.rst-content .wy-alert-success.warning .admonition-title,.rst-content .wy-alert-success.seealso .admonition-title,.rst-content .wy-alert-success.admonition-todo .admonition-title{background:#1abc9c}.wy-alert.wy-alert-neutral,.rst-content .wy-alert-neutral.note,.rst-content .wy-alert-neutral.attention,.rst-content .wy-alert-neutral.caution,.rst-content .wy-alert-neutral.danger,.rst-content .wy-alert-neutral.error,.rst-content .wy-alert-neutral.hint,.rst-content .wy-alert-neutral.important,.rst-content .wy-alert-neutral.tip,.rst-content .wy-alert-neutral.warning,.rst-content .wy-alert-neutral.seealso,.rst-content .wy-alert-neutral.admonition-todo{background:#f3f6f6}.wy-alert.wy-alert-neutral .wy-alert-title,.rst-content .wy-alert-neutral.note .wy-alert-title,.rst-content .wy-alert-neutral.attention .wy-alert-title,.rst-content .wy-alert-neutral.caution .wy-alert-title,.rst-content .wy-alert-neutral.danger .wy-alert-title,.rst-content .wy-alert-neutral.error .wy-alert-title,.rst-content .wy-alert-neutral.hint .wy-alert-title,.rst-content .wy-alert-neutral.important .wy-alert-title,.rst-content .wy-alert-neutral.tip .wy-alert-title,.rst-content .wy-alert-neutral.warning .wy-alert-title,.rst-content .wy-alert-neutral.seealso .wy-alert-title,.rst-content .wy-alert-neutral.admonition-todo .wy-alert-title,.wy-alert.wy-alert-neutral .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-neutral .admonition-title,.rst-content .wy-alert-neutral.note .admonition-title,.rst-content .wy-alert-neutral.attention .admonition-title,.rst-content .wy-alert-neutral.caution .admonition-title,.rst-content .wy-alert-neutral.danger .admonition-title,.rst-content .wy-alert-neutral.error .admonition-title,.rst-content .wy-alert-neutral.hint .admonition-title,.rst-content .wy-alert-neutral.important .admonition-title,.rst-content .wy-alert-neutral.tip .admonition-title,.rst-content .wy-alert-neutral.warning .admonition-title,.rst-content .wy-alert-neutral.seealso .admonition-title,.rst-content .wy-alert-neutral.admonition-todo .admonition-title{color:#404040;background:#e1e4e5}.wy-alert.wy-alert-neutral a,.rst-content .wy-alert-neutral.note a,.rst-content .wy-alert-neutral.attention a,.rst-content .wy-alert-neutral.caution a,.rst-content .wy-alert-neutral.danger a,.rst-content .wy-alert-neutral.error a,.rst-content .wy-alert-neutral.hint a,.rst-content .wy-alert-neutral.important a,.rst-content .wy-alert-neutral.tip a,.rst-content .wy-alert-neutral.warning a,.rst-content .wy-alert-neutral.seealso a,.rst-content .wy-alert-neutral.admonition-todo a{color:#2980B9}.wy-alert p:last-child,.rst-content .note p:last-child,.rst-content .attention p:last-child,.rst-content .caution p:last-child,.rst-content .danger p:last-child,.rst-content .error p:last-child,.rst-content .hint p:last-child,.rst-content .important p:last-child,.rst-content .tip p:last-child,.rst-content .warning p:last-child,.rst-content .seealso p:last-child,.rst-content .admonition-todo p:last-child{margin-bottom:0}.wy-tray-container{position:fixed;bottom:0px;left:0;z-index:600}.wy-tray-container li{display:block;width:300px;background:transparent;color:#fff;text-align:center;box-shadow:0 5px 5px 0 rgba(0,0,0,0.1);padding:0 24px;min-width:20%;opacity:0;height:0;line-height:56px;overflow:hidden;-webkit-transition:all 0.3s ease-in;-moz-transition:all 0.3s ease-in;transition:all 0.3s ease-in}.wy-tray-container li.wy-tray-item-success{background:#27AE60}.wy-tray-container li.wy-tray-item-info{background:#2980B9}.wy-tray-container li.wy-tray-item-warning{background:#E67E22}.wy-tray-container li.wy-tray-item-danger{background:#E74C3C}.wy-tray-container li.on{opacity:1;height:56px}@media screen and (max-width: 768px){.wy-tray-container{bottom:auto;top:0;width:100%}.wy-tray-container li{width:100%}}button{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle;cursor:pointer;line-height:normal;-webkit-appearance:button;*overflow:visible}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}button[disabled]{cursor:default}.btn{display:inline-block;border-radius:2px;line-height:normal;white-space:nowrap;text-align:center;cursor:pointer;font-size:100%;padding:6px 12px 8px 12px;color:#fff;border:1px solid rgba(0,0,0,0.1);background-color:#27AE60;text-decoration:none;font-weight:normal;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;box-shadow:0px 1px 2px -1px rgba(255,255,255,0.5) inset,0px -2px 0px 0px rgba(0,0,0,0.1) inset;outline-none:false;vertical-align:middle;*display:inline;zoom:1;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transition:all 0.1s linear;-moz-transition:all 0.1s linear;transition:all 0.1s linear}.btn-hover{background:#2e8ece;color:#fff}.btn:hover{background:#2cc36b;color:#fff}.btn:focus{background:#2cc36b;outline:0}.btn:active{box-shadow:0px -1px 0px 0px rgba(0,0,0,0.05) inset,0px 2px 0px 0px rgba(0,0,0,0.1) inset;padding:8px 12px 6px 12px}.btn:visited{color:#fff}.btn:disabled{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:0.4;cursor:not-allowed;box-shadow:none}.btn-disabled{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:0.4;cursor:not-allowed;box-shadow:none}.btn-disabled:hover,.btn-disabled:focus,.btn-disabled:active{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:0.4;cursor:not-allowed;box-shadow:none}.btn::-moz-focus-inner{padding:0;border:0}.btn-small{font-size:80%}.btn-info{background-color:#2980B9 !important}.btn-info:hover{background-color:#2e8ece !important}.btn-neutral{background-color:#f3f6f6 !important;color:#404040 !important}.btn-neutral:hover{background-color:#e5ebeb !important;color:#404040}.btn-neutral:visited{color:#404040 !important}.btn-success{background-color:#27AE60 !important}.btn-success:hover{background-color:#295 !important}.btn-danger{background-color:#E74C3C !important}.btn-danger:hover{background-color:#ea6153 !important}.btn-warning{background-color:#E67E22 !important}.btn-warning:hover{background-color:#e98b39 !important}.btn-invert{background-color:#222}.btn-invert:hover{background-color:#2f2f2f !important}.btn-link{background-color:transparent !important;color:#2980B9;box-shadow:none;border-color:transparent !important}.btn-link:hover{background-color:transparent !important;color:#409ad5 !important;box-shadow:none}.btn-link:active{background-color:transparent !important;color:#409ad5 !important;box-shadow:none}.btn-link:visited{color:#9B59B6}.wy-btn-group .btn,.wy-control .btn{vertical-align:middle}.wy-btn-group{margin-bottom:24px;*zoom:1}.wy-btn-group:before,.wy-btn-group:after{display:table;content:""}.wy-btn-group:after{clear:both}.wy-dropdown{position:relative;display:inline-block}.wy-dropdown-active .wy-dropdown-menu{display:block}.wy-dropdown-menu{position:absolute;left:0;display:none;float:left;top:100%;min-width:100%;background:#fcfcfc;z-index:100;border:solid 1px #cfd7dd;box-shadow:0 2px 2px 0 rgba(0,0,0,0.1);padding:12px}.wy-dropdown-menu>dd>a{display:block;clear:both;color:#404040;white-space:nowrap;font-size:90%;padding:0 12px;cursor:pointer}.wy-dropdown-menu>dd>a:hover{background:#2980B9;color:#fff}.wy-dropdown-menu>dd.divider{border-top:solid 1px #cfd7dd;margin:6px 0}.wy-dropdown-menu>dd.search{padding-bottom:12px}.wy-dropdown-menu>dd.search input[type="search"]{width:100%}.wy-dropdown-menu>dd.call-to-action{background:#e3e3e3;text-transform:uppercase;font-weight:500;font-size:80%}.wy-dropdown-menu>dd.call-to-action:hover{background:#e3e3e3}.wy-dropdown-menu>dd.call-to-action .btn{color:#fff}.wy-dropdown.wy-dropdown-up .wy-dropdown-menu{bottom:100%;top:auto;left:auto;right:0}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu{background:#fcfcfc;margin-top:2px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a{padding:6px 12px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a:hover{background:#2980B9;color:#fff}.wy-dropdown.wy-dropdown-left .wy-dropdown-menu{right:0;left:auto;text-align:right}.wy-dropdown-arrow:before{content:" ";border-bottom:5px solid #f5f5f5;border-left:5px solid transparent;border-right:5px solid transparent;position:absolute;display:block;top:-4px;left:50%;margin-left:-3px}.wy-dropdown-arrow.wy-dropdown-arrow-left:before{left:11px}.wy-form-stacked select{display:block}.wy-form-aligned input,.wy-form-aligned textarea,.wy-form-aligned select,.wy-form-aligned .wy-help-inline,.wy-form-aligned label{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-form-aligned .wy-control-group>label{display:inline-block;vertical-align:middle;width:10em;margin:6px 12px 0 0;float:left}.wy-form-aligned .wy-control{float:left}.wy-form-aligned .wy-control label{display:block}.wy-form-aligned .wy-control select{margin-top:6px}fieldset{border:0;margin:0;padding:0}legend{display:block;width:100%;border:0;padding:0;white-space:normal;margin-bottom:24px;font-size:150%;*margin-left:-7px}label{display:block;margin:0 0 0.3125em 0;color:#333;font-size:90%}input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}.wy-control-group{margin-bottom:24px;*zoom:1;max-width:68em;margin-left:auto;margin-right:auto;*zoom:1}.wy-control-group:before,.wy-control-group:after{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group:before,.wy-control-group:after{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group.wy-control-group-required>label:after{content:" *";color:#E74C3C}.wy-control-group .wy-form-full,.wy-control-group .wy-form-halves,.wy-control-group .wy-form-thirds{padding-bottom:12px}.wy-control-group .wy-form-full select,.wy-control-group .wy-form-halves select,.wy-control-group .wy-form-thirds select{width:100%}.wy-control-group .wy-form-full input[type="text"],.wy-control-group .wy-form-full input[type="password"],.wy-control-group .wy-form-full input[type="email"],.wy-control-group .wy-form-full input[type="url"],.wy-control-group .wy-form-full input[type="date"],.wy-control-group .wy-form-full input[type="month"],.wy-control-group .wy-form-full input[type="time"],.wy-control-group .wy-form-full input[type="datetime"],.wy-control-group .wy-form-full input[type="datetime-local"],.wy-control-group .wy-form-full input[type="week"],.wy-control-group .wy-form-full input[type="number"],.wy-control-group .wy-form-full input[type="search"],.wy-control-group .wy-form-full input[type="tel"],.wy-control-group .wy-form-full input[type="color"],.wy-control-group .wy-form-halves input[type="text"],.wy-control-group .wy-form-halves input[type="password"],.wy-control-group .wy-form-halves input[type="email"],.wy-control-group .wy-form-halves input[type="url"],.wy-control-group .wy-form-halves input[type="date"],.wy-control-group .wy-form-halves input[type="month"],.wy-control-group .wy-form-halves input[type="time"],.wy-control-group .wy-form-halves input[type="datetime"],.wy-control-group .wy-form-halves input[type="datetime-local"],.wy-control-group .wy-form-halves input[type="week"],.wy-control-group .wy-form-halves input[type="number"],.wy-control-group .wy-form-halves input[type="search"],.wy-control-group .wy-form-halves input[type="tel"],.wy-control-group .wy-form-halves input[type="color"],.wy-control-group .wy-form-thirds input[type="text"],.wy-control-group .wy-form-thirds input[type="password"],.wy-control-group .wy-form-thirds input[type="email"],.wy-control-group .wy-form-thirds input[type="url"],.wy-control-group .wy-form-thirds input[type="date"],.wy-control-group .wy-form-thirds input[type="month"],.wy-control-group .wy-form-thirds input[type="time"],.wy-control-group .wy-form-thirds input[type="datetime"],.wy-control-group .wy-form-thirds input[type="datetime-local"],.wy-control-group .wy-form-thirds input[type="week"],.wy-control-group .wy-form-thirds input[type="number"],.wy-control-group .wy-form-thirds input[type="search"],.wy-control-group .wy-form-thirds input[type="tel"],.wy-control-group .wy-form-thirds input[type="color"]{width:100%}.wy-control-group .wy-form-full{float:left;display:block;margin-right:2.35765%;width:100%;margin-right:0}.wy-control-group .wy-form-full:last-child{margin-right:0}.wy-control-group .wy-form-halves{float:left;display:block;margin-right:2.35765%;width:48.82117%}.wy-control-group .wy-form-halves:last-child{margin-right:0}.wy-control-group .wy-form-halves:nth-of-type(2n){margin-right:0}.wy-control-group .wy-form-halves:nth-of-type(2n+1){clear:left}.wy-control-group .wy-form-thirds{float:left;display:block;margin-right:2.35765%;width:31.76157%}.wy-control-group .wy-form-thirds:last-child{margin-right:0}.wy-control-group .wy-form-thirds:nth-of-type(3n){margin-right:0}.wy-control-group .wy-form-thirds:nth-of-type(3n+1){clear:left}.wy-control-group.wy-control-group-no-input .wy-control{margin:6px 0 0 0;font-size:90%}.wy-control-no-input{display:inline-block;margin:6px 0 0 0;font-size:90%}.wy-control-group.fluid-input input[type="text"],.wy-control-group.fluid-input input[type="password"],.wy-control-group.fluid-input input[type="email"],.wy-control-group.fluid-input input[type="url"],.wy-control-group.fluid-input input[type="date"],.wy-control-group.fluid-input input[type="month"],.wy-control-group.fluid-input input[type="time"],.wy-control-group.fluid-input input[type="datetime"],.wy-control-group.fluid-input input[type="datetime-local"],.wy-control-group.fluid-input input[type="week"],.wy-control-group.fluid-input input[type="number"],.wy-control-group.fluid-input input[type="search"],.wy-control-group.fluid-input input[type="tel"],.wy-control-group.fluid-input input[type="color"]{width:100%}.wy-form-message-inline{display:inline-block;padding-left:0.3em;color:#666;vertical-align:middle;font-size:90%}.wy-form-message{display:block;color:#999;font-size:70%;margin-top:0.3125em;font-style:italic}.wy-form-message p{font-size:inherit;font-style:italic;margin-bottom:6px}.wy-form-message p:last-child{margin-bottom:0}input{line-height:normal}input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;*overflow:visible}input[type="text"],input[type="password"],input[type="email"],input[type="url"],input[type="date"],input[type="month"],input[type="time"],input[type="datetime"],input[type="datetime-local"],input[type="week"],input[type="number"],input[type="search"],input[type="tel"],input[type="color"]{-webkit-appearance:none;padding:6px;display:inline-block;border:1px solid #ccc;font-size:80%;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;box-shadow:inset 0 1px 3px #ddd;border-radius:0;-webkit-transition:border 0.3s linear;-moz-transition:border 0.3s linear;transition:border 0.3s linear}input[type="datetime-local"]{padding:0.34375em 0.625em}input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0;margin-right:0.3125em;*height:13px;*width:13px}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}input[type="text"]:focus,input[type="password"]:focus,input[type="email"]:focus,input[type="url"]:focus,input[type="date"]:focus,input[type="month"]:focus,input[type="time"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="week"]:focus,input[type="number"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="color"]:focus{outline:0;outline:thin dotted \9;border-color:#333}input.no-focus:focus{border-color:#ccc !important}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:1px auto #129FEA}input[type="text"][disabled],input[type="password"][disabled],input[type="email"][disabled],input[type="url"][disabled],input[type="date"][disabled],input[type="month"][disabled],input[type="time"][disabled],input[type="datetime"][disabled],input[type="datetime-local"][disabled],input[type="week"][disabled],input[type="number"][disabled],input[type="search"][disabled],input[type="tel"][disabled],input[type="color"][disabled]{cursor:not-allowed;background-color:#fafafa}input:focus:invalid,textarea:focus:invalid,select:focus:invalid{color:#E74C3C;border:1px solid #E74C3C}input:focus:invalid:focus,textarea:focus:invalid:focus,select:focus:invalid:focus{border-color:#E74C3C}input[type="file"]:focus:invalid:focus,input[type="radio"]:focus:invalid:focus,input[type="checkbox"]:focus:invalid:focus{outline-color:#E74C3C}input.wy-input-large{padding:12px;font-size:100%}textarea{overflow:auto;vertical-align:top;width:100%;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif}select,textarea{padding:0.5em 0.625em;display:inline-block;border:1px solid #ccc;font-size:80%;box-shadow:inset 0 1px 3px #ddd;-webkit-transition:border 0.3s linear;-moz-transition:border 0.3s linear;transition:border 0.3s linear}select{border:1px solid #ccc;background-color:#fff}select[multiple]{height:auto}select:focus,textarea:focus{outline:0}select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{cursor:not-allowed;background-color:#fafafa}input[type="radio"][disabled],input[type="checkbox"][disabled]{cursor:not-allowed}.wy-checkbox,.wy-radio{margin:6px 0;color:#404040;display:block}.wy-checkbox input,.wy-radio input{vertical-align:baseline}.wy-form-message-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-input-prefix,.wy-input-suffix{white-space:nowrap;padding:6px}.wy-input-prefix .wy-input-context,.wy-input-suffix .wy-input-context{line-height:27px;padding:0 8px;display:inline-block;font-size:80%;background-color:#f3f6f6;border:solid 1px #ccc;color:#999}.wy-input-suffix .wy-input-context{border-left:0}.wy-input-prefix .wy-input-context{border-right:0}.wy-switch{width:36px;height:12px;margin:12px 0;position:relative;border-radius:4px;background:#ccc;cursor:pointer;-webkit-transition:all 0.2s ease-in-out;-moz-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out}.wy-switch:before{position:absolute;content:"";display:block;width:18px;height:18px;border-radius:4px;background:#999;left:-3px;top:-3px;-webkit-transition:all 0.2s ease-in-out;-moz-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out}.wy-switch:after{content:"false";position:absolute;left:48px;display:block;font-size:12px;color:#ccc}.wy-switch.active{background:#1e8449}.wy-switch.active:before{left:24px;background:#27AE60}.wy-switch.active:after{content:"true"}.wy-switch.disabled,.wy-switch.active.disabled{cursor:not-allowed}.wy-control-group.wy-control-group-error .wy-form-message,.wy-control-group.wy-control-group-error>label{color:#E74C3C}.wy-control-group.wy-control-group-error input[type="text"],.wy-control-group.wy-control-group-error input[type="password"],.wy-control-group.wy-control-group-error input[type="email"],.wy-control-group.wy-control-group-error input[type="url"],.wy-control-group.wy-control-group-error input[type="date"],.wy-control-group.wy-control-group-error input[type="month"],.wy-control-group.wy-control-group-error input[type="time"],.wy-control-group.wy-control-group-error input[type="datetime"],.wy-control-group.wy-control-group-error input[type="datetime-local"],.wy-control-group.wy-control-group-error input[type="week"],.wy-control-group.wy-control-group-error input[type="number"],.wy-control-group.wy-control-group-error input[type="search"],.wy-control-group.wy-control-group-error input[type="tel"],.wy-control-group.wy-control-group-error input[type="color"]{border:solid 1px #E74C3C}.wy-control-group.wy-control-group-error textarea{border:solid 1px #E74C3C}.wy-inline-validate{white-space:nowrap}.wy-inline-validate .wy-input-context{padding:0.5em 0.625em;display:inline-block;font-size:80%}.wy-inline-validate.wy-inline-validate-success .wy-input-context{color:#27AE60}.wy-inline-validate.wy-inline-validate-danger .wy-input-context{color:#E74C3C}.wy-inline-validate.wy-inline-validate-warning .wy-input-context{color:#E67E22}.wy-inline-validate.wy-inline-validate-info .wy-input-context{color:#2980B9}.rotate-90{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.rotate-180{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.rotate-270{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.mirror{-webkit-transform:scaleX(-1);-moz-transform:scaleX(-1);-ms-transform:scaleX(-1);-o-transform:scaleX(-1);transform:scaleX(-1)}.mirror.rotate-90{-webkit-transform:scaleX(-1) rotate(90deg);-moz-transform:scaleX(-1) rotate(90deg);-ms-transform:scaleX(-1) rotate(90deg);-o-transform:scaleX(-1) rotate(90deg);transform:scaleX(-1) rotate(90deg)}.mirror.rotate-180{-webkit-transform:scaleX(-1) rotate(180deg);-moz-transform:scaleX(-1) rotate(180deg);-ms-transform:scaleX(-1) rotate(180deg);-o-transform:scaleX(-1) rotate(180deg);transform:scaleX(-1) rotate(180deg)}.mirror.rotate-270{-webkit-transform:scaleX(-1) rotate(270deg);-moz-transform:scaleX(-1) rotate(270deg);-ms-transform:scaleX(-1) rotate(270deg);-o-transform:scaleX(-1) rotate(270deg);transform:scaleX(-1) rotate(270deg)}@media only screen and (max-width: 480px){.wy-form button[type="submit"]{margin:0.7em 0 0}.wy-form input[type="text"],.wy-form input[type="password"],.wy-form input[type="email"],.wy-form input[type="url"],.wy-form input[type="date"],.wy-form input[type="month"],.wy-form input[type="time"],.wy-form input[type="datetime"],.wy-form input[type="datetime-local"],.wy-form input[type="week"],.wy-form input[type="number"],.wy-form input[type="search"],.wy-form input[type="tel"],.wy-form input[type="color"]{margin-bottom:0.3em;display:block}.wy-form label{margin-bottom:0.3em;display:block}.wy-form input[type="password"],.wy-form input[type="email"],.wy-form input[type="url"],.wy-form input[type="date"],.wy-form input[type="month"],.wy-form input[type="time"],.wy-form input[type="datetime"],.wy-form input[type="datetime-local"],.wy-form input[type="week"],.wy-form input[type="number"],.wy-form input[type="search"],.wy-form input[type="tel"],.wy-form input[type="color"]{margin-bottom:0}.wy-form-aligned .wy-control-group label{margin-bottom:0.3em;text-align:left;display:block;width:100%}.wy-form-aligned .wy-control{margin:1.5em 0 0 0}.wy-form .wy-help-inline,.wy-form-message-inline,.wy-form-message{display:block;font-size:80%;padding:6px 0}}@media screen and (max-width: 768px){.tablet-hide{display:none}}@media screen and (max-width: 480px){.mobile-hide{display:none}}.float-left{float:left}.float-right{float:right}.full-width{width:100%}.wy-table,.rst-content table.docutils,.rst-content table.field-list{border-collapse:collapse;border-spacing:0;empty-cells:show;margin-bottom:24px}.wy-table caption,.rst-content table.docutils caption,.rst-content table.field-list caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.wy-table td,.rst-content table.docutils td,.rst-content table.field-list td,.wy-table th,.rst-content table.docutils th,.rst-content table.field-list th{font-size:90%;margin:0;overflow:visible;padding:8px 16px}.wy-table td:first-child,.rst-content table.docutils td:first-child,.rst-content table.field-list td:first-child,.wy-table th:first-child,.rst-content table.docutils th:first-child,.rst-content table.field-list th:first-child{border-left-width:0}.wy-table thead,.rst-content table.docutils thead,.rst-content table.field-list thead{color:#000;text-align:left;vertical-align:bottom;white-space:nowrap}.wy-table thead th,.rst-content table.docutils thead th,.rst-content table.field-list thead th{font-weight:bold;border-bottom:solid 2px #e1e4e5}.wy-table td,.rst-content table.docutils td,.rst-content table.field-list td{background-color:transparent;vertical-align:middle}.wy-table td p,.rst-content table.docutils td p,.rst-content table.field-list td p{line-height:18px}.wy-table td p:last-child,.rst-content table.docutils td p:last-child,.rst-content table.field-list td p:last-child{margin-bottom:0}.wy-table .wy-table-cell-min,.rst-content table.docutils .wy-table-cell-min,.rst-content table.field-list .wy-table-cell-min{width:1%;padding-right:0}.wy-table .wy-table-cell-min input[type=checkbox],.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox],.wy-table .wy-table-cell-min input[type=checkbox],.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox]{margin:0}.wy-table-secondary{color:gray;font-size:90%}.wy-table-tertiary{color:gray;font-size:80%}.wy-table-odd td,.wy-table-striped tr:nth-child(2n-1) td,.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td{background-color:#f3f6f6}.wy-table-backed{background-color:#f3f6f6}.wy-table-bordered-all,.rst-content table.docutils{border:1px solid #e1e4e5}.wy-table-bordered-all td,.rst-content table.docutils td{border-bottom:1px solid #e1e4e5;border-left:1px solid #e1e4e5}.wy-table-bordered-all tbody>tr:last-child td,.rst-content table.docutils tbody>tr:last-child td{border-bottom-width:0}.wy-table-bordered{border:1px solid #e1e4e5}.wy-table-bordered-rows td{border-bottom:1px solid #e1e4e5}.wy-table-bordered-rows tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal td,.wy-table-horizontal th{border-width:0 0 1px 0;border-bottom:1px solid #e1e4e5}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-responsive{margin-bottom:24px;max-width:100%;overflow:auto}.wy-table-responsive table{margin-bottom:0 !important}.wy-table-responsive table td,.wy-table-responsive table th{white-space:nowrap}a{color:#2980B9;text-decoration:none;cursor:pointer}a:hover{color:#3091d1}a:visited{color:#9B59B6}html{height:100%;overflow-x:hidden}body{font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;font-weight:normal;color:#404040;min-height:100%;overflow-x:hidden;background:#edf0f2}.wy-text-left{text-align:left}.wy-text-center{text-align:center}.wy-text-right{text-align:right}.wy-text-large{font-size:120%}.wy-text-normal{font-size:100%}.wy-text-small,small{font-size:80%}.wy-text-strike{text-decoration:line-through}.wy-text-warning{color:#E67E22 !important}a.wy-text-warning:hover{color:#eb9950 !important}.wy-text-info{color:#2980B9 !important}a.wy-text-info:hover{color:#409ad5 !important}.wy-text-success{color:#27AE60 !important}a.wy-text-success:hover{color:#36d278 !important}.wy-text-danger{color:#E74C3C !important}a.wy-text-danger:hover{color:#ed7669 !important}.wy-text-neutral{color:#404040 !important}a.wy-text-neutral:hover{color:#595959 !important}h1,h2,.rst-content p.caption,h3,h4,h5,h6,legend{margin-top:0;font-weight:700;font-family:"Roboto Slab","ff-tisa-web-pro","Georgia",Arial,sans-serif}p{line-height:24px;margin:0;font-size:16px;margin-bottom:24px}h1{font-size:175%}h2,.rst-content p.caption{font-size:150%}h3{font-size:125%}h4{font-size:115%}h5{font-size:110%}h6{font-size:100%}hr{display:block;height:1px;border:0;border-top:1px solid #e1e4e5;margin:24px 0;padding:0}code,.rst-content tt,.rst-content code{white-space:nowrap;max-width:100%;background:#fff;border:solid 1px #e1e4e5;font-size:75%;padding:0 5px;font-family:Consolas,"Andale Mono WT","Andale Mono","Lucida Console","Lucida Sans Typewriter","DejaVu Sans Mono","Bitstream Vera Sans Mono","Liberation Mono","Nimbus Mono L",Monaco,"Courier New",Courier,monospace;color:#E74C3C;overflow-x:auto}code.code-large,.rst-content tt.code-large{font-size:90%}.wy-plain-list-disc,.rst-content .section ul,.rst-content .toctree-wrapper ul,article ul{list-style:disc;line-height:24px;margin-bottom:24px}.wy-plain-list-disc li,.rst-content .section ul li,.rst-content .toctree-wrapper ul li,article ul li{list-style:disc;margin-left:24px}.wy-plain-list-disc li p:last-child,.rst-content .section ul li p:last-child,.rst-content .toctree-wrapper ul li p:last-child,article ul li p:last-child{margin-bottom:0}.wy-plain-list-disc li ul,.rst-content .section ul li ul,.rst-content .toctree-wrapper ul li ul,article ul li ul{margin-bottom:0}.wy-plain-list-disc li li,.rst-content .section ul li li,.rst-content .toctree-wrapper ul li li,article ul li li{list-style:circle}.wy-plain-list-disc li li li,.rst-content .section ul li li li,.rst-content .toctree-wrapper ul li li li,article ul li li li{list-style:square}.wy-plain-list-disc li ol li,.rst-content .section ul li ol li,.rst-content .toctree-wrapper ul li ol li,article ul li ol li{list-style:decimal}.wy-plain-list-decimal,.rst-content .section ol,.rst-content ol.arabic,article ol{list-style:decimal;line-height:24px;margin-bottom:24px}.wy-plain-list-decimal li,.rst-content .section ol li,.rst-content ol.arabic li,article ol li{list-style:decimal;margin-left:24px}.wy-plain-list-decimal li p:last-child,.rst-content .section ol li p:last-child,.rst-content ol.arabic li p:last-child,article ol li p:last-child{margin-bottom:0}.wy-plain-list-decimal li ul,.rst-content .section ol li ul,.rst-content ol.arabic li ul,article ol li ul{margin-bottom:0}.wy-plain-list-decimal li ul li,.rst-content .section ol li ul li,.rst-content ol.arabic li ul li,article ol li ul li{list-style:disc}.codeblock-example{border:1px solid #e1e4e5;border-bottom:none;padding:24px;padding-top:48px;font-weight:500;background:#fff;position:relative}.codeblock-example:after{content:"Example";position:absolute;top:0px;left:0px;background:#9B59B6;color:#fff;padding:6px 12px}.codeblock-example.prettyprint-example-only{border:1px solid #e1e4e5;margin-bottom:24px}.codeblock,pre.literal-block,.rst-content .literal-block,.rst-content pre.literal-block,div[class^='highlight']{border:1px solid #e1e4e5;padding:0px;overflow-x:auto;background:#fff;margin:1px 0 24px 0}.codeblock div[class^='highlight'],pre.literal-block div[class^='highlight'],.rst-content .literal-block div[class^='highlight'],div[class^='highlight'] div[class^='highlight']{border:none;background:none;margin:0}div[class^='highlight'] td.code{width:100%}.linenodiv pre{border-right:solid 1px #e6e9ea;margin:0;padding:12px 12px;font-family:Consolas,"Andale Mono WT","Andale Mono","Lucida Console","Lucida Sans Typewriter","DejaVu Sans Mono","Bitstream Vera Sans Mono","Liberation Mono","Nimbus Mono L",Monaco,"Courier New",Courier,monospace;font-size:12px;line-height:1.5;color:#d9d9d9}div[class^='highlight'] pre{white-space:pre;margin:0;padding:12px 12px;font-family:Consolas,"Andale Mono WT","Andale Mono","Lucida Console","Lucida Sans Typewriter","DejaVu Sans Mono","Bitstream Vera Sans Mono","Liberation Mono","Nimbus Mono L",Monaco,"Courier New",Courier,monospace;font-size:12px;line-height:1.5;display:block;overflow:auto;color:#404040}@media print{.codeblock,pre.literal-block,.rst-content .literal-block,.rst-content pre.literal-block,div[class^='highlight'],div[class^='highlight'] pre{white-space:pre-wrap}}.hll{background-color:#ffc;margin:0 -12px;padding:0 12px;display:block}.c{color:#998;font-style:italic}.err{color:#a61717;background-color:#e3d2d2}.k{font-weight:bold}.o{font-weight:bold}.cm{color:#998;font-style:italic}.cp{color:#999;font-weight:bold}.c1{color:#998;font-style:italic}.cs{color:#999;font-weight:bold;font-style:italic}.gd{color:#000;background-color:#fdd}.gd .x{color:#000;background-color:#faa}.ge{font-style:italic}.gr{color:#a00}.gh{color:#999}.gi{color:#000;background-color:#dfd}.gi .x{color:#000;background-color:#afa}.go{color:#888}.gp{color:#555}.gs{font-weight:bold}.gu{color:purple;font-weight:bold}.gt{color:#a00}.kc{font-weight:bold}.kd{font-weight:bold}.kn{font-weight:bold}.kp{font-weight:bold}.kr{font-weight:bold}.kt{color:#458;font-weight:bold}.m{color:#099}.s{color:#d14}.n{color:#333}.na{color:teal}.nb{color:#0086b3}.nc{color:#458;font-weight:bold}.no{color:teal}.ni{color:purple}.ne{color:#900;font-weight:bold}.nf{color:#900;font-weight:bold}.nn{color:#555}.nt{color:navy}.nv{color:teal}.ow{font-weight:bold}.w{color:#bbb}.mf{color:#099}.mh{color:#099}.mi{color:#099}.mo{color:#099}.sb{color:#d14}.sc{color:#d14}.sd{color:#d14}.s2{color:#d14}.se{color:#d14}.sh{color:#d14}.si{color:#d14}.sx{color:#d14}.sr{color:#009926}.s1{color:#d14}.ss{color:#990073}.bp{color:#999}.vc{color:teal}.vg{color:teal}.vi{color:teal}.il{color:#099}.gc{color:#999;background-color:#EAF2F5}.wy-breadcrumbs li{display:inline-block}.wy-breadcrumbs li.wy-breadcrumbs-aside{float:right}.wy-breadcrumbs li a{display:inline-block;padding:5px}.wy-breadcrumbs li a:first-child{padding-left:0}.wy-breadcrumbs-extra{margin-bottom:0;color:#b3b3b3;font-size:80%;display:inline-block}@media screen and (max-width: 480px){.wy-breadcrumbs-extra{display:none}.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}@media print{.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}.wy-affix{position:fixed;top:1.618em}.wy-menu a:hover{text-decoration:none}.wy-menu-horiz{*zoom:1}.wy-menu-horiz:before,.wy-menu-horiz:after{display:table;content:""}.wy-menu-horiz:after{clear:both}.wy-menu-horiz ul,.wy-menu-horiz li{display:inline-block}.wy-menu-horiz li:hover{background:rgba(255,255,255,0.1)}.wy-menu-horiz li.divide-left{border-left:solid 1px #404040}.wy-menu-horiz li.divide-right{border-right:solid 1px #404040}.wy-menu-horiz a{height:32px;display:inline-block;line-height:32px;padding:0 16px}.wy-menu-vertical header,.wy-menu-vertical p.caption{height:32px;display:inline-block;line-height:32px;padding:0 1.618em;margin-bottom:0;display:block;font-weight:bold;text-transform:uppercase;font-size:80%;color:#555;white-space:nowrap}.wy-menu-vertical ul{margin-bottom:0}.wy-menu-vertical li.divide-top{border-top:solid 1px #404040}.wy-menu-vertical li.divide-bottom{border-bottom:solid 1px #404040}.wy-menu-vertical li.current{background:#e3e3e3}.wy-menu-vertical li.current a{color:gray;border-right:solid 1px #c9c9c9;padding:0.4045em 2.427em}.wy-menu-vertical li.current a:hover{background:#d6d6d6}.wy-menu-vertical li code,.wy-menu-vertical li .rst-content tt,.rst-content .wy-menu-vertical li tt{border:none;background:inherit;color:inherit;padding-left:0;padding-right:0}.wy-menu-vertical li span.toctree-expand{display:block;float:left;margin-left:-1.2em;font-size:0.8em;line-height:1.6em;color:#4d4d4d}.wy-menu-vertical li.on a,.wy-menu-vertical li.current>a{color:#404040;padding:0.4045em 1.618em;font-weight:bold;position:relative;background:#fcfcfc;border:none;border-bottom:solid 1px #c9c9c9;border-top:solid 1px #c9c9c9;padding-left:1.618em -4px}.wy-menu-vertical li.on a:hover,.wy-menu-vertical li.current>a:hover{background:#fcfcfc}.wy-menu-vertical li.on a:hover span.toctree-expand,.wy-menu-vertical li.current>a:hover span.toctree-expand{color:gray}.wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.current>a span.toctree-expand{display:block;font-size:0.8em;line-height:1.6em;color:#333}.wy-menu-vertical li.toctree-l1.current li.toctree-l2>ul,.wy-menu-vertical li.toctree-l2.current li.toctree-l3>ul{display:none}.wy-menu-vertical li.toctree-l1.current li.toctree-l2.current>ul,.wy-menu-vertical li.toctree-l2.current li.toctree-l3.current>ul{display:block}.wy-menu-vertical li.toctree-l2.current>a{background:#c9c9c9;padding:0.4045em 2.427em}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{display:block;background:#c9c9c9;padding:0.4045em 4.045em}.wy-menu-vertical li.toctree-l2 a:hover span.toctree-expand{color:gray}.wy-menu-vertical li.toctree-l2 span.toctree-expand{color:#a3a3a3}.wy-menu-vertical li.toctree-l3{font-size:0.9em}.wy-menu-vertical li.toctree-l3.current>a{background:#bdbdbd;padding:0.4045em 4.045em}.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{display:block;background:#bdbdbd;padding:0.4045em 5.663em;border-top:none;border-bottom:none}.wy-menu-vertical li.toctree-l3 a:hover span.toctree-expand{color:gray}.wy-menu-vertical li.toctree-l3 span.toctree-expand{color:#969696}.wy-menu-vertical li.toctree-l4{font-size:0.9em}.wy-menu-vertical li.current ul{display:block}.wy-menu-vertical li ul{margin-bottom:0;display:none}.wy-menu-vertical .local-toc li ul{display:block}.wy-menu-vertical li ul li a{margin-bottom:0;color:#b3b3b3;font-weight:normal}.wy-menu-vertical a{display:inline-block;line-height:18px;padding:0.4045em 1.618em;display:block;position:relative;font-size:90%;color:#b3b3b3}.wy-menu-vertical a:hover{background-color:#4e4a4a;cursor:pointer}.wy-menu-vertical a:hover span.toctree-expand{color:#b3b3b3}.wy-menu-vertical a:active{background-color:#2980B9;cursor:pointer;color:#fff}.wy-menu-vertical a:active span.toctree-expand{color:#fff}.wy-side-nav-search{z-index:200;background-color:#2980B9;text-align:center;padding:0.809em;display:block;color:#fcfcfc;margin-bottom:0.809em}.wy-side-nav-search input[type=text]{width:100%;border-radius:50px;padding:6px 12px;border-color:#2472a4}.wy-side-nav-search img{display:block;margin:auto auto 0.809em auto;height:45px;width:45px;background-color:#2980B9;padding:5px;border-radius:100%}.wy-side-nav-search>a,.wy-side-nav-search .wy-dropdown>a{color:#fcfcfc;font-size:100%;font-weight:bold;display:inline-block;padding:4px 6px;margin-bottom:0.809em}.wy-side-nav-search>a:hover,.wy-side-nav-search .wy-dropdown>a:hover{background:rgba(255,255,255,0.1)}.wy-side-nav-search>a img.logo,.wy-side-nav-search .wy-dropdown>a img.logo{display:block;margin:0 auto;height:auto;width:auto;border-radius:0;max-width:100%;background:transparent}.wy-side-nav-search>a.icon img.logo,.wy-side-nav-search .wy-dropdown>a.icon img.logo{margin-top:0.85em}.wy-nav .wy-menu-vertical header{color:#2980B9}.wy-nav .wy-menu-vertical a{color:#b3b3b3}.wy-nav .wy-menu-vertical a:hover{background-color:#2980B9;color:#fff}[data-menu-wrap]{-webkit-transition:all 0.2s ease-in;-moz-transition:all 0.2s ease-in;transition:all 0.2s ease-in;position:absolute;opacity:1;width:100%;opacity:0}[data-menu-wrap].move-center{left:0;right:auto;opacity:1}[data-menu-wrap].move-left{right:auto;left:-100%;opacity:0}[data-menu-wrap].move-right{right:-100%;left:auto;opacity:0}.wy-body-for-nav{background:left repeat-y #fcfcfc;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoxOERBMTRGRDBFMUUxMUUzODUwMkJCOThDMEVFNURFMCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDoxOERBMTRGRTBFMUUxMUUzODUwMkJCOThDMEVFNURFMCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjE4REExNEZCMEUxRTExRTM4NTAyQkI5OEMwRUU1REUwIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjE4REExNEZDMEUxRTExRTM4NTAyQkI5OEMwRUU1REUwIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+EwrlwAAAAA5JREFUeNpiMDU0BAgwAAE2AJgB9BnaAAAAAElFTkSuQmCC);background-size:300px 1px}.wy-grid-for-nav{position:absolute;width:100%;height:100%}.wy-nav-side{position:fixed;top:0;bottom:0;left:0;padding-bottom:2em;width:300px;overflow-x:hidden;overflow-y:scroll;min-height:100%;background:#343131;z-index:200}.wy-nav-top{display:none;background:#2980B9;color:#fff;padding:0.4045em 0.809em;position:relative;line-height:50px;text-align:center;font-size:100%;*zoom:1}.wy-nav-top:before,.wy-nav-top:after{display:table;content:""}.wy-nav-top:after{clear:both}.wy-nav-top a{color:#fff;font-weight:bold}.wy-nav-top img{margin-right:12px;height:45px;width:45px;background-color:#2980B9;padding:5px;border-radius:100%}.wy-nav-top i{font-size:30px;float:left;cursor:pointer}.wy-nav-content-wrap{margin-left:300px;background:#fcfcfc;min-height:100%}.wy-nav-content{padding:1.618em 3.236em;height:100%;max-width:800px;margin:auto}.wy-body-mask{position:fixed;width:100%;height:100%;background:rgba(0,0,0,0.2);display:none;z-index:499}.wy-body-mask.on{display:block}footer{color:#999}footer p{margin-bottom:12px}.rst-footer-buttons{*zoom:1}.rst-footer-buttons:before,.rst-footer-buttons:after{display:table;content:""}.rst-footer-buttons:after{clear:both}#search-results .search li{margin-bottom:24px;border-bottom:solid 1px #e1e4e5;padding-bottom:24px}#search-results .search li:first-child{border-top:solid 1px #e1e4e5;padding-top:24px}#search-results .search li a{font-size:120%;margin-bottom:12px;display:inline-block}#search-results .context{color:gray;font-size:90%}@media screen and (max-width: 768px){.wy-body-for-nav{background:#fcfcfc}.wy-nav-top{display:block}.wy-nav-side{left:-300px}.wy-nav-side.shift{width:85%;left:0}.wy-nav-content-wrap{margin-left:0}.wy-nav-content-wrap .wy-nav-content{padding:1.618em}.wy-nav-content-wrap.shift{position:fixed;min-width:100%;left:85%;top:0;height:100%;overflow:hidden}}@media screen and (min-width: 1400px){.wy-nav-content-wrap{background:rgba(0,0,0,0.05)}.wy-nav-content{margin:0;background:#fcfcfc}}@media print{.rst-versions,footer,.wy-nav-side{display:none}.wy-nav-content-wrap{margin-left:0}}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;border-top:solid 10px #343131;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;z-index:400}.rst-versions a{color:#2980B9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27AE60;*zoom:1}.rst-versions .rst-current-version:before,.rst-versions .rst-current-version:after{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-versions .rst-current-version .fa,.rst-versions .rst-current-version .wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li .rst-versions .rst-current-version span.toctree-expand,.rst-versions .rst-current-version .rst-content .admonition-title,.rst-content .rst-versions .rst-current-version .admonition-title,.rst-versions .rst-current-version .rst-content h1 .headerlink,.rst-content h1 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h2 .headerlink,.rst-content h2 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content p.caption .headerlink,.rst-content p.caption .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h3 .headerlink,.rst-content h3 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h4 .headerlink,.rst-content h4 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h5 .headerlink,.rst-content h5 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h6 .headerlink,.rst-content h6 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content dl dt .headerlink,.rst-content dl dt .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content tt.download span:first-child,.rst-content tt.download .rst-versions .rst-current-version span:first-child,.rst-versions .rst-current-version .rst-content code.download span:first-child,.rst-content code.download .rst-versions .rst-current-version span:first-child,.rst-versions .rst-current-version .icon{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#E74C3C;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#F1C40F;color:#000}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:gray;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:solid 1px #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px}.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge .rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width: 768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}img{width:100%;height:auto}}.rst-content img{max-width:100%;height:auto !important}.rst-content div.figure{margin-bottom:24px}.rst-content div.figure.align-center{text-align:center}.rst-content .section>img,.rst-content .section>a>img{margin-bottom:24px}.rst-content blockquote{margin-left:24px;line-height:24px;margin-bottom:24px}.rst-content .note .last,.rst-content .attention .last,.rst-content .caution .last,.rst-content .danger .last,.rst-content .error .last,.rst-content .hint .last,.rst-content .important .last,.rst-content .tip .last,.rst-content .warning .last,.rst-content .seealso .last,.rst-content .admonition-todo .last{margin-bottom:0}.rst-content .admonition-title:before{margin-right:4px}.rst-content .admonition table{border-color:rgba(0,0,0,0.1)}.rst-content .admonition table td,.rst-content .admonition table th{background:transparent !important;border-color:rgba(0,0,0,0.1) !important}.rst-content .section ol.loweralpha,.rst-content .section ol.loweralpha li{list-style:lower-alpha}.rst-content .section ol.upperalpha,.rst-content .section ol.upperalpha li{list-style:upper-alpha}.rst-content .section ol p,.rst-content .section ul p{margin-bottom:12px}.rst-content .line-block{margin-left:24px}.rst-content .topic-title{font-weight:bold;margin-bottom:12px}.rst-content .toc-backref{color:#404040}.rst-content .align-right{float:right;margin:0px 0px 24px 24px}.rst-content .align-left{float:left;margin:0px 24px 24px 0px}.rst-content .align-center{margin:auto;display:block}.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content p.caption .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content dl dt .headerlink,.rst-content p.caption .headerlink{display:none;visibility:hidden;font-size:14px}.rst-content h1 .headerlink:after,.rst-content h2 .headerlink:after,.rst-content p.caption .headerlink:after,.rst-content h3 .headerlink:after,.rst-content h4 .headerlink:after,.rst-content h5 .headerlink:after,.rst-content h6 .headerlink:after,.rst-content dl dt .headerlink:after,.rst-content p.caption .headerlink:after{visibility:visible;content:"";font-family:FontAwesome;display:inline-block}.rst-content h1:hover .headerlink,.rst-content h2:hover .headerlink,.rst-content p.caption:hover .headerlink,.rst-content h3:hover .headerlink,.rst-content h4:hover .headerlink,.rst-content h5:hover .headerlink,.rst-content h6:hover .headerlink,.rst-content dl dt:hover .headerlink,.rst-content p.caption:hover .headerlink{display:inline-block}.rst-content .sidebar{float:right;width:40%;display:block;margin:0 0 24px 24px;padding:24px;background:#f3f6f6;border:solid 1px #e1e4e5}.rst-content .sidebar p,.rst-content .sidebar ul,.rst-content .sidebar dl{font-size:90%}.rst-content .sidebar .last{margin-bottom:0}.rst-content .sidebar .sidebar-title{display:block;font-family:"Roboto Slab","ff-tisa-web-pro","Georgia",Arial,sans-serif;font-weight:bold;background:#e1e4e5;padding:6px 12px;margin:-24px;margin-bottom:24px;font-size:100%}.rst-content .highlighted{background:#F1C40F;display:inline-block;font-weight:bold;padding:0 6px}.rst-content .footnote-reference,.rst-content .citation-reference{vertical-align:super;font-size:90%}.rst-content table.docutils.citation,.rst-content table.docutils.footnote{background:none;border:none;color:#999}.rst-content table.docutils.citation td,.rst-content table.docutils.citation tr,.rst-content table.docutils.footnote td,.rst-content table.docutils.footnote tr{border:none;background-color:transparent !important;white-space:normal}.rst-content table.docutils.citation td.label,.rst-content table.docutils.footnote td.label{padding-left:0;padding-right:0;vertical-align:top}.rst-content table.field-list{border:none}.rst-content table.field-list td{border:none;padding-top:5px}.rst-content table.field-list td>strong{display:inline-block;margin-top:3px}.rst-content table.field-list .field-name{padding-right:10px;text-align:left;white-space:nowrap}.rst-content table.field-list .field-body{text-align:left;padding-left:0}.rst-content tt,.rst-content tt,.rst-content code{color:#000}.rst-content tt big,.rst-content tt em,.rst-content tt big,.rst-content code big,.rst-content tt em,.rst-content code em{font-size:100% !important;line-height:normal}.rst-content tt .xref,a .rst-content tt,.rst-content tt .xref,.rst-content code .xref,a .rst-content tt,a .rst-content code{font-weight:bold}.rst-content a tt,.rst-content a tt,.rst-content a code{color:#2980B9}.rst-content dl{margin-bottom:24px}.rst-content dl dt{font-weight:bold}.rst-content dl p,.rst-content dl table,.rst-content dl ul,.rst-content dl ol{margin-bottom:12px !important}.rst-content dl dd{margin:0 0 12px 24px}.rst-content dl:not(.docutils){margin-bottom:24px}.rst-content dl:not(.docutils) dt{display:inline-block;margin:6px 0;font-size:90%;line-height:normal;background:#e7f2fa;color:#2980B9;border-top:solid 3px #6ab0de;padding:6px;position:relative}.rst-content dl:not(.docutils) dt:before{color:#6ab0de}.rst-content dl:not(.docutils) dt .headerlink{color:#404040;font-size:100% !important}.rst-content dl:not(.docutils) dl dt{margin-bottom:6px;border:none;border-left:solid 3px #ccc;background:#f0f0f0;color:gray}.rst-content dl:not(.docutils) dl dt .headerlink{color:#404040;font-size:100% !important}.rst-content dl:not(.docutils) dt:first-child{margin-top:0}.rst-content dl:not(.docutils) tt,.rst-content dl:not(.docutils) tt,.rst-content dl:not(.docutils) code{font-weight:bold}.rst-content dl:not(.docutils) tt.descname,.rst-content dl:not(.docutils) tt.descclassname,.rst-content dl:not(.docutils) tt.descname,.rst-content dl:not(.docutils) code.descname,.rst-content dl:not(.docutils) tt.descclassname,.rst-content dl:not(.docutils) code.descclassname{background-color:transparent;border:none;padding:0;font-size:100% !important}.rst-content dl:not(.docutils) tt.descname,.rst-content dl:not(.docutils) tt.descname,.rst-content dl:not(.docutils) code.descname{font-weight:bold}.rst-content dl:not(.docutils) .optional{display:inline-block;padding:0 4px;color:#000;font-weight:bold}.rst-content dl:not(.docutils) .property{display:inline-block;padding-right:8px}.rst-content .viewcode-link,.rst-content .viewcode-back{display:inline-block;color:#27AE60;font-size:80%;padding-left:24px}.rst-content .viewcode-back{display:block;float:right}.rst-content p.rubric{margin-bottom:12px;font-weight:bold}.rst-content tt.download,.rst-content code.download{background:inherit;padding:inherit;font-family:inherit;font-size:inherit;color:inherit;border:inherit;white-space:inherit}.rst-content tt.download span:first-child:before,.rst-content code.download span:first-child:before{margin-right:4px}@media screen and (max-width: 480px){.rst-content .sidebar{width:100%}}span[id*='MathJax-Span']{color:#404040}.math{text-align:center}@font-face{font-family:"Inconsolata";font-style:normal;font-weight:400;src:local("Inconsolata"),url(../fonts/Inconsolata.ttf) format("truetype")}@font-face{font-family:"Inconsolata";font-style:normal;font-weight:700;src:local("Inconsolata Bold"),local("Inconsolata-Bold"),url(../fonts/Inconsolata-Bold.ttf) format("truetype")}@font-face{font-family:"Lato";font-style:normal;font-weight:400;src:local("Lato Regular"),local("Lato-Regular"),url(../fonts/Lato-Regular.ttf) format("truetype")}@font-face{font-family:"Lato";font-style:normal;font-weight:700;src:local("Lato Bold"),local("Lato-Bold"),url(../fonts/Lato-Bold.ttf) format("truetype")}@font-face{font-family:"Roboto Slab";font-style:normal;font-weight:400;src:local("Roboto Slab Regular"),local("RobotoSlab-Regular"),url(../fonts/RobotoSlab-Regular.ttf) format("truetype")}@font-face{font-family:"Roboto Slab";font-style:normal;font-weight:700;src:local("Roboto Slab Bold"),local("RobotoSlab-Bold"),url(../fonts/RobotoSlab-Bold.ttf) format("truetype")} +/*# sourceMappingURL=theme.css.map */ diff --git a/docsrc/exts/themes/cyrus/static/fonts/Inconsolata-Bold.ttf b/docsrc/exts/themes/cyrus/static/fonts/Inconsolata-Bold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..360a232dd09e43114a50814b999f67351cdf9a24 GIT binary patch literal 47064 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 literal 0 HcmV?d00001 diff --git a/docsrc/exts/themes/cyrus/static/fonts/Inconsolata.ttf b/docsrc/exts/themes/cyrus/static/fonts/Inconsolata.ttf new file mode 100644 index 0000000000000000000000000000000000000000..4b8a36d249a05a0fe1575dc3d96ef7079dba6b07 GIT binary patch literal 63184 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 literal 0 HcmV?d00001 diff --git a/docsrc/exts/themes/cyrus/static/fonts/Lato-Bold.ttf b/docsrc/exts/themes/cyrus/static/fonts/Lato-Bold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..e8b9bf6a20e1f67fd0e8b42b25e3f0e627babe39 GIT binary patch literal 82368 zcmc${2b^40*#~^jy>qAR^u9YgGdq2Io$Z_5oo(5g-Z#A`3+XWlfrJ)nFn}V`6c7!F zAVH;xAPAzbB6bD)tFOLD@dJ53QOHid|8wr#+1bq|0rdC#0?Evrd(LxDdCt?%a|9*` zf*t>81Y7^yISZ_depw^1s+1r&E&U4?bsuX!c2Hnlb5U#OoCVc&zxv+?ZxDp%eum#` z)^A(8^SXTe6rQigKVMtFZ*NHV-GaLW;YB}wS8dw4dE4&M-6=eORS>j)-n@3tPQfhX z13uL^Z9e~kP0u`ZmsSuM>OW=LvT^N(lfV6YzaTuL$MeQ5D6sxR_j$bU1b)Z1Y}Cd^%|MJ84MVBOwekLMS@T*>FmyUhe>B@E>RZ^bY}twCa%Tri)&)hk%c8NeXmO%L(@>v? zMl519QtYhn5Hk<)vr1%Pd$onyOfBtk4>< z&2`7>0{+^#+a0g<2kK((^cSVSpR{yITTgykb756yqHk?m)10=lc+9hAcf6rIUYd+X zD=aokV7%C0N6qT|f!dhc9jnz```&1u91uj|$EW@-3RpLT5D;EVSp>nCZ?oW+LDtB$ zRt8LPA!ZPWAJZ_#um&O)3~L}s4k@I;8raWL#jRAyKTDMi6hewKy(j~P7P|nQz%CS-!du!LDrzpt z&o5~%3N@E{<>TYeFMnv=x`&pFGv51S_DNHT*IUwr-e4{-m#!DThq=rX+``6`!)O!) zquc1VTTzmy)o4}RFLap`;_Opi$}2>b3aA@H6Z#KB;lt2b zSTvHTX7;c>`<0D)b@8%TnbsrrtKa0~=|9|2QC(ee2MbMnQ~F(uy}JYbo*|@|CWZZy z!q&yF8BGoKb=6g+#ff+4uqH&spkPK|0buOo3s-w}$f|!^VM5YNL7_ECb0Bd#iXKhGLtO9T{ z)vVO!bJcKq8;02zqV!tobBuSNzJ;|J?2s_04fTyp&ZuNz<;=-{cCw^1+SI|?7qgd&pp>H1$dbv2DUI`pl@ zJ4arewLMzFI==7J)i!KM9t(vf)A)TqNWRE!NpGo%$_AO$rN32E#%?K!SsZhiYjYyb zx=Sk3W9;UVqC7eM3<}b36vZu$*ZxQu+**zX$w=GAGjft zsAUu_0VoD&_z3F=UF9lPj0q&-=XF*|4cK~}jOJ1oWL}QGRbsIelt4B`E2Bwe^;FWq zn2VZNB=*CP{a|1uFYNHtrRFy$`j77DZQpzUcB2>zEVqx{)-uE5cUemtQpM4MkMEk< zvH#0EP4tL;vaq(hI5M^^?ekTq5=Bk3>%0crn*Lo@XHi*M9(%^sxa{gpBRB3Ik`L!6 zzHMLJxZLG(7Wxh8b)JTWhgPk;=g@5ZC%whu;Y3SC$ebRt>=9p2v{ptfY_~34(?2-J5u8G?P%HEa%h-yPXYs<3q3%?3V{LUsSu8@-Rjc7#(2v!q!Kw*53Hv!A z=mfn%r>AeCNHdQ~WcDI(KbeU!Et6%FjCB}35kfmG*16iDJ~h^&F<7TV8`5PqU-PtW zH5yLY)g>WP6yo7fmC0%t!%(lY0m`%RSbkm z>NsdPVZBPjfhEL035^J)bifs2v2Nf>vaUnqn5AIRIckcpG_5$;J#cVYUEQ*S0|OV1 z)_v1c+z<@bC*1BteK6Qi>=ExW#X?_w|0Pr0_qcrN)ap-rdG)x*6X(^vnt}O8R@T+6 zJTiab)vJ=pRaY-;on7O0*UWBh909uW#B}9<~4Ok_iqzZ#=&PX4bJ19Te zIJ&nZ%$zP?b<`cG?TQ7Po7*DkU7gnrc>PD-+L(SpV{}+H&tBSc{;g|zF4(d#IDCEo z@Kqby-hZQMX?wV-mR(tY8HosxJ=iFhJ?5qIK#jP>A*m9F$3W6H#BD{~0DZ{_8==et zqBwveMClPB3jM;wO_eexM2lR30yW3d&x>YlMDPo`l*X0EjOEPb@CKRNrL{7J)Hm^; zI<3f38&>LMmu36VmhPgW?kz*xEiUtl4dR}c(z_ordkn4ueb4T{y!O_iLvO$K=iS}< z0;kjWP1`x%#&Xu>sHcx*!2(j zoX!G$_wGNx_V%GeZ@u=H-97pOm%(Fxh#lka8Ik(LpU7_rNns10&!mtn^zr#5`WvaK zC@+aci#!gy*`U{0FjtV}Xbx%S1T!N+u6&wGm{zJ3W2 zF>e)XXGu(>u7h=QE~)brF&bpCC&1W3S!)d1KihVvBkFWU9e1|gX)iMBz>$I{4q(!GIPsPEW1X0Ggu=OCw5~&dq#Ir=2 z5RpE@8ZNJf-C=vw9&QNR#pCRX^o8F|A7YnlK9%0|Sb77y<1uy{n$AuC58Ka*grKlG zr7iSnHKK~g4l83^Ngxbm%tZ67$cIy&SosPRD%JTU^C{=eXbDIYK!2KYgnu2!qNWb1 z2_#^yJJA?QG$$N^=J^ff4x`=}3KeRL>f`QPNCPXZZjaQAjcq6^wtDm~y(wDR5cHNb zqVF5n|0|A(&w&udQ(DqM(DxJ+!_Y!J2M?}^X7L~}iO>hJ6T#_kj@ zO=(G1;A1B(47wRXp>aD{NW{2F@yaQ6E2X4s<&*` z9ioSWQ+1-Nr>a5h)Zb3sEd}J4fFqSDt1hQ_Fi?kA6 ziv($pWWiq<{IL?}7IDCys@y7hBVLpIi?T}a3Zd@QTbjk-gCt+=Pvxo7lt#r4Uq*7m zJ2;QS8)!E=NF`9P1QwMEnT5nIdhX_GS2*_(q-oAgGF9j!gE7n{a^}Dwb~v~w%N$b$ z56$9v*FU#w*R#jw&OP?*u3gVvKkro4tPPC~>qjapN7gqqZkSai{`9HzUmsnz>`~@@ z>S^YoZ|T>b{>)1UYikd_^qI^jP1qM8j#tX}VGy58nH+YT)nYb)b7tlFs0oG>5tJR9 z4%kL~-dKdr!+rw64{TY(wJuuzkXn^X`!xGG^{iAcRW@A}jRunxov2HoNmIhA#l!ac zCROibNjs1k%Nv(|WG*zj!ur|liSIMb$v-?H4c9h)*{HW0&tv=Fw?Bb#EkqCNv6eN$ zqbVB`%1UApm(ykzYFJHHPp+(B8p(*!i9rGSG5C5NBo{P>5Zs1={Y18WSdw;8gTtNYI9LMnr%hz%M6_<<{eQ7q)mqFK#RjfzgY*=8j?e`d|ImU zTO8eRd|!9bT6h_|kjjN88T7 zW#!zfFWNgJ{Z)&#GJezif<`ZUym`}x%`NqF8Vg595@E@^I4X6i5#fVI%&T#2HFEvVCW;kV32P~%*(){57GyKirMub znL|+wikljtlY4{E%sa4Mu__I;I&n52Wdkh(OVDhP?-guv+Uc-%Itk$5T= zAdCM&i25291o|pGm5DHmDta0aUZrW7TG*A?P`On_5jYNGNSOkLS0GKl0ktr1*weHz zupweJjrdeCo1_g`$iSw_vc!@S;dNO0@}s_j%U>Ss^8L zoosE9_mK3-^n%b($@r%L94Isb+_XR@Ef@ZfvXz$=$6-Utci8mA6jZEiE0sl=l`u*6 zFkm7K!Z18a8d3~piJ^mJz9mZ%1bS$w8c;jF;~gSbXlci{oCyS)F)aXL*Jpuc0l0}| zq`E&;TT#UFM6;cszL07`*yqwl!xGSq+kClN%CS$;L^;msik)HUw>`7dyX)7@+x_6a z8S`%V_TJuu=Pi$oT`0$aDp(~!;z3G>G*$?w0rHGrP4e1n%L}L>+S3A=Txbwz;Ywu|Is#p^(A0P2XZ~lIGqm3JA{{!29>cQ4B_y&e(dt)ZTHz6x0qwt>_PK2! zH3176&ruyHiXD^Fj^3F;2btS$8Z#QUvURku1QPi!<`kPKHCc0|*cECyopr zzG7@^&w+b4Y`FJ8&)C*04i6rAVrTn`&d`y)dyj-VSG3QVU+4DK&uwa&+fd-Hn{S)3 z{f;%4JX~J!x!v=RZEb7YdTjpg&sCH^e94+Sw$FGr+OfE9|G|U%>lSxJ#XAz6^U6zy zS|X8_q0;hsowUk8^vi%VbNL$73ZGH-S|V29#a_d_Pwce-r`j+?07bCtFzqV4BC(VU zE9zd0Wa@%!YlyRfzE8AL>33zO5;i2n=ZTu=jY5r3ND>jfOWkRFY8A5>O=kw_VCS%K zld59+@X(GE9m6;5>K(Z3(d|1PKGfqapAk<#V(%&c6MNPkwA3A7)>!xQ#^%w^$e}$m zR;I#YSN+!8x2(PYlA)Q0Phk3YY;8!Fe)wOhn8lXZ{gS4G9)X2a{oVi8@2H|}^`U=k@ zUxREf@Em%4IQJ3yN0Y8rq5jh5R_set6()O*dPxe@uBi&t)ZbGTD)FyVH7vrzUC@td zPJULk%J6I zm7`L=%bWg`HyH>dz3e=%>*TBA&)8>9xWcBdo9sHB-Sng>>^i|dtI&n3*-cVfdI0#N z6OyUCjA2B;dSr2jyp@D2;0%O2B+n2c0e2ugkPU!Tr>muXC$FWy;>hD-{$sr2pV8lO z^w&=PwF>AjoN|p#aUz?=ak33D_n%$pWJMeLiaxuf{GU)qpY&MJ&#zNI)9W_?mMFwe z{aq>n{VEeW*t(RZt);fQv^W-VIx@aV+K<)KJHi!S0Vtqg8lq7dGcP$6$PDpensK|X zvU5L7GZ>Xs7siKamU$cP@yhAPhN)3w4%CsM5rjk7bHJ|77Na1O!bAe0G9&cCZOvRJ zbap`T$cX`{hankZ0E&}hnmB-XWZtUnsU_EMYOd&+Ju@kLzi4L_-6P!7&zC@KiP|Kc=zK@@sU zS+%wDCSifFo^_`}ixx6r}+pos;enU1pQ9CP8Jrh1!j`i+c1j@+$>KV zWl|n!r3BZVtO-Iumjx|!Nj-E(y&_%;d6Jk1j%G4|s2W8%C)L*iZs(Arqx6vu>?7=P+g-)K5_8mCMS;-al1U4W4-6O+m4KM zuIwxdv@Y5AiDk34C)e1l1u=KoaC3Oxjo&+P`G0?5<)*K^ech}pcdm%JECEwwOZv61 zJd%F#zb|gubi;`s>^#Qg|2ojQ>(;d1*HBYp9t=e~&Yx4&^mwX&prc~e){d5sZCl-6 zn(s+}JXIbn$u~5tIWqgQ7p~}8|G;Zkeg0qfF0=>YZewU!@8aD*XLa8^?|Tp5G}gBI z;Zt{=_vE#6?y{BkCYev$xMF`Q)ejm2olCw3a0bu~nTC4(2Saq52DGXJ#837dJl|C}!P?#J( zQkeVlS(t_48^cQJ{!f}r^p#^)45LaFdX%Hx9XoqTbwkgLe+M!7>`+#g5Y_6ieOtuR&{ zY%Zz@j^2{lG3#&DGH%IMCGfIL8%!i(pa}hPS}RHgwEzc({GB{&WvC*w*RqYcDxz5K zV5?INSQ>6GK?I2^Wyh0sjZj(3*(caL$NuZm8NtrAJ*;fzmCqkezs~H#8`}$msSW+< zw|;reu}iN0i+sFs!?9(_mGip2J*QUOu`4AWOfQYim|Iyr+~EKEhHbmn5X0+$57PwR zQz`r)gA1-W1{EPfIU8VE;#enRs=@dz0?5iBUH$3Vs- zra;ua?ksIZfFj*JM+1Uv2NK`*!5X1Q3ef^N0BVsIr7Hfp+t|?L+TH0>kFGucd1n8@-ES`*)fafYHAB0WZ2HoLeSQ1xTG6y@xF?+FVT53@eMZS$f-CP%C+)_>%weFvYutk2{t4H^(&M0_1MDc=m7GzkS{7x%cF zb^|O)SzR{AF3xrS3<4q`N8N7I+Qp&Qa_JZQh}2r5gJ-pigPK8%snd8IGBG*&-XY32 zk3EzA`{&1B7E3O=SFH_OG-~y!7Nw`S>r=JARnn z{7Vc2eP5?Hk1*tCdxj}M&&W&9M`TiB=?K^TCd* z!Y{$hms1BcfV!_3HOLBhdiQzf#lZNV(r;7O7yfemtJHI4@3v#_)(C&5=!23(xTvte zZq0*tM}WOPOYPbM;AoHvn2|{oRU~UgP<~jLX-u4vDxn70%4C1w$P~kjA_7p|#4Tq4 zp@Ddz;RfX_up9sg|HEGH`A}`SBLS8PwHM?b$n5EOU1O6SETbKfnHGcza2Cz?wg%Ay zklZF>2c)v)SG7Ol3$p)i+JDt;%RZa_$G5hPJ;yu`KFp-i+1^BcL8xcm#_sbTJlH++ z@Rwf*2beD4zGeKelD331v$<{0pTBkC!MM$t@H+;s{Knox&t2J{#TR)o-vftJmK>Ms zgoQX?<&8o@W;twBwN&{gKL^+t;eoQVfmy&}j@21ntU$@s!UG{=w<-m5Q2&z`r{5kQ zO~1{oaNt_S1LIdCGV&ARcC7JNfh^CWzmhO7>-$vpsR@V&9OhOu@>~)QTTn)?!e7OL z<^>4)pRiPUKp*6d#3rLIuxHbMXJk-Dt;DIf#Fz2aBRmL-=eAkQ#tg-a0JaY<2nu&l zrUc*=mYeYe5@!yh26vlbr!e3s)dZuQsHmD~U_av(;eV34`MXm1v_Z2s_KzofMJ0OsPj4kG61hGT2N5;tpX*BQ+VIh*$%a#X3%HgGI@0qRt8A z4LHs+#$agSjAn>cA^wlBj@{RpsB^IE3!2JaO&55}^1}@U>>q!tskWszyXvYIrQcy@ zX#ftje}xLh@AW54ri#e;@Vh2lBBoD;fKVlVRl)5?2R#1wtaEA?lF2Zo$**pjwP-DK?ps(<)%bv2X+}Q;b*q?Q?wpO-V`*TWdn`P>nU+ zr;*j<5E(O*>Lmzu(zg(nfCBhF?0i^(i^>#m)Kv+Gofi`xVW{Neg7w``W!S#Jy4JUW z{DWTLRD(T9v^_gMR^-TcI*j7G7{$?0nQPo6NpF5!J}w#TmXj^fo`AIDy-}A>dM?!I zI|*8c)#-sOI}U#M|8pEdR(n)fQ%3B{34oNxx$O1%^xMyljXle(pI0QXH##AKjolB0 zZU6makit4i3VZv79XnoN);sTH))#i{{C4_nNMlE4&OGweev-;aCKHMFXzsxbScF1F zf*~mYzsxdBxD)gTE<7v-S#`->i9JGlN~QiP9{aKWkQKO0o>O1tO$bRBDOhBp4v*s} z`HL1FFQ88qiHS;Nw3%qJs%|5k`tGcm~v9{?yYX`8len>mFrA(FZq!)Ot=9~!XIA|g1bm&|| zraQnqZWqgp)j_I-!sOs$ov4gSA?+r2TA+o1ZdRP37PSQ#RVR_=QZ?{%qdxFhiB-&z zP^LqJlHv3F*pA=T%nJQ1d0y)Wz=yRD-*#zjdZ#b?n#FPsv{3K@PTS+qK4QY>NLr6Y z{672wXClnVYIkun8uO{cYoHX+`HJk^<)DkslVvt4=0NY|i1WlvKfS86eBS<%WSoutJz8r||Hxii zvgf{$U4yY3KlOmvF#dh{c>DHSR}5Y@Ha9=eIR2X7$A0MZJe%lQ(X@RZ&?9#0E$ROS zF0~6UkhQg}grf1`V-&M{B?2k~>qz9Jec)e@S z+*HQ9iDA?B%QRHH-K`&}%~`zMig_y&I1A$z$ubDg&&2d|vq6sDjH<*Msl z-qF0E#ow~(z@Y=HT6!-1`hmVHFFdbowz0@r&^qV5;XQ}(=psDoyx_#HOI{w)-05)? zC5mA5EJ^m(B+6Ts93EZwrHcm(>t>c;YH^m#4h;N5tLK&_mISV?H*Bo-*;TxLbr)YhEkDeh)6B|^HiXO@Y74T|E+ zvoBm!$;=Dx_}$T?zq@?_GgmIW@Rj;iS1yp&o&4;jzrJ(XvO9l$DZbyi;L6nyeL#aD zb6$lp*o9>&JwnjTAY`hv>C|(X1-(%WS`abSzE3<71(KSdYyQOzsS3L{%+FS2+eY=NOF^2+$*@5sj^g(r`dZ*JMMRNC!Lyf;eyga2M1M*m8M zttnG!NvJ63w_9>7j^3C@PwE~*bh$i1>j-69?dPP&l7PvUBt?&Q=Qhkd$?dOGm7XBF zQujS1OYy@&EDBMBY>X^w`eU?O{||#zr*|5eAC|^B(JBM;d2BkX{vW!U$WPOq@1&pC znzi^p{VYZp_Mf~nG+b6T9Fo?06Z9)JyLg~TT3Zl4`EiUB!N%ey1>OOh2r_5vFe%L-{AgSH-8T z_VG8(1!nf^`1q`Gv)>_>ncRl7U=Q#yp86N?FN!g`5D%<(!CQp`4cQTzBy2|LdeBa? zLWa7s?wp6%Er6zIzRuIiGpow5TW~x{!9*?>V`U|G`knE&-;9=8n86#dn8RMCL%iPK z#Jcg9#5!qj#Fq|~&x$8zm9am0$gR&XLm**#x~WdR9MNf9k1 z==&r=9|s-bl_DJubUa%@(LZp|G3OaAju6e(Ay`?`0xKI4s`;S zj#K}GSYjt)i47D>j6P5-_3#NLmY4`LUS<}EPUFA>1Bqcwi6y3!cnVwhk5zQp#r`eD z!*=>wd@tx$7Pmn_vD;|#k}M1zRVAQQ ziZZdDmL8}}Mo7|WGJXxk&ymz<9`Oe9?z9%@^&aaThM@0h_OZJpL%yAb{dGQHvM~L7 zd%pM?bRPW>(!Y{irw*e3J^Z`_c2#DVQG|t+b{Faq(XsII;z zC%I0(aphfiVI5Ctjt9A-$&o!jJ?8 zLu!=9rgVuu_@O#1Tv$;lVDwbZ)gjn`yCQk965hzjLD^uzAx)2T-;QWWo~L+t?r2lj z_Bj>p$KH5o$$}Yk+vAZT-ZOw8P>r^*<;VmNkdFnlW)0|5c~n)--_z6bNPP@|360CkT;{ zudJ|)^b7JIiHf(4f)Hv+p9}^N#q5Rw3X2Q+06Vj)J~0Ot|6DD z6}u+l{jzVArhOw+4+%%(l=or}qp@o1PEKtM&WQ*Dh;l@9%th1`=izdjQiqBD)t#j& zoy5T)aVAHRRtc6wTIP(iHIfj8OH2fU#+ow_bAlWfJC-Y;FTZ`X_f6LrAqf z2-c|tT3_{U`)!*S9^Kf~vFDzR)w5Gg1x9V4fVI!sR$aEfm7>W4jkDyJ#vkpP)pz7u zhxa^x!#roCHrVI$Nb|ee()IPFWs5IgHhO3_2o4iEPrWVOrEv%qOiWqIN{{0qigvGRYa6VK zdxO^g(lwj6H?F?#&|uf$uV1j|!9J^}s?gygNakXwZa07mk6EPms zEtzxh*v0oGr>j~>Hz2Hp)?}1#I9EdoRyE~rX-)?fQ%iDcV`u<4(Lksy;r-OqI;ClL zJDss9cBFtE$+wdt2oNxVwp07L8euz0cq@Z=DkLVzkZQ%@+bJA@0cX>C{wU&8jUh(|l-PlY` zRbueHx<_z`_r+vc*&^CXbFjIwjO=+U4xGGTSazJ@72yqtY z+>-WHy%&25vIbNGY^FK^yaPkRaP)Aq(h8FQ>8kbO9N<9d zrX714&wKpp*}WG(cHsPjcJ?D*<9v;yWB-FY{BgJ8vp4x8ev?tzUPpg$)z&Ajnfvg; zoi&S6aoS^y&V-0xmA{Et{)f5GJ0OsMr@-YPn?cr!R&K>&fZUPINR2V4z+!$(3rZaH z4Iq0qT>ufP;+!TVOp+5OK{Yiv^aK5Zs#|69ekUhtqEI7~33j4>?nyABOVl`HkWAWf zA{7T!72}T*0s(IpX&?3z%L36`8`d9N*53|yaJZtcrhpmK zfNuw|fvLbyA8qt?(*r##Jfdxc?|CswbIm&YAi}V?hQY=nRSJy9oa% z$Wb&qT7s|2ePq5Moy-b#Low?WQ|wyS#77#WauPoCfy5jd*f-Sp77_}TlT}p0{^*~{9ueTr?4bu3u9 zzN#!)*tV*-Z$now{dQGvrFS|0cq{ufu0r1muTQr7T0ly~u1>7^6y|p#v_Ok0%ja;~->iwsK33nc{(0Dsb3#%hecRVR>DyZm)k1Sg@ z66>fWH5N;71e-tvUvmrJ<1ra-!R@d?TZhz>wbEi!Nz6qq2Sua=3s59yNR-%ylOy_b z>cUJ2vPmdM;vBEZPh=@FTrSjXOMo^46v*a{!Xw4UG%ko&b!J7`4JS704e# z>Q|1CMov9CMxnDGd3VMQYZqR&r1IS*OHw=QAbowiWoFCf>lcsj5kJ0ab8Fo=;)H~~ zn3NOp_px2Ph`fRI!sW=*;}>3-wO$l}?qFCHx?zUhlJ6(Z$5rPJH*e%t$czZq7pn3y zwnIL#K@3Cyicdh}3NF|t6kNPeNT`)y-=yj^E%ZU=4X*TJbWF8wW@7Ex(RZ2OSKb;9 zwUiYUl(mGyt>r$A_P$V)9))Uq=5EAr@!8I%ho(VZ7rdH=eWMUjMHMt!fK2;_{1x+q38Z@1J z!~c^TarwPA19hS%qBk;8h17=jw%Qv4kPSId48WO~12PGpK4;Ncheo3_iu95%9#0mT zr=7uH_v~AiG~`|3GFropC7Sr@(}{jxh5giu{S?G(!V`o~3Q_*>Z?#HQ z6nw~F1-QhK7;5@x1)$^Mssg|5ls!@O$MmyyBwGvF*y7&@N^I%(t-)aPyYfpXAGA1G z8_pM8?v9$RCEm2fmCvs5TGC~hHvD12P59?1en{|TP%aO?`zGuq#QiZ>e8;IiadWni z$I>XXVdc=sUx5bPwsID$&BTT}icY=<`oLR*K5FBndkKF_c~DXzRN%}&6qXfu_l(E{ zmbI*uP`nw^U_mZ1Lu3wUp?G63csnSQr3gkuiJRSNt$1wgl==Wpf{UW9Q^rIX%)YG^@vEhn-tzQvR_u-{{ic?euimw=nVB_VpIW|(O~-8G=0P^&0}A69)O zkUv99ku@fVs(!l0YAbB(nN_v+P*MKC;-ZZS$&zs&PB|g}H{R=YVD7yPOvl2n8OO-A1#_DG}MP zLI~P|vc-83H$KLI=$JT_4-tK(*`?qvwH`e`8_&wEI~{AuoFlHx1&Mvd>CL%0QDzo# z5MuJI*^BySEv=tmNSLO1q56bt3QGb{g6^rQ$GkXk`teIChZ`}7peRM|B4{g4=Hzoj z+KL~8B#Z+#K&m79jJe6!+|+qFV;yLcD*N&gfDGZtfr1(^adYSs50wz>iCXl^EPGPb ziHv6MLJ7Mn3npK;oG(KxP8V5n22pvVF_@vPax#l#OwP%+b6E-m?NCgzdT(elB*zTNc5;SVo1Pm3~;B=kc!Y zUpn)O=eS9%p*p=nbN5tx81_T@Vd+iaKp`w*SEoDyYG zi2W$s5O=F49eb$4-{SS0{OVMr4(A(^1Nh*9Wsc&?JpycUHVa8yoHo*y4jZ-55!~EF zN{-$MIsleRSz?IzQRr+ury^ik5NVL5qeN7*DP@Sul%ukgfr?!MXA1HFPvtgB6P1Ne z*CdzeXfU_*7M_r1_{3N6mip=5g3#ru3@Fo7u}XmZpVka%CEyV`dpl?rst%=YYQ>t7 z(V}il1Z8W}O)Ey~LXyjFtuLRoJ)sf(k&9Muk3QkBS{BV8zZ7pMgHNgiJS!9XQ<8{= zefe3NHO(E5{Ry5u_6N3!YzWWP*q`Z}P8goE4Y|J}#bbZY+2#Yp{!Fq9OoaY$!+$pR zNBnc1$L=U??5iGJSl&OnYP7$+am%gi8#b<-6KpXCz24Hs!RCt2QfGPp^3}`x%j?$O zxO(i%tx~Ja>?&||)P*Y}g`v{Ur5!_umM5K&s=`%vhcD=JM=JAURd`h1y{5Nw_oC#? z7R+@qV!{6?&k!Pv(fI^AS>&WtNoIH&BP_!Cp%pV;fzy0a2(eLQIg>;Ldf+#0Wg<|d z8IUGN7EQ#76T0$Mn$iXi5}Dzs-2*Zb*D6kDMMvSMQd~UHT(M>{_VX)l*y0L&p0X{AOS-@9saOP%BnRq1R#HiS_4V2PMgi1Kd<5Mz`M_dgRulz%L%MS|Ux)mHRk1 zPHOnXe_?mIr+Hisfw@2}M-Pyz5p$x1Se0jtI6U$zcRWzIa(^-$xKRTekd{dIygwm- z(qz>c3oQ3*WBJ<(W7_-7?mV5{e2bhYcryLucS4pY3|3idF+6E0c}kgx%Ejg7iz~&1 z%ZF+CQTe>m^2Jp&E$^o*#Cd_XK(H-1{%{3)NO6QAtf8My()oQ3o5ck6QjIq9x~(wG zf_d_YDup)!q1BZvnDm%XlrUb2dyD2i{8ReNY|Y;gQS~c>?HPnq{Z_QIx2^W{7wr){vp5}T-}wLd z9c*JPKmALDQvnB{KNMjE9^w3y-s7TNOdLl^a&uV_W0Q-d5C>^!LYXFy#N7_qCF zg`TED6OH&IQm(PkBp}g8W>DDXNTYok>aw?t(b(h9q}RS24C#Muv}q9|_mV#DeIfl9 zUm?3)derY2f5X@84>bBkqRZcZ2=BNa&I5IJk!Agk|$2*~k z5}QyH49GUcc6GL@)8!=45@I=F2yP%1RPhtHaYH}OdJsdWn+il-kZ0aTUbK zR(tizRjX@94vp4sH#<$*rL&qgu3k}{=xr*?GnO{@#;aGX-qo8Z6FeB$28DS_Wth#14M!`aGnN7D+JP64NYX0Ig&uESRJdS2)H;6T8 zQ`exUyDQa@tSWcHzA~`}MR0nNzmu}!VM}7>!D|tefp02Slad5JQ+u|myjRg|6TT7n z8c?1qn(A_-sO=Cj&DrH>Qj+BIbJwsJz?GJ<9$-0=?ueE>H_ZZ+w8mnsCDSYbEf~A4 zdKI7lWwqPPF3kT3pZ|DobEz?}tf@D_=YJOF-)Y`nJId#OWi>4v=4u@~rb$S4Xq5eQ zUOOL|Zjt$45BpgmD}*nSl4;0bS1?#X>8B0FMG}1BkxMAzqz%|ilub*43m9uMW2`3| zNHk-x7ysJa@tx9HI|mxpE*S~sd>5}C=$dtCS&cvJ&wjx=;?9cn!#L3GKs;GMI7B!x z<<1JiltKt~L|Z`+AVe!zLoyrCMioDZ)bmA!Szw~FL_{q@yO2Z%q7su3EYl)G3!HRf zDoH1$*pyU1@A6wD(rj1 zLlic5-i9g9r9E0)R(gK(?g#eHy?FhgZ+)mB9&pCXli|&q*saAy=?81ehX%zVtG_t^ zWLKo4+W$@Q-bn2mtG;;gQ0dIoO`W!|C+@Rcb>Pi)`6b`#-dthd;z$%ZZ`TJZ+e;aI zDWb4lcv0ii>_dN>giojP=$;?H4>UrRmRhV96B4saLYP9f+{oQ8;`pM(0%ph={vxl4 zT+W~y5E%FlR56xJda0fd&=#TqF-z=GfWT&l!G>Ug>bjb`yxQ8o5S6H$N>bxb@J@TmD$ms*&eRZ1fTiGPO}VuZcB(^cXp*|!cyp&(;f;ZErik#uoMLUQ{^dHP( z$oAb3zJj^ZyMGX^F#XzB{uk3-vzl;jLN?F|3n%5;QarUF>R5iD5@CfZ3o3!z;oL_c_$1${ zRj4LtIw1_C2GRo|Igspd@|Wp%Pri(nc=xJPS4nrtj|hXpGT^(VzptjMyfhM;WYuXJ zWK3Q%r=tLzGNEKN6^KGi9PGl&Ce?3l>$i)~>r@_1Hr#2tNmD%$HReEBW#+rOu|QamEx!q4FLP01@r_Y&DKBgDC(fnjHG z=ckWME>sq!GNLx9!$mVCf__RM0WK)u@vSP&Wfo6y(qCAc@OTonh5lr*hwbwul73vR zg=;_R{QhLZBb)rn1zY|Ae&H$Z>*5z~slS0oIH-8)@A7-#S>-~%u$sM>@{BH>J<^@3 zucLfh1<(uhU;_M(7|O`j?}E`5VnbWRaYe1v8b-Lvm$bGe#4rpKL3qP zo1XgoRcjjP`%{}XeS^MVwep_dTzv8GKEJAb_Kqv>ShVQ&E4R%q!>I}VlK$cTLtk9K z>HZ6QhuW6uZLWM*@!*!O-Yxxco5%A?E~Jf5-J?Lg=Np?Y`{TW9*4+EY%a+`Abl1F! zig~+^-i2wNCv}P2<*(zMUW4#|DNlJ>byZnIc|)9{33AVAP?outFuX98#NOES=QO~8 zu!#{2%4G+Yk}5t-!lcw00H|jpvPUZbNZ_zY3z&eT9@$N-z}cm=6I zXFFYyaUYVyNI6|0ZeNh^*PHSysv5#&y|smrg~!gXu8dSff^MfzSJZsvYzm}L|2)we zY#XU`#HB&AH|7eu@;v38rQyEjxKz+sX>s6gm6l|6tZQj~`t8ENJkjDVw1p7;23nRqUBJyE2Fn&>s6_XG2P&&7YK`gQy^ER}k(>(QWW;Y$)nK zNE_5kV%$goK|)`{86I=K&Lt6~*!=PMazukwDffs7|K5Eank+3Z#7!}S!eaK_l&`*? z?)<7BtRLv@ZfR<4AWJJ*+PEx7W9dNZdp!%n^{f+dih<7Qz<$nYkshI&8X^)Dv`#Dv z0|g;hd;J%z>&Y*# zSc^j%kGxdrxFN5gplMmMJ8m(B+p5kJfBGRv?T^w=N|#=FXxSA-=3-y^2VthOSZ}pQ z>Ow`;MOGk{OY^iiCa-`b^1<(@afyq^@0VA6miAqfWEJ0#ALp{yf+?~WVS^WSrfPL| zZdV}@{H!{gB7#q`rQ|R?F4#6TtUNq8c=4*n##I*&4jx|F@PMznGagS>)8&5gcxSaw zv%de(iiU<2hx+?2TG`mR@}eF*EiA;-L|2X9U(?0u$8upV?lpP^x#g_FND9$yWKW)) zX%6;-R23vFNQ{b70fT`+S;`gB-J0iDEHep`N%Mrmb z`92izD{k`Pa!f|~#T7NA(AA&4Hjz`3OlV+4Na+L74AlFK;nB)dGO0J4;G)LdyEBk@ z1X=r6wJz@r6_hpxF7Y>dFZCCV|H*9ov8TjuM?%aJv$4P{8+GgLH)(f8TIW=i_I9)e zFVh=>1zTI}3ENAa+S*!gtTJ5Wa3Fcnp6yr@CJadzi5oBv?ZQ{+K9i;fQ88fPa|B zCW*+1Kg{EQi-aP-PxTPS#lUNVm=9L>_4brRKCy4J=dNl4-#& zJdJShP%yEz$ODKCSvRFqN_DCSivZcL61)vw1>-A)v~u@!CNB3h2X&&DQk6rXL^yYj zpSoy9M^B<{P28wESl=?qSG}O9ywDU2SF9?1tD#Qw8rCX&s#>Ny1D(QVzE;RxJLz6G zWnN%rMqS*!1U$#OVGIye7 zJU_G#fp&Z!(uZ=V+7$k=oXm9@!&?bA*DZkY4!PZ7yz8OQ9>BnRj->Aq^WeoV6yBs< zEnc@7=1cN-aN9dcZee6j5X1sTm`IYRSOVRg@CzpZBnf6F@+}z8S<$0Zq;RXyWQaJ@ zp93&ckM=-Jtw)z(p%0W2MmZ&)c{%C=$12ZMjT0-P_DXg7P-54xDqawLp1TJ}1d`lB zn#obv_?XV>^xDGVf#J&AT+0TcsnN#L{-{^`Cmc>Ha0CkSZtC+4C&P^ix5+p{zBpku z_}EEjZpyeone`m{S)xD}X52q=JRtLRNly9X#Z< zV7h_PRKRr8;WHWn`VW&`6B)$8lbR5=?GE34RGwvXSo7tkzkX^@dY<$Twk6qaGUYk`0a&{oFuccICi< z#nsh|4-5=lu(+mX@dZOYU0pr>U0w3y74tqeIJAF3Ma6>sLxUfiSCMuvTDENA!ez@A zDPy<+`rF(I{VndY3(()<{Qk>M*4Tvkz{QxIxFNtfO&Qa1_048;SV(<-Res3MDC&$bbDI#mOdAd>50f`Hb5m9Zk4f+G{;<(UN_GtU4-fZLd4y>kL1pvY&R8p;Jk z`7VI#YL7k~FtQc_hj0!ib3vk0xu44&Z9u{ux}PgP75^CwyHb*U$Jdq^le)bfm0Jr| zIczg-O8-8;5U#p8UwVJj)WFG`fZzjvwGb@$zF+X(yVoZOvrO7J!Z z)30N#CBD|@^R;di`q{x$(3sahv#+Td>yka2~iJ zR6}aZtT)p8N;sdXtUK;5Ro0y{2xI@L%RUj^k7ZYrXbemRnX~j~hl=-u{%|w`2B>!s z%=8LUpyZ)Yny%6)yEJolHUO#8VouX;&{~7ITytO*Jgfu!7+RiXdfNGFwb_g29+) zH00GG%Ye~f!Zi*FAy3eYd2~t^ZrLnh5zJ;1B5XJ-On$Tp+5k+;%Ls_;{{ye#(9LE@ zf-xJ8!*O4;N`~+%BVI+cY{N9KVmdT4*G(N6zzAlG&P+o)*B~c`1%%HlOl|vjU!&D? zs(6Mu&AyHkMdMU_J&lfiH1$cLb>Ex7V9#V)ce3(>>sNVRRlkyUpMfHZ-}_*SSEx`` zyiPh*vI)7PCjB|7UgM-YcyN2f>38sutcUAuARQsF15|;oZl{^M zPL}j~T;!Wj&w@kYof-`z)ki1pwwW{eZkuj?w~Z}oOV6Krxy|>34W-_y#TU*V85^#z zst()r`s?X#8$^T`Nq;!~Zkto52rcDnw5M>p2+fjCc$pm#glWouHL3j7 zZ2e!et8?oAHCz7M+;UxBw)~Yz<@2-UzhT$l{o<+rfi>d)pldl0VfvGl3;umY5>hV! zP%>1JJcJ}Df{s>S5Ghq6wzVF&SL&feCHP1%Ae|00N;y&tBQl-dP@`0k1cf(-B?@$b znoI{~qA5;U02O9@uvQaSAb@<~#dM}QgAgoCmsrtXDd(CM`(FMe+BV+V_p@Q;Tg;yXHsAEeUKx`sKnfUAH2BBRNVP??~Un?+h8x>`&!0 zp|`uWr6EZfd4qnh8=Bbw8_0S|hYO%MHQ`Q|Hj@$eaLr`6iiqwI!G#1`*^dUn=hx_Ot9g{$M6p&`D?MDYWxtAG`G*oA2LUs6*bf5#Q z4qOAYoNQ4LISA)r3CLhPa7mSL=6n>$6hsG5@u{y+VgyKc=Sml9u2r^?!Ye*FW_Kl;6SOE9I|HIYf>I@bNdnH*G>#xF_WZk{Kc2 zi`%j-bX7eReCPngHF3)YZ2gjslqHInCutsQ%VXj)n4gnW0*|0~@U#Jw+UY1)P{v|Q zxmV6q4Jn2Qchu_Cij1|2Es9@(4mqZhbaxevKI1UEy*Ocm?NF=TlQ@}=los* zKIb^+$Yq|NOaujoUf5m{tA_2ipGTRY6>)4;5pN! zGzJ-WR2oE`ffXBAlYwar=_lEu%hL~}zjQfUoPOdm*3WvS|4BcYe&ABJApNCF*<#jz zS^5dq2Uy5Hdg?~pt?())w@PSXj+CXbzPvOPge?~LyJX|^o5BSMqD$756l-LSMUQj3 zFePA*Q$l{E#>gdhbV?3O$`AFalJd08VVC6gNZcfsLo25?CwkT}-P{anqOciGt6D_49toNG z*}u$H5F5WTdn7O~G4|Y^i^u3fi0#kLZ!>!ef}U%?x@Fh<%UYYoSzE57t0AOMR#%RH zWAz0&*F%(*Y%K{f(*_nf!7quZtC{ccS#|%|kbeF6o=3Z-vd)>fEn@S1sgr-K0-_QP zpxoyiADc7ycrC}TspY?7x#fh9O8sB6TPNysyi>|wQOcFP&>a2@4*yrI8=n*RRM>Dn z;12R^1PYyYP!MDbrBfZ*Olo1&%^VNUxm-Y@8k6!FK?jA z&8f{Wb7-ZiA{CQc(F@?(fXV=Wtc-J;s{527dIOuId2)5^Xas;Uy8bWQjI?3e7HUiG zcvZKBV*DZ{RJqUav~X8ky{cZns^zIjaQF2$K6ZRdO>tXqTXEgc(xJM}^RJ&PoA`Ak^6X#VJe(OJWNy`AmNjmg?7+%%od6WPOhY{Y%J64KQs>frMgCCb4_W?ckB z=%IL#s|SfA%}kpItmCO8ttL?ikrc`Ikn0+GS`g4c)RG_iM_yL4!+Lm?*-wUZE@jmGQ`O;&o|0PrSt63zvlnM^rz07)YE*O}jC$`}Y&oa0?q zX3_~JY!*JrIz7|?A(6WZ=NQlRn65Sd{yU7sNuz=hHyH9yb=v4NOj-x|T(+F?J$WKL zfpu`js>4aZMy%5tXfOiHBXo*lP`GLs=!GKjtnV`xrndgaUS-tCd`J__-e?5RMmRrx zgvr=Re{!9FQc+;V^VCd$J-ySH{xM~wY! z>mD(kWv7z+tN5v=S>W5>u>$onodo0^H@==2)VlF z&09Kac**!T;l5O`b3-3{_KFK?SM*cz58!cU`W}h$HTSW5DTb%3v#ut`YSYL1 zcnlBu(|bshYpypLVRh_*qKZ8^)nr3CN^?v$t|A6;59kbQjZSAHeNf3;^6!H3D488} zAG{G16GV+Po%1E=E@&-fQ6xS^od=OqZjx4F3~<{G<%jKr^#jN3C@dC+5PqCo4SFDq zLM@#WS}+bfXHF=I?6SPjaHzkyAgm8;d~(5wTAb>i*RrBJ+H=`67j5~GL$=6pU58eEg z&7b_=yBGExeq_&zTUSuMJz>E%0g#@cz!o51oYrkIo2Q(6@dmshq&Qmy3_v@l1iresa_fT)Ho>$O=WZG z$Z}CL9a(NJq9e;we~a%w#=bel=`y}_N&$_b{M1)9qneEn0Lq1WR+w^BR#eni*3$`H zI0^A$Mic^biWdm6COReWdoleN|U!Jp22z zOr8g|@eP24!KAg|+`-v8p4(8-=_epeQtBschFq=BBw6NXR!OU8F0RpQdA7|EK zeUv1&&$Lw!&0r@Vpz ze|2&A$9>OUK*=Day4uN)k-*>rbGJB*7^78h}- zD0kYs!H|(?0)jE=$Jpd#hMd}%G;+#w%dZZ}dH1yG3MVqvZs43n&?m$$i4c*hRD?Pu;#Q(heUrB z93k9MaAb_*NG3-v>jP5=T_6!8{$VnrBJPk(+yo5iB;y9&)yHxFoqFP8I2- zmE_UD%brtj>kAP(jk`hFA5yTFlT?deIK4(08dO&vR0q%EV28g7GL96h+&8a3}^1owR}x35o^v4Ju`(TlB&6;VWtz8SIt64g82E zBTK8Inl(sd)X%wTS6?`OF?%nq6)!z`!;;rOann0rUcLIu@7#3b8%v7*zuMjezUuS5 z^ZiRmLL4}NWQ-l-MIaU%1je##5XcCdO$HJRVH+?+0WV2xM5G*pZ51h#YPD%@>ric1 zHi)vDB{>Em2(b;al@8jM+uFIgzOCCy`^ik(OefQ(b33We{C-~vj9sVO^ctU^-t(US zd7t;$-t#Wc|M@R`uIVdVo1e?hey(}zSDKz%n0WO4;q&ev6h2q{qqvbL?mqXGAN<4I z7cbT3<<(w#@x@Cud3iOLuxiael3vwXYJQLttcbs9>GUNJWZuKx-ijqF7T$kPPG(NV zY(-Zp#-68l%#WKt{_3vGgY)7-$x8V*YVz==%*bYpqIKd%X*)(60%PKbpIeZmpImLl zj2o?F_E)WO)W+39SyqSx;969YIAj4?4RtR zo_ELo$vE8;nBW5^6-JM!$A7QCk$5<*kU}Grh{3D3;pdiUiy`j%`M35IuFFAuZByZY zd}>o+Vg3X2Z@MKlk3EH=w;#x9|Mpi;maSM>{{3gmez4ujVlR+E<<^x|+xM=&ATKBijXWu|H3EHNHvbdntbY-DjUIDxMXg zBuo9&^Y4ahRri_a-`yR@BR7Xr(cExveAAITZg^JPG5UXd@{|cD|LkW8ucm$_F*JH~ zDDf*A!gRw|e6Tg)>G(Sm|EKOPxI?*wLbu;~^JL#)Kn@ck{_TY$H+CpCP``{0h*FoP zYqwv2bnoe!s3ROc@1{5X+$)*T)PJ^#;giG9%*GdR%g69THMUNFAU|Vn!IBv>mK4m* z$bVpZ&D|My&Yyp0#@&f?=dHc}_S^4YJ8$ml`)<4KzSVPQ-h1!N+4tNdzllpY9RKaa z-_!jJzxdo7PHUoHQpa!6$gPE)7kIt{+N^p1f2{kyCb~&i=uXv7uHa1d+Ktk>$^zJ| ztEMVm&Bs>WvcImqks*KNLJtCWUcJ!w-TUEt`hvANO#hSXwJ^Q+b1s!Otb}VfU-ND2 zgC?%s)bQ)lO~swKeOkjE_pg~deaZcIPr7aD|9Qv4H5t=$@1K|W$kaItH$RxJptAJY zDoj^FniH`@(tlt4_w|$UFTY>%(5N}T`os9|e}ClriGTgC{eI#X|NiXA_n#a!7*~^Y zvm(cIzN%$|?$K6U|NRTNO*?5cyM$hHk3PEmnXO+8B_}6_Z@YQop*KwkZZN8(a%V9M7tV zH$IRY;)jsKJ%R35zx@lk74z51;--J0h}!<;GF$X(g&7}6mhnGAmh|lliXm3tevLe5 z{7c0g_b301;AhUaMiKm?Pf6~&4`jpY-^U-u{|KG@|J%RMDDb*&{8Rml3w|f~y-|Os zqsSWq<@_7D$7^`=biB4yWmH~1jgR{z=by&_IhQ}s#~O%-bN+p15dEDMFYJHfi32aJ zSnydU)M*5-}FZ93DzzgwFl z{j~i5-P#=Kr)RUPf4w}VpKJTRzecjxq^TA)@m&AE*I39mN;rGXu!{WWlS$_d_YOZD zMLSkbOXG)34X2_@nsno>aXe1!llkbiL^re2@4I(q)_pl~3({v)-}LmWZQFnA_m^!5 zO`bIVrdy}oy)@&6gK2TUoRRjirmAtrXWa4e@mpJ7$lI`B#^kXn$=g@{_;+^waL>ln z|FAPIZs({2zwx6zYqoDL9Gf!n=38%`cyRyPn`SAZV%*JR*W5Jg)El$r&l(+ivgr9o zUhVnTD`RgSr;p?*lHtqo%gHnHulYS!;*ekM(axv8ul=ZmDTzZtTJT?&PEw0$!AR;h zd?V>vOxoO(iJmHITgR?3GHLXqdlc8BMX_&X9Dj!r5)#4fmA}k*md%CRLh%`JsSxE}aIva@U+L2$)rA@c8so z{zguSc+8)+N=6>^x8z%wD`#&^OOBs6ZCmBK^!T#B`?zxCQGZhlfA585V?y7)Y0R`` z&n)}GuSSo0n8*E%$aG<1hmOzFm-;zFx^LXs@NRaXykh-EYuwX#TupT zDCto{rc|b`%^s$7{g>i>jfO?dtv~rbce(1}-S9D-X;zzX*F_{=qxlIPw{dN9`x!m> zIpaKJLfIhi)h*UMaPi*f4i;}dwC=ZldEYbXB`^HrIo!{ph{% zH>ReJ{rH2V*r+iR$92UehLV3GZN$g^Bq@mBH#(%>^jSg1r}Bg>{U>sZOWxm23di?fR(iDxOTFQEjGV;)Nx63Wd*DYEX z+#7%DhZClceI`La^2v$MjGaE=hrjq`QaCwzS-hTEoiu7$a`OLUI`KhC;s@~)M;EYe z)l=24TeoT<_RlR@E#l8il&)WGmP}i?`mQ-^7fqYCXziT4Rxh0P!qwGg((le$sZ4j7 zE9cB!kvU~b=8D;~GBan*oCZgMs`TOTzqpFHKZ<{MR7Jw~5-%qONm)r>Px|@jnWL*lA5Kn4&P+Zv z=H@YPg_?B#;#=c3j*EsP++)I zFDUY;PtvS3Vy5_AlSJwQ&nvcGe^vI$|Rz6bjNZ}*TJ@UdM6_5P(BhC3+ z^NaFd%CE|QHUIVe!>w7Q`2fFSw;(=K75F3)e>;J@xplk8gRrYr{7-{Pu?L zZTQK?q>Y&yzrAr_Q`)A&O*Naox9O*wAK(1Kmb5J&eL3{yC%#oWBjeFnT~WLD%mVmhktF=Y2c&$j6PzKbLoEAeGMfFJYzb`5XB!u0k$6 z7z~bD8&oE|9L&;dMbgUPfyBCCY21fFW&FnAIlb15N(8OW*KW{jt6pEyt0F!%_@-Yf|CU}a>-A@&9u8(C?Fg17en)pj z-4yIid>~ko_(8BYp;WJ@^!}*c|18)WzcV;H>bYQM;?Cf;gix?|^m2Ws`lQ@oS;C(N zulaA{?fUE<-9mjdxH&Nz{HEGWNS+&vOZ<{vx5fUygrQ)G_;`L)IQCQXBl^EFN;9VT zZ^dE>HwEhwb_TVhE(W>!`#{3nAUFPP@!_l@-wdiWW!f2kOYHX(9tmnyu1l&5s$8$v z0}0#pSKk?RPf(>k&K{K{8GbV;PMD)HXkIWnVPSBy%A-e}43>%RZF=?S^|0tac~$l* z@7Bw*|At;;ea)y}1cmC`-zVLzBsdq8uds(}UbgJ1`&KY%l(HS``pxmp+K+DzR>yx! zIdw!ku{4+(f4AztrM@>S4@R>3*Au*&_-e40*LRgS>)~KNa<}Y1^BTQ2_EYNuJy;hb zulSv@{nEv6>hGXlA0^EV?z^f7>)`sA`t=-ou`aHESr^h-!Y_j;a<}Y1^GbSN{8|^% z!}YKD+hZSC{`&ilUPB2b!9&;dU|n4Ql3etDj^**Gmvn*7^w(`AKd*lOVeo)t{pXU` zR=whM{UPc2kZk-(y&m^#)OhXrjOXv;;_Y|hD}vp6y&C@?V~^rL=XmZ_7xdr%Tft`2)Ha-_H-WuDSa4ou&C}gR~&{pYchnKmLulS4X$SozUCg z_2-HsIjTQtc)q>gQ-euDj~tWqn{YsXr|Wa4F!8M8TR|-Dp1Ae#zaRgT_z%-2rQMQt zd)lSZ+vFc+-RIC z(xR91qX{#gh$gJqym4y!)G2#5rbYAfH%^T%-83aFy3nPCn>M9I$E?`)w5RD)RZ5G_ zcVWJ-xSYQ+?W<{f_H0XwhVnOVRgI20r$$3A-S5)PQz~q!@FlW=I5!xaipAj9M z{!lbYufVTm(WGVTHbzG;n{!6|EZh1}bn-K|>bg-G`YcT(<5xTtja%{L*5z}f30Lca zIq7dECCu2Gwqj5EHZue5V2b+}O`9Sfu2PJSnvuS3xxSm25sllLCVrN!wj5MQe`r%Q z6JhNwBdRkh} z9<_4AC!eOxn5pRmu(YWc~1JuZ40NQtDTkBN%At< zQWL{XiGplYZzPO4(L@`AzpL-bUu3vyeUwmsG9`WLrcYXwN+y||G|@<$Il@kQj<~#$ z>S%KML;7rGx&$^ynw=Y+4EO3;{D^FVM>oz(%aKP9+sajed?LK08S2c#`gB_~ZpBmS zPY%0R`iMN$ow?DQMu;uDD$uPSK*YdRnctj|o;J^%uaxuTY?}Axn7BzY)-PPEmfSz7 zzU5jqS6}_=r>>bIk~a?9ft*izzhPcXzJhF!8@J>B=#sqDbSN$+jK8nPeN+!zkS@q<(dl= zE)C))oYm5K>^xEc#~##7WI}9?aAItOFokj|_35$qRWqIPOv&m)_}F(%it?~w+^fa z8^A`e32X*i=;uLtcnCZU9s!Sn$H3#@8}#-BcoIAXo(9i=t>8JZ4LlEC055{?LA`_W z6}amJdysiQI6%!HI3x@OW5itu9finIdhM$`5>nIdhN1?zv3I*0tD6oz~fpruLtfNq19fbnxC=^&np};x{ z1=dk0u#Q53brcG$qflTSg#zm+6j(>0z&Z*A)=?<1jzWQT6bh`PP+%Q}0_!LgSVy72 zItm5WQ7EvELV$`5>nIdhN1?zv3I*0tD6oz~fps)iTKKVWCO8|+1hc@E zu@Cj>DliW$03QXnb4>~O3Rnl$gAHIK*aS9%Z}8m{;7RZlcp5wdwu0xtHt;-n0lWyl zM{6A_hq1IUmKMg+!dO}uOABLZVJt0-rG>GyFqRg^(!y9;7)uLdX<;lajHQLKv@n(y z#?r!AS{O?UV`*V5EsUjwv9vIj7RJ)TSXvlM3u9?vEG>+sg|W0SmKMg+!dO}uOABLZ zVJt0-rG>GyFqRg^(!y9;7)uLdX<;lajHQLKv@n(y#?r!AS{O?UV`*V5EsUjwv9vIj z7RJ)TSXvlM3u9?vEG>+sg|W0SmKMg+!dO}uOABLZ6M{rp;DjIqhQW!kGS#HVdW18< z*Lb*bQd35` zoboGtS_jsH4PYbK1U7>$P`?DNcJMvwuh32>*hS0TU@zDQ4)Ez9I3%1XnQRb_iM=fh zQ4WI>_%sDf<ORqEPrCKSYyaU$z-eWf!KgBmrsjmCjyp%6|_(ZR)N)E z4Ok1l47Si(7vJgzd+13osQMR)VX*Jn-SzpQ?U!>;+*yEw2L$_;fwxM=3u>`SDntuH2yA zpwwU^HJf5TQhBrNAyry%`OC2*!tKy4f}kTIyZ~MVf5??@fp3HFfR~V7JNPa&@6pc=zI6pTbb?(-rW@?RLV79p zf&J7BaOEI4Bvfdhe)rR5Z@t10<#GCDOqV~peu6AHUG`>7<(lc>g4h|=WUD9X8bkh6 zm=n`BfyR)_!d&W?(#}?}h}I%t8CXF(m0%TE4c36Q;LBhOEqC#)Zm@^`^iu8v`&Fak zbIr9hdjiAYL|NeUU|OtQn6B2QYg94L2IngG#dLXuYqG!vu^lQeq_u2W&UB41&BC16 zYGE!ln`Ft;W!1**e5(jrJD^nzmQWv|erN1{UAYS^<}9bhq73YLRc zz)o-g90Z4iv#_XHSkx>mYF1#2nuSHp!lGtjQ5vh%!&w@sjJBv*Skx>mY8DnX3yYeC zMa>FqQL_SD)GUqX?+a~FvovlSZBer{M>5)?W@(OOv_;L*9LZ>lnxzptDzrt-(wJptVY{3akcez*_KS@C{lx0iFa;fv3SU;91&irF;%- z1J8pOz>DAyx$-UWZSWoNU9f{|dXPiEaIWOjBb*TH6Q+Qv)Jz8}z)G+RtOjeqTJUAC zhwt_a=gIco5vFTYnI~^G&IU8VEO2G)4^_Vk%mW|Rm@`lFYS%vsZjcwu(|q8(@Ci|w zC!ckBJ1y*hN-mFLrr0a`^a%j)F5o`jR!4`V^2K_k!o&-;Ur@=E| zD|ilU1J8pOz>DA|xM&C8qx}x*uh6Sbu#0|ngFVQ(mvSH2Pt5>V4uV5M?L290QN*T3 zp-jd`?MTq%3LSN3Df0}H@M!3wUg1gpSmum-FJUj`4-+9B{T zcmzBO9s`eqZ_x4y@FaK&JPn=!TfuW+8+abP0A2(;z#h2k7iOWsEHs#f2D8v$78=Y# zgIQ=W3k_zW!7MbGg$A?GU=|w8LW5aoFbfT4p}{OPn1u$j&|nrC%tC`%XfO*6W}(3> zG?;}3v(R7`8q7k2S!gf|4Q8RiEHrqZ#)JXo{F@2R1~b7daDhhD`!pBo6>g`d1bhXo z1M9&Cun}wmo59!k?(5(_a6kB-K3yOg?hyL7b%Dk!qkmx+@C&;jxJ|3b1^R_GrfY7n zfM3`J>aEMO!MU-8DrZv80++|esb*zN5|_Oh^T5@yH7e)R+B&d+`t_6_rTiG>$74Hn zY>vIC`YqIaIrg&3+o8CFnqshoniu(QDK+Jwf6W(2cSir3FOcqx{xx49 z-5LFBzCf!^b5{q}gAHIK*aS9%2jTP(co;ka9tDqq$H6z??gV%eJO!Qx&wyv?b1UU@ zU>kTIyZ~MVf5??@fp3HFfS2I39ekIX_vmK_-?~D5C+PXZ0$HGO02~B|gbQUAJwneY z7BZt)D0^^?XA}$N1xC*(7D|#v&nOm3l19%c7D|#v&nOm(N}u-Tyr#}p%NvAVQ)jcL z&K8v%mA$6U7A=>(rp}h_?Gt)Uovny6%}Ql~SA zI-50hwk*(Puc@;Guc@G|cHlL2w&pD^drh4kcuk$nnmU^`b+%?Q zKT?g?)Y+`5vsqJT%MMM~YwB#x*v*UA)Y;nKaJ|>m*@4&8*{rFv1FxyGwd3Jyyr#|$ zyr$09zK3hPrp}gxjb2k{OTtF4sk0?vqu12gvQ@Y5HFdUjNQ_=nXKRPV=rwh=c1Vm~ zQ)g?B(dadGw)Pl}UQ=glkJ0Egb++~xjb2k{Ymd?BHFdW37>!<2X9r$WXKSa?Wv{8T zwbN+ynmSuMjYhAjvjeZGvjeZGvjeZGvjeZGv$a?ABca#S*@4&8+1jyjKfR{T*1nD9 z;5Bu2;5Bu2;5Bu&EXo$*HFb92HFdVE%Qaq8XKN3~=r#2s>}`?kZI8;fw?)|7BH3HH z$`iHown+Boaw^wMQ@qI{S(mS$8~d(sxq7uoR`h{z6_^LE*8cn=*^KKS1s{)ft8DEr zlJ?zlF=)LnlHQHGz*6dWQ?|wzN#nl00=ku86<7_{fVJSu;6ZwI2s{iP0gr;mz~kT> z^z8(A5h-(J8au6I6 zE|$#S5qeFrSpIADnqsj$*XT9HVoCcCg8v& ztSJ_=rdTZbn~K*Ii{*W8(`$;wlC#lkipBC5qt_IRVzKPp{q&k*u`Jvzdrh%e7ViFdO|e+A zGI~w1Sl0WFPA_!wDIBBygdAC~%VBVW)&)6|`;dDOr ziX%tTHv0EEM>2QW>y8}Rd9iRMZLR|Iz|~rheo|#l=5SgACK+QH5(~! zioLG#6Y`N9jgv14w@~BtNRE8OyzJn+#h}+CIT|5dzf->!Ir0?ai?mkCHM^-PXnBhruJ@QScae9DIX5 zoB&UPr@+(T8SpIqZ>4+=Yy;1O7r=|)54rL!@NMuN@Dg%s2j8W}>!2LjkF|dV>;$`z zOgGqrRd_coNB(H+r)GdF2f-oX1G1vaLR-rNvX*|~OmH@s31)#SWB*B?t^)JG0`O7r z@z`JK(@n8I5^e#v^Q|4UUksK|Q%boUe1)1iupVpx8^I>98GHjOC%}{7DeyFS25be- zfoBvj6PjmqLIhw z)72#!d5k_?U80f4=+o6D8hMO9U0tG)$LQ15C9;+ebq?xX*<5yIbG1rx*}Jm2?8@ef z$6l4aE1N4Gjoy{b6{jwHS2kCxryWA?%I0bfwL$1z*<7umRtvo=n=2bQBJ{3ou6Xyi zyepe4e>W}f%H~QMuJ^8NZs1+nTy|x1HA?$a@5<(CwdGH}E1N61`Fiil=1Oix@5<&% zZbt9Q=1Oix@5<%|-j&S_yepdH}yPe z+-T}~(uJ=y^*l-5HKv{?$s0}mVf_Lw6^6htI3ZT0niQ~znh3Zvcv|(lz};XO^<7{$ z*u%GaDffZ>s#$|J*PzWc;;vOS*5(?txdv^nQU6_UZLX2U8m-MWvQ?wCxkeoMTh`_p zapW3nbB#DMTAN?eSkWO|1?GVT;G^Ih;0f>~cnUlXo&j6Ib6^{I9=rfv1UrQJ@Rbi= z`S6twU-|Hr4`2E4l@DL}@Rbi=`S6twU-|Hr4`2E4l@DL}@Rbi=>!7s`TI-;-4qD2p zERR?Rt#!~^2d#C`S_iFl&{_wrb;*}rkQ zez_jgjKz2eJPaNIkAla*<6sZp>KAU(tn!G^t?A4hOr>TzxKduZNmgpi0}H@M!3wUa z1gpSmum-FJUk2ac`V-(u@Dz9&JOj3Z=fF1bJa_@T2zG$(|0d03UJ9O2&wn6H0eirH z;b#16Gyb(%J?~JB{cE#+i;ecL&H7a}+P^mISJi0$+N@tyqy1~MepQY3ug&^ZHQK*6 z>sQri|Js5Kw;;nU$Z(5Rkw;W-8E#Qe{#a-kZb61y)DxF2!!26t`5Mb`i&pnW%W#WU z_eRTbi&pnW%W#YOY_trwsLw{raEtnEv<$bX&qm8|i~4M|47aGyM$2%ER%$N^EyF@) zHHCp^HHFM-3YpauGOH5QkXcP3vzkI?HHFM-3YpauGOH z(UF!#nzOjvPf2BJPkV1vPf2BbfjgGtjOp{%OY8k(UF!#vLaJ= zq-Bxjf#%MUmPOKzW$sAJBF+6=<4DUQ&HXk6J7jN0$9nCMy}9gIuN~4_nb5IbJESjv z>R2!BC2Kczhb-+oLdSaTkiESl%+dO5hwN=Y=vc2EvN5;gSg#$jF{5L>c1YSr$9nCM zw2hAS+97Eh9qYA2Hs;nG>$O8RW^}CA4%wK?j`i9hj>>{!`d>`{i|Kzc{V%5f#q__J z{uk5#V)|c9|BLB=G5yynSrm)ue=+?prvJtCznK0P)Bj@nUrhgt>3=c(FQ)&+^uL(? z7t{Y@`d>`{i|Kzc{V%5fCHQ*@{$7H=m*DRu_L!u_u?y-y`^Y1b>gL!u_1b>g#JvsuUkD#m7tW@lw(Cryiq9@$pi8 zyc8cV#m7tW@lt%e6dy0e$4l|?QhdBreRB&Qqe}7dQhdA=A1}qnOY!kie7qDNFU7}8 z@$pi8yc8cV#m9FencYZcH4 zQ_BzPl*PZWirbZB6z@sdzp!O^oOT!~+vCdcxH3Gh438_r3GCZyfk1NCD%J8@{ zJgy9nE5qZ;@VGKOPNOn({R>-$$Ccr6Wq4efIC4+?3tNWAmEmz^cw8ACSBA%x;c;bn zTp1o$hR2oRabD{?z+y6|yK_?|rrkS(MTHY!$L7 zqxab=WKl-%vsJLqR>3}71^a9jl9GGqeYOg%WR2cut6-n4f_=6M$PYu11p8NU|D9RwK!3Bw39ltC3_ilB`CO)kv}$ zNme7tY9v{WB&(5RHIl4GlGRAE8c9|o$!a87jU=m)WHpkkMv~P?vKmQNBgtwcS&byC zkz_TJtVWX6NU|D9RwK!3Bw39ltC3_ilB`COHAu1sN!B3A8YEeRBx{gl4U()uk~K)O z21(W+$r>bCgCuK^WDSz6L6S8{vIa@kAjujeS%V~NkYo*#tU;1BNU{b=)*#6mBw2$b zYmj6OlB_|JHAu1sN!B3A8YEeRBx{gl4U()uk~K)O21(W+$r>bCgCuK^WDSz6L6S8{ zvIa@kAjujeS%V~NkYo*#tVNQwNU|15)*{JTBw33jYmsCvlB`9NwMeoSN!B9CS|nME zBx{jmEt0H7lC?;(7D?73$yy{?izI82WG#}cMUu5hvKC3!BFS1LS&JlVkz_5BtVNQw zNU|15)*{JTBw33jYmsCvlB`9NwMeoSN!B9CS|nMEBx{jmEt0H7lC?;(7D?73$yy{? zizI827n>rqS{Cujso*$J@W6@0J96rG@u}-ig{PUAXL+ z(!J7%%if9FtJ#auJ5hTzdog+^YOiE|Md+QVy^?uU_<&9x_e%1v_fFJaR;GI;bGPQ5 zsJ)V;(K}IlHHR^JCu*foggUh3eb4qkM>ky@^UmpXV+w3PZ>2QPK-QU@<}@Sfogg zUh3eb4qocuMVXIi*}T-jOC7w_!Al*y)WJ&~ywt%<9lX@ROC7w_!%IE9)Wb_Xywt-> zJ-pPzOFg{Q!%IE9)Wb_Xywt->J-pPzOFg{Q!%IE9)Wb_Xywt->J-pPzOFeq2hnISI zsfU+(c&Ue%dU&aamwI@qhnISIX@Hjocxix_26$h|X@-|(cxi^0W_W3amu7g;U0L$bW_W3amu7frhL>h| zQH+4bgl2eYhL>h|X@-|(c+vWXc07(X!%H)~G{Z|Xyfnj0GrTmzOEbJQ!%H)~G{Z|X zyu2nZdV<%~=RTqDi+N3bc8#N0UlT>6qgY=PMWdrwUlT>6qgY=PMWdrwUsIcX!Rxg7 zI&HpAo3GR6>$LegZN5&MuhZu1wD~%1zD}F3)8^~6`8sXxqs@J^xsNt=FRAG6qs@J^ zxsNvY(dItd+((=HXmcNJ?xW3pw7H))_tWNn+T2f@`)PAOZSJSd{j|BCHuux!e%jnm zoBL^VKW(-Ulh&e^S8GqfF=;Ktq_v33CY2qN)*@OiJ0`6~5xiPC6O-0Llu?UjBT>~j zCapzt5|OQJ0`6~J1W{2){ctXbWB={c2taxNoye{t%aDh7VWXP-Z5z{ z+G%mwF=;J|-Sv)`W71kQdwE^xn6wt1#=azUOj?U(GN$F2v=;sD`@4=wYtc-`^^Qqv z(ca!dp<~ioh)HYFtiabeCap#LG`_|$X)Thf`EpEJi==9FOj?ViYIICmi==9FOj?U( zK1Ro+wP@yJbWB={WT8s8=jE+fb(Y}q*F=;K@w=p^oIUwB`J@+^u-5EWPIw0K{J&!uT_;Y~q=YY6#e>{&m z!1!}O-1P(p#Y?NukwOR6f1_hd4iXn}P!{O2V@nQdBs4m<j<=tKnOC2LhC4e9fj6WXdQ*tQD_~7)=_93h1OAM9fj6WXdQ*tF=!ow)-h-ugVr%< z9fQ^}XdQ#rF=!ow)-h-ugVr%<9fQ^}XdQ#rF=!ow)^X7~5F8gRqvN=ai=xYpB0H|N z-UmWQksX(h_*2Jm9Vcq#xO(EUgu(Q#bIMcwE)uH&L^bR5@lQ9lrz zfcgojpMd%asGorP38v=vTU;j|S_Tj8`7PFvx$6;4~>v=vTU;j|S_Tj8`7 zPFvx$6;97V{T$TKLH!)m&q4hh)Xzcv9MsQ2{T$TKLH!)m&q4hh)Xzcv9MsQ2{T$TK zLH!)m&q2Kn>TOVOgL)g(+o0YC^){%tLA?#?ZBTE6dK=W+pxy@cHmJ8jy$$MZP;Y~J z8`RsNeje)Qp?)6f=b?Tc>gS<;9_r_zeje)Qp?)6f=b?Tc>gS<;9_r_zeje)Qp?)6f z=b?Tc>KCAX0qPf^egWzipnd`B7odIt>KCAX0qPf^egWzipnd`B7odIt>KCAX0qPf^ zegWzipnehR7omO;>KCDY5$YGAuI$1ZS1&^SBGfNJ{UX#aLj5AtFGBqy)GtE)BGfNJ z{UX#aLj5AtFKLdXUp38$UJ^Qr?~-Oju5kp~CC!}wSm+3}OPVjzGJl*^bc>XqPmr^!1KFyQEpA(Gh5uG^;c^0_~FKlSW6NUDABg=m@k+ znok-Xfp$srL!%?mE@^i3Qg9jRT}FDBk=|vbcNytjMtYZ#-eshB8R=a{dY6&jWu$i* z>0L&8myzCOq<0zVT}FDBk=|vbcNyumBfWN{*N*hsk)AS?i0gKw*N*hskzPB}Ye#zR zNUt5~wIjWDq}Pu0+L2y6(rZV0?MSa3>9r%hcBI#i^xBbLJJM@MdhJNB9qF|ry>_J6 zj`Z4*UI)_aKzbcWuLJ3IAiWNx*MampkX{GUQ}m)@7ZtrIU34J54y4zC^g57U2h!_6 zdL2lw1L<`jy$+;zMbtM0S0ux?g^n?}BI-t;(q54~jXtHlB6%7e2c>)a6zOzDefv=8 zIH)U{rEe8F4(f_}>rWjAbw&L#Iu7cJr0o_QV{k>%HaZUKill9H9Mly_+vqr`E9$eq z3=8v@1*~o^uLq-chdh(`rk?aJL!KX{qLmzUF!LR zT3PxHdXguuE%UqhkfTv=%lxR!=$Yb)%zh zbkvQGd|zpXK6N~2H#+J@N8RYC8y$6{qi%H6jgGp}Q8zm3Mn~P~s2d%1qoZzg)Qyh1 z(NQ-#>PAQ1=%^bVb)%zhbkvQGy3tWLI_gG8-RP(r9d)ClZgkX*j=IrNH#+J@N8RYC z8y$6{qi%H6jgGp}Q8zm3Mn~P~s2d%1qoZzg)Qyh1(NQ-#>PAQ1=%^bVb)%zhbkvQG zy3tXO#(_COk46BabKmtyQ;JZLc6x-)XV@dX7&AfVzUyH$=+S7fR%PeD>(Mx{N$7lr zJsN3W5;~t@k49RTo%^mwBZJ#_?zG;W)gbKmty8m@QlyB^8G=-hWb8dZ$Web=M$#OU02J(7vh zx$k37cH4{H_F}i%Z>HX3OD}fYi{18Ox4qbHFLv9D-S%R)z1VFpcH4{H_F}ia z*ljO%+l$@yVz<56Z7+7)i{18Ox4qbHFLv9D-S%R)z1VFpcH4{H_F}ia*liy=>O)6; z=%^1J^`WCabfjH2$)^t;^`WCabkxV#;(QDl`qX1fA3EwoM}6q14;}TPqds)hhmQKt zQ6D<$V{GX|M}6q14;}TPqds)h$Jo+`j{4A1A3EwoM}6q14;}TPqdvx#K6KQFj{4A1 zA3Ew|Z0SQsedwqU9rdB3K6KQFj{4A1A3EwoM}6q14;}TPqds)hhmQKtQ6D<$Lq~n+ zs1F_Wp`$)@)Q67x&`}>c>O)6;=%^1J^`WDF#+H7@mVU;Te#Vx5#+H7@mVU;Te#Vx5 z>7^&=XKd+bY*F?ijV=9*E&Yrw{fsUBj4l0)E&Yrw{fsUBj4l0)E&Yrw{fsUBj4l0) zE&Yrw{fsUBj4l0)E&Yrw{fsUBj4l0)E&Yrw{fsUBj4l0)E&Yrw{fsUBj4l0)E&Yrw z{fsUBj4l0)E&Yrw1I)VyWW8?(1I)Vyn0F1xk`)Um8#a30I3Vjadfqs|yla4Y*8uab z0p?u;%)17dcMUM_8erZvz`Scf7U&i{Zyb;X8a;0ukOdk&Zyb;X8a;0uVBR&rylX(3 zbx%BR9AMrxAT29Sk^T?T|3UgcNdE`v{~-Mzr2m8Te~|tU(*HsFKS=)v>Hi@8AEf_- z^nZ~457PfZ`aekj2kHMH{U4HJ?AEN(5 z^nZx{57GZ2`aeYfhv@$h{U4(LL-c=${_F8Jy6;O*l}Q+*C!r)OtNd^|UghMG@+jS5 zIdP<%pbVykBjrTh6In7+PE!5lk@9$DlNt)v2HSMbQye^`SCQ@@-Kluye9GH`Z|MD6 zo&RjtHO~jXp?iFPBX~A=Mz#L?l*Uj!vufn~Y1dkCZDufE5#0BD&Zm#-`w_MFtY~~g zSKgzHc=zaP<)zZQ4f^zX^}*MCBbYPNlV?@;b$wbaKAuti^D6Dq6;J8iRr+(U(f_)> zzf)H__uSpO_9A-O5Gx$e(UXUK= zC&?w~EHFvhNY>N7Ldq^aPA7rmmA`qSvfZWX34N1-8-vMuYUs_u7lK>#bi7-G+mxU2 z4)uPjP6E^QTRTIUEoUiS{VqKtY>s|~=BhV$Bd<*5C(BZ{tNWFiXrX?m7D*;K$}F%% zzfenq2gTts>0pI=yh`^9KOC&q{k3a@FG}x^NK)&9f?$2{sP2kg1=I{&~uXgcHNOvBpn`*2EHk+*cNt4H!lP)2LB~^ zNtRWr^F_re2N#0h3;u(im-Ox6H-oKmWn`BY&4Ctk@MP z4t*`M?S*INJ+zFTX#V=pE_R(N`(YBr6kUjVrP=T)S=bx1I z&F#-bz7dQcMt$bb{ftoCrTslF_;arR#>B5r{QB5iCw@JpA~h$aA}M+NTVp>O_s;mY z;@%ziv*Zi$RpZ|pb#(k&32PG$j{BJ&PJ1HxLU`Jkim|tj{b<60EpF>crFudYO(nNvRk{zfa8(x6|caiQ?IwrRPcO-zZ5lRlM7ClJT67 zJm)U?o%1&;3%>kiqWmRSo@d{<4bQkkp0P$A_a*(CCf``E??0x0v*Z<9qsmw_$L zWmK6jJJcOUvcp~S!BYLZ4=Z$}xFQ2(yRV4CUj19DsH`UWVzVrGrF`PJ{O^Q3<5Ah; z1$o^?{VS9uw#(Yu4(QW`|+~Ius$$q5j>j-<%za1X!lo z=Vi@3FKgy`SttD+I_K}u{PVKT_&YQMy{z;74xQ_F=rq1VzcRi@&UeW9{y5(q=X>LP zXWS0W|1N9xcUg14%bNLJ*1YesW__1+3NC-qUuR);4pwJib^g_hdO7#1Gp{=DsIdODw{ zvw1p~r!#pvkEgSEI)|q-cshTlvv)c!!I?Xqx6@fW9gh&vd*|zPwod2jbf!+{>2#J( z#}hc3z_A35Byb#oqX>v05KZUgbVg3+<8(Go=i+oGPUqot7Eb5jbOui6-*om(=iYSY zO`q*M>!x#VI^(AEZ93bg*1dr)Q_>kFolnx)B%MprnIxS@(pe;(L-I!HYCyUgkgf)#s{!fC^UW)Y zgY_zOKr$bYTn8lA0m*ehavhLd2PD@4$#p<6slAFw?NvN#ucA@Ck{gg;UA1rLQvAfm zx5~!1isBh;+}RVIJJFe#oHx-~6P+{B855l^(b*E6D=}Z+ah^nHNpy}xXGnB@L}y2I zZbWBBbY4VfMRZO?XGC;9L}x>EE<|TSbRI-!L39qpf67;!^UxU&o$t`u4xQ`JnGT)j z&{+M;ny`fW=PV00!oHPzYL8i z&WZIMNnAPkRqxz^&K&5xfzBG}oPo|5=zM|B7U=x@&J^f8fzG_|9D&Xd==^}rxbJ-X z&J5_hfX)i&oPf><=zM_Au6Z_fJXJo?V~ z=X`(8_UFuR&h+Ozf6nsf9DmO6=lp)o?&sWo&g|#Be$MLWoPN&e=X`$7=I2~~&gADj ze$L|O9DdH==lp%n-sjwX&fMp`ea_nFoPEyN=X`z6*5_P(&eZ2Tea_P79DUBv=lp!m z&ga~G&dle$e9p?}oP5s6=X`w5{pMVJ&cx@eZ_dK!9DL5e=lpxlzPD^dLwl~%P`Nbp zp)^!34egO;(xjC=(#ChCg?-Y(2hzd^(!vMQzyV4A14;b@NxXYRsvkgLlVu9 zG(VIyGe)HOp`^J-(%d6y?vXV2NSb>j%{`Ll9!YGUB(_fy+b4* z)Gw+t-#PD{v)(!9oipA!-<`AFIoF*t-8s*lGiN(*wlmy0znwE?J72c5Wjn8(v)VbQ zoio}wpPjSWIhUO?**TA$v)DO@oio@uf1R_}Id`2i*Ew&Uv(`Choio-sU!AknIai%C z)j3a{v(!09oio%qKb^DFIX9g%(>X8QJ>ujtx^uoTXA5(#FlP#Lo-k(#bB-`)2y=cg zX9sg`FlPpHUNC0`b51a41am$xX9FwO%bCEO2h3T(oCC}mz?}cf*}t6o%bCBN_sdzo zob$^Wznt&O*}k0X%bC8M=gV2Xoa4(GzMS97*}a_G%bC5L*UMSGoYPCsJkbosnT4EJ z$XSJ)Q^*;GoKMKvgq%yrnS`82$XSG(L&zC~oIl9fgPc2PoW7~&jOgWDEY8H@JS@(_ z;v6i_z~cNX&c5PPPoH@v=o>%KH?%XXmvff*xgQ;pS%+liIgaNy9pbq|Ja>ra4)NR} zo;$>|=PVuKxkEg6i02OR+##MlKk3jc&w0w6&%-&&oT1G5$()_cSv;J>!+FV^mCQNG zoRQ4=$efMLxyYP}%z4P1h0Hm~oPo^w$DDo4xyPJ&%z4M0b<8=(oN>(g#++@;xyGDn z%z4HpXjHym{;g*%=;b?_eW$eVX7;_zzDL^kG5aoN-^1)Xn0^1U?_T!3%L}wWq33kz z0liFNAbyBmFPqwj3=eT~i@=G)WeE zZMv*`x?0&Jx?9!KCbhJhm|SOx^!V%9s$+4l&RB=%Bg3;+$KS5h_Z)lc$XmzVIuoSx zKsw^q@wSe(b*!x;Z5?OpC|k$aI>OfRwajAG2S?UAu9jJ>-aDe!@wCqHSgLwQ(mIaT zQM8Vsbp);BXB|E3*jY!;I&Su#n&mo9)={#Kk#&Tu<6|8i>)2RF#yT$6QL&DRbwsS= zVI2+YSXf8GIu6!Ru#SOs1gzs<9sTOqS4X}&?$uGRj(HuP73-{7*E!bJk*D>}pfvCiv%EPGZC2)%sok0Vwcuj*)3$ErF~)p4qhQgw`Km#*=BK8{XxY^v|@ zaa?Mudg53q$4EI6>O<-5=hD}QYTdCFj=^#SmgBD+edX9IM_xJZDoy+x z5f8(oprcP5J>kd`$DKIp#4#t1IB~p*qfH!Z;z$$6nK;VCF(!^MaeRrROB`F`$P&ku zII6@kC5|X@Jc*-8982OzlB*-?jpF5icyW}lo*}2dj%jp6qvLKI&FEN0M?E;^!BLEk zVRQte;};#h=-5R^E;??}QHzdQTq(XD6kl`XIUA&(InvLA@|O3---Gg&_ca#j2?Bcg zyvrvkK1cBht=fwb96LVQ^0}5z%za+&({i7c`!vgESyg)ZjNB*W zJ|Fk#xX;FYdgZe#pNjiT+$Z8bv+{|R&%*tDLO-3*&n9%f96y)PPbGAwoD+IEYld@X zoYu?vGMp{LxpABs$9Zv_6~{Soe9GOSzdqsi`L<8DeYWkBZJ%rVRC}J}t!EJG<C;Z1b^4^!=bS#}^ckm5IDNk9(@mdk`ef7RnrZ6! z2I*Dfu>OYi@|lBA9K7G{(}v+*e@DGmu42hAM_%j56vw4FD#bA=j!5yjf=?BErr;9= zpC|Y;1dMLo%r-%ct7i3wI5dW?ANww*9;u_zW2ktXEwYab_;*w WwHG^1yNvPL2mL_!h-%}4hyNEi*y0iZ literal 0 HcmV?d00001 diff --git a/docsrc/exts/themes/cyrus/static/fonts/Lato-Regular.ttf b/docsrc/exts/themes/cyrus/static/fonts/Lato-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..7608bc3e0fd03fc3cf3a41501ed9c1b49b773ac4 GIT binary patch literal 81980 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 literal 0 HcmV?d00001 diff --git a/docsrc/exts/themes/cyrus/static/fonts/RobotoSlab-Bold.ttf b/docsrc/exts/themes/cyrus/static/fonts/RobotoSlab-Bold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..e6ed0de530e99cc8c0ef6e4a20012ed1533b62d1 GIT binary patch literal 36596 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
    V$fDV|Iw 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',a,""].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},z=function(b){var c=a.matchMedia||a.msMatchMedia;if(c)return c(b).matches;var d;return y("@media "+b+" { #"+h+" { position: absolute; } }",function(b){d=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle)["position"]=="absolute"}),d},A=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;return f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=F(e[d],"function"),F(e[d],"undefined")||(e[d]=c),e.removeAttribute(d))),e=null,f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),B={}.hasOwnProperty,C;!F(B,"undefined")&&!F(B.call,"undefined")?C=function(a,b){return B.call(a,b)}:C=function(a,b){return b in a&&F(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=w.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(w.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(w.call(arguments)))};return e}),s.flexbox=function(){return J("flexWrap")},s.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},s.canvastext=function(){return!!e.canvas&&!!F(b.createElement("canvas").getContext("2d").fillText,"function")},s.webgl=function(){return!!a.WebGLRenderingContext},s.touch=function(){var c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch?c=!0:y(["@media (",n.join("touch-enabled),("),h,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(a){c=a.offsetTop===9}),c},s.geolocation=function(){return"geolocation"in navigator},s.postmessage=function(){return!!a.postMessage},s.websqldatabase=function(){return!!a.openDatabase},s.indexedDB=function(){return!!J("indexedDB",a)},s.hashchange=function(){return A("hashchange",a)&&(b.documentMode===c||b.documentMode>7)},s.history=function(){return!!a.history&&!!history.pushState},s.draganddrop=function(){var a=b.createElement("div");return"draggable"in a||"ondragstart"in a&&"ondrop"in a},s.websockets=function(){return"WebSocket"in a||"MozWebSocket"in a},s.rgba=function(){return D("background-color:rgba(150,255,150,.5)"),G(j.backgroundColor,"rgba")},s.hsla=function(){return D("background-color:hsla(120,40%,100%,.5)"),G(j.backgroundColor,"rgba")||G(j.backgroundColor,"hsla")},s.multiplebgs=function(){return D("background:url(https://),url(https://),red url(https://)"),/(url\s*\(.*?){3}/.test(j.background)},s.backgroundsize=function(){return J("backgroundSize")},s.borderimage=function(){return J("borderImage")},s.borderradius=function(){return J("borderRadius")},s.boxshadow=function(){return J("boxShadow")},s.textshadow=function(){return b.createElement("div").style.textShadow===""},s.opacity=function(){return E("opacity:.55"),/^0.55$/.test(j.opacity)},s.cssanimations=function(){return J("animationName")},s.csscolumns=function(){return J("columnCount")},s.cssgradients=function(){var a="background-image:",b="gradient(linear,left top,right bottom,from(#9f9),to(white));",c="linear-gradient(left top,#9f9, white);";return D((a+"-webkit- ".split(" ").join(b+a)+n.join(c+a)).slice(0,-a.length)),G(j.backgroundImage,"gradient")},s.cssreflections=function(){return J("boxReflect")},s.csstransforms=function(){return!!J("transform")},s.csstransforms3d=function(){var a=!!J("perspective");return a&&"webkitPerspective"in g.style&&y("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b,c){a=b.offsetLeft===9&&b.offsetHeight===3}),a},s.csstransitions=function(){return J("transition")},s.fontface=function(){var a;return y('@font-face {font-family:"font";src:url("https://")}',function(c,d){var e=b.getElementById("smodernizr"),f=e.sheet||e.styleSheet,g=f?f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"":"";a=/src/i.test(g)&&g.indexOf(d.split(" ")[0])===0}),a},s.generatedcontent=function(){var a;return y(["#",h,"{font:0/0 a}#",h,':after{content:"',l,'";visibility:hidden;font:3px/1 a}'].join(""),function(b){a=b.offsetHeight>=3}),a},s.video=function(){var a=b.createElement("video"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('video/ogg; codecs="theora"').replace(/^no$/,""),c.h264=a.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(/^no$/,""),c.webm=a.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,"")}catch(d){}return c},s.audio=function(){var a=b.createElement("audio"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),c.mp3=a.canPlayType("audio/mpeg;").replace(/^no$/,""),c.wav=a.canPlayType('audio/wav; codecs="1"').replace(/^no$/,""),c.m4a=(a.canPlayType("audio/x-m4a;")||a.canPlayType("audio/aac;")).replace(/^no$/,"")}catch(d){}return c},s.localstorage=function(){try{return localStorage.setItem(h,h),localStorage.removeItem(h),!0}catch(a){return!1}},s.sessionstorage=function(){try{return sessionStorage.setItem(h,h),sessionStorage.removeItem(h),!0}catch(a){return!1}},s.webworkers=function(){return!!a.Worker},s.applicationcache=function(){return!!a.applicationCache},s.svg=function(){return!!b.createElementNS&&!!b.createElementNS(r.svg,"svg").createSVGRect},s.inlinesvg=function(){var a=b.createElement("div");return a.innerHTML="",(a.firstChild&&a.firstChild.namespaceURI)==r.svg},s.smil=function(){return!!b.createElementNS&&/SVGAnimate/.test(m.call(b.createElementNS(r.svg,"animate")))},s.svgclippaths=function(){return!!b.createElementNS&&/SVGClipPath/.test(m.call(b.createElementNS(r.svg,"clipPath")))};for(var L in s)C(s,L)&&(x=L.toLowerCase(),e[x]=s[L](),v.push((e[x]?"":"no-")+x));return e.input||K(),e.addTest=function(a,b){if(typeof a=="object")for(var d in a)C(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},D(""),i=k=null,function(a,b){function k(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function l(){var a=r.elements;return typeof a=="string"?a.split(" "):a}function m(a){var b=i[a[g]];return b||(b={},h++,a[g]=h,i[h]=b),b}function n(a,c,f){c||(c=b);if(j)return c.createElement(a);f||(f=m(c));var g;return f.cache[a]?g=f.cache[a].cloneNode():e.test(a)?g=(f.cache[a]=f.createElem(a)).cloneNode():g=f.createElem(a),g.canHaveChildren&&!d.test(a)?f.frag.appendChild(g):g}function o(a,c){a||(a=b);if(j)return a.createDocumentFragment();c=c||m(a);var d=c.frag.cloneNode(),e=0,f=l(),g=f.length;for(;e",f="hidden"in a,j=a.childNodes.length==1||function(){b.createElement("a");var a=b.createDocumentFragment();return typeof a.cloneNode=="undefined"||typeof a.createDocumentFragment=="undefined"||typeof a.createElement=="undefined"}()}catch(c){f=!0,j=!0}})();var r={elements:c.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:c.shivCSS!==!1,supportsUnknownElements:j,shivMethods:c.shivMethods!==!1,type:"default",shivDocument:q,createElement:n,createDocumentFragment:o};a.html5=r,q(b)}(this,b),e._version=d,e._prefixes=n,e._domPrefixes=q,e._cssomPrefixes=p,e.mq=z,e.hasEvent=A,e.testProp=function(a){return H([a])},e.testAllProps=J,e.testStyles=y,e.prefixed=function(a,b,c){return b?J(a,b,c):J(a,"pfx")},g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+v.join(" "):""),e}(this,this.document),function(a,b,c){function d(a){return"[object Function]"==o.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=p.shift();q=1,a?a.t?m(function(){("c"==a.t?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l=b.createElement(a),o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};1===y[c]&&(r=1,y[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),"img"!=a&&(r||2===y[c]?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i("c"==b?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),1==p.length&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&"[object Opera]"==o.call(a.opera),l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return"[object Array]"==o.call(a)},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f ul li.current').removeClass('current'); + parent_li.toggleClass('current'); +} + +$(document).ready(function() { + // Shift nav in mobile when clicking the menu. + $(document).on('click', "[data-toggle='wy-nav-top']", function() { + $("[data-toggle='wy-nav-shift']").toggleClass("shift"); + $("[data-toggle='rst-versions']").toggleClass("shift"); + }); + // Nav menu link click operations + $(document).on('click', ".wy-menu-vertical .current ul li a", function() { + var target = $(this); + // Close menu when you click a link. + $("[data-toggle='wy-nav-shift']").removeClass("shift"); + $("[data-toggle='rst-versions']").toggleClass("shift"); + // Handle dynamic display of l3 and l4 nav lists + toggleCurrent(target); + if (typeof(window.SphinxRtdTheme) != 'undefined') { + window.SphinxRtdTheme.StickyNav.hashChange(); + } + }); + $(document).on('click', "[data-toggle='rst-current-version']", function() { + $("[data-toggle='rst-versions']").toggleClass("shift-up"); + }); + // Make tables responsive + $("table.docutils:not(.field-list)").wrap("
    "); + + // Add expand links to all parents of nested ul + $('.wy-menu-vertical ul').siblings('a').each(function () { + var link = $(this); + expand = $(''); + expand.on('click', function (ev) { + toggleCurrent(link); + ev.stopPropagation(); + return false; + }); + link.prepend(expand); + }); +}); + +// Sphinx theme state +window.SphinxRtdTheme = (function (jquery) { + var stickyNav = (function () { + var navBar, + win, + winScroll = false, + linkScroll = false, + winPosition = 0, + enable = function () { + init(); + reset(); + win.on('hashchange', reset); + + // Set scrolling + win.on('scroll', function () { + if (!linkScroll) { + winScroll = true; + } + }); + setInterval(function () { + if (winScroll) { + winScroll = false; + var newWinPosition = win.scrollTop(), + navPosition = navBar.scrollTop(), + newNavPosition = navPosition + (newWinPosition - winPosition); + navBar.scrollTop(newNavPosition); + winPosition = newWinPosition; + } + }, 25); + }, + init = function () { + navBar = jquery('nav.wy-nav-side:first'); + win = jquery(window); + }, + reset = function () { + // Get anchor from URL and open up nested nav + var anchor = encodeURI(window.location.hash); + if (anchor) { + try { + var link = $('.wy-menu-vertical') + .find('[href="' + anchor + '"]'); + $('.wy-menu-vertical li.toctree-l1 li.current') + .removeClass('current'); + link.closest('li.toctree-l2').addClass('current'); + link.closest('li.toctree-l3').addClass('current'); + link.closest('li.toctree-l4').addClass('current'); + } + catch (err) { + console.log("Error expanding nav for anchor", err); + } + } + }, + hashChange = function () { + linkScroll = true; + win.one('hashchange', function () { + linkScroll = false; + }); + }; + jquery(init); + return { + enable: enable, + hashChange: hashChange + }; + }()); + return { + StickyNav: stickyNav + }; +}($)); diff --git a/docsrc/exts/themes/cyrus/theme.conf b/docsrc/exts/themes/cyrus/theme.conf new file mode 100644 index 00000000..3fcc55ae --- /dev/null +++ b/docsrc/exts/themes/cyrus/theme.conf @@ -0,0 +1,9 @@ +[theme] +inherit = sphinx_rtd_theme +stylesheet = css/theme.css + +[options] +typekit_id = hiw1hhg +analytics_id = +sticky_navigation = false +logo_only = true diff --git a/docsrc/exts/themes/cyrus/versions.html b/docsrc/exts/themes/cyrus/versions.html new file mode 100644 index 00000000..8b3eb79d --- /dev/null +++ b/docsrc/exts/themes/cyrus/versions.html @@ -0,0 +1,37 @@ +{% if READTHEDOCS %} +{# Add rst-badge after rst-versions for small badge style. #} +
    + + Read the Docs + v: {{ current_version }} + + +
    +
    +
    Versions
    + {% for slug, url in versions %} +
    {{ slug }}
    + {% endfor %} +
    +
    +
    Downloads
    + {% for type, url in downloads %} +
    {{ type }}
    + {% endfor %} +
    +
    +
    On Read the Docs
    +
    + Project Home +
    +
    + Builds +
    +
    +
    + Free document hosting provided by Read the Docs. + +
    +
    +{% endif %} + diff --git a/docsrc/exts/themes/sphinx_rtd_theme/__init__.py b/docsrc/exts/themes/sphinx_rtd_theme/__init__.py new file mode 100644 index 00000000..95ddc52a --- /dev/null +++ b/docsrc/exts/themes/sphinx_rtd_theme/__init__.py @@ -0,0 +1,17 @@ +"""Sphinx ReadTheDocs theme. + +From https://github.com/ryan-roemer/sphinx-bootstrap-theme. + +""" +import os + +VERSION = (0, 1, 8) + +__version__ = ".".join(str(v) for v in VERSION) +__version_full__ = __version__ + + +def get_html_theme_path(): + """Return list of HTML theme paths.""" + cur_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) + return cur_dir diff --git a/docsrc/exts/themes/sphinx_rtd_theme/breadcrumbs.html b/docsrc/exts/themes/sphinx_rtd_theme/breadcrumbs.html new file mode 100644 index 00000000..0028421e --- /dev/null +++ b/docsrc/exts/themes/sphinx_rtd_theme/breadcrumbs.html @@ -0,0 +1,23 @@ +
    + +
    +
    diff --git a/docsrc/exts/themes/sphinx_rtd_theme/footer.html b/docsrc/exts/themes/sphinx_rtd_theme/footer.html new file mode 100644 index 00000000..6347a440 --- /dev/null +++ b/docsrc/exts/themes/sphinx_rtd_theme/footer.html @@ -0,0 +1,36 @@ +
    + {% if next or prev %} + + {% endif %} + +
    + +
    +

    + {%- if show_copyright %} + {%- if hasdoc('copyright') %} + {% trans path=pathto('copyright'), copyright=copyright|e %}© Copyright {{ copyright }}.{% endtrans %} + {%- else %} + {% trans copyright=copyright|e %}© Copyright {{ copyright }}.{% endtrans %} + {%- endif %} + {%- endif %} + + {%- if last_updated %} + {% trans last_updated=last_updated|e %}Last updated on {{ last_updated }}.{% endtrans %} + {%- endif %} +

    +
    + + {%- if show_sphinx %} + {% trans %}Built with Sphinx using a theme provided by Read the Docs{% endtrans %}. + {%- endif %} + +
    + diff --git a/docsrc/exts/themes/sphinx_rtd_theme/layout.html b/docsrc/exts/themes/sphinx_rtd_theme/layout.html new file mode 100644 index 00000000..9481d8b4 --- /dev/null +++ b/docsrc/exts/themes/sphinx_rtd_theme/layout.html @@ -0,0 +1,181 @@ +{# TEMPLATE VAR SETTINGS #} +{%- set url_root = pathto('', 1) %} +{%- if url_root == '#' %}{% set url_root = '' %}{% endif %} +{%- if not embedded and docstitle %} + {%- set titlesuffix = " — "|safe + docstitle|e %} +{%- else %} + {%- set titlesuffix = "" %} +{%- endif %} + + + + + + + {{ metatags }} + + {% block htmltitle %} + {{ title|striptags|e }}{{ titlesuffix }} + {% endblock %} + + {# FAVICON #} + {% if favicon %} + + {% endif %} + + {# CSS #} + + {# OPENSEARCH #} + {% if not embedded %} + {% if use_opensearch %} + + {% endif %} + + {% endif %} + + {# RTD hosts this file, so just load on non RTD builds #} + {% if not READTHEDOCS %} + + {% endif %} + + {% for cssfile in css_files %} + + {% endfor %} + + {% for cssfile in extra_css_files %} + + {% endfor %} + + {%- block linktags %} + {%- if hasdoc('about') %} + + {%- endif %} + {%- if hasdoc('genindex') %} + + {%- endif %} + {%- if hasdoc('search') %} + + {%- endif %} + {%- if hasdoc('copyright') %} + + {%- endif %} + + {%- if parents %} + + {%- endif %} + {%- if next %} + + {%- endif %} + {%- if prev %} + + {%- endif %} + {%- endblock %} + {%- block extrahead %} {% endblock %} + + {# Keep modernizr in head - http://modernizr.com/docs/#installing #} + + + + + + +
    + + {# SIDE NAV, TOGGLES ON MOBILE #} + + +
    + + {# MOBILE NAV, TRIGGLES SIDE NAV ON TOGGLE #} + + + + {# PAGE CONTENT #} +
    +
    + {% include "breadcrumbs.html" %} +
    + {% block body %}{% endblock %} +
    + {% include "footer.html" %} +
    +
    + +
    + +
    + {% include "versions.html" %} + + {% if not embedded %} + + + {%- for scriptfile in script_files %} + + {%- endfor %} + + {% endif %} + + {# RTD hosts this file, so just load on non RTD builds #} + {% if not READTHEDOCS %} + + {% endif %} + + {# STICKY NAVIGATION #} + {% if theme_sticky_navigation %} + + {% endif %} + + {%- block footer %} {% endblock %} + + + diff --git a/docsrc/exts/themes/sphinx_rtd_theme/layout_old.html b/docsrc/exts/themes/sphinx_rtd_theme/layout_old.html new file mode 100644 index 00000000..deb8df2a --- /dev/null +++ b/docsrc/exts/themes/sphinx_rtd_theme/layout_old.html @@ -0,0 +1,205 @@ +{# + basic/layout.html + ~~~~~~~~~~~~~~~~~ + + Master layout template for Sphinx themes. + + :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +#} +{%- block doctype -%} + +{%- endblock %} +{%- set reldelim1 = reldelim1 is not defined and ' »' or reldelim1 %} +{%- set reldelim2 = reldelim2 is not defined and ' |' or reldelim2 %} +{%- set render_sidebar = (not embedded) and (not theme_nosidebar|tobool) and + (sidebars != []) %} +{%- set url_root = pathto('', 1) %} +{# XXX necessary? #} +{%- if url_root == '#' %}{% set url_root = '' %}{% endif %} +{%- if not embedded and docstitle %} + {%- set titlesuffix = " — "|safe + docstitle|e %} +{%- else %} + {%- set titlesuffix = "" %} +{%- endif %} + +{%- macro relbar() %} + +{%- endmacro %} + +{%- macro sidebar() %} + {%- if render_sidebar %} +
    +
    + {%- block sidebarlogo %} + {%- if logo %} + + {%- endif %} + {%- endblock %} + {%- if sidebars != None %} + {#- new style sidebar: explicitly include/exclude templates #} + {%- for sidebartemplate in sidebars %} + {%- include sidebartemplate %} + {%- endfor %} + {%- else %} + {#- old style sidebars: using blocks -- should be deprecated #} + {%- block sidebartoc %} + {%- include "localtoc.html" %} + {%- endblock %} + {%- block sidebarrel %} + {%- include "relations.html" %} + {%- endblock %} + {%- block sidebarsourcelink %} + {%- include "sourcelink.html" %} + {%- endblock %} + {%- if customsidebar %} + {%- include customsidebar %} + {%- endif %} + {%- block sidebarsearch %} + {%- include "searchbox.html" %} + {%- endblock %} + {%- endif %} +
    +
    + {%- endif %} +{%- endmacro %} + +{%- macro script() %} + + {%- for scriptfile in script_files %} + + {%- endfor %} +{%- endmacro %} + +{%- macro css() %} + + + {%- for cssfile in css_files %} + + {%- endfor %} +{%- endmacro %} + + + + + {{ metatags }} + {%- block htmltitle %} + {{ title|striptags|e }}{{ titlesuffix }} + {%- endblock %} + {{ css() }} + {%- if not embedded %} + {{ script() }} + {%- if use_opensearch %} + + {%- endif %} + {%- if favicon %} + + {%- endif %} + {%- endif %} +{%- block linktags %} + {%- if hasdoc('about') %} + + {%- endif %} + {%- if hasdoc('genindex') %} + + {%- endif %} + {%- if hasdoc('search') %} + + {%- endif %} + {%- if hasdoc('copyright') %} + + {%- endif %} + + {%- if parents %} + + {%- endif %} + {%- if next %} + + {%- endif %} + {%- if prev %} + + {%- endif %} +{%- endblock %} +{%- block extrahead %} {% endblock %} + + +{%- block header %}{% endblock %} + +{%- block relbar1 %}{{ relbar() }}{% endblock %} + +{%- block content %} + {%- block sidebar1 %} {# possible location for sidebar #} {% endblock %} + +
    + {%- block document %} +
    + {%- if render_sidebar %} +
    + {%- endif %} +
    + {% block body %} {% endblock %} +
    + {%- if render_sidebar %} +
    + {%- endif %} +
    + {%- endblock %} + + {%- block sidebar2 %}{{ sidebar() }}{% endblock %} +
    +
    +{%- endblock %} + +{%- block relbar2 %}{{ relbar() }}{% endblock %} + +{%- block footer %} + +

    asdf asdf asdf asdf 22

    +{%- endblock %} + + + diff --git a/docsrc/exts/themes/sphinx_rtd_theme/search.html b/docsrc/exts/themes/sphinx_rtd_theme/search.html new file mode 100644 index 00000000..e3aa9b5c --- /dev/null +++ b/docsrc/exts/themes/sphinx_rtd_theme/search.html @@ -0,0 +1,50 @@ +{# + basic/search.html + ~~~~~~~~~~~~~~~~~ + + Template for the search page. + + :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +#} +{%- extends "layout.html" %} +{% set title = _('Search') %} +{% set script_files = script_files + ['_static/searchtools.js'] %} +{% block footer %} + + {# this is used when loading the search index using $.ajax fails, + such as on Chrome for documents on localhost #} + + {{ super() }} +{% endblock %} +{% block body %} + + + {% if search_performed %} +

    {{ _('Search Results') }}

    + {% if not search_results %} +

    {{ _('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.') }}

    + {% endif %} + {% endif %} +
    + {% if search_results %} +
      + {% for href, caption, context in search_results %} +
    • + {{ caption }} +

      {{ context|e }}

      +
    • + {% endfor %} +
    + {% endif %} +
    +{% endblock %} diff --git a/docsrc/exts/themes/sphinx_rtd_theme/searchbox.html b/docsrc/exts/themes/sphinx_rtd_theme/searchbox.html new file mode 100644 index 00000000..35ad52c5 --- /dev/null +++ b/docsrc/exts/themes/sphinx_rtd_theme/searchbox.html @@ -0,0 +1,9 @@ +{%- if builder != 'singlehtml' %} +
    +
    + + + +
    +
    +{%- endif %} diff --git a/docsrc/exts/themes/sphinx_rtd_theme/static/css/badge_only.css b/docsrc/exts/themes/sphinx_rtd_theme/static/css/badge_only.css new file mode 100644 index 00000000..7e17fb14 --- /dev/null +++ b/docsrc/exts/themes/sphinx_rtd_theme/static/css/badge_only.css @@ -0,0 +1,2 @@ +.fa:before{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-weight:normal;font-style:normal;src:url("../font/fontawesome_webfont.eot");src:url("../font/fontawesome_webfont.eot?#iefix") format("embedded-opentype"),url("../font/fontawesome_webfont.woff") format("woff"),url("../font/fontawesome_webfont.ttf") format("truetype"),url("../font/fontawesome_webfont.svg#FontAwesome") format("svg")}.fa:before{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;text-decoration:inherit}a .fa{display:inline-block;text-decoration:inherit}li .fa{display:inline-block}li .fa-large:before,li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-0.8em}ul.fas li .fa{width:0.8em}ul.fas li .fa-large:before,ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before{content:""}.icon-book:before{content:""}.fa-caret-down:before{content:""}.icon-caret-down:before{content:""}.fa-caret-up:before{content:""}.icon-caret-up:before{content:""}.fa-caret-left:before{content:""}.icon-caret-left:before{content:""}.fa-caret-right:before{content:""}.icon-caret-right:before{content:""}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;border-top:solid 10px #343131;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;z-index:400}.rst-versions a{color:#2980B9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27AE60;*zoom:1}.rst-versions .rst-current-version:before,.rst-versions .rst-current-version:after{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book{float:left}.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#E74C3C;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#F1C40F;color:#000}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:gray;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:solid 1px #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px}.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge .fa-book{float:none}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book{float:left}.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge .rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width: 768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}img{width:100%;height:auto}} +/*# sourceMappingURL=badge_only.css.map */ diff --git a/docsrc/exts/themes/sphinx_rtd_theme/static/css/theme.css b/docsrc/exts/themes/sphinx_rtd_theme/static/css/theme.css new file mode 100644 index 00000000..57b98fe6 --- /dev/null +++ b/docsrc/exts/themes/sphinx_rtd_theme/static/css/theme.css @@ -0,0 +1,5 @@ +*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}[hidden]{display:none}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a:hover,a:active{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}blockquote{margin:0}dfn{font-style:italic}ins{background:#ff9;color:#000;text-decoration:none}mark{background:#ff0;color:#000;font-style:italic;font-weight:bold}pre,code,.rst-content tt,.rst-content code,kbd,samp{font-family:monospace,serif;_font-family:"courier new",monospace;font-size:1em}pre{white-space:pre}q{quotes:none}q:before,q:after{content:"";content:none}small{font-size:85%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}ul,ol,dl{margin:0;padding:0;list-style:none;list-style-image:none}li{list-style:none}dd{margin:0}img{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle;max-width:100%}svg:not(:root){overflow:hidden}figure{margin:0}form{margin:0}fieldset{border:0;margin:0;padding:0}label{cursor:pointer}legend{border:0;*margin-left:-7px;padding:0;white-space:normal}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button;*overflow:visible}button[disabled],input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0;*width:13px;*height:13px}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top;resize:vertical}table{border-collapse:collapse;border-spacing:0}td{vertical-align:top}.chromeframe{margin:0.2em 0;background:#ccc;color:#000;padding:0.2em 0}.ir{display:block;border:0;text-indent:-999em;overflow:hidden;background-color:transparent;background-repeat:no-repeat;text-align:left;direction:ltr;*line-height:0}.ir br{display:none}.hidden{display:none !important;visibility:hidden}.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.invisible{visibility:hidden}.relative{position:relative}big,small{font-size:100%}@media print{html,body,section{background:none !important}*{box-shadow:none !important;text-shadow:none !important;filter:none !important;-ms-filter:none !important}a,a:visited{text-decoration:underline}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,.rst-content p.caption,h3{orphans:3;widows:3}h2,.rst-content p.caption,h3{page-break-after:avoid}}.fa:before,.wy-menu-vertical li span.toctree-expand:before,.wy-menu-vertical li.on a span.toctree-expand:before,.wy-menu-vertical li.current>a span.toctree-expand:before,.rst-content .admonition-title:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content dl dt .headerlink:before,.rst-content tt.download span:first-child:before,.rst-content code.download span:first-child:before,.icon:before,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-alert,.rst-content .note,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .warning,.rst-content .seealso,.rst-content .admonition-todo,.btn,input[type="text"],input[type="password"],input[type="email"],input[type="url"],input[type="date"],input[type="month"],input[type="time"],input[type="datetime"],input[type="datetime-local"],input[type="week"],input[type="number"],input[type="search"],input[type="tel"],input[type="color"],select,textarea,.wy-menu-vertical li.on a,.wy-menu-vertical li.current>a,.wy-side-nav-search>a,.wy-side-nav-search .wy-dropdown>a,.wy-nav-top a{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}/*! + * Font Awesome 4.2.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */@font-face{font-family:'FontAwesome';src:url("../fonts/fontawesome-webfont.eot?v=4.2.0");src:url("../fonts/fontawesome-webfont.eot?#iefix&v=4.2.0") format("embedded-opentype"),url("../fonts/fontawesome-webfont.woff?v=4.2.0") format("woff"),url("../fonts/fontawesome-webfont.ttf?v=4.2.0") format("truetype"),url("../fonts/fontawesome-webfont.svg?v=4.2.0#fontawesomeregular") format("svg");font-weight:normal;font-style:normal}.fa,.wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.current>a span.toctree-expand,.rst-content .admonition-title,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content p.caption .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content dl dt .headerlink,.rst-content tt.download span:first-child,.rst-content code.download span:first-child,.icon{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333em;line-height:0.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14286em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14286em;width:2.14286em;top:0.14286em;text-align:center}.fa-li.fa-lg{left:-1.85714em}.fa-border{padding:.2em .25em .15em;border:solid 0.08em #eee;border-radius:.1em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left,.wy-menu-vertical li span.pull-left.toctree-expand,.wy-menu-vertical li.on a span.pull-left.toctree-expand,.wy-menu-vertical li.current>a span.pull-left.toctree-expand,.rst-content .pull-left.admonition-title,.rst-content h1 .pull-left.headerlink,.rst-content h2 .pull-left.headerlink,.rst-content p.caption .pull-left.headerlink,.rst-content h3 .pull-left.headerlink,.rst-content h4 .pull-left.headerlink,.rst-content h5 .pull-left.headerlink,.rst-content h6 .pull-left.headerlink,.rst-content dl dt .pull-left.headerlink,.rst-content tt.download span.pull-left:first-child,.rst-content code.download span.pull-left:first-child,.pull-left.icon{margin-right:.3em}.fa.pull-right,.wy-menu-vertical li span.pull-right.toctree-expand,.wy-menu-vertical li.on a span.pull-right.toctree-expand,.wy-menu-vertical li.current>a span.pull-right.toctree-expand,.rst-content .pull-right.admonition-title,.rst-content h1 .pull-right.headerlink,.rst-content h2 .pull-right.headerlink,.rst-content p.caption .pull-right.headerlink,.rst-content h3 .pull-right.headerlink,.rst-content h4 .pull-right.headerlink,.rst-content h5 .pull-right.headerlink,.rst-content h6 .pull-right.headerlink,.rst-content dl dt .pull-right.headerlink,.rst-content tt.download span.pull-right:first-child,.rst-content code.download span.pull-right:first-child,.pull-right.icon{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0);-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:""}.fa-music:before{content:""}.fa-search:before,.icon-search:before{content:""}.fa-envelope-o:before{content:""}.fa-heart:before{content:""}.fa-star:before{content:""}.fa-star-o:before{content:""}.fa-user:before{content:""}.fa-film:before{content:""}.fa-th-large:before{content:""}.fa-th:before{content:""}.fa-th-list:before{content:""}.fa-check:before{content:""}.fa-remove:before,.fa-close:before,.fa-times:before{content:""}.fa-search-plus:before{content:""}.fa-search-minus:before{content:""}.fa-power-off:before{content:""}.fa-signal:before{content:""}.fa-gear:before,.fa-cog:before{content:""}.fa-trash-o:before{content:""}.fa-home:before,.icon-home:before{content:""}.fa-file-o:before{content:""}.fa-clock-o:before{content:""}.fa-road:before{content:""}.fa-download:before,.rst-content tt.download span:first-child:before,.rst-content code.download span:first-child:before{content:""}.fa-arrow-circle-o-down:before{content:""}.fa-arrow-circle-o-up:before{content:""}.fa-inbox:before{content:""}.fa-play-circle-o:before{content:""}.fa-rotate-right:before,.fa-repeat:before{content:""}.fa-refresh:before{content:""}.fa-list-alt:before{content:""}.fa-lock:before{content:""}.fa-flag:before{content:""}.fa-headphones:before{content:""}.fa-volume-off:before{content:""}.fa-volume-down:before{content:""}.fa-volume-up:before{content:""}.fa-qrcode:before{content:""}.fa-barcode:before{content:""}.fa-tag:before{content:""}.fa-tags:before{content:""}.fa-book:before,.icon-book:before{content:""}.fa-bookmark:before{content:""}.fa-print:before{content:""}.fa-camera:before{content:""}.fa-font:before{content:""}.fa-bold:before{content:""}.fa-italic:before{content:""}.fa-text-height:before{content:""}.fa-text-width:before{content:""}.fa-align-left:before{content:""}.fa-align-center:before{content:""}.fa-align-right:before{content:""}.fa-align-justify:before{content:""}.fa-list:before{content:""}.fa-dedent:before,.fa-outdent:before{content:""}.fa-indent:before{content:""}.fa-video-camera:before{content:""}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:""}.fa-pencil:before{content:""}.fa-map-marker:before{content:""}.fa-adjust:before{content:""}.fa-tint:before{content:""}.fa-edit:before,.fa-pencil-square-o:before{content:""}.fa-share-square-o:before{content:""}.fa-check-square-o:before{content:""}.fa-arrows:before{content:""}.fa-step-backward:before{content:""}.fa-fast-backward:before{content:""}.fa-backward:before{content:""}.fa-play:before{content:""}.fa-pause:before{content:""}.fa-stop:before{content:""}.fa-forward:before{content:""}.fa-fast-forward:before{content:""}.fa-step-forward:before{content:""}.fa-eject:before{content:""}.fa-chevron-left:before{content:""}.fa-chevron-right:before{content:""}.fa-plus-circle:before{content:""}.fa-minus-circle:before{content:""}.fa-times-circle:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before{content:""}.fa-check-circle:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before{content:""}.fa-question-circle:before{content:""}.fa-info-circle:before{content:""}.fa-crosshairs:before{content:""}.fa-times-circle-o:before{content:""}.fa-check-circle-o:before{content:""}.fa-ban:before{content:""}.fa-arrow-left:before{content:""}.fa-arrow-right:before{content:""}.fa-arrow-up:before{content:""}.fa-arrow-down:before{content:""}.fa-mail-forward:before,.fa-share:before{content:""}.fa-expand:before{content:""}.fa-compress:before{content:""}.fa-plus:before{content:""}.fa-minus:before{content:""}.fa-asterisk:before{content:""}.fa-exclamation-circle:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.rst-content .admonition-title:before{content:""}.fa-gift:before{content:""}.fa-leaf:before{content:""}.fa-fire:before,.icon-fire:before{content:""}.fa-eye:before{content:""}.fa-eye-slash:before{content:""}.fa-warning:before,.fa-exclamation-triangle:before{content:""}.fa-plane:before{content:""}.fa-calendar:before{content:""}.fa-random:before{content:""}.fa-comment:before{content:""}.fa-magnet:before{content:""}.fa-chevron-up:before{content:""}.fa-chevron-down:before{content:""}.fa-retweet:before{content:""}.fa-shopping-cart:before{content:""}.fa-folder:before{content:""}.fa-folder-open:before{content:""}.fa-arrows-v:before{content:""}.fa-arrows-h:before{content:""}.fa-bar-chart-o:before,.fa-bar-chart:before{content:""}.fa-twitter-square:before{content:""}.fa-facebook-square:before{content:""}.fa-camera-retro:before{content:""}.fa-key:before{content:""}.fa-gears:before,.fa-cogs:before{content:""}.fa-comments:before{content:""}.fa-thumbs-o-up:before{content:""}.fa-thumbs-o-down:before{content:""}.fa-star-half:before{content:""}.fa-heart-o:before{content:""}.fa-sign-out:before{content:""}.fa-linkedin-square:before{content:""}.fa-thumb-tack:before{content:""}.fa-external-link:before{content:""}.fa-sign-in:before{content:""}.fa-trophy:before{content:""}.fa-github-square:before{content:""}.fa-upload:before{content:""}.fa-lemon-o:before{content:""}.fa-phone:before{content:""}.fa-square-o:before{content:""}.fa-bookmark-o:before{content:""}.fa-phone-square:before{content:""}.fa-twitter:before{content:""}.fa-facebook:before{content:""}.fa-github:before,.icon-github:before{content:""}.fa-unlock:before{content:""}.fa-credit-card:before{content:""}.fa-rss:before{content:""}.fa-hdd-o:before{content:""}.fa-bullhorn:before{content:""}.fa-bell:before{content:""}.fa-certificate:before{content:""}.fa-hand-o-right:before{content:""}.fa-hand-o-left:before{content:""}.fa-hand-o-up:before{content:""}.fa-hand-o-down:before{content:""}.fa-arrow-circle-left:before,.icon-circle-arrow-left:before{content:""}.fa-arrow-circle-right:before,.icon-circle-arrow-right:before{content:""}.fa-arrow-circle-up:before{content:""}.fa-arrow-circle-down:before{content:""}.fa-globe:before{content:""}.fa-wrench:before{content:""}.fa-tasks:before{content:""}.fa-filter:before{content:""}.fa-briefcase:before{content:""}.fa-arrows-alt:before{content:""}.fa-group:before,.fa-users:before{content:""}.fa-chain:before,.fa-link:before,.icon-link:before{content:""}.fa-cloud:before{content:""}.fa-flask:before{content:""}.fa-cut:before,.fa-scissors:before{content:""}.fa-copy:before,.fa-files-o:before{content:""}.fa-paperclip:before{content:""}.fa-save:before,.fa-floppy-o:before{content:""}.fa-square:before{content:""}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:""}.fa-list-ul:before{content:""}.fa-list-ol:before{content:""}.fa-strikethrough:before{content:""}.fa-underline:before{content:""}.fa-table:before{content:""}.fa-magic:before{content:""}.fa-truck:before{content:""}.fa-pinterest:before{content:""}.fa-pinterest-square:before{content:""}.fa-google-plus-square:before{content:""}.fa-google-plus:before{content:""}.fa-money:before{content:""}.fa-caret-down:before,.wy-dropdown .caret:before,.icon-caret-down:before{content:""}.fa-caret-up:before{content:""}.fa-caret-left:before{content:""}.fa-caret-right:before{content:""}.fa-columns:before{content:""}.fa-unsorted:before,.fa-sort:before{content:""}.fa-sort-down:before,.fa-sort-desc:before{content:""}.fa-sort-up:before,.fa-sort-asc:before{content:""}.fa-envelope:before{content:""}.fa-linkedin:before{content:""}.fa-rotate-left:before,.fa-undo:before{content:""}.fa-legal:before,.fa-gavel:before{content:""}.fa-dashboard:before,.fa-tachometer:before{content:""}.fa-comment-o:before{content:""}.fa-comments-o:before{content:""}.fa-flash:before,.fa-bolt:before{content:""}.fa-sitemap:before{content:""}.fa-umbrella:before{content:""}.fa-paste:before,.fa-clipboard:before{content:""}.fa-lightbulb-o:before{content:""}.fa-exchange:before{content:""}.fa-cloud-download:before{content:""}.fa-cloud-upload:before{content:""}.fa-user-md:before{content:""}.fa-stethoscope:before{content:""}.fa-suitcase:before{content:""}.fa-bell-o:before{content:""}.fa-coffee:before{content:""}.fa-cutlery:before{content:""}.fa-file-text-o:before{content:""}.fa-building-o:before{content:""}.fa-hospital-o:before{content:""}.fa-ambulance:before{content:""}.fa-medkit:before{content:""}.fa-fighter-jet:before{content:""}.fa-beer:before{content:""}.fa-h-square:before{content:""}.fa-plus-square:before{content:""}.fa-angle-double-left:before{content:""}.fa-angle-double-right:before{content:""}.fa-angle-double-up:before{content:""}.fa-angle-double-down:before{content:""}.fa-angle-left:before{content:""}.fa-angle-right:before{content:""}.fa-angle-up:before{content:""}.fa-angle-down:before{content:""}.fa-desktop:before{content:""}.fa-laptop:before{content:""}.fa-tablet:before{content:""}.fa-mobile-phone:before,.fa-mobile:before{content:""}.fa-circle-o:before{content:""}.fa-quote-left:before{content:""}.fa-quote-right:before{content:""}.fa-spinner:before{content:""}.fa-circle:before{content:""}.fa-mail-reply:before,.fa-reply:before{content:""}.fa-github-alt:before{content:""}.fa-folder-o:before{content:""}.fa-folder-open-o:before{content:""}.fa-smile-o:before{content:""}.fa-frown-o:before{content:""}.fa-meh-o:before{content:""}.fa-gamepad:before{content:""}.fa-keyboard-o:before{content:""}.fa-flag-o:before{content:""}.fa-flag-checkered:before{content:""}.fa-terminal:before{content:""}.fa-code:before{content:""}.fa-mail-reply-all:before,.fa-reply-all:before{content:""}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:""}.fa-location-arrow:before{content:""}.fa-crop:before{content:""}.fa-code-fork:before{content:""}.fa-unlink:before,.fa-chain-broken:before{content:""}.fa-question:before{content:""}.fa-info:before{content:""}.fa-exclamation:before{content:""}.fa-superscript:before{content:""}.fa-subscript:before{content:""}.fa-eraser:before{content:""}.fa-puzzle-piece:before{content:""}.fa-microphone:before{content:""}.fa-microphone-slash:before{content:""}.fa-shield:before{content:""}.fa-calendar-o:before{content:""}.fa-fire-extinguisher:before{content:""}.fa-rocket:before{content:""}.fa-maxcdn:before{content:""}.fa-chevron-circle-left:before{content:""}.fa-chevron-circle-right:before{content:""}.fa-chevron-circle-up:before{content:""}.fa-chevron-circle-down:before{content:""}.fa-html5:before{content:""}.fa-css3:before{content:""}.fa-anchor:before{content:""}.fa-unlock-alt:before{content:""}.fa-bullseye:before{content:""}.fa-ellipsis-h:before{content:""}.fa-ellipsis-v:before{content:""}.fa-rss-square:before{content:""}.fa-play-circle:before{content:""}.fa-ticket:before{content:""}.fa-minus-square:before{content:""}.fa-minus-square-o:before,.wy-menu-vertical li.on a span.toctree-expand:before,.wy-menu-vertical li.current>a span.toctree-expand:before{content:""}.fa-level-up:before{content:""}.fa-level-down:before{content:""}.fa-check-square:before{content:""}.fa-pencil-square:before{content:""}.fa-external-link-square:before{content:""}.fa-share-square:before{content:""}.fa-compass:before{content:""}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:""}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:""}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:""}.fa-euro:before,.fa-eur:before{content:""}.fa-gbp:before{content:""}.fa-dollar:before,.fa-usd:before{content:""}.fa-rupee:before,.fa-inr:before{content:""}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:""}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:""}.fa-won:before,.fa-krw:before{content:""}.fa-bitcoin:before,.fa-btc:before{content:""}.fa-file:before{content:""}.fa-file-text:before{content:""}.fa-sort-alpha-asc:before{content:""}.fa-sort-alpha-desc:before{content:""}.fa-sort-amount-asc:before{content:""}.fa-sort-amount-desc:before{content:""}.fa-sort-numeric-asc:before{content:""}.fa-sort-numeric-desc:before{content:""}.fa-thumbs-up:before{content:""}.fa-thumbs-down:before{content:""}.fa-youtube-square:before{content:""}.fa-youtube:before{content:""}.fa-xing:before{content:""}.fa-xing-square:before{content:""}.fa-youtube-play:before{content:""}.fa-dropbox:before{content:""}.fa-stack-overflow:before{content:""}.fa-instagram:before{content:""}.fa-flickr:before{content:""}.fa-adn:before{content:""}.fa-bitbucket:before,.icon-bitbucket:before{content:""}.fa-bitbucket-square:before{content:""}.fa-tumblr:before{content:""}.fa-tumblr-square:before{content:""}.fa-long-arrow-down:before{content:""}.fa-long-arrow-up:before{content:""}.fa-long-arrow-left:before{content:""}.fa-long-arrow-right:before{content:""}.fa-apple:before{content:""}.fa-windows:before{content:""}.fa-android:before{content:""}.fa-linux:before{content:""}.fa-dribbble:before{content:""}.fa-skype:before{content:""}.fa-foursquare:before{content:""}.fa-trello:before{content:""}.fa-female:before{content:""}.fa-male:before{content:""}.fa-gittip:before{content:""}.fa-sun-o:before{content:""}.fa-moon-o:before{content:""}.fa-archive:before{content:""}.fa-bug:before{content:""}.fa-vk:before{content:""}.fa-weibo:before{content:""}.fa-renren:before{content:""}.fa-pagelines:before{content:""}.fa-stack-exchange:before{content:""}.fa-arrow-circle-o-right:before{content:""}.fa-arrow-circle-o-left:before{content:""}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:""}.fa-dot-circle-o:before{content:""}.fa-wheelchair:before{content:""}.fa-vimeo-square:before{content:""}.fa-turkish-lira:before,.fa-try:before{content:""}.fa-plus-square-o:before,.wy-menu-vertical li span.toctree-expand:before{content:""}.fa-space-shuttle:before{content:""}.fa-slack:before{content:""}.fa-envelope-square:before{content:""}.fa-wordpress:before{content:""}.fa-openid:before{content:""}.fa-institution:before,.fa-bank:before,.fa-university:before{content:""}.fa-mortar-board:before,.fa-graduation-cap:before{content:""}.fa-yahoo:before{content:""}.fa-google:before{content:""}.fa-reddit:before{content:""}.fa-reddit-square:before{content:""}.fa-stumbleupon-circle:before{content:""}.fa-stumbleupon:before{content:""}.fa-delicious:before{content:""}.fa-digg:before{content:""}.fa-pied-piper:before{content:""}.fa-pied-piper-alt:before{content:""}.fa-drupal:before{content:""}.fa-joomla:before{content:""}.fa-language:before{content:""}.fa-fax:before{content:""}.fa-building:before{content:""}.fa-child:before{content:""}.fa-paw:before{content:""}.fa-spoon:before{content:""}.fa-cube:before{content:""}.fa-cubes:before{content:""}.fa-behance:before{content:""}.fa-behance-square:before{content:""}.fa-steam:before{content:""}.fa-steam-square:before{content:""}.fa-recycle:before{content:""}.fa-automobile:before,.fa-car:before{content:""}.fa-cab:before,.fa-taxi:before{content:""}.fa-tree:before{content:""}.fa-spotify:before{content:""}.fa-deviantart:before{content:""}.fa-soundcloud:before{content:""}.fa-database:before{content:""}.fa-file-pdf-o:before{content:""}.fa-file-word-o:before{content:""}.fa-file-excel-o:before{content:""}.fa-file-powerpoint-o:before{content:""}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:""}.fa-file-zip-o:before,.fa-file-archive-o:before{content:""}.fa-file-sound-o:before,.fa-file-audio-o:before{content:""}.fa-file-movie-o:before,.fa-file-video-o:before{content:""}.fa-file-code-o:before{content:""}.fa-vine:before{content:""}.fa-codepen:before{content:""}.fa-jsfiddle:before{content:""}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:""}.fa-circle-o-notch:before{content:""}.fa-ra:before,.fa-rebel:before{content:""}.fa-ge:before,.fa-empire:before{content:""}.fa-git-square:before{content:""}.fa-git:before{content:""}.fa-hacker-news:before{content:""}.fa-tencent-weibo:before{content:""}.fa-qq:before{content:""}.fa-wechat:before,.fa-weixin:before{content:""}.fa-send:before,.fa-paper-plane:before{content:""}.fa-send-o:before,.fa-paper-plane-o:before{content:""}.fa-history:before{content:""}.fa-circle-thin:before{content:""}.fa-header:before{content:""}.fa-paragraph:before{content:""}.fa-sliders:before{content:""}.fa-share-alt:before{content:""}.fa-share-alt-square:before{content:""}.fa-bomb:before{content:""}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:""}.fa-tty:before{content:""}.fa-binoculars:before{content:""}.fa-plug:before{content:""}.fa-slideshare:before{content:""}.fa-twitch:before{content:""}.fa-yelp:before{content:""}.fa-newspaper-o:before{content:""}.fa-wifi:before{content:""}.fa-calculator:before{content:""}.fa-paypal:before{content:""}.fa-google-wallet:before{content:""}.fa-cc-visa:before{content:""}.fa-cc-mastercard:before{content:""}.fa-cc-discover:before{content:""}.fa-cc-amex:before{content:""}.fa-cc-paypal:before{content:""}.fa-cc-stripe:before{content:""}.fa-bell-slash:before{content:""}.fa-bell-slash-o:before{content:""}.fa-trash:before{content:""}.fa-copyright:before{content:""}.fa-at:before{content:""}.fa-eyedropper:before{content:""}.fa-paint-brush:before{content:""}.fa-birthday-cake:before{content:""}.fa-area-chart:before{content:""}.fa-pie-chart:before{content:""}.fa-line-chart:before{content:""}.fa-lastfm:before{content:""}.fa-lastfm-square:before{content:""}.fa-toggle-off:before{content:""}.fa-toggle-on:before{content:""}.fa-bicycle:before{content:""}.fa-bus:before{content:""}.fa-ioxhost:before{content:""}.fa-angellist:before{content:""}.fa-cc:before{content:""}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:""}.fa-meanpath:before{content:""}.fa,.wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.current>a span.toctree-expand,.rst-content .admonition-title,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content p.caption .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content dl dt .headerlink,.rst-content tt.download span:first-child,.rst-content code.download span:first-child,.icon,.wy-dropdown .caret,.wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-inline-validate.wy-inline-validate-info .wy-input-context{font-family:inherit}.fa:before,.wy-menu-vertical li span.toctree-expand:before,.wy-menu-vertical li.on a span.toctree-expand:before,.wy-menu-vertical li.current>a span.toctree-expand:before,.rst-content .admonition-title:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content dl dt .headerlink:before,.rst-content tt.download span:first-child:before,.rst-content code.download span:first-child:before,.icon:before,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before{font-family:"FontAwesome";display:inline-block;font-style:normal;font-weight:normal;line-height:1;text-decoration:inherit}a .fa,a .wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li a span.toctree-expand,.wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.current>a span.toctree-expand,a .rst-content .admonition-title,.rst-content a .admonition-title,a .rst-content h1 .headerlink,.rst-content h1 a .headerlink,a .rst-content h2 .headerlink,.rst-content h2 a .headerlink,a .rst-content p.caption .headerlink,.rst-content p.caption a .headerlink,a .rst-content h3 .headerlink,.rst-content h3 a .headerlink,a .rst-content h4 .headerlink,.rst-content h4 a .headerlink,a .rst-content h5 .headerlink,.rst-content h5 a .headerlink,a .rst-content h6 .headerlink,.rst-content h6 a .headerlink,a .rst-content dl dt .headerlink,.rst-content dl dt a .headerlink,a .rst-content tt.download span:first-child,.rst-content tt.download a span:first-child,a .rst-content code.download span:first-child,.rst-content code.download a span:first-child,a .icon{display:inline-block;text-decoration:inherit}.btn .fa,.btn .wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li .btn span.toctree-expand,.btn .wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.on a .btn span.toctree-expand,.btn .wy-menu-vertical li.current>a span.toctree-expand,.wy-menu-vertical li.current>a .btn span.toctree-expand,.btn .rst-content .admonition-title,.rst-content .btn .admonition-title,.btn .rst-content h1 .headerlink,.rst-content h1 .btn .headerlink,.btn .rst-content h2 .headerlink,.rst-content h2 .btn .headerlink,.btn .rst-content p.caption .headerlink,.rst-content p.caption .btn .headerlink,.btn .rst-content h3 .headerlink,.rst-content h3 .btn .headerlink,.btn .rst-content h4 .headerlink,.rst-content h4 .btn .headerlink,.btn .rst-content h5 .headerlink,.rst-content h5 .btn .headerlink,.btn .rst-content h6 .headerlink,.rst-content h6 .btn .headerlink,.btn .rst-content dl dt .headerlink,.rst-content dl dt .btn .headerlink,.btn .rst-content tt.download span:first-child,.rst-content tt.download .btn span:first-child,.btn .rst-content code.download span:first-child,.rst-content code.download .btn span:first-child,.btn .icon,.nav .fa,.nav .wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li .nav span.toctree-expand,.nav .wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.on a .nav span.toctree-expand,.nav .wy-menu-vertical li.current>a span.toctree-expand,.wy-menu-vertical li.current>a .nav span.toctree-expand,.nav .rst-content .admonition-title,.rst-content .nav .admonition-title,.nav .rst-content h1 .headerlink,.rst-content h1 .nav .headerlink,.nav .rst-content h2 .headerlink,.rst-content h2 .nav .headerlink,.nav .rst-content p.caption .headerlink,.rst-content p.caption .nav .headerlink,.nav .rst-content h3 .headerlink,.rst-content h3 .nav .headerlink,.nav .rst-content h4 .headerlink,.rst-content h4 .nav .headerlink,.nav .rst-content h5 .headerlink,.rst-content h5 .nav .headerlink,.nav .rst-content h6 .headerlink,.rst-content h6 .nav .headerlink,.nav .rst-content dl dt .headerlink,.rst-content dl dt .nav .headerlink,.nav .rst-content tt.download span:first-child,.rst-content tt.download .nav span:first-child,.nav .rst-content code.download span:first-child,.rst-content code.download .nav span:first-child,.nav .icon{display:inline}.btn .fa.fa-large,.btn .wy-menu-vertical li span.fa-large.toctree-expand,.wy-menu-vertical li .btn span.fa-large.toctree-expand,.btn .rst-content .fa-large.admonition-title,.rst-content .btn .fa-large.admonition-title,.btn .rst-content h1 .fa-large.headerlink,.rst-content h1 .btn .fa-large.headerlink,.btn .rst-content h2 .fa-large.headerlink,.rst-content h2 .btn .fa-large.headerlink,.btn .rst-content p.caption .fa-large.headerlink,.rst-content p.caption .btn .fa-large.headerlink,.btn .rst-content h3 .fa-large.headerlink,.rst-content h3 .btn .fa-large.headerlink,.btn .rst-content h4 .fa-large.headerlink,.rst-content h4 .btn .fa-large.headerlink,.btn .rst-content h5 .fa-large.headerlink,.rst-content h5 .btn .fa-large.headerlink,.btn .rst-content h6 .fa-large.headerlink,.rst-content h6 .btn .fa-large.headerlink,.btn .rst-content dl dt .fa-large.headerlink,.rst-content dl dt .btn .fa-large.headerlink,.btn .rst-content tt.download span.fa-large:first-child,.rst-content tt.download .btn span.fa-large:first-child,.btn .rst-content code.download span.fa-large:first-child,.rst-content code.download .btn span.fa-large:first-child,.btn .fa-large.icon,.nav .fa.fa-large,.nav .wy-menu-vertical li span.fa-large.toctree-expand,.wy-menu-vertical li .nav span.fa-large.toctree-expand,.nav .rst-content .fa-large.admonition-title,.rst-content .nav .fa-large.admonition-title,.nav .rst-content h1 .fa-large.headerlink,.rst-content h1 .nav .fa-large.headerlink,.nav .rst-content h2 .fa-large.headerlink,.rst-content h2 .nav .fa-large.headerlink,.nav .rst-content p.caption .fa-large.headerlink,.rst-content p.caption .nav .fa-large.headerlink,.nav .rst-content h3 .fa-large.headerlink,.rst-content h3 .nav .fa-large.headerlink,.nav .rst-content h4 .fa-large.headerlink,.rst-content h4 .nav .fa-large.headerlink,.nav .rst-content h5 .fa-large.headerlink,.rst-content h5 .nav .fa-large.headerlink,.nav .rst-content h6 .fa-large.headerlink,.rst-content h6 .nav .fa-large.headerlink,.nav .rst-content dl dt .fa-large.headerlink,.rst-content dl dt .nav .fa-large.headerlink,.nav .rst-content tt.download span.fa-large:first-child,.rst-content tt.download .nav span.fa-large:first-child,.nav .rst-content code.download span.fa-large:first-child,.rst-content code.download .nav span.fa-large:first-child,.nav .fa-large.icon{line-height:0.9em}.btn .fa.fa-spin,.btn .wy-menu-vertical li span.fa-spin.toctree-expand,.wy-menu-vertical li .btn span.fa-spin.toctree-expand,.btn .rst-content .fa-spin.admonition-title,.rst-content .btn .fa-spin.admonition-title,.btn .rst-content h1 .fa-spin.headerlink,.rst-content h1 .btn .fa-spin.headerlink,.btn .rst-content h2 .fa-spin.headerlink,.rst-content h2 .btn .fa-spin.headerlink,.btn .rst-content p.caption .fa-spin.headerlink,.rst-content p.caption .btn .fa-spin.headerlink,.btn .rst-content h3 .fa-spin.headerlink,.rst-content h3 .btn .fa-spin.headerlink,.btn .rst-content h4 .fa-spin.headerlink,.rst-content h4 .btn .fa-spin.headerlink,.btn .rst-content h5 .fa-spin.headerlink,.rst-content h5 .btn .fa-spin.headerlink,.btn .rst-content h6 .fa-spin.headerlink,.rst-content h6 .btn .fa-spin.headerlink,.btn .rst-content dl dt .fa-spin.headerlink,.rst-content dl dt .btn .fa-spin.headerlink,.btn .rst-content tt.download span.fa-spin:first-child,.rst-content tt.download .btn span.fa-spin:first-child,.btn .rst-content code.download span.fa-spin:first-child,.rst-content code.download .btn span.fa-spin:first-child,.btn .fa-spin.icon,.nav .fa.fa-spin,.nav .wy-menu-vertical li span.fa-spin.toctree-expand,.wy-menu-vertical li .nav span.fa-spin.toctree-expand,.nav .rst-content .fa-spin.admonition-title,.rst-content .nav .fa-spin.admonition-title,.nav .rst-content h1 .fa-spin.headerlink,.rst-content h1 .nav .fa-spin.headerlink,.nav .rst-content h2 .fa-spin.headerlink,.rst-content h2 .nav .fa-spin.headerlink,.nav .rst-content p.caption .fa-spin.headerlink,.rst-content p.caption .nav .fa-spin.headerlink,.nav .rst-content h3 .fa-spin.headerlink,.rst-content h3 .nav .fa-spin.headerlink,.nav .rst-content h4 .fa-spin.headerlink,.rst-content h4 .nav .fa-spin.headerlink,.nav .rst-content h5 .fa-spin.headerlink,.rst-content h5 .nav .fa-spin.headerlink,.nav .rst-content h6 .fa-spin.headerlink,.rst-content h6 .nav .fa-spin.headerlink,.nav .rst-content dl dt .fa-spin.headerlink,.rst-content dl dt .nav .fa-spin.headerlink,.nav .rst-content tt.download span.fa-spin:first-child,.rst-content tt.download .nav span.fa-spin:first-child,.nav .rst-content code.download span.fa-spin:first-child,.rst-content code.download .nav span.fa-spin:first-child,.nav .fa-spin.icon{display:inline-block}.btn.fa:before,.wy-menu-vertical li span.btn.toctree-expand:before,.rst-content .btn.admonition-title:before,.rst-content h1 .btn.headerlink:before,.rst-content h2 .btn.headerlink:before,.rst-content p.caption .btn.headerlink:before,.rst-content h3 .btn.headerlink:before,.rst-content h4 .btn.headerlink:before,.rst-content h5 .btn.headerlink:before,.rst-content h6 .btn.headerlink:before,.rst-content dl dt .btn.headerlink:before,.rst-content tt.download span.btn:first-child:before,.rst-content code.download span.btn:first-child:before,.btn.icon:before{opacity:0.5;-webkit-transition:opacity 0.05s ease-in;-moz-transition:opacity 0.05s ease-in;transition:opacity 0.05s ease-in}.btn.fa:hover:before,.wy-menu-vertical li span.btn.toctree-expand:hover:before,.rst-content .btn.admonition-title:hover:before,.rst-content h1 .btn.headerlink:hover:before,.rst-content h2 .btn.headerlink:hover:before,.rst-content p.caption .btn.headerlink:hover:before,.rst-content h3 .btn.headerlink:hover:before,.rst-content h4 .btn.headerlink:hover:before,.rst-content h5 .btn.headerlink:hover:before,.rst-content h6 .btn.headerlink:hover:before,.rst-content dl dt .btn.headerlink:hover:before,.rst-content tt.download span.btn:first-child:hover:before,.rst-content code.download span.btn:first-child:hover:before,.btn.icon:hover:before{opacity:1}.btn-mini .fa:before,.btn-mini .wy-menu-vertical li span.toctree-expand:before,.wy-menu-vertical li .btn-mini span.toctree-expand:before,.btn-mini .rst-content .admonition-title:before,.rst-content .btn-mini .admonition-title:before,.btn-mini .rst-content h1 .headerlink:before,.rst-content h1 .btn-mini .headerlink:before,.btn-mini .rst-content h2 .headerlink:before,.rst-content h2 .btn-mini .headerlink:before,.btn-mini .rst-content p.caption .headerlink:before,.rst-content p.caption .btn-mini .headerlink:before,.btn-mini .rst-content h3 .headerlink:before,.rst-content h3 .btn-mini .headerlink:before,.btn-mini .rst-content h4 .headerlink:before,.rst-content h4 .btn-mini .headerlink:before,.btn-mini .rst-content h5 .headerlink:before,.rst-content h5 .btn-mini .headerlink:before,.btn-mini .rst-content h6 .headerlink:before,.rst-content h6 .btn-mini .headerlink:before,.btn-mini .rst-content dl dt .headerlink:before,.rst-content dl dt .btn-mini .headerlink:before,.btn-mini .rst-content tt.download span:first-child:before,.rst-content tt.download .btn-mini span:first-child:before,.btn-mini .rst-content code.download span:first-child:before,.rst-content code.download .btn-mini span:first-child:before,.btn-mini .icon:before{font-size:14px;vertical-align:-15%}.wy-alert,.rst-content .note,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .warning,.rst-content .seealso,.rst-content .admonition-todo{padding:12px;line-height:24px;margin-bottom:24px;background:#e7f2fa}.wy-alert-title,.rst-content .admonition-title{color:#fff;font-weight:bold;display:block;color:#fff;background:#6ab0de;margin:-12px;padding:6px 12px;margin-bottom:12px}.wy-alert.wy-alert-danger,.rst-content .wy-alert-danger.note,.rst-content .wy-alert-danger.attention,.rst-content .wy-alert-danger.caution,.rst-content .danger,.rst-content .error,.rst-content .wy-alert-danger.hint,.rst-content .wy-alert-danger.important,.rst-content .wy-alert-danger.tip,.rst-content .wy-alert-danger.warning,.rst-content .wy-alert-danger.seealso,.rst-content .wy-alert-danger.admonition-todo{background:#fdf3f2}.wy-alert.wy-alert-danger .wy-alert-title,.rst-content .wy-alert-danger.note .wy-alert-title,.rst-content .wy-alert-danger.attention .wy-alert-title,.rst-content .wy-alert-danger.caution .wy-alert-title,.rst-content .danger .wy-alert-title,.rst-content .error .wy-alert-title,.rst-content .wy-alert-danger.hint .wy-alert-title,.rst-content .wy-alert-danger.important .wy-alert-title,.rst-content .wy-alert-danger.tip .wy-alert-title,.rst-content .wy-alert-danger.warning .wy-alert-title,.rst-content .wy-alert-danger.seealso .wy-alert-title,.rst-content .wy-alert-danger.admonition-todo .wy-alert-title,.wy-alert.wy-alert-danger .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-danger .admonition-title,.rst-content .wy-alert-danger.note .admonition-title,.rst-content .wy-alert-danger.attention .admonition-title,.rst-content .wy-alert-danger.caution .admonition-title,.rst-content .danger .admonition-title,.rst-content .error .admonition-title,.rst-content .wy-alert-danger.hint .admonition-title,.rst-content .wy-alert-danger.important .admonition-title,.rst-content .wy-alert-danger.tip .admonition-title,.rst-content .wy-alert-danger.warning .admonition-title,.rst-content .wy-alert-danger.seealso .admonition-title,.rst-content .wy-alert-danger.admonition-todo .admonition-title{background:#f29f97}.wy-alert.wy-alert-warning,.rst-content .wy-alert-warning.note,.rst-content .attention,.rst-content .caution,.rst-content .wy-alert-warning.danger,.rst-content .wy-alert-warning.error,.rst-content .wy-alert-warning.hint,.rst-content .wy-alert-warning.important,.rst-content .wy-alert-warning.tip,.rst-content .warning,.rst-content .wy-alert-warning.seealso,.rst-content .admonition-todo{background:#ffedcc}.wy-alert.wy-alert-warning .wy-alert-title,.rst-content .wy-alert-warning.note .wy-alert-title,.rst-content .attention .wy-alert-title,.rst-content .caution .wy-alert-title,.rst-content .wy-alert-warning.danger .wy-alert-title,.rst-content .wy-alert-warning.error .wy-alert-title,.rst-content .wy-alert-warning.hint .wy-alert-title,.rst-content .wy-alert-warning.important .wy-alert-title,.rst-content .wy-alert-warning.tip .wy-alert-title,.rst-content .warning .wy-alert-title,.rst-content .wy-alert-warning.seealso .wy-alert-title,.rst-content .admonition-todo .wy-alert-title,.wy-alert.wy-alert-warning .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-warning .admonition-title,.rst-content .wy-alert-warning.note .admonition-title,.rst-content .attention .admonition-title,.rst-content .caution .admonition-title,.rst-content .wy-alert-warning.danger .admonition-title,.rst-content .wy-alert-warning.error .admonition-title,.rst-content .wy-alert-warning.hint .admonition-title,.rst-content .wy-alert-warning.important .admonition-title,.rst-content .wy-alert-warning.tip .admonition-title,.rst-content .warning .admonition-title,.rst-content .wy-alert-warning.seealso .admonition-title,.rst-content .admonition-todo .admonition-title{background:#f0b37e}.wy-alert.wy-alert-info,.rst-content .note,.rst-content .wy-alert-info.attention,.rst-content .wy-alert-info.caution,.rst-content .wy-alert-info.danger,.rst-content .wy-alert-info.error,.rst-content .wy-alert-info.hint,.rst-content .wy-alert-info.important,.rst-content .wy-alert-info.tip,.rst-content .wy-alert-info.warning,.rst-content .seealso,.rst-content .wy-alert-info.admonition-todo{background:#e7f2fa}.wy-alert.wy-alert-info .wy-alert-title,.rst-content .note .wy-alert-title,.rst-content .wy-alert-info.attention .wy-alert-title,.rst-content .wy-alert-info.caution .wy-alert-title,.rst-content .wy-alert-info.danger .wy-alert-title,.rst-content .wy-alert-info.error .wy-alert-title,.rst-content .wy-alert-info.hint .wy-alert-title,.rst-content .wy-alert-info.important .wy-alert-title,.rst-content .wy-alert-info.tip .wy-alert-title,.rst-content .wy-alert-info.warning .wy-alert-title,.rst-content .seealso .wy-alert-title,.rst-content .wy-alert-info.admonition-todo .wy-alert-title,.wy-alert.wy-alert-info .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-info .admonition-title,.rst-content .note .admonition-title,.rst-content .wy-alert-info.attention .admonition-title,.rst-content .wy-alert-info.caution .admonition-title,.rst-content .wy-alert-info.danger .admonition-title,.rst-content .wy-alert-info.error .admonition-title,.rst-content .wy-alert-info.hint .admonition-title,.rst-content .wy-alert-info.important .admonition-title,.rst-content .wy-alert-info.tip .admonition-title,.rst-content .wy-alert-info.warning .admonition-title,.rst-content .seealso .admonition-title,.rst-content .wy-alert-info.admonition-todo .admonition-title{background:#6ab0de}.wy-alert.wy-alert-success,.rst-content .wy-alert-success.note,.rst-content .wy-alert-success.attention,.rst-content .wy-alert-success.caution,.rst-content .wy-alert-success.danger,.rst-content .wy-alert-success.error,.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .wy-alert-success.warning,.rst-content .wy-alert-success.seealso,.rst-content .wy-alert-success.admonition-todo{background:#dbfaf4}.wy-alert.wy-alert-success .wy-alert-title,.rst-content .wy-alert-success.note .wy-alert-title,.rst-content .wy-alert-success.attention .wy-alert-title,.rst-content .wy-alert-success.caution .wy-alert-title,.rst-content .wy-alert-success.danger .wy-alert-title,.rst-content .wy-alert-success.error .wy-alert-title,.rst-content .hint .wy-alert-title,.rst-content .important .wy-alert-title,.rst-content .tip .wy-alert-title,.rst-content .wy-alert-success.warning .wy-alert-title,.rst-content .wy-alert-success.seealso .wy-alert-title,.rst-content .wy-alert-success.admonition-todo .wy-alert-title,.wy-alert.wy-alert-success .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-success .admonition-title,.rst-content .wy-alert-success.note .admonition-title,.rst-content .wy-alert-success.attention .admonition-title,.rst-content .wy-alert-success.caution .admonition-title,.rst-content .wy-alert-success.danger .admonition-title,.rst-content .wy-alert-success.error .admonition-title,.rst-content .hint .admonition-title,.rst-content .important .admonition-title,.rst-content .tip .admonition-title,.rst-content .wy-alert-success.warning .admonition-title,.rst-content .wy-alert-success.seealso .admonition-title,.rst-content .wy-alert-success.admonition-todo .admonition-title{background:#1abc9c}.wy-alert.wy-alert-neutral,.rst-content .wy-alert-neutral.note,.rst-content .wy-alert-neutral.attention,.rst-content .wy-alert-neutral.caution,.rst-content .wy-alert-neutral.danger,.rst-content .wy-alert-neutral.error,.rst-content .wy-alert-neutral.hint,.rst-content .wy-alert-neutral.important,.rst-content .wy-alert-neutral.tip,.rst-content .wy-alert-neutral.warning,.rst-content .wy-alert-neutral.seealso,.rst-content .wy-alert-neutral.admonition-todo{background:#f3f6f6}.wy-alert.wy-alert-neutral .wy-alert-title,.rst-content .wy-alert-neutral.note .wy-alert-title,.rst-content .wy-alert-neutral.attention .wy-alert-title,.rst-content .wy-alert-neutral.caution .wy-alert-title,.rst-content .wy-alert-neutral.danger .wy-alert-title,.rst-content .wy-alert-neutral.error .wy-alert-title,.rst-content .wy-alert-neutral.hint .wy-alert-title,.rst-content .wy-alert-neutral.important .wy-alert-title,.rst-content .wy-alert-neutral.tip .wy-alert-title,.rst-content .wy-alert-neutral.warning .wy-alert-title,.rst-content .wy-alert-neutral.seealso .wy-alert-title,.rst-content .wy-alert-neutral.admonition-todo .wy-alert-title,.wy-alert.wy-alert-neutral .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-neutral .admonition-title,.rst-content .wy-alert-neutral.note .admonition-title,.rst-content .wy-alert-neutral.attention .admonition-title,.rst-content .wy-alert-neutral.caution .admonition-title,.rst-content .wy-alert-neutral.danger .admonition-title,.rst-content .wy-alert-neutral.error .admonition-title,.rst-content .wy-alert-neutral.hint .admonition-title,.rst-content .wy-alert-neutral.important .admonition-title,.rst-content .wy-alert-neutral.tip .admonition-title,.rst-content .wy-alert-neutral.warning .admonition-title,.rst-content .wy-alert-neutral.seealso .admonition-title,.rst-content .wy-alert-neutral.admonition-todo .admonition-title{color:#404040;background:#e1e4e5}.wy-alert.wy-alert-neutral a,.rst-content .wy-alert-neutral.note a,.rst-content .wy-alert-neutral.attention a,.rst-content .wy-alert-neutral.caution a,.rst-content .wy-alert-neutral.danger a,.rst-content .wy-alert-neutral.error a,.rst-content .wy-alert-neutral.hint a,.rst-content .wy-alert-neutral.important a,.rst-content .wy-alert-neutral.tip a,.rst-content .wy-alert-neutral.warning a,.rst-content .wy-alert-neutral.seealso a,.rst-content .wy-alert-neutral.admonition-todo a{color:#2980B9}.wy-alert p:last-child,.rst-content .note p:last-child,.rst-content .attention p:last-child,.rst-content .caution p:last-child,.rst-content .danger p:last-child,.rst-content .error p:last-child,.rst-content .hint p:last-child,.rst-content .important p:last-child,.rst-content .tip p:last-child,.rst-content .warning p:last-child,.rst-content .seealso p:last-child,.rst-content .admonition-todo p:last-child{margin-bottom:0}.wy-tray-container{position:fixed;bottom:0px;left:0;z-index:600}.wy-tray-container li{display:block;width:300px;background:transparent;color:#fff;text-align:center;box-shadow:0 5px 5px 0 rgba(0,0,0,0.1);padding:0 24px;min-width:20%;opacity:0;height:0;line-height:56px;overflow:hidden;-webkit-transition:all 0.3s ease-in;-moz-transition:all 0.3s ease-in;transition:all 0.3s ease-in}.wy-tray-container li.wy-tray-item-success{background:#27AE60}.wy-tray-container li.wy-tray-item-info{background:#2980B9}.wy-tray-container li.wy-tray-item-warning{background:#E67E22}.wy-tray-container li.wy-tray-item-danger{background:#E74C3C}.wy-tray-container li.on{opacity:1;height:56px}@media screen and (max-width: 768px){.wy-tray-container{bottom:auto;top:0;width:100%}.wy-tray-container li{width:100%}}button{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle;cursor:pointer;line-height:normal;-webkit-appearance:button;*overflow:visible}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}button[disabled]{cursor:default}.btn{display:inline-block;border-radius:2px;line-height:normal;white-space:nowrap;text-align:center;cursor:pointer;font-size:100%;padding:6px 12px 8px 12px;color:#fff;border:1px solid rgba(0,0,0,0.1);background-color:#27AE60;text-decoration:none;font-weight:normal;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;box-shadow:0px 1px 2px -1px rgba(255,255,255,0.5) inset,0px -2px 0px 0px rgba(0,0,0,0.1) inset;outline-none:false;vertical-align:middle;*display:inline;zoom:1;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transition:all 0.1s linear;-moz-transition:all 0.1s linear;transition:all 0.1s linear}.btn-hover{background:#2e8ece;color:#fff}.btn:hover{background:#2cc36b;color:#fff}.btn:focus{background:#2cc36b;outline:0}.btn:active{box-shadow:0px -1px 0px 0px rgba(0,0,0,0.05) inset,0px 2px 0px 0px rgba(0,0,0,0.1) inset;padding:8px 12px 6px 12px}.btn:visited{color:#fff}.btn:disabled{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:0.4;cursor:not-allowed;box-shadow:none}.btn-disabled{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:0.4;cursor:not-allowed;box-shadow:none}.btn-disabled:hover,.btn-disabled:focus,.btn-disabled:active{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:0.4;cursor:not-allowed;box-shadow:none}.btn::-moz-focus-inner{padding:0;border:0}.btn-small{font-size:80%}.btn-info{background-color:#2980B9 !important}.btn-info:hover{background-color:#2e8ece !important}.btn-neutral{background-color:#f3f6f6 !important;color:#404040 !important}.btn-neutral:hover{background-color:#e5ebeb !important;color:#404040}.btn-neutral:visited{color:#404040 !important}.btn-success{background-color:#27AE60 !important}.btn-success:hover{background-color:#295 !important}.btn-danger{background-color:#E74C3C !important}.btn-danger:hover{background-color:#ea6153 !important}.btn-warning{background-color:#E67E22 !important}.btn-warning:hover{background-color:#e98b39 !important}.btn-invert{background-color:#222}.btn-invert:hover{background-color:#2f2f2f !important}.btn-link{background-color:transparent !important;color:#2980B9;box-shadow:none;border-color:transparent !important}.btn-link:hover{background-color:transparent !important;color:#409ad5 !important;box-shadow:none}.btn-link:active{background-color:transparent !important;color:#409ad5 !important;box-shadow:none}.btn-link:visited{color:#9B59B6}.wy-btn-group .btn,.wy-control .btn{vertical-align:middle}.wy-btn-group{margin-bottom:24px;*zoom:1}.wy-btn-group:before,.wy-btn-group:after{display:table;content:""}.wy-btn-group:after{clear:both}.wy-dropdown{position:relative;display:inline-block}.wy-dropdown-active .wy-dropdown-menu{display:block}.wy-dropdown-menu{position:absolute;left:0;display:none;float:left;top:100%;min-width:100%;background:#fcfcfc;z-index:100;border:solid 1px #cfd7dd;box-shadow:0 2px 2px 0 rgba(0,0,0,0.1);padding:12px}.wy-dropdown-menu>dd>a{display:block;clear:both;color:#404040;white-space:nowrap;font-size:90%;padding:0 12px;cursor:pointer}.wy-dropdown-menu>dd>a:hover{background:#2980B9;color:#fff}.wy-dropdown-menu>dd.divider{border-top:solid 1px #cfd7dd;margin:6px 0}.wy-dropdown-menu>dd.search{padding-bottom:12px}.wy-dropdown-menu>dd.search input[type="search"]{width:100%}.wy-dropdown-menu>dd.call-to-action{background:#e3e3e3;text-transform:uppercase;font-weight:500;font-size:80%}.wy-dropdown-menu>dd.call-to-action:hover{background:#e3e3e3}.wy-dropdown-menu>dd.call-to-action .btn{color:#fff}.wy-dropdown.wy-dropdown-up .wy-dropdown-menu{bottom:100%;top:auto;left:auto;right:0}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu{background:#fcfcfc;margin-top:2px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a{padding:6px 12px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a:hover{background:#2980B9;color:#fff}.wy-dropdown.wy-dropdown-left .wy-dropdown-menu{right:0;left:auto;text-align:right}.wy-dropdown-arrow:before{content:" ";border-bottom:5px solid #f5f5f5;border-left:5px solid transparent;border-right:5px solid transparent;position:absolute;display:block;top:-4px;left:50%;margin-left:-3px}.wy-dropdown-arrow.wy-dropdown-arrow-left:before{left:11px}.wy-form-stacked select{display:block}.wy-form-aligned input,.wy-form-aligned textarea,.wy-form-aligned select,.wy-form-aligned .wy-help-inline,.wy-form-aligned label{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-form-aligned .wy-control-group>label{display:inline-block;vertical-align:middle;width:10em;margin:6px 12px 0 0;float:left}.wy-form-aligned .wy-control{float:left}.wy-form-aligned .wy-control label{display:block}.wy-form-aligned .wy-control select{margin-top:6px}fieldset{border:0;margin:0;padding:0}legend{display:block;width:100%;border:0;padding:0;white-space:normal;margin-bottom:24px;font-size:150%;*margin-left:-7px}label{display:block;margin:0 0 0.3125em 0;color:#333;font-size:90%}input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}.wy-control-group{margin-bottom:24px;*zoom:1;max-width:68em;margin-left:auto;margin-right:auto;*zoom:1}.wy-control-group:before,.wy-control-group:after{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group:before,.wy-control-group:after{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group.wy-control-group-required>label:after{content:" *";color:#E74C3C}.wy-control-group .wy-form-full,.wy-control-group .wy-form-halves,.wy-control-group .wy-form-thirds{padding-bottom:12px}.wy-control-group .wy-form-full select,.wy-control-group .wy-form-halves select,.wy-control-group .wy-form-thirds select{width:100%}.wy-control-group .wy-form-full input[type="text"],.wy-control-group .wy-form-full input[type="password"],.wy-control-group .wy-form-full input[type="email"],.wy-control-group .wy-form-full input[type="url"],.wy-control-group .wy-form-full input[type="date"],.wy-control-group .wy-form-full input[type="month"],.wy-control-group .wy-form-full input[type="time"],.wy-control-group .wy-form-full input[type="datetime"],.wy-control-group .wy-form-full input[type="datetime-local"],.wy-control-group .wy-form-full input[type="week"],.wy-control-group .wy-form-full input[type="number"],.wy-control-group .wy-form-full input[type="search"],.wy-control-group .wy-form-full input[type="tel"],.wy-control-group .wy-form-full input[type="color"],.wy-control-group .wy-form-halves input[type="text"],.wy-control-group .wy-form-halves input[type="password"],.wy-control-group .wy-form-halves input[type="email"],.wy-control-group .wy-form-halves input[type="url"],.wy-control-group .wy-form-halves input[type="date"],.wy-control-group .wy-form-halves input[type="month"],.wy-control-group .wy-form-halves input[type="time"],.wy-control-group .wy-form-halves input[type="datetime"],.wy-control-group .wy-form-halves input[type="datetime-local"],.wy-control-group .wy-form-halves input[type="week"],.wy-control-group .wy-form-halves input[type="number"],.wy-control-group .wy-form-halves input[type="search"],.wy-control-group .wy-form-halves input[type="tel"],.wy-control-group .wy-form-halves input[type="color"],.wy-control-group .wy-form-thirds input[type="text"],.wy-control-group .wy-form-thirds input[type="password"],.wy-control-group .wy-form-thirds input[type="email"],.wy-control-group .wy-form-thirds input[type="url"],.wy-control-group .wy-form-thirds input[type="date"],.wy-control-group .wy-form-thirds input[type="month"],.wy-control-group .wy-form-thirds input[type="time"],.wy-control-group .wy-form-thirds input[type="datetime"],.wy-control-group .wy-form-thirds input[type="datetime-local"],.wy-control-group .wy-form-thirds input[type="week"],.wy-control-group .wy-form-thirds input[type="number"],.wy-control-group .wy-form-thirds input[type="search"],.wy-control-group .wy-form-thirds input[type="tel"],.wy-control-group .wy-form-thirds input[type="color"]{width:100%}.wy-control-group .wy-form-full{float:left;display:block;margin-right:2.35765%;width:100%;margin-right:0}.wy-control-group .wy-form-full:last-child{margin-right:0}.wy-control-group .wy-form-halves{float:left;display:block;margin-right:2.35765%;width:48.82117%}.wy-control-group .wy-form-halves:last-child{margin-right:0}.wy-control-group .wy-form-halves:nth-of-type(2n){margin-right:0}.wy-control-group .wy-form-halves:nth-of-type(2n+1){clear:left}.wy-control-group .wy-form-thirds{float:left;display:block;margin-right:2.35765%;width:31.76157%}.wy-control-group .wy-form-thirds:last-child{margin-right:0}.wy-control-group .wy-form-thirds:nth-of-type(3n){margin-right:0}.wy-control-group .wy-form-thirds:nth-of-type(3n+1){clear:left}.wy-control-group.wy-control-group-no-input .wy-control{margin:6px 0 0 0;font-size:90%}.wy-control-no-input{display:inline-block;margin:6px 0 0 0;font-size:90%}.wy-control-group.fluid-input input[type="text"],.wy-control-group.fluid-input input[type="password"],.wy-control-group.fluid-input input[type="email"],.wy-control-group.fluid-input input[type="url"],.wy-control-group.fluid-input input[type="date"],.wy-control-group.fluid-input input[type="month"],.wy-control-group.fluid-input input[type="time"],.wy-control-group.fluid-input input[type="datetime"],.wy-control-group.fluid-input input[type="datetime-local"],.wy-control-group.fluid-input input[type="week"],.wy-control-group.fluid-input input[type="number"],.wy-control-group.fluid-input input[type="search"],.wy-control-group.fluid-input input[type="tel"],.wy-control-group.fluid-input input[type="color"]{width:100%}.wy-form-message-inline{display:inline-block;padding-left:0.3em;color:#666;vertical-align:middle;font-size:90%}.wy-form-message{display:block;color:#999;font-size:70%;margin-top:0.3125em;font-style:italic}.wy-form-message p{font-size:inherit;font-style:italic;margin-bottom:6px}.wy-form-message p:last-child{margin-bottom:0}input{line-height:normal}input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;*overflow:visible}input[type="text"],input[type="password"],input[type="email"],input[type="url"],input[type="date"],input[type="month"],input[type="time"],input[type="datetime"],input[type="datetime-local"],input[type="week"],input[type="number"],input[type="search"],input[type="tel"],input[type="color"]{-webkit-appearance:none;padding:6px;display:inline-block;border:1px solid #ccc;font-size:80%;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;box-shadow:inset 0 1px 3px #ddd;border-radius:0;-webkit-transition:border 0.3s linear;-moz-transition:border 0.3s linear;transition:border 0.3s linear}input[type="datetime-local"]{padding:0.34375em 0.625em}input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0;margin-right:0.3125em;*height:13px;*width:13px}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}input[type="text"]:focus,input[type="password"]:focus,input[type="email"]:focus,input[type="url"]:focus,input[type="date"]:focus,input[type="month"]:focus,input[type="time"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="week"]:focus,input[type="number"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="color"]:focus{outline:0;outline:thin dotted \9;border-color:#333}input.no-focus:focus{border-color:#ccc !important}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:1px auto #129FEA}input[type="text"][disabled],input[type="password"][disabled],input[type="email"][disabled],input[type="url"][disabled],input[type="date"][disabled],input[type="month"][disabled],input[type="time"][disabled],input[type="datetime"][disabled],input[type="datetime-local"][disabled],input[type="week"][disabled],input[type="number"][disabled],input[type="search"][disabled],input[type="tel"][disabled],input[type="color"][disabled]{cursor:not-allowed;background-color:#fafafa}input:focus:invalid,textarea:focus:invalid,select:focus:invalid{color:#E74C3C;border:1px solid #E74C3C}input:focus:invalid:focus,textarea:focus:invalid:focus,select:focus:invalid:focus{border-color:#E74C3C}input[type="file"]:focus:invalid:focus,input[type="radio"]:focus:invalid:focus,input[type="checkbox"]:focus:invalid:focus{outline-color:#E74C3C}input.wy-input-large{padding:12px;font-size:100%}textarea{overflow:auto;vertical-align:top;width:100%;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif}select,textarea{padding:0.5em 0.625em;display:inline-block;border:1px solid #ccc;font-size:80%;box-shadow:inset 0 1px 3px #ddd;-webkit-transition:border 0.3s linear;-moz-transition:border 0.3s linear;transition:border 0.3s linear}select{border:1px solid #ccc;background-color:#fff}select[multiple]{height:auto}select:focus,textarea:focus{outline:0}select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{cursor:not-allowed;background-color:#fafafa}input[type="radio"][disabled],input[type="checkbox"][disabled]{cursor:not-allowed}.wy-checkbox,.wy-radio{margin:6px 0;color:#404040;display:block}.wy-checkbox input,.wy-radio input{vertical-align:baseline}.wy-form-message-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-input-prefix,.wy-input-suffix{white-space:nowrap;padding:6px}.wy-input-prefix .wy-input-context,.wy-input-suffix .wy-input-context{line-height:27px;padding:0 8px;display:inline-block;font-size:80%;background-color:#f3f6f6;border:solid 1px #ccc;color:#999}.wy-input-suffix .wy-input-context{border-left:0}.wy-input-prefix .wy-input-context{border-right:0}.wy-switch{width:36px;height:12px;margin:12px 0;position:relative;border-radius:4px;background:#ccc;cursor:pointer;-webkit-transition:all 0.2s ease-in-out;-moz-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out}.wy-switch:before{position:absolute;content:"";display:block;width:18px;height:18px;border-radius:4px;background:#999;left:-3px;top:-3px;-webkit-transition:all 0.2s ease-in-out;-moz-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out}.wy-switch:after{content:"false";position:absolute;left:48px;display:block;font-size:12px;color:#ccc}.wy-switch.active{background:#1e8449}.wy-switch.active:before{left:24px;background:#27AE60}.wy-switch.active:after{content:"true"}.wy-switch.disabled,.wy-switch.active.disabled{cursor:not-allowed}.wy-control-group.wy-control-group-error .wy-form-message,.wy-control-group.wy-control-group-error>label{color:#E74C3C}.wy-control-group.wy-control-group-error input[type="text"],.wy-control-group.wy-control-group-error input[type="password"],.wy-control-group.wy-control-group-error input[type="email"],.wy-control-group.wy-control-group-error input[type="url"],.wy-control-group.wy-control-group-error input[type="date"],.wy-control-group.wy-control-group-error input[type="month"],.wy-control-group.wy-control-group-error input[type="time"],.wy-control-group.wy-control-group-error input[type="datetime"],.wy-control-group.wy-control-group-error input[type="datetime-local"],.wy-control-group.wy-control-group-error input[type="week"],.wy-control-group.wy-control-group-error input[type="number"],.wy-control-group.wy-control-group-error input[type="search"],.wy-control-group.wy-control-group-error input[type="tel"],.wy-control-group.wy-control-group-error input[type="color"]{border:solid 1px #E74C3C}.wy-control-group.wy-control-group-error textarea{border:solid 1px #E74C3C}.wy-inline-validate{white-space:nowrap}.wy-inline-validate .wy-input-context{padding:0.5em 0.625em;display:inline-block;font-size:80%}.wy-inline-validate.wy-inline-validate-success .wy-input-context{color:#27AE60}.wy-inline-validate.wy-inline-validate-danger .wy-input-context{color:#E74C3C}.wy-inline-validate.wy-inline-validate-warning .wy-input-context{color:#E67E22}.wy-inline-validate.wy-inline-validate-info .wy-input-context{color:#2980B9}.rotate-90{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.rotate-180{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.rotate-270{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.mirror{-webkit-transform:scaleX(-1);-moz-transform:scaleX(-1);-ms-transform:scaleX(-1);-o-transform:scaleX(-1);transform:scaleX(-1)}.mirror.rotate-90{-webkit-transform:scaleX(-1) rotate(90deg);-moz-transform:scaleX(-1) rotate(90deg);-ms-transform:scaleX(-1) rotate(90deg);-o-transform:scaleX(-1) rotate(90deg);transform:scaleX(-1) rotate(90deg)}.mirror.rotate-180{-webkit-transform:scaleX(-1) rotate(180deg);-moz-transform:scaleX(-1) rotate(180deg);-ms-transform:scaleX(-1) rotate(180deg);-o-transform:scaleX(-1) rotate(180deg);transform:scaleX(-1) rotate(180deg)}.mirror.rotate-270{-webkit-transform:scaleX(-1) rotate(270deg);-moz-transform:scaleX(-1) rotate(270deg);-ms-transform:scaleX(-1) rotate(270deg);-o-transform:scaleX(-1) rotate(270deg);transform:scaleX(-1) rotate(270deg)}@media only screen and (max-width: 480px){.wy-form button[type="submit"]{margin:0.7em 0 0}.wy-form input[type="text"],.wy-form input[type="password"],.wy-form input[type="email"],.wy-form input[type="url"],.wy-form input[type="date"],.wy-form input[type="month"],.wy-form input[type="time"],.wy-form input[type="datetime"],.wy-form input[type="datetime-local"],.wy-form input[type="week"],.wy-form input[type="number"],.wy-form input[type="search"],.wy-form input[type="tel"],.wy-form input[type="color"]{margin-bottom:0.3em;display:block}.wy-form label{margin-bottom:0.3em;display:block}.wy-form input[type="password"],.wy-form input[type="email"],.wy-form input[type="url"],.wy-form input[type="date"],.wy-form input[type="month"],.wy-form input[type="time"],.wy-form input[type="datetime"],.wy-form input[type="datetime-local"],.wy-form input[type="week"],.wy-form input[type="number"],.wy-form input[type="search"],.wy-form input[type="tel"],.wy-form input[type="color"]{margin-bottom:0}.wy-form-aligned .wy-control-group label{margin-bottom:0.3em;text-align:left;display:block;width:100%}.wy-form-aligned .wy-control{margin:1.5em 0 0 0}.wy-form .wy-help-inline,.wy-form-message-inline,.wy-form-message{display:block;font-size:80%;padding:6px 0}}@media screen and (max-width: 768px){.tablet-hide{display:none}}@media screen and (max-width: 480px){.mobile-hide{display:none}}.float-left{float:left}.float-right{float:right}.full-width{width:100%}.wy-table,.rst-content table.docutils,.rst-content table.field-list{border-collapse:collapse;border-spacing:0;empty-cells:show;margin-bottom:24px}.wy-table caption,.rst-content table.docutils caption,.rst-content table.field-list caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.wy-table td,.rst-content table.docutils td,.rst-content table.field-list td,.wy-table th,.rst-content table.docutils th,.rst-content table.field-list th{font-size:90%;margin:0;overflow:visible;padding:8px 16px}.wy-table td:first-child,.rst-content table.docutils td:first-child,.rst-content table.field-list td:first-child,.wy-table th:first-child,.rst-content table.docutils th:first-child,.rst-content table.field-list th:first-child{border-left-width:0}.wy-table thead,.rst-content table.docutils thead,.rst-content table.field-list thead{color:#000;text-align:left;vertical-align:bottom;white-space:nowrap}.wy-table thead th,.rst-content table.docutils thead th,.rst-content table.field-list thead th{font-weight:bold;border-bottom:solid 2px #e1e4e5}.wy-table td,.rst-content table.docutils td,.rst-content table.field-list td{background-color:transparent;vertical-align:middle}.wy-table td p,.rst-content table.docutils td p,.rst-content table.field-list td p{line-height:18px}.wy-table td p:last-child,.rst-content table.docutils td p:last-child,.rst-content table.field-list td p:last-child{margin-bottom:0}.wy-table .wy-table-cell-min,.rst-content table.docutils .wy-table-cell-min,.rst-content table.field-list .wy-table-cell-min{width:1%;padding-right:0}.wy-table .wy-table-cell-min input[type=checkbox],.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox],.wy-table .wy-table-cell-min input[type=checkbox],.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox]{margin:0}.wy-table-secondary{color:gray;font-size:90%}.wy-table-tertiary{color:gray;font-size:80%}.wy-table-odd td,.wy-table-striped tr:nth-child(2n-1) td,.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td{background-color:#f3f6f6}.wy-table-backed{background-color:#f3f6f6}.wy-table-bordered-all,.rst-content table.docutils{border:1px solid #e1e4e5}.wy-table-bordered-all td,.rst-content table.docutils td{border-bottom:1px solid #e1e4e5;border-left:1px solid #e1e4e5}.wy-table-bordered-all tbody>tr:last-child td,.rst-content table.docutils tbody>tr:last-child td{border-bottom-width:0}.wy-table-bordered{border:1px solid #e1e4e5}.wy-table-bordered-rows td{border-bottom:1px solid #e1e4e5}.wy-table-bordered-rows tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal td,.wy-table-horizontal th{border-width:0 0 1px 0;border-bottom:1px solid #e1e4e5}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-responsive{margin-bottom:24px;max-width:100%;overflow:auto}.wy-table-responsive table{margin-bottom:0 !important}.wy-table-responsive table td,.wy-table-responsive table th{white-space:nowrap}a{color:#2980B9;text-decoration:none;cursor:pointer}a:hover{color:#3091d1}a:visited{color:#9B59B6}html{height:100%;overflow-x:hidden}body{font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;font-weight:normal;color:#404040;min-height:100%;overflow-x:hidden;background:#edf0f2}.wy-text-left{text-align:left}.wy-text-center{text-align:center}.wy-text-right{text-align:right}.wy-text-large{font-size:120%}.wy-text-normal{font-size:100%}.wy-text-small,small{font-size:80%}.wy-text-strike{text-decoration:line-through}.wy-text-warning{color:#E67E22 !important}a.wy-text-warning:hover{color:#eb9950 !important}.wy-text-info{color:#2980B9 !important}a.wy-text-info:hover{color:#409ad5 !important}.wy-text-success{color:#27AE60 !important}a.wy-text-success:hover{color:#36d278 !important}.wy-text-danger{color:#E74C3C !important}a.wy-text-danger:hover{color:#ed7669 !important}.wy-text-neutral{color:#404040 !important}a.wy-text-neutral:hover{color:#595959 !important}h1,h2,.rst-content p.caption,h3,h4,h5,h6,legend{margin-top:0;font-weight:700;font-family:"Roboto Slab","ff-tisa-web-pro","Georgia",Arial,sans-serif}p{line-height:24px;margin:0;font-size:16px;margin-bottom:24px}h1{font-size:175%}h2,.rst-content p.caption{font-size:150%}h3{font-size:125%}h4{font-size:115%}h5{font-size:110%}h6{font-size:100%}hr{display:block;height:1px;border:0;border-top:1px solid #e1e4e5;margin:24px 0;padding:0}code,.rst-content tt,.rst-content code{white-space:nowrap;max-width:100%;background:#fff;border:solid 1px #e1e4e5;font-size:75%;padding:0 5px;font-family:Consolas,"Andale Mono WT","Andale Mono","Lucida Console","Lucida Sans Typewriter","DejaVu Sans Mono","Bitstream Vera Sans Mono","Liberation Mono","Nimbus Mono L",Monaco,"Courier New",Courier,monospace;color:#E74C3C;overflow-x:auto}code.code-large,.rst-content tt.code-large{font-size:90%}.wy-plain-list-disc,.rst-content .section ul,.rst-content .toctree-wrapper ul,article ul{list-style:disc;line-height:24px;margin-bottom:24px}.wy-plain-list-disc li,.rst-content .section ul li,.rst-content .toctree-wrapper ul li,article ul li{list-style:disc;margin-left:24px}.wy-plain-list-disc li p:last-child,.rst-content .section ul li p:last-child,.rst-content .toctree-wrapper ul li p:last-child,article ul li p:last-child{margin-bottom:0}.wy-plain-list-disc li ul,.rst-content .section ul li ul,.rst-content .toctree-wrapper ul li ul,article ul li ul{margin-bottom:0}.wy-plain-list-disc li li,.rst-content .section ul li li,.rst-content .toctree-wrapper ul li li,article ul li li{list-style:circle}.wy-plain-list-disc li li li,.rst-content .section ul li li li,.rst-content .toctree-wrapper ul li li li,article ul li li li{list-style:square}.wy-plain-list-disc li ol li,.rst-content .section ul li ol li,.rst-content .toctree-wrapper ul li ol li,article ul li ol li{list-style:decimal}.wy-plain-list-decimal,.rst-content .section ol,.rst-content ol.arabic,article ol{list-style:decimal;line-height:24px;margin-bottom:24px}.wy-plain-list-decimal li,.rst-content .section ol li,.rst-content ol.arabic li,article ol li{list-style:decimal;margin-left:24px}.wy-plain-list-decimal li p:last-child,.rst-content .section ol li p:last-child,.rst-content ol.arabic li p:last-child,article ol li p:last-child{margin-bottom:0}.wy-plain-list-decimal li ul,.rst-content .section ol li ul,.rst-content ol.arabic li ul,article ol li ul{margin-bottom:0}.wy-plain-list-decimal li ul li,.rst-content .section ol li ul li,.rst-content ol.arabic li ul li,article ol li ul li{list-style:disc}.codeblock-example{border:1px solid #e1e4e5;border-bottom:none;padding:24px;padding-top:48px;font-weight:500;background:#fff;position:relative}.codeblock-example:after{content:"Example";position:absolute;top:0px;left:0px;background:#9B59B6;color:#fff;padding:6px 12px}.codeblock-example.prettyprint-example-only{border:1px solid #e1e4e5;margin-bottom:24px}.codeblock,pre.literal-block,.rst-content .literal-block,.rst-content pre.literal-block,div[class^='highlight']{border:1px solid #e1e4e5;padding:0px;overflow-x:auto;background:#fff;margin:1px 0 24px 0}.codeblock div[class^='highlight'],pre.literal-block div[class^='highlight'],.rst-content .literal-block div[class^='highlight'],div[class^='highlight'] div[class^='highlight']{border:none;background:none;margin:0}div[class^='highlight'] td.code{width:100%}.linenodiv pre{border-right:solid 1px #e6e9ea;margin:0;padding:12px 12px;font-family:Consolas,"Andale Mono WT","Andale Mono","Lucida Console","Lucida Sans Typewriter","DejaVu Sans Mono","Bitstream Vera Sans Mono","Liberation Mono","Nimbus Mono L",Monaco,"Courier New",Courier,monospace;font-size:12px;line-height:1.5;color:#d9d9d9}div[class^='highlight'] pre{white-space:pre;margin:0;padding:12px 12px;font-family:Consolas,"Andale Mono WT","Andale Mono","Lucida Console","Lucida Sans Typewriter","DejaVu Sans Mono","Bitstream Vera Sans Mono","Liberation Mono","Nimbus Mono L",Monaco,"Courier New",Courier,monospace;font-size:12px;line-height:1.5;display:block;overflow:auto;color:#404040}@media print{.codeblock,pre.literal-block,.rst-content .literal-block,.rst-content pre.literal-block,div[class^='highlight'],div[class^='highlight'] pre{white-space:pre-wrap}}.hll{background-color:#ffc;margin:0 -12px;padding:0 12px;display:block}.c{color:#998;font-style:italic}.err{color:#a61717;background-color:#e3d2d2}.k{font-weight:bold}.o{font-weight:bold}.cm{color:#998;font-style:italic}.cp{color:#999;font-weight:bold}.c1{color:#998;font-style:italic}.cs{color:#999;font-weight:bold;font-style:italic}.gd{color:#000;background-color:#fdd}.gd .x{color:#000;background-color:#faa}.ge{font-style:italic}.gr{color:#a00}.gh{color:#999}.gi{color:#000;background-color:#dfd}.gi .x{color:#000;background-color:#afa}.go{color:#888}.gp{color:#555}.gs{font-weight:bold}.gu{color:purple;font-weight:bold}.gt{color:#a00}.kc{font-weight:bold}.kd{font-weight:bold}.kn{font-weight:bold}.kp{font-weight:bold}.kr{font-weight:bold}.kt{color:#458;font-weight:bold}.m{color:#099}.s{color:#d14}.n{color:#333}.na{color:teal}.nb{color:#0086b3}.nc{color:#458;font-weight:bold}.no{color:teal}.ni{color:purple}.ne{color:#900;font-weight:bold}.nf{color:#900;font-weight:bold}.nn{color:#555}.nt{color:navy}.nv{color:teal}.ow{font-weight:bold}.w{color:#bbb}.mf{color:#099}.mh{color:#099}.mi{color:#099}.mo{color:#099}.sb{color:#d14}.sc{color:#d14}.sd{color:#d14}.s2{color:#d14}.se{color:#d14}.sh{color:#d14}.si{color:#d14}.sx{color:#d14}.sr{color:#009926}.s1{color:#d14}.ss{color:#990073}.bp{color:#999}.vc{color:teal}.vg{color:teal}.vi{color:teal}.il{color:#099}.gc{color:#999;background-color:#EAF2F5}.wy-breadcrumbs li{display:inline-block}.wy-breadcrumbs li.wy-breadcrumbs-aside{float:right}.wy-breadcrumbs li a{display:inline-block;padding:5px}.wy-breadcrumbs li a:first-child{padding-left:0}.wy-breadcrumbs-extra{margin-bottom:0;color:#b3b3b3;font-size:80%;display:inline-block}@media screen and (max-width: 480px){.wy-breadcrumbs-extra{display:none}.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}@media print{.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}.wy-affix{position:fixed;top:1.618em}.wy-menu a:hover{text-decoration:none}.wy-menu-horiz{*zoom:1}.wy-menu-horiz:before,.wy-menu-horiz:after{display:table;content:""}.wy-menu-horiz:after{clear:both}.wy-menu-horiz ul,.wy-menu-horiz li{display:inline-block}.wy-menu-horiz li:hover{background:rgba(255,255,255,0.1)}.wy-menu-horiz li.divide-left{border-left:solid 1px #404040}.wy-menu-horiz li.divide-right{border-right:solid 1px #404040}.wy-menu-horiz a{height:32px;display:inline-block;line-height:32px;padding:0 16px}.wy-menu-vertical header,.wy-menu-vertical p.caption{height:32px;display:inline-block;line-height:32px;padding:0 1.618em;margin-bottom:0;display:block;font-weight:bold;text-transform:uppercase;font-size:80%;color:#555;white-space:nowrap}.wy-menu-vertical ul{margin-bottom:0}.wy-menu-vertical li.divide-top{border-top:solid 1px #404040}.wy-menu-vertical li.divide-bottom{border-bottom:solid 1px #404040}.wy-menu-vertical li.current{background:#e3e3e3}.wy-menu-vertical li.current a{color:gray;border-right:solid 1px #c9c9c9;padding:0.4045em 2.427em}.wy-menu-vertical li.current a:hover{background:#d6d6d6}.wy-menu-vertical li code,.wy-menu-vertical li .rst-content tt,.rst-content .wy-menu-vertical li tt{border:none;background:inherit;color:inherit;padding-left:0;padding-right:0}.wy-menu-vertical li span.toctree-expand{display:block;float:left;margin-left:-1.2em;font-size:0.8em;line-height:1.6em;color:#4d4d4d}.wy-menu-vertical li.on a,.wy-menu-vertical li.current>a{color:#404040;padding:0.4045em 1.618em;font-weight:bold;position:relative;background:#fcfcfc;border:none;border-bottom:solid 1px #c9c9c9;border-top:solid 1px #c9c9c9;padding-left:1.618em -4px}.wy-menu-vertical li.on a:hover,.wy-menu-vertical li.current>a:hover{background:#fcfcfc}.wy-menu-vertical li.on a:hover span.toctree-expand,.wy-menu-vertical li.current>a:hover span.toctree-expand{color:gray}.wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.current>a span.toctree-expand{display:block;font-size:0.8em;line-height:1.6em;color:#333}.wy-menu-vertical li.toctree-l1.current li.toctree-l2>ul,.wy-menu-vertical li.toctree-l2.current li.toctree-l3>ul{display:none}.wy-menu-vertical li.toctree-l1.current li.toctree-l2.current>ul,.wy-menu-vertical li.toctree-l2.current li.toctree-l3.current>ul{display:block}.wy-menu-vertical li.toctree-l2.current>a{background:#c9c9c9;padding:0.4045em 2.427em}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{display:block;background:#c9c9c9;padding:0.4045em 4.045em}.wy-menu-vertical li.toctree-l2 a:hover span.toctree-expand{color:gray}.wy-menu-vertical li.toctree-l2 span.toctree-expand{color:#a3a3a3}.wy-menu-vertical li.toctree-l3{font-size:0.9em}.wy-menu-vertical li.toctree-l3.current>a{background:#bdbdbd;padding:0.4045em 4.045em}.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{display:block;background:#bdbdbd;padding:0.4045em 5.663em;border-top:none;border-bottom:none}.wy-menu-vertical li.toctree-l3 a:hover span.toctree-expand{color:gray}.wy-menu-vertical li.toctree-l3 span.toctree-expand{color:#969696}.wy-menu-vertical li.toctree-l4{font-size:0.9em}.wy-menu-vertical li.current ul{display:block}.wy-menu-vertical li ul{margin-bottom:0;display:none}.wy-menu-vertical .local-toc li ul{display:block}.wy-menu-vertical li ul li a{margin-bottom:0;color:#b3b3b3;font-weight:normal}.wy-menu-vertical a{display:inline-block;line-height:18px;padding:0.4045em 1.618em;display:block;position:relative;font-size:90%;color:#b3b3b3}.wy-menu-vertical a:hover{background-color:#4e4a4a;cursor:pointer}.wy-menu-vertical a:hover span.toctree-expand{color:#b3b3b3}.wy-menu-vertical a:active{background-color:#2980B9;cursor:pointer;color:#fff}.wy-menu-vertical a:active span.toctree-expand{color:#fff}.wy-side-nav-search{z-index:200;background-color:#2980B9;text-align:center;padding:0.809em;display:block;color:#fcfcfc;margin-bottom:0.809em}.wy-side-nav-search input[type=text]{width:100%;border-radius:50px;padding:6px 12px;border-color:#2472a4}.wy-side-nav-search img{display:block;margin:auto auto 0.809em auto;height:45px;width:45px;background-color:#2980B9;padding:5px;border-radius:100%}.wy-side-nav-search>a,.wy-side-nav-search .wy-dropdown>a{color:#fcfcfc;font-size:100%;font-weight:bold;display:inline-block;padding:4px 6px;margin-bottom:0.809em}.wy-side-nav-search>a:hover,.wy-side-nav-search .wy-dropdown>a:hover{background:rgba(255,255,255,0.1)}.wy-side-nav-search>a img.logo,.wy-side-nav-search .wy-dropdown>a img.logo{display:block;margin:0 auto;height:auto;width:auto;border-radius:0;max-width:100%;background:transparent}.wy-side-nav-search>a.icon img.logo,.wy-side-nav-search .wy-dropdown>a.icon img.logo{margin-top:0.85em}.wy-nav .wy-menu-vertical header{color:#2980B9}.wy-nav .wy-menu-vertical a{color:#b3b3b3}.wy-nav .wy-menu-vertical a:hover{background-color:#2980B9;color:#fff}[data-menu-wrap]{-webkit-transition:all 0.2s ease-in;-moz-transition:all 0.2s ease-in;transition:all 0.2s ease-in;position:absolute;opacity:1;width:100%;opacity:0}[data-menu-wrap].move-center{left:0;right:auto;opacity:1}[data-menu-wrap].move-left{right:auto;left:-100%;opacity:0}[data-menu-wrap].move-right{right:-100%;left:auto;opacity:0}.wy-body-for-nav{background:left repeat-y #fcfcfc;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoxOERBMTRGRDBFMUUxMUUzODUwMkJCOThDMEVFNURFMCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDoxOERBMTRGRTBFMUUxMUUzODUwMkJCOThDMEVFNURFMCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjE4REExNEZCMEUxRTExRTM4NTAyQkI5OEMwRUU1REUwIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjE4REExNEZDMEUxRTExRTM4NTAyQkI5OEMwRUU1REUwIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+EwrlwAAAAA5JREFUeNpiMDU0BAgwAAE2AJgB9BnaAAAAAElFTkSuQmCC);background-size:300px 1px}.wy-grid-for-nav{position:absolute;width:100%;height:100%}.wy-nav-side{position:fixed;top:0;bottom:0;left:0;padding-bottom:2em;width:300px;overflow-x:hidden;overflow-y:scroll;min-height:100%;background:#343131;z-index:200}.wy-nav-top{display:none;background:#2980B9;color:#fff;padding:0.4045em 0.809em;position:relative;line-height:50px;text-align:center;font-size:100%;*zoom:1}.wy-nav-top:before,.wy-nav-top:after{display:table;content:""}.wy-nav-top:after{clear:both}.wy-nav-top a{color:#fff;font-weight:bold}.wy-nav-top img{margin-right:12px;height:45px;width:45px;background-color:#2980B9;padding:5px;border-radius:100%}.wy-nav-top i{font-size:30px;float:left;cursor:pointer}.wy-nav-content-wrap{margin-left:300px;background:#fcfcfc;min-height:100%}.wy-nav-content{padding:1.618em 3.236em;height:100%;max-width:800px;margin:auto}.wy-body-mask{position:fixed;width:100%;height:100%;background:rgba(0,0,0,0.2);display:none;z-index:499}.wy-body-mask.on{display:block}footer{color:#999}footer p{margin-bottom:12px}.rst-footer-buttons{*zoom:1}.rst-footer-buttons:before,.rst-footer-buttons:after{display:table;content:""}.rst-footer-buttons:after{clear:both}#search-results .search li{margin-bottom:24px;border-bottom:solid 1px #e1e4e5;padding-bottom:24px}#search-results .search li:first-child{border-top:solid 1px #e1e4e5;padding-top:24px}#search-results .search li a{font-size:120%;margin-bottom:12px;display:inline-block}#search-results .context{color:gray;font-size:90%}@media screen and (max-width: 768px){.wy-body-for-nav{background:#fcfcfc}.wy-nav-top{display:block}.wy-nav-side{left:-300px}.wy-nav-side.shift{width:85%;left:0}.wy-nav-content-wrap{margin-left:0}.wy-nav-content-wrap .wy-nav-content{padding:1.618em}.wy-nav-content-wrap.shift{position:fixed;min-width:100%;left:85%;top:0;height:100%;overflow:hidden}}@media screen and (min-width: 1400px){.wy-nav-content-wrap{background:rgba(0,0,0,0.05)}.wy-nav-content{margin:0;background:#fcfcfc}}@media print{.rst-versions,footer,.wy-nav-side{display:none}.wy-nav-content-wrap{margin-left:0}}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;border-top:solid 10px #343131;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;z-index:400}.rst-versions a{color:#2980B9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27AE60;*zoom:1}.rst-versions .rst-current-version:before,.rst-versions .rst-current-version:after{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-versions .rst-current-version .fa,.rst-versions .rst-current-version .wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li .rst-versions .rst-current-version span.toctree-expand,.rst-versions .rst-current-version .rst-content .admonition-title,.rst-content .rst-versions .rst-current-version .admonition-title,.rst-versions .rst-current-version .rst-content h1 .headerlink,.rst-content h1 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h2 .headerlink,.rst-content h2 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content p.caption .headerlink,.rst-content p.caption .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h3 .headerlink,.rst-content h3 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h4 .headerlink,.rst-content h4 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h5 .headerlink,.rst-content h5 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h6 .headerlink,.rst-content h6 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content dl dt .headerlink,.rst-content dl dt .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content tt.download span:first-child,.rst-content tt.download .rst-versions .rst-current-version span:first-child,.rst-versions .rst-current-version .rst-content code.download span:first-child,.rst-content code.download .rst-versions .rst-current-version span:first-child,.rst-versions .rst-current-version .icon{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#E74C3C;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#F1C40F;color:#000}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:gray;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:solid 1px #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px}.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge .rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width: 768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}img{width:100%;height:auto}}.rst-content img{max-width:100%;height:auto !important}.rst-content div.figure{margin-bottom:24px}.rst-content div.figure.align-center{text-align:center}.rst-content .section>img,.rst-content .section>a>img{margin-bottom:24px}.rst-content blockquote{margin-left:24px;line-height:24px;margin-bottom:24px}.rst-content .note .last,.rst-content .attention .last,.rst-content .caution .last,.rst-content .danger .last,.rst-content .error .last,.rst-content .hint .last,.rst-content .important .last,.rst-content .tip .last,.rst-content .warning .last,.rst-content .seealso .last,.rst-content .admonition-todo .last{margin-bottom:0}.rst-content .admonition-title:before{margin-right:4px}.rst-content .admonition table{border-color:rgba(0,0,0,0.1)}.rst-content .admonition table td,.rst-content .admonition table th{background:transparent !important;border-color:rgba(0,0,0,0.1) !important}.rst-content .section ol.loweralpha,.rst-content .section ol.loweralpha li{list-style:lower-alpha}.rst-content .section ol.upperalpha,.rst-content .section ol.upperalpha li{list-style:upper-alpha}.rst-content .section ol p,.rst-content .section ul p{margin-bottom:12px}.rst-content .line-block{margin-left:24px}.rst-content .topic-title{font-weight:bold;margin-bottom:12px}.rst-content .toc-backref{color:#404040}.rst-content .align-right{float:right;margin:0px 0px 24px 24px}.rst-content .align-left{float:left;margin:0px 24px 24px 0px}.rst-content .align-center{margin:auto;display:block}.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content p.caption .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content dl dt .headerlink,.rst-content p.caption .headerlink{display:none;visibility:hidden;font-size:14px}.rst-content h1 .headerlink:after,.rst-content h2 .headerlink:after,.rst-content p.caption .headerlink:after,.rst-content h3 .headerlink:after,.rst-content h4 .headerlink:after,.rst-content h5 .headerlink:after,.rst-content h6 .headerlink:after,.rst-content dl dt .headerlink:after,.rst-content p.caption .headerlink:after{visibility:visible;content:"";font-family:FontAwesome;display:inline-block}.rst-content h1:hover .headerlink,.rst-content h2:hover .headerlink,.rst-content p.caption:hover .headerlink,.rst-content h3:hover .headerlink,.rst-content h4:hover .headerlink,.rst-content h5:hover .headerlink,.rst-content h6:hover .headerlink,.rst-content dl dt:hover .headerlink,.rst-content p.caption:hover .headerlink{display:inline-block}.rst-content .sidebar{float:right;width:40%;display:block;margin:0 0 24px 24px;padding:24px;background:#f3f6f6;border:solid 1px #e1e4e5}.rst-content .sidebar p,.rst-content .sidebar ul,.rst-content .sidebar dl{font-size:90%}.rst-content .sidebar .last{margin-bottom:0}.rst-content .sidebar .sidebar-title{display:block;font-family:"Roboto Slab","ff-tisa-web-pro","Georgia",Arial,sans-serif;font-weight:bold;background:#e1e4e5;padding:6px 12px;margin:-24px;margin-bottom:24px;font-size:100%}.rst-content .highlighted{background:#F1C40F;display:inline-block;font-weight:bold;padding:0 6px}.rst-content .footnote-reference,.rst-content .citation-reference{vertical-align:super;font-size:90%}.rst-content table.docutils.citation,.rst-content table.docutils.footnote{background:none;border:none;color:#999}.rst-content table.docutils.citation td,.rst-content table.docutils.citation tr,.rst-content table.docutils.footnote td,.rst-content table.docutils.footnote tr{border:none;background-color:transparent !important;white-space:normal}.rst-content table.docutils.citation td.label,.rst-content table.docutils.footnote td.label{padding-left:0;padding-right:0;vertical-align:top}.rst-content table.field-list{border:none}.rst-content table.field-list td{border:none;padding-top:5px}.rst-content table.field-list td>strong{display:inline-block;margin-top:3px}.rst-content table.field-list .field-name{padding-right:10px;text-align:left;white-space:nowrap}.rst-content table.field-list .field-body{text-align:left;padding-left:0}.rst-content tt,.rst-content tt,.rst-content code{color:#000}.rst-content tt big,.rst-content tt em,.rst-content tt big,.rst-content code big,.rst-content tt em,.rst-content code em{font-size:100% !important;line-height:normal}.rst-content tt .xref,a .rst-content tt,.rst-content tt .xref,.rst-content code .xref,a .rst-content tt,a .rst-content code{font-weight:bold}.rst-content a tt,.rst-content a tt,.rst-content a code{color:#2980B9}.rst-content dl{margin-bottom:24px}.rst-content dl dt{font-weight:bold}.rst-content dl p,.rst-content dl table,.rst-content dl ul,.rst-content dl ol{margin-bottom:12px !important}.rst-content dl dd{margin:0 0 12px 24px}.rst-content dl:not(.docutils){margin-bottom:24px}.rst-content dl:not(.docutils) dt{display:inline-block;margin:6px 0;font-size:90%;line-height:normal;background:#e7f2fa;color:#2980B9;border-top:solid 3px #6ab0de;padding:6px;position:relative}.rst-content dl:not(.docutils) dt:before{color:#6ab0de}.rst-content dl:not(.docutils) dt .headerlink{color:#404040;font-size:100% !important}.rst-content dl:not(.docutils) dl dt{margin-bottom:6px;border:none;border-left:solid 3px #ccc;background:#f0f0f0;color:gray}.rst-content dl:not(.docutils) dl dt .headerlink{color:#404040;font-size:100% !important}.rst-content dl:not(.docutils) dt:first-child{margin-top:0}.rst-content dl:not(.docutils) tt,.rst-content dl:not(.docutils) tt,.rst-content dl:not(.docutils) code{font-weight:bold}.rst-content dl:not(.docutils) tt.descname,.rst-content dl:not(.docutils) tt.descclassname,.rst-content dl:not(.docutils) tt.descname,.rst-content dl:not(.docutils) code.descname,.rst-content dl:not(.docutils) tt.descclassname,.rst-content dl:not(.docutils) code.descclassname{background-color:transparent;border:none;padding:0;font-size:100% !important}.rst-content dl:not(.docutils) tt.descname,.rst-content dl:not(.docutils) tt.descname,.rst-content dl:not(.docutils) code.descname{font-weight:bold}.rst-content dl:not(.docutils) .optional{display:inline-block;padding:0 4px;color:#000;font-weight:bold}.rst-content dl:not(.docutils) .property{display:inline-block;padding-right:8px}.rst-content .viewcode-link,.rst-content .viewcode-back{display:inline-block;color:#27AE60;font-size:80%;padding-left:24px}.rst-content .viewcode-back{display:block;float:right}.rst-content p.rubric{margin-bottom:12px;font-weight:bold}.rst-content tt.download,.rst-content code.download{background:inherit;padding:inherit;font-family:inherit;font-size:inherit;color:inherit;border:inherit;white-space:inherit}.rst-content tt.download span:first-child:before,.rst-content code.download span:first-child:before{margin-right:4px}@media screen and (max-width: 480px){.rst-content .sidebar{width:100%}}span[id*='MathJax-Span']{color:#404040}.math{text-align:center}@font-face{font-family:"Inconsolata";font-style:normal;font-weight:400;src:local("Inconsolata"),url(../fonts/Inconsolata.ttf) format("truetype")}@font-face{font-family:"Inconsolata";font-style:normal;font-weight:700;src:local("Inconsolata Bold"),local("Inconsolata-Bold"),url(../fonts/Inconsolata-Bold.ttf) format("truetype")}@font-face{font-family:"Lato";font-style:normal;font-weight:400;src:local("Lato Regular"),local("Lato-Regular"),url(../fonts/Lato-Regular.ttf) format("truetype")}@font-face{font-family:"Lato";font-style:normal;font-weight:700;src:local("Lato Bold"),local("Lato-Bold"),url(../fonts/Lato-Bold.ttf) format("truetype")}@font-face{font-family:"Roboto Slab";font-style:normal;font-weight:400;src:local("Roboto Slab Regular"),local("RobotoSlab-Regular"),url(../fonts/RobotoSlab-Regular.ttf) format("truetype")}@font-face{font-family:"Roboto Slab";font-style:normal;font-weight:700;src:local("Roboto Slab Bold"),local("RobotoSlab-Bold"),url(../fonts/RobotoSlab-Bold.ttf) format("truetype")} +/*# sourceMappingURL=theme.css.map */ diff --git a/docsrc/exts/themes/sphinx_rtd_theme/static/fonts/Inconsolata-Bold.ttf b/docsrc/exts/themes/sphinx_rtd_theme/static/fonts/Inconsolata-Bold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..360a232dd09e43114a50814b999f67351cdf9a24 GIT binary patch literal 47064 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 literal 0 HcmV?d00001 diff --git a/docsrc/exts/themes/sphinx_rtd_theme/static/fonts/Inconsolata.ttf b/docsrc/exts/themes/sphinx_rtd_theme/static/fonts/Inconsolata.ttf new file mode 100644 index 0000000000000000000000000000000000000000..4b8a36d249a05a0fe1575dc3d96ef7079dba6b07 GIT binary patch literal 63184 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 literal 0 HcmV?d00001 diff --git a/docsrc/exts/themes/sphinx_rtd_theme/static/fonts/Lato-Bold.ttf b/docsrc/exts/themes/sphinx_rtd_theme/static/fonts/Lato-Bold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..e8b9bf6a20e1f67fd0e8b42b25e3f0e627babe39 GIT binary patch literal 82368 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 WwHG^1yNvPL2mL_!h-%}4hyNEi*y0iZ literal 0 HcmV?d00001 diff --git a/docsrc/exts/themes/sphinx_rtd_theme/static/fonts/Lato-Regular.ttf b/docsrc/exts/themes/sphinx_rtd_theme/static/fonts/Lato-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..7608bc3e0fd03fc3cf3a41501ed9c1b49b773ac4 GIT binary patch literal 81980 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 literal 0 HcmV?d00001 diff --git a/docsrc/exts/themes/sphinx_rtd_theme/static/fonts/RobotoSlab-Bold.ttf b/docsrc/exts/themes/sphinx_rtd_theme/static/fonts/RobotoSlab-Bold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..e6ed0de530e99cc8c0ef6e4a20012ed1533b62d1 GIT binary patch literal 36596 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
    V$fDV|Iw z-#ZH8@kAo&8X6qN(~8+vauls2VmxK&6M~O83OR_xEJ{?4GZ$vqTJvKqld>-g({5yZ zQg}d+aKr=sA0y&0N0jUP@W+l-E-5LOEh#@sE>(PF$z%fAxLms77r=&*IN+7kRQjJx z7)f!ZSVPr=oSQMt$IFbh6K+)1sO%~!q*8%5&`OO;C2axw!GSS%A17;M5BiZ$*&=OG zjlEmuazo|%&rG?fTpW)wL%EL1HO5Xj3qM@G?|$?Ia#QdID%V)M;Z(V-WNSazpDuAo zHTG^?uBp_uOqiK9ti6udyQbH z7slF&%5}!-jR)gpd5^eM8FuGfZ$cd@efF?^Lw`DUW0CO< z^$j>Hd(ZFP3C{Gk$vvk6Efc0^$@ly>ULd&WOz#BWvl88NW3HUvv+?Q5Gc;$~uPn=r zRWhFHXdVQUGplXawtz_97=lfQ!*~!=X3>XZ6lF>zFbX>YGXRsEBW)b6aADX4IvG0s5>sZmuo|SX_=VFgY zV_N(u-2z%#Zmb-B-g06b7?drNJw-C{joCo5W2p0LD$Jl_=S=P&;L@j0r`WK(^o0Q(Z3C5IKRtzxnfznlS04*>PKd z>}{z%K={em^tQxucw7^D?Ay>{)pXE~wjeP=5t?Q8z zJ?pT`p3G+PRfp?J27A`gi8CC4alCt74@_cLKbiUtuR_AFeEJyssWHo~gL!HWlJ&?u zollK)_7iAoRKeEufCMi084fVXRD5KK0V(kr_EUKnv`I=y8L5J-C%uhWn$t$pYh7_C+bU;?Rl}hhR*GXFEt3B#)5( zI<$56?5(qlZAhas}%!{evS#;{97qv0-Eui-TYy^&?TElbwldixSgj4M$h z))~UC;YHID_Z_%umAmCCM|jOW zt8cvfroAigSsiv<1^RntcXrMm{<-ADmk&V zWm(&{*FHTubN;5~(`S2KGp8-zG;hYh@bAcq-$Htv!(Yi+M_ZYJ38~(xc+P!{iD^fX zG7Um4Gl;XlK&=eOhgz6``+}(79T{0Lq^PnvHmCe@5s$ak z!hIDvl`L6km;NY3n0U#e0uT^RU5#y{G7cjyG@vRDvh^Y959NnCP9?MDMw(nQdY(lO z&-a!WOE=pL-il(d+VaFet}4esV`TgfTN;+Ydf_?YzD^QH9u}La9 z7DndQ0+W{?`&1hG^w@H=1k9($J{U>n{_>?a-E=9s0lH1k(xp9io1qH4nn%u+lJI5A zbGJdm^N8{8(0tBLH?11J8i!l&grw2-qYI=-Jp zgc%W^kp~N ziT?%F2@MCR93o!O(W+_qW?c5UGb{)RpTQsdsj(kgSKrtF9SVzwIBJVf# z#i(7<7#ryYkQeFy(f~QnfOBgx1=|pL5RHFj5jvi>%~_~2YA%+}GO<0pk>nZ>+ygMe z1(^2qWitP8peU0?#)y%y)l4=V8r%~P?4Q}X?Ec>4AAEH(cEQqEtgxbf>#2*pMZ^hK z-GKuht5K;_cj<$>2QZ-zBD#qr}X9&8x&Y(lUL_<7S3-_Dnvj0z-uy>HwRi` z;yMj$5KK6)DN}bA_24q9hMGWaz~3Rqo1-H6MeD%`8Y-2jIn1O|Rx_#>I*96Ow*3EU z7CL_7#g`v{=*_q3kN$qMNo4D^HDbtK;jOS(?c(wit3^{;_15DL?5}j+bn2o1QCmS< z(s1E3ec;jO6_-4_R;qh?Q{^D1qzgG4FLG*zq5s?vQF14Zkbice;<+;L+5fB|u`LP7 zCB$Cf!+Bw&>;)FnNEa;Z9?O8BVk!mQ5b=)Ec+@H#+iD_J=4BP)K3sYFMt&CaDS3W9 zl8pFK<}`~*iDq<6n1(?DF!c49#e^%zvaYG%c&Oq)?3(P@AR0f*a-ILVBjfJ9k> z&LfN4MWsP$qbPD(PkE$}Q zgaZjPAVo0&5|Y40)(M!q0g&!!cOGp7ElnEmm2~r5)?zhUrB z#C+q}A(=C#2oQspoH&&k=gfHQLt-%-N$&tIqNU3J;nT9pT3Z1JJNG4KRn#Jtw6-F> zh%Sq@O(_c+$)=55!aPkD6UlF1?Sca7ypWzI=0>EC_5EEdiwd)N@_EbMAC0LZECcbta4B*30Mi_35;wu$smZ4!_cUJqxWN& zdGJRPn1N=yj zna!UAqhqGy#==7BGr?;HJ+o7{d@g;S1`7fL+9y4l#sdP=%<#Ir+oZmfZw+oaO{s0! z2Lk13iu46Q7U8^P<3V!%z*Y}PcMt(q3aj>f*SQtx0QP*Y6Xq<9xbaF0ONY@-aQl8G8fq3#At70 zlfz=2U0^Ksi*yHgGSUuv9X@EGNz+Ik6W~OVE!q%TF@mAtEj7 z)ImCs&QZ_5y|WMm@n#Sd0zdY~`hjZ@AH+Wlmm(+91n>=yS`;g>t0@o04e^`37`?!Y zA(7mXut<9&ZUX2Kj?Q%hOy&&*WwslVYZH#pmw$8Arl4u1N`Jc~C7yp~ zKQLVl&1es;D7XfI9Z$amKTb(BQ#EZ#XL>iP(}eF+C-%&BqQ7UIK1oRoJ-kjmYc9TO{L*EUm~&L=53e{X!RQ*b zuk2{(4EB)v0Hkm2VrBe1%8%pDE!gxzdO(28UD!IB06i&6dX)Q0uPzu$1R7FQpw)oZ zX|ztGb%GnnL_CuVhp38D4_Y#4DcktoA>(JijQK^-z%f3q*~9CgjAot9r6%;_^4wVk zJV8&yh%rB~aElYNGYQy)G6@sNn6bqWV~5DZKu9TAFuk<9veSRD3s}^iUHzfv+1^s` zni;b%ar&Jhf6wB>O21MIAcVz!`taf&e+ccrWKPc-bk^+V_=i=1Wr59GQE92K?kS(S z5Ii{pAKD%~5@eC6p^DV|J1e_Or!QDIv%IIe-cniNwLu0#02pe-rRkE?N1P*`mX^hs z1mUv_lkbn>%~{fQ5;Pv5@YhJJ>y#_Kj%NWEnFU-HCL#Ud4+K^*ZDRn`AEZBElK}yZ zL@TGMlhQXQam*|oPrNHVW7{hSNA9(Ou6N}jLdK&cs6WdkYVXODdm;YC5wS>?*+^nk zJMe6dZkR2O63CJ7JZkj3LXN6Hkk7|(u$cTn26YGe3vpTnvr@X{s_m3i=t?`j z1zw^%;2K_%jcu0slRR=P1NtsSqe;gS(#tHiIun=TTYCSV>{z;g)6R%NQ>ZaSc5d3g zv_lSRfpM5Pb$#okr|Cyi)Z7R5Y@gX}=Q)nIchB6u=YhHMK$y!rPvc#9@px!;8{Pg9 z5e}obM`Zb=g}dw;YEd+qe1|^29Aphm<<>D_$9IHrG11$OS@h%u+JhvvBybT>5F*p% ztxr2e+)yme{vqsn^6wPVZZwf|2a&8dB^ML!Ps3FDLpVK2=Ag=yI~KvY_36(V=aOZE zn%(H2pTOThIU1b)kw&3mXeqANou<~_AWwEXmbx0(bv2t9V~Ig)HELL~u5D#qLGRvP z9SG^vAW1XmDpr2yeNxh(MkGS&MRpCBKNj_22h#u%PJ!)~$7XCW zL7kM~l^S(i%g&Mhm-GqE>6CG!W>94S+xmJ=g4ux8nHX701&ME^n;-A#lddqR1{o!O zX(muG2PosB2_$sTv|+|it`oETM6b&_2B6(yG>AG2TDs96?Iw8L-0Sy9k3FU>bksfY zlJwY1(tqLKTbZE?f85wq22Z6}I$q~;4|UPc;6Kncqr3ZO!((0WfJ6CX(ORTcWw7@- zl0lO1-l4BuE{f92AS{Z@u@=`Lir`mbExdAsCG%Q*6ok=vwIaTvK|UG2eMY=^`T6M4 z!8E|WRhb5}&woCA89h$E9l9+DOD~gx&=W>JAD0RjO)lok=sbMIxtO z8^lSzhmrKK80uLVV#h18;fP;!2Z5Vr{md%E&^1+XndSNCw2xT8Dh8~mNp06lb!;M$ z`f2JH^sz@$AHN@oTqAwF3@nAN6X31ymfU?e>A#xOaqhpfe$)QO>AJE37ndUhPM}`uYejXyYa5Oz${SuvvgY-c$tG_PTsdF zk3&^}L#-4Xg{$iX);v`?Pw6y=GoEZ?3y5XFcj=@&DlIoD7_I93Ez)|aR$9O1e5H<2 zn9zvXXHh8h%R0WgSr)DvCLDhA@Pr0=^PJOM{MPT1`EA=#0-)U;#aGJ|Lmk1&Qnl zI)e{3N<(DN6)&BrD69u#`x036I!_L$)Sx&&`cclp_k0K@YJmwI7l8Vm+q6cL z_BK%b(T|t2K&2vk`PZd;UeXFGCH?Zqn8=*p&M|_~gAC<_Y>4O*qgWpv!(mj#ZkNko zFzQD!0i%VyvxYFj>-k${Qy z%W5$pMWHG6ob()630I*38FQ(m4x@2nDj|CO!)o9AYrjc2^X2mkQ|JjLE+veX6!ZTa6wFkXmk?^G3vr0Uda-lLrS8X zN=dsBJyJ^Q)B{?jlBGo5&|Q;U61p!)6bJk;p-$>d;&55OmnRE=U``eo^%)+A%hR)a z<$tEd0W1?O&wq=b!sTgM0G%VBe49vLng2d><35K*c60ijT6r9JP9PCT`zdK7NRu<^ zN5{e4bfmVf54@o>O79xAIwSBJrBl!)4W|2DcI8s=+sP9bQeF2W4O~+R9Tycg0DF$Q%!kCfSE&_L-`dDrV zXgMf2G}_>ZZr=xx5)mvd!sn5eL+6RC5tikbBv%eU&Tm#`2Av|{(Xq0LA{GroOl~Z1 zjVurSDdzmM5D38z_8|e9G#Cwfk(gXTzmi`jB7f5VL}ltjBa+p^>4A>-dZ=Jlqz=Tgt5J%u zcq5^kxJX$H+#w6$sGyuxUd4uHf(ym8Vh1DrnwQq7Sw<_`9OwmzA4_+)F2)Vi4(SeD zs3jfXg2CmB)Jl#nr!88B(VGe!#k!p@)POe)N)>Hm9g>Zv!Haq%A=sdxmUfJLahKpL zE;Jh$R;$(g?Wo3#X=gZ=Wf=(AcSY@btyn)!&~4BOZve`Qp07QMU9x~?Xc{KgX*9YG zc7LZvqhF`iZ{ANc=t2Nlo=@xJ^bl%~)?DQ5a7(_7%z~YNI7JKdhmjB*cLp5Un6c#0 zL#W9+b%Ln9U@@-g;;(=9%weP=tWavTDz>bza!x;}Cdp#2f*%OFyU~lhUb+FFc^GxE zU7~i6PWa2QKkrZ!sCKCVRI-J>-YIVjx;9x-RPaQWMpt1;4NvU;~*8x z1_;Np0!$zyhlkx6Ezx4d-kIHk?tbf=58elSI+eowOM_B+1>*s z4Y+7D`TjntG9E+PVA*n=aPSG!W72H~LC}D;FDbRVwBp>Ef({*6FKVyA=c3i-Spoqf zM4|@aS*P6IG%-OMS|r=uWRar=BSs_jRV3?ZTn%TsnK{?tOdMSJ5b6{p4-vTJH`rMy^M_!_;fJuUGg;ty+==!xHY&RGTf;2BM z&o;!d`k?Lyr{h|ehz z_>>fs21z>wXtcc;^$gJ~T1?j3s2Fow-Ql1Y??6hByhGLzY0_h8FD)}+)7jGI#zQ*u zUfklarG=-n1_vJd=i!W_lK}vmywW=^aM#t|3E=3oyJw(1Yu(b@1dsf!dwAPX8~>x% z??X$q5e~eD>+^{FI=r}O0jp9O_S@O>z={ia+fEz51YC4JYu|5Bsn~^U@hLZW9!F!w z98iwbX9hEtJ(Nf!Qb?7S-a;E_*YQNcg?ee~h|LE3(XUPg`-!YATb99my;ftBj(~of z{HxLGrTfz-VEwl4G{t;~+A&N`Bsf79Oyr_tc(XU+37Wk|5BiK^ND4BB170HzO0?F* zB4KkhjDDOnT^nLN1UR&&g~J&>l-(vw6kjM_Tca>= zD(#fDZ^qrX%`CZX`epsiuRANcn&#I`S11|+oz-ojYNyy$;A^VsE^p)6Mo)W1W56fS zi6^HN9=^J3&4elobNUn*qE3US!r%}9#hv#6F!VM2YKSjxydZU_ug+JX;h^*|pjnN< z?g@c!++nv>#Q`9_jHU;L&RQJG^CKALoXBAr(r9w_yD?%D5;wEp4VdGjNTO%ffVvu* z8XC-CGhno)1W4&?q!(&rSuKk>QH{Twb7GmF>Dgz7nE+##Y9Om-0bOqO;xiN#mDO{a z;&yNtjonAJQ!`OJgfWGYmq(KfkTH=mYLPsd5N(OYgj~^9fTN@x`7mCJVUfA-#}hS}vX4o9p^|=%qaLIrwy-5hTnY|h=}bKh)@ziQ+)X2VxE02v z>p8tzr!;@_hBP?2>Yr7UrS~R$aQ6pH{~xOij0t!&r<@r;CWB~V`*2;q8xXGe=sai? zlu8=V8~?T-^_fCYLkPFfm#i7e|-~(vx$AJ`>H-&AV-&oty-B~js^@B51`ZIf7&*t$h zA)64?8~lOU7aE{>M#ZWt4_>tG9;Z}(AAr0RSd4?PR3Hf#Wo@;26>(FzT7pGj??M%6t=BAat{Kl?a0qI%-ln&W%a z{k8o1{qigg!K5pH>cO#UKQywMYZJ) z{myNza7}5hYp(aN8$SgWJM85E`0eoW0zZTs;`7`>lfNuj(PR?M#Wf{OPFr9~g@?15 zbQ`EFzk8hIi#gJmh}oAnQZx5k%tXtDRvg?ypoK9>F_h_+(@lcgqmjm3Z{&|Rov9&K z#=!b%(%%_{jur$HQ0m=P-66YZDpd1IrCo4$R`=Tqd;z<6+thh?v>T`Ru821%gLsJ`V zocWO;i2g-b^p|$dh0|tvBb$!>L8oA`5L*w-rVN`68W2f9YZ368P3Y{}Xf5Vm!U-2O zpq9|*xm^S)Gz~=QBK-`B?R?NnfGN#kOvp-Nu#m(g8{{yEhA~|ZZ@L_#40E>>84U(w z(bMhispoqpO#?sf2>RVht{niK$pTt=O{v%2(c$uyYWP!-);J=yMP^gca)mhWtE5k)Pp_(IQ<+Svw(|Wju)iFwr?lry4o9XbT)bC33AoKg)nSL(>V|1KZj| zwdS%?ANcgHk}~s?$|9XbC@s|Y=AakkpAQs9F;&Z z+%}884m4i=4ULz%{;`l+O6{QbQ@2x(5d9k?2BLS(BB7_Y#vjJmw#Kk~jMtKRc@fk* zBIM=yBVN*Bnn8Hfi;ZC>9uL~AAxynI=OSGM!*`=z;UYZ*glTkl3}hS@Gks6)XSnbA z$LOK-i$SZ!Vhw_s=bbmyuv&UyO<31zI~=Z+r@VK-P!s%P(D~tMV7F z>H<#|`p0(!3JU`rR}`@R@XFnVEKh zHPWTkHh**P^WFBk=pRxm$HiifS=zA5H-6rV>HcuoKm9mbL>vw!{fjrokAGuAYTn12 z8hbdind@m>_ZeR2O(q_#GdgL#^beq)bYR77>Dvj9%s^KMdLHS)H<>AEV=aDL7#xsp za6?Nu*dfP8Vt(I$Q6kRV2b`=K$HbaoMiIu=UUSCS0-^x#gmYA1I|84ZO{x?CcWKm0 z>*pnQ`nPIz>I=}LR;etXm)WG_0t5xYe^}@X1!+>qgE<7yE7a>N!7_t+=sb|R)nwFH z!i!z>b(J|j1Uxp0gtrbOj$%6w_6(S5&WfX}Vu0)c7C^S5L4d??>nNwnPIK|of`V7< zcuuKQ7@jE>=@@VPiBps=L~69j^|Zh%l+qBmRq>}`#%CJ5>rrcrzX#HfbULk%o}uxk zf>3gMk>U*A0q{Q!SB=J-p=6wKf)havcUuCVNhbM}`!eR-0J+|b!BL$ORqS!Q4SJIf zQqT$Ydc&%&KM(EvbJuEvP7l-D^zQWb!bwIDHwi)@l?Vt56^I{BuDQ3Zdzqr3K(Va5 z?cO!RHz^s1ic7Kwh~E>lEf=Ftn=u1(kdGjJ9{rD*l^Uc>e^8LdRP+ZX6aSwub@?We~t7f!u{@F(+3JMGn@22^Ly#9 z(rZ8`eJTAz`Z*|~cS=8(z69e49zDhGB=L0mY-zkWBA1N-BX4#GFL1k*Dc_R5SeqICYa3TuKiN{T?Q@sn(hBSTHr`xA20gsiWWoxNf_&9=2b4^QHT4 z0k?pKsSYnH&tU2>Ts6P#a2t5zsY6eJ&!r=~K|gpo_0$|V@uO6i9X^xiV=<>O;wUtd z;Gk7Z7mmgsZ(1&(vXWyiJyVYPi;a|~X6`d3-r4=U^r7imubrtZ@Ja8VNbEXsVpjsZ zUQ+aMQ3?5Zc+-qi2WD*AG=sTh#-@wmRjr*n-`WoJ$<E!4^`mQNHl>%(kp}T@zm4-P(4-- zZx4Gp`$HtB;|#4h_`zR1> z1xSo=0#4)zHh~}QX7CZr3la0NI97tLQf!U{iwXn2?$}!0ua>k0Rm5@=#oGE{Zk1|4wUU(OiXITj87g>hmi?T{GjR0v9Lz1;z%=oZ*Ch4qH*~9+GbR z=8)d3WqGLdn(a!u$W!NY?l=jyfzsQX3;^ESI>lw2InyX;8jY(rR1{u1eqlnPI07$o zc$JE(YF_2B7kZU^QK3TN9TMypc66J@RnbO;$rJJRJ!eqfbQ9;Pqo2M{vN>xDjXML5 zb(*45N3F8vg>4T_v{yQvdUZ(f&kId4wGjSK`CTcFgqI zA1u{kp&m)PVr?`KL<5x`5Dr7!uu;qzz;e9Y)=nDjXRr<+j1stdX8OuOd2se5#r(ai zXc()UaQ%~}j$p;@4^#v?%-WF0`KveFzM48UtG`R?zgxrF^;LI%`?$xc-={Q|ulv39 zkG;Kt@-U;Y_&A{81ntVl0e!+&T+ECECBwX5x0Q!1rj>#<+T4DzW>H7=d{gmE&|tQ6 ztjWaj1t!tPBY~ae3sN*6EMQix;xxC_&2WU4ifyaluOpV2yVarb=uP9Co!9)<$JUxW z>K;?!Laixa25L|nj^7FsDlJo*;?X>ewb2_PoMYh1KcVUTCY?4|)3JHu z@+njMR?e8#)L^zexG)|M2HAwP{U6dLSNZ(b;wfK_Gm4Ians79_8an>qjK-!;8w114 zA4xwYLRhN2GGC-QY&7MlHAndpm(HIX_7|ztK#)GWM_p7@J+5uP-aH{!m&ot-Q?VH<@%=h8@)=^yxTEp{|AzZY*P~(C{mR zR=QiI)v2UAwF;#vjje~2B!iStsX)RYiVU&+pUT8$P%yMo-yJN~GNO2j1VS@|0RuocmlB3FuM?noicXPxW)R>r`0rL3c!H;J2}TqO4i10D z5*?{QnrDjUlIeTO{@vlo@t9F2iHk6zRB#V!iXZ3{`Bgv-l#Od&kJ>XpG6vJ#3Jb?x z4-F$}=@!3dqG8G0p&-M#Dih#YO%`^2aQ5Yi>VE5;j(tAbD)@anKF>GXKoeDRKO@A~b( zVlHc*Jh?S0sJWZhtS+SuG^5GqW24cWu9n%7{YJuMlwQIIQ*-ejml)cNL!_XP+T05( z;r~iq1S6>}L!a${H`5mneE{zyypjZ?mEB2V77LN&Hx=m|6jc)?^A?j{vhwUEcXAo_ zkt8EFWA&0K^FiWk!%2!bN*zap7UOULoMg?DFC_he)L6i~F00jL0ViD+i_1E6s;sGT zZc`I8JzhDvX>QYjrt-2TFewy=53f!PElsTH;x$@+;^H?KPvo^49vsHUo65?Ym?A5_ zkNp4DrZQ<}c~et4c(|-dOf3(^|BAQ%D*whq@HTLB?D@@`pO5X)@|`8nwl@gl|Gmc>oVgzz3>97x5A!kUEZbb5@f#gt{>%tmiQQ4<5yMl1OB& zv2Y~ulT5udo)c(1RREda1I-=*d8Re zka~h1X~8$Bi2^6Yg#iTAgeI^*yp9ga4T0~En}7)75mG>OHz&=T@I7$>v6YM1z5@6l zv3j9e$K+WvOkiO6^tl%N5SrW;wGeL9^o`T)>}26BY9+&p>>@_5vMFfkc7|bTn&&yj z$N&fdr02vKB;F!1R|!;;yf*hdw>ns?2Wq8R&}xCsQ($2jlRBtx)8$^!yC(Q&3Bg-mO5ExXn0>5r3 z-6q)d1r9@z%EOnl<1RLtTJPRe0-4IoLcykDK?7Q5I(-&%n@2%A0jQ}3bbEoQ=b1R` zEHNu-#ZJAFX88Jc0P2hN6~&NND?yQHae^`*qt|JyKxbzaR=pZPBhV;~N*#wvLUYB8 z$RMedVf0o2GzL+xWR#F)8IIP{i^XWt3XC|(Vc-R2 zkp*>Q^pXl)1pqW@QMc9@)z*1x!#KZBsbN%t$J6aLv9wlS#@RF$wZ2nlRB{Ch&ZVQd zirTiI@u#(uJW89vQiK`4mq$BI*VnH5)p^^>&7jCpcC>Txmh~$eUz=CmRRW>Mj~ZPe zYKmCDZgyo@bFO<&+TY~5d%Sd6&XufK#h~JMu$b=mo0(N z5WQ*VRbKtmAMb58yQJSphr#@wni~&n3-}pf#n$Zyk}eRU-+ANL^Ges=H1rQNp~LCV zd^2VGo{i%#>uS=!PagtGQ^({T;|oNnqcq-nzH#%UeEgD*pU~$$z6S0^o*w#0THBkB>H)CC`VC0Zl=? zzPm6|##vGKqLIeH!WYKEEljsx3)PEtk`P@5Fmr9VhLE}DJ=$sZ=R6dW_%Vc zP$ry0e?Cmm7L(2Q7`2VD2pF@CxjEP{e`eoHg*O^$`5tuZ$ z>Ckx=S5I4bMs-7}h=u*z3Ee z_V1QAq*Hh!+Xf7g?VDtblng?NRf(sv477ly7=%e6tO?D##7$L=m4GxxNije_?2D-r zwYNl4Cn6CzIdV7xl+uQiW%Z4vTg%G8VW*!fYzo5FFtU5APL~Q8O$-z?(n_7~Qf-B9 z2)5|UAeFrq{Y0d%rS&JvN-r&GY$(HwhfFD4O-ByH=B@fNeJY>_Py>$W%XC}y`XSh= zA7+0b@y7m95sv4;|HOV@A|r#rv_~|%H4w0WM_e8(`b{##pE^Vlf^tYarNm!K>vAUr zvb=vR#SRjLM%l{~q`hX*LgIghk&@KL#E6$pGn0{=Y1HhQTp1kv5ia^`<=4u9J=q=_ z2(>5e0p-_~e=Q1^)ENNPy#gdwbOXvD_3inOJ$wEG43^ZDgE@Pp3-y9MAbo+Ufq@}l z7xduvz0$Grx{@LrNUUBhC2VvbzF?1BRtA^VPa;^;!malVOS#RmSY}jRPhGryQ9JoV z>+5=8qGz2nNJ>M;C7BbhZ)hDU$!pR$yrd6G1P>1k^sHM4Ue1*xWB+pFxb+rnBFHef zK_o_5tiF6h4-0w?#-gf{xy?3TQ=`w;JhwDdWHd1IM+_<-gFjd%^%dKZgi=yc=mGZP zzDbtr#uyhWkUsGydm8nlZfrv(;077MG2^fQhq#^;h~I!GLf~ScJP>ZJFbeLu3lDvF()I- zf_LFMJ;3#`NvfTiNHW;Uk;02dLfj2>40cI+La-`BGuR5!gb0nm7{uR4F+tNwgXsV_ zPQd5-0`|d<*F;f>3cq4a@%AO-65$KG8+H1pOocX4q>aCAkYO>7i-B74I6dXKSQ`+J z589;(sl-o!>L>8L+Q6|buZy*!C_c{`N?mpgq~-_)wYpc$1|eel>xKbbv4DJ`d>iSH zkhC+V8cQ9Sll_b`VlXW+1xELY{03zj%)TuH4%acFNf!fR9Eet_jASxE_D@czq5#$tXtpnJuhjbAngFvev=`H*Y>v3D@G>x&? z7{_wLwKYf)QIrKvQ?|Its0Td52;Pldhu5EPD^PjY^k3V=(Tu(f2pS8^ z8Wg5ly`d;tUQ(!qoS;;(P{(rxOAnO4~YYHdV=W z1Ax2MU|~5C$(RhSHrK2!ENYrxUC083uc5!Yq+P4=D4|7E+ab`f#$tCv?Sg>1#Zy(R zgp9p>VN3s|Dm_gD^dGW%rOb`{Aon#pnNpEauZo&Ot)zCLFEXnKV;)?xij+=k1|JhO zt3L#MNPoj0V=U_PBV8Abj5seS3<6Qlt)qe!Qe6-htYM|K6V zLMyA~@Q2vFI?ZemI%jNBD7CsG-ssdhPgMTb+SN0vs$O5Ub}`Zn2c*-7{v!QJryKy_ z&|iQb1STE)xs;MVkpBCv-B%|b01GCyRWh7T&v94(E>u|wS)EE#zo>K5>;h3yZbbz% z&2P1pF|6Iz1m?^O2bDEZyQ0w7((=%}!f~47!fjs;c_!#}cDHA|%W=Eb!Ln*?v5r;u zF7NYso>_eUB1h4QroNjd=&YX}k{8!?UcaZmrDMxeYc>KV@xYan;y36ts2jk>=GKi` zof`G1hLvz}@3uPhbX11cJ}r8>t(4VH?@MiT*o7L$%qKd>M+C08u8Oly&i4mypp=w| z`OyiVE7GqqYrP5bn1t8|3_KbvjTS~=E;{!7bH@(+(&PQ5bbIQh6ZZih6FKox>T%$^ z&(qsG@0)`MzhRpt$B=Zv(zk)_Ct&>VQf1PIZ!ZN$hrr*QzmtBF#zv;t%Q%W!jqNQo z7Ew8hCkPp6Jk~+%N&x8disE$^ud~G<8VRvT+h=r0wLwD^wuk8Or_AA1_A=M}-u|V% z)0+&&_0rMTM7v!)4$7DNCic!>GIy4H!wdU1v=&6{yrrvi@yxmLN^ZigC3Bm@ZVSt3 z6ppUCT3sOAeNmH-wT81z?%A^GI`HG3P0cP^ z=PXdE-j}`w_CNu6>!eOlXe%b|oKk&{Z=6vt4W&Mxv61=Rsj|%9#u@aq85@D4ea;r? zpFq21PCJ-znmP?8qMvIzI%aR#k|%2xAZe*Oom(>|ZKvf7iBU`{?21(OO_hu$4-}ZIQwWm`KWNlvSN--T)-UlC}!>)IBQ`C(?tZWmW%rI&hs8UO&zEcs`QL%~TX;Q4*01OJp%Co?WRh7EG;VG@@nDtr#KG z#NGwbZFb{KDUm+Cyg_>HCwE9+-~Rf8#>)-?{+XR`ZHA79)0EawV*FexvH9sfsL;)g zw)ggT`oVqDN(1;j z+C$-`c8%FQb>M0c27zH7D3Ilw=)@WxWMq{t8w}J6BKhl?R460@6(JdtHD^|gQ7V0q zNjxi^{Mmp`c$?-_O0D&y%u>*yonVXJZk4vA7bgKj_QK@Pq?6AII=HkQa4JK>s^~gD zyY?N{P)}@PO?d0l^D`?_ffks4ilcIK`Pbew>a#hW>LXVsJE&znYTq*_8;=@sOq@#; z={`9Rr0<*=+M~`VcRE|fHue7jDoYD$004N}V_;-pU|?ZjXo@RJkLS1f%D~Oe00QUc zW`)D(|Ns9pus5)QxEu^jAPN9Cg$rB&004N}V_;-pU}N}qmw|!3;Xe?tH!uK2kO5;K z0I6LEeE@jcg;cRl12GKsT`m_1IMIcLE)`;6XcwS}@qPfdj!1|PKuCyzP7zn5ugFYzITwTLGqsUul~03g?(GI z$Nvn^x|r_)-_XCSO{+dM*h6>eWewk3wb=*uYlgFXwsW!`?@s5i?!;@H#-=g%hhvaf z8cNdU8*<&++t|&1TT_KNm%!Jd-1eZCbC!&d^qr3*cWcXy&v~Etq88bC(d033+1s4k zf(LUyxoCJuH5v1^Qe*XLf9@+Jl5a~kl_C@U{B0r(8#HJ~G2{_N;1iZoDGhkn}5)14*olpEb$m@Oe z7GBPD_ElHqefpq!-0K*}=F8OX-u*y2YP`-7(W58n*+^Fm=(lJU<~;+Z+=HgCdLMW5 zkb9ry4R#FSQ|DRjPTOLhym^OUKNrb$n1#66*f$ln7kg%9oK@|$^7{vZ16004N} zV_;wqBLm7Y1TaiuxWeefSircBiGj(6S%tZY#e?M>%P&?N)@7`J*h1Kju&1&A;RxZF z#PNXBgL4JvKdvCI30$|hb+~8oxbRf)oZ>a(jp1Fw=fbywUyR>}f0;mpK$pNHK`p^m zLM}qvgeycWM5c&*5cLvWBIYM{K-@??O?;F1HwhJq0Eror0+M}_Kco_*CP-bAW|LNu z4wEjCULyTUMoPv@_Xd}DVQnbDXdUeY%)rH9jbWYPBcmLn2gX9iLB?lHq)hBg_LzJ# zwJ@Dy#$Xm^w#Hn^e3M0h#RJP4%TrcjR!LSHZ1>sm+2z6FPkDM8tU7XjsM7g|ko#s~LcE#PreUpcr$2w0p&qbaGJnwn_@sjfL@oMmz=e5UM z#5=}&osXB#312PWeZD{ZGW_27yZN68kO;^M*ca#$xGC^mkWo-p(1~E9kTYQ%VUxms zh5Lk8gdd3zh=_?;5%DF`Au=m+O60!C7f}XLby0hwS)$FNCq=)D35zL-*%50NTM_#R z1mgnY_QlJ@*Ciw*+)HdqJd~uB)RS~8nI$tRB z7FGSJ_Nks!eXqum8x&?Ko>b}&=)tA-JYfx$W)I6z0q@}9mNUKz9 zTshx$_qHC1o+?ZT0KC^I-vD^pV_;-p zV4TJz$soc20!%>62!sp_4q!e502Y`53;=lAb&$_a!axwlzZLvLjGhef*cju%1Gd!@ zH$+hr1cC&;7NpWBf6`VIAHxUm;K2v+q&JT~fzRRB=~lpKHoNnincZ(@2fzxRk%CHR z0NC6yD`e@#Jcm^rYffPUP0eX+;a>ARHu0o+fp1?mFH-$e^Agt8gXRp@)T8EQY^xW| zZ^)_-&F?VP7tU~kG7MBPL57)Yn*%w!k}1*~V$6)kx?TBq^rlTps=BoP)EoC_LLuW0E*b4fzt@a8jE17u;y)%T zecDh@G~gdfq8h2pc78yGk<>XN^{GCVzC!ky#|~Fg-MaGnVFenLC;7x zl3FKNGE=}D$8ngMnVFd!W@d1h6Q{bRS$N65-R`PVLv{79U%e$N>7U1!OIMZt&kr6^ zO^HfnQ0e~CJ*B%#_mv(*85LAfLmdq?(Lx&?bTNX_(!HgJN)KQRa)K7RTXuoPZOt1t;NToPtwv8cxRDFxN~h83bOxPCXVKYo4xLNq(fM=%T}T(v z#dHZ>N|({)bOl{WSJBmU4P8sukwMp!Nml7mvdJMqJ?fK79&M!o`4mt{k|NqhF(s5z zM)R~li?l?`bOYT;H_^>>3*Ab$(d~2x-AQ+q9pDX&!MZYEQCr``!Y2Ba7`&9eBnIzR9OFX-l2s5_bh6v|{FC$TPSx+lT zYQ`IwO9mlUeuSR3=A)9=w4=NS@wFh z#OsHqU$$kxn#N}0R$Li~2CpUz(@!g@7l=wMO{e3?h0td~nHxi;mPM+odZ8s3+mUZB z8MYVOzTiD0VW#z1^kR{?4dsen(3ke0((}!Jix1;Ot_(%enwNeS2!s7;7oysrS;$#b z+ZNl>5p~PdeK|Gz75+;qmXw2rY63GJRHN7n)0%AtA~q{M8K(T*cWPd0`kviR#bRo> z!t1+fOUnzMle#Vb)(;I|^wLf)+9FIv+|HF)4e#di)+|ZA-cm)KrR{|dkIUy3vK~9q zGi{-wX3TqzkoCy3(<~OXNQAcMw*oUVl&>PLnT}eJBg}pZ$4je;YsR8#yMiO6F07lR zA~Gz~9xRx#)9slY!lBj}3KbRfYGg797#K3D_hhW>9X))g=#>hkDz*wc?eISHvCL22 z9V+?=&B)IZLjj`|cwr&7a}a5{E(f~rZp#FRgy$)(>4iO+PfP4rh%j+w+AXH#sA%%U zTxwZnI26q|mJ8aCb}ni!8o8WB#dnPe9U_Gzb|>+ch0)7=zf;IbVEX=;ShRgJFjw5F z^t~R#PMAH;kytdu5(ABIqp1Yjmx<_bR6;N8>)}<7XDAxB>5I@Y<63NnjtuIy34FexmyaGrYDt?Dw$o!2ia6h_T`0yuq8tvOEw=70%|QQMjCRQ#T8&gnd8A`jYfvao2xB7Am6MwaASDZTE22E3l)d78Dg9? zD!@)TPLi_ga8fWDICx>j629NIRako**i^J!zQzLGT2yGOYblFziwekij!0t_ksH=o z^a7*nOj)#kl3Ip2Tw0>G5OdDE)znM|NsSqm57V?_PxNdv5iNz>JWs0qSY}a0#j?s6 z$())cOlF9(ouz!05l6+0G=99Ol9=_`BR2jUU%`~6cgC<`i`@`uwvLflQkM*VO^J!K%puNUW?E=nf zWM>F%T~V0hQ^sp5m|Gi+?U?W0WJYApYx&9vgJEGcm>2k-`(i|g*ceu@POj!it*cUM z1Wudhrmjpl_@a?yUaD@ap+Kc}tl3rWx?= zW@w9AAe@1hwtLDY-es#`*9F%BH>auIL{E%6GP4wvLKSh1zjc-zf9p()zjeAgS8H{C zd(Fhga7Jr&Xx$OXfXhbBHzU<)proBZTIyUn8#@KQHQrj=GMN@j=VE@(eA+PN!{lSD zT>br}RzU?En6b4KsA*^o4Jy4Q79*8~`R(!rM)|mE60jrH9;a4V4uo6pGuK6?(_os@ zxM--igc>=b1x+oCW~ae1=IUko74>3hYKM53Kf1zq1pzUchg>qS_?GN6UtFmV%(xniN5;)ipu6Y2Z&+ z>?E10F*cbpTRE#1AZBLb>bM=_-HQ@0SyPb4S8T(gRWYU}rkeWcr`E5rk^LQ6eL3iI zom0LxHhjTJuV9!98nO9z{fyAGu2aI8+Bn(DOTMlMoc5g7s',a,""].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},z=function(b){var c=a.matchMedia||a.msMatchMedia;if(c)return c(b).matches;var d;return y("@media "+b+" { #"+h+" { position: absolute; } }",function(b){d=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle)["position"]=="absolute"}),d},A=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;return f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=F(e[d],"function"),F(e[d],"undefined")||(e[d]=c),e.removeAttribute(d))),e=null,f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),B={}.hasOwnProperty,C;!F(B,"undefined")&&!F(B.call,"undefined")?C=function(a,b){return B.call(a,b)}:C=function(a,b){return b in a&&F(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=w.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(w.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(w.call(arguments)))};return e}),s.flexbox=function(){return J("flexWrap")},s.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},s.canvastext=function(){return!!e.canvas&&!!F(b.createElement("canvas").getContext("2d").fillText,"function")},s.webgl=function(){return!!a.WebGLRenderingContext},s.touch=function(){var c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch?c=!0:y(["@media (",n.join("touch-enabled),("),h,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(a){c=a.offsetTop===9}),c},s.geolocation=function(){return"geolocation"in navigator},s.postmessage=function(){return!!a.postMessage},s.websqldatabase=function(){return!!a.openDatabase},s.indexedDB=function(){return!!J("indexedDB",a)},s.hashchange=function(){return A("hashchange",a)&&(b.documentMode===c||b.documentMode>7)},s.history=function(){return!!a.history&&!!history.pushState},s.draganddrop=function(){var a=b.createElement("div");return"draggable"in a||"ondragstart"in a&&"ondrop"in a},s.websockets=function(){return"WebSocket"in a||"MozWebSocket"in a},s.rgba=function(){return D("background-color:rgba(150,255,150,.5)"),G(j.backgroundColor,"rgba")},s.hsla=function(){return D("background-color:hsla(120,40%,100%,.5)"),G(j.backgroundColor,"rgba")||G(j.backgroundColor,"hsla")},s.multiplebgs=function(){return D("background:url(https://),url(https://),red url(https://)"),/(url\s*\(.*?){3}/.test(j.background)},s.backgroundsize=function(){return J("backgroundSize")},s.borderimage=function(){return J("borderImage")},s.borderradius=function(){return J("borderRadius")},s.boxshadow=function(){return J("boxShadow")},s.textshadow=function(){return b.createElement("div").style.textShadow===""},s.opacity=function(){return E("opacity:.55"),/^0.55$/.test(j.opacity)},s.cssanimations=function(){return J("animationName")},s.csscolumns=function(){return J("columnCount")},s.cssgradients=function(){var a="background-image:",b="gradient(linear,left top,right bottom,from(#9f9),to(white));",c="linear-gradient(left top,#9f9, white);";return D((a+"-webkit- ".split(" ").join(b+a)+n.join(c+a)).slice(0,-a.length)),G(j.backgroundImage,"gradient")},s.cssreflections=function(){return J("boxReflect")},s.csstransforms=function(){return!!J("transform")},s.csstransforms3d=function(){var a=!!J("perspective");return a&&"webkitPerspective"in g.style&&y("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b,c){a=b.offsetLeft===9&&b.offsetHeight===3}),a},s.csstransitions=function(){return J("transition")},s.fontface=function(){var a;return y('@font-face {font-family:"font";src:url("https://")}',function(c,d){var e=b.getElementById("smodernizr"),f=e.sheet||e.styleSheet,g=f?f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"":"";a=/src/i.test(g)&&g.indexOf(d.split(" ")[0])===0}),a},s.generatedcontent=function(){var a;return y(["#",h,"{font:0/0 a}#",h,':after{content:"',l,'";visibility:hidden;font:3px/1 a}'].join(""),function(b){a=b.offsetHeight>=3}),a},s.video=function(){var a=b.createElement("video"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('video/ogg; codecs="theora"').replace(/^no$/,""),c.h264=a.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(/^no$/,""),c.webm=a.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,"")}catch(d){}return c},s.audio=function(){var a=b.createElement("audio"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),c.mp3=a.canPlayType("audio/mpeg;").replace(/^no$/,""),c.wav=a.canPlayType('audio/wav; codecs="1"').replace(/^no$/,""),c.m4a=(a.canPlayType("audio/x-m4a;")||a.canPlayType("audio/aac;")).replace(/^no$/,"")}catch(d){}return c},s.localstorage=function(){try{return localStorage.setItem(h,h),localStorage.removeItem(h),!0}catch(a){return!1}},s.sessionstorage=function(){try{return sessionStorage.setItem(h,h),sessionStorage.removeItem(h),!0}catch(a){return!1}},s.webworkers=function(){return!!a.Worker},s.applicationcache=function(){return!!a.applicationCache},s.svg=function(){return!!b.createElementNS&&!!b.createElementNS(r.svg,"svg").createSVGRect},s.inlinesvg=function(){var a=b.createElement("div");return a.innerHTML="",(a.firstChild&&a.firstChild.namespaceURI)==r.svg},s.smil=function(){return!!b.createElementNS&&/SVGAnimate/.test(m.call(b.createElementNS(r.svg,"animate")))},s.svgclippaths=function(){return!!b.createElementNS&&/SVGClipPath/.test(m.call(b.createElementNS(r.svg,"clipPath")))};for(var L in s)C(s,L)&&(x=L.toLowerCase(),e[x]=s[L](),v.push((e[x]?"":"no-")+x));return e.input||K(),e.addTest=function(a,b){if(typeof a=="object")for(var d in a)C(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},D(""),i=k=null,function(a,b){function k(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function l(){var a=r.elements;return typeof a=="string"?a.split(" "):a}function m(a){var b=i[a[g]];return b||(b={},h++,a[g]=h,i[h]=b),b}function n(a,c,f){c||(c=b);if(j)return c.createElement(a);f||(f=m(c));var g;return f.cache[a]?g=f.cache[a].cloneNode():e.test(a)?g=(f.cache[a]=f.createElem(a)).cloneNode():g=f.createElem(a),g.canHaveChildren&&!d.test(a)?f.frag.appendChild(g):g}function o(a,c){a||(a=b);if(j)return a.createDocumentFragment();c=c||m(a);var d=c.frag.cloneNode(),e=0,f=l(),g=f.length;for(;e",f="hidden"in a,j=a.childNodes.length==1||function(){b.createElement("a");var a=b.createDocumentFragment();return typeof a.cloneNode=="undefined"||typeof a.createDocumentFragment=="undefined"||typeof a.createElement=="undefined"}()}catch(c){f=!0,j=!0}})();var r={elements:c.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:c.shivCSS!==!1,supportsUnknownElements:j,shivMethods:c.shivMethods!==!1,type:"default",shivDocument:q,createElement:n,createDocumentFragment:o};a.html5=r,q(b)}(this,b),e._version=d,e._prefixes=n,e._domPrefixes=q,e._cssomPrefixes=p,e.mq=z,e.hasEvent=A,e.testProp=function(a){return H([a])},e.testAllProps=J,e.testStyles=y,e.prefixed=function(a,b,c){return b?J(a,b,c):J(a,"pfx")},g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+v.join(" "):""),e}(this,this.document),function(a,b,c){function d(a){return"[object Function]"==o.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=p.shift();q=1,a?a.t?m(function(){("c"==a.t?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l=b.createElement(a),o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};1===y[c]&&(r=1,y[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),"img"!=a&&(r||2===y[c]?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i("c"==b?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),1==p.length&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&"[object Opera]"==o.call(a.opera),l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return"[object Array]"==o.call(a)},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f ul li.current').removeClass('current'); + parent_li.toggleClass('current'); +} + +$(document).ready(function() { + // Shift nav in mobile when clicking the menu. + $(document).on('click', "[data-toggle='wy-nav-top']", function() { + $("[data-toggle='wy-nav-shift']").toggleClass("shift"); + $("[data-toggle='rst-versions']").toggleClass("shift"); + }); + // Nav menu link click operations + $(document).on('click', ".wy-menu-vertical .current ul li a", function() { + var target = $(this); + // Close menu when you click a link. + $("[data-toggle='wy-nav-shift']").removeClass("shift"); + $("[data-toggle='rst-versions']").toggleClass("shift"); + // Handle dynamic display of l3 and l4 nav lists + toggleCurrent(target); + if (typeof(window.SphinxRtdTheme) != 'undefined') { + window.SphinxRtdTheme.StickyNav.hashChange(); + } + }); + $(document).on('click', "[data-toggle='rst-current-version']", function() { + $("[data-toggle='rst-versions']").toggleClass("shift-up"); + }); + // Make tables responsive + $("table.docutils:not(.field-list)").wrap("
    "); + + // Add expand links to all parents of nested ul + $('.wy-menu-vertical ul').siblings('a').each(function () { + var link = $(this); + expand = $(''); + expand.on('click', function (ev) { + toggleCurrent(link); + ev.stopPropagation(); + return false; + }); + link.prepend(expand); + }); +}); + +// Sphinx theme state +window.SphinxRtdTheme = (function (jquery) { + var stickyNav = (function () { + var navBar, + win, + winScroll = false, + linkScroll = false, + winPosition = 0, + enable = function () { + init(); + reset(); + win.on('hashchange', reset); + + // Set scrolling + win.on('scroll', function () { + if (!linkScroll) { + winScroll = true; + } + }); + setInterval(function () { + if (winScroll) { + winScroll = false; + var newWinPosition = win.scrollTop(), + navPosition = navBar.scrollTop(), + newNavPosition = navPosition + (newWinPosition - winPosition); + navBar.scrollTop(newNavPosition); + winPosition = newWinPosition; + } + }, 25); + }, + init = function () { + navBar = jquery('nav.wy-nav-side:first'); + win = jquery(window); + }, + reset = function () { + // Get anchor from URL and open up nested nav + var anchor = encodeURI(window.location.hash); + if (anchor) { + try { + var link = $('.wy-menu-vertical') + .find('[href="' + anchor + '"]'); + $('.wy-menu-vertical li.toctree-l1 li.current') + .removeClass('current'); + link.closest('li.toctree-l2').addClass('current'); + link.closest('li.toctree-l3').addClass('current'); + link.closest('li.toctree-l4').addClass('current'); + } + catch (err) { + console.log("Error expanding nav for anchor", err); + } + } + }, + hashChange = function () { + linkScroll = true; + win.one('hashchange', function () { + linkScroll = false; + }); + }; + jquery(init); + return { + enable: enable, + hashChange: hashChange + }; + }()); + return { + StickyNav: stickyNav + }; +}($)); diff --git a/docsrc/exts/themes/sphinx_rtd_theme/theme.conf b/docsrc/exts/themes/sphinx_rtd_theme/theme.conf new file mode 100644 index 00000000..b71548b2 --- /dev/null +++ b/docsrc/exts/themes/sphinx_rtd_theme/theme.conf @@ -0,0 +1,9 @@ +[theme] +inherit = basic +stylesheet = css/theme.css + +[options] +typekit_id = hiw1hhg +analytics_id = +sticky_navigation = False +logo_only = diff --git a/docsrc/exts/themes/sphinx_rtd_theme/versions.html b/docsrc/exts/themes/sphinx_rtd_theme/versions.html new file mode 100644 index 00000000..8b3eb79d --- /dev/null +++ b/docsrc/exts/themes/sphinx_rtd_theme/versions.html @@ -0,0 +1,37 @@ +{% if READTHEDOCS %} +{# Add rst-badge after rst-versions for small badge style. #} +
    + + Read the Docs + v: {{ current_version }} + + +
    +
    +
    Versions
    + {% for slug, url in versions %} +
    {{ slug }}
    + {% endfor %} +
    +
    +
    Downloads
    + {% for type, url in downloads %} +
    {{ type }}
    + {% endfor %} +
    +
    +
    On Read the Docs
    +
    + Project Home +
    +
    + Builds +
    +
    +
    + Free document hosting provided by Read the Docs. + +
    +
    +{% endif %} + diff --git a/docsrc/index.rst b/docsrc/index.rst new file mode 100644 index 00000000..3778491b --- /dev/null +++ b/docsrc/index.rst @@ -0,0 +1,86 @@ +========== +Cyrus SASL +========== + +Welcome to Cyrus SASL. + +What is Cyrus SASL? +=================== +Simple Authentication and Security Layer (SASL_) is a specification that describes how authentication mechanisms can be plugged into an application protocol on the wire. Cyrus SASL is an implementation of SASL that makes it easy for application developers to integrate authentication mechanisms into their application in a generic way. + +The latest stable version of Cyrus SASL is |sasl_current_stable_version|. + +Features +-------- +Cyrus SASL provides a number of authentication plugins out of the box. + + Berkeley DB, GDBM, or NDBM (sasldb), PAM, MySQL, PostgreSQL, SQLite, LDAP, Active Directory(LDAP), DCE, Kerberos 4 and 5, proxied IMAP auth, getpwent, shadow, SIA, Courier Authdaemon, httpform, APOP and SASL mechanisms: ANONYMOUS, CRAM-MD5, DIGEST-MD5, EXTERNAL, GSSAPI, LOGIN, NTLM, OTP, PASSDSS, PLAIN, SR + +Cyrus IMAP uses Cyrus SASL to provide authentication support to the mail server, however it is just one project using Cyrus SASL. + +.. _SASL: https://en.wikipedia.org/wiki/Simple_Authentication_and_Security_Layer + +This document is an introduction to **Cyrus SASL**. It is not intended to be an exhaustive reference for the SASL Application Programming Interface (API), which is detailed in the SASL manual pages, and the libsasl.h header file. + + +Known Bugs +---------- + +.. todo: + Is this still true? + +``libtool`` doesn't always link libraries together. In our environment, +we only have static Krb5 libraries; the GSSAPI plugin should link +these libraries in on platforms that support it (Solaris and Linux +among them) but it does not. It also doesn't always get the runpath +of libraries correct. + +Note for Packagers +------------------ + +People considering doing binary distributions that include saslauthd +should be aware that the code is covered by several slightly different +(but compatible) licenses, due to how it was contributed. Details can +be found within the source code. + + +.. toctree:: + :maxdepth: 1 + :caption: Overview + + download + sasl/quickstart + sasl/installation + sasl/upgrading + sasl/appconvert + +.. toctree:: + :maxdepth: 1 + :caption: Management + + sasl/concepts + sasl/components + sasl/options + sasl/sysadmin + sasl/advanced + +.. toctree:: + :maxdepth: 1 + :caption: Reference + + sasl/auxiliary_properties + sasl/authentication_mechanisms + sasl/pwcheck + sasl/faq + sasl/sasl_migration + sasl/resources + +.. toctree:: + :maxdepth: 1 + :caption: Developers + + contribute + developers + sasl/developer/programming + sasl/developer/plugprog + sasl/developer/testing diff --git a/docsrc/sasl/advanced.rst b/docsrc/sasl/advanced.rst new file mode 100644 index 00000000..e6e01a60 --- /dev/null +++ b/docsrc/sasl/advanced.rst @@ -0,0 +1,34 @@ +.. _advanced: + +============== +Advanced Usage +============== + +Notes for Advanced Usage of libsasl +=================================== + +Using Cyrus SASL as a static library +------------------------------------ + +As of v2.0.2-ALPHA, Cyrus SASL supports the option to compile all of the +supported mechanisms and glue code into a single static library that may +be linked into any application. In practice, this saves memory by avoiding +the need to have a jump table for each process's reference into the shared +library, and ensures that all the mechanisms are loaded when the application +loads (thus reducing the overhead of loading the DSOs). + +However, this is not a recommended procedure to use in general. It loses +the flexibility of the DSOs that allow one to simply drop in a new mechanism +that even currently-running applications will see for each new connection. +That is, if you choose to use the static version of the library, not only +will you need to recompile the library each time you add a mechanism (provided +the mechanisms even support being compiled staticly), but you will need to +recompile every application that uses Cyrus SASL as well. + +However, if you are sure you wish to use a static version of Cyrus SASL, +compile it by giving ``configure`` the ``--enable-static`` option. +This will compile both a dynamic and a static version. Then, whenever +an application links to libsasl, it will also need to explicitly pull in +any dynamic libraries that may be needed by Cyrus SASL. Most notably, these +might include the GSSAPI, Kerberos, and Database libraries. To avoid compiling +the dynamic version, pass ``--disable-shared``. diff --git a/docsrc/sasl/appconvert.rst b/docsrc/sasl/appconvert.rst new file mode 100644 index 00000000..48820d99 --- /dev/null +++ b/docsrc/sasl/appconvert.rst @@ -0,0 +1,101 @@ +.. _appconvert: + +===================================== +Converting Applications from v1 to v2 +===================================== + +This documents our conversion experience with Cyrus IMAPd, an application +that uses almost every part of SASL, so it should give a good idea what caveats +need to be looked for when one is converting an application which uses SASLv1 +to use SASLv2. + +The major changes in the SASLv2 API have to do with memory management. +That is, the rule "If you allocate it, you free it" is now enforced. That +means that if the application allocates something (for example, an interaction +or callback response), it must free it. Likewise, the application does +NOT free anything handed to it by the SASL library, such as responses +given by sasl_client_step or sasl_decode. + + +Tips for both clients and servers +================================= + +* Change configure scripts to search for libsasl2 and include files + prefixed with sasl/ (sasl/sasl.h, sasl/saslutil.h, etc) +* ``sasl_decode64`` now takes an + additional parameter that is the size of the buffer it is passed. +* External authentication properties are no longer handled by a + ``sasl_external_properties_t``. Instead you make 2 separate calls to + ``sasl_setprop.`` + + * One with SASL_SSF_EXTERNAL to tell the SASL library what SSF is being + provided by the external layer. + * The other sets SASL_AUTH_EXTERNAL to indicate + the authentication name. + +* ``sasl_getprop`` now returns its value in a ``const void \*\*`` + +* ``sasl_encode`` and ``sasl_decode`` now return a constant output buffer, which + you do not need to free (it is only valid until the next call for this sasl\_ + conn_t, however) + +* The SASL_IP_REMOTE and SASL_IP_LOCAL properties are now SASL_IPLOCALPORT + and SASL_IPREMOTEPORT and take strings instead of sockaddrs. These strings + may also be passed to the sasl_[client/server]_new functions. They + are in one of the following formats: + + * a.b.c.d;p (IPv4, with port) + * e:f:g:h:i:j:k:l;p (IPv6, with port) + * e:j:k:l;p (IPv6, abbreviated zero fields, with port) + +* Error handling and reporting is different. All of the functions that used + to return a "reply" string no longer do. Now you should (always) check + ``sasl_errdetail``. Callbacks MUST likewise use ``sasl_seterror`` + instead of setting their (now nonexistent) reply parameter. + +* Be very careful about your handling of maxoutbuf. If you claim that + you can only read 4096 bytes at a time, be sure to only pass at most + that much at a time to the SASL library! + + +Tips for clients +================ + +* In ``sasl_client_new`` you can now pass ip address strings as + parameters 3 and 4 instead of calling setprop later on sockaddr's. + This is preferred but not required (not passing them by either method disables + mechs which require IP address information). You might find the iptostring() + function in utils/smtptest.c to be useful for this. If the protocol supports + the server sending data on success you should pass SASL_SUCCESS_DATA as a + flag. +* ``sasl_client_start`` loses the 3rd "secret" parameter. + Also, NULL clientout and clientoutlen indicates that the protocol does not + support client-send-first. A NULL return value indicates that there is no + first client send. (as opposed to an empty string, which indicates that + the first client send is the empty string). + +* Both ``sasl_client_start`` and ``sasl_client_step`` now take + const clientout parameters that you are no longer responsible for freeing + (it is only valid until the next call for this ``sasl_conn_t``, however) + +* When interactions and callbacks happen you are responsible for freeing + the results. + +Tips for Servers +================ + +* SASL_SECURITY_LAYER flag no longer exists, whether or not to use a + security layer is solely determined by the security properties information, + namely, the ``maxbufsize`` member of the + ``sasl_security_properties_t`` +* ``sasl_server_new`` now can take ip address strings. +* ``sasl_checkpass`` no longer has a "reply" parameter. There + are also considerably fewer possible values for the pwcheck_method + option (now only auxprop, saslauthd, authdaemond, and pwcheck). +* ``sasl_server_start`` / ``sasl_server_step`` have same + output parameter deal as their equivalents on the client side +* ``sasl_listmech`` has a constant output parameter +* If you used to canonicalize the username in a SASL_CB_PROXY_POLICY + callback you should now separate the functionality of authorization and + canonicalization. That is, only do authorization in SASL_CB_PROXY_POLICY, + and do canonicalization in the SASL_CB_CANON_USER callback diff --git a/docsrc/sasl/authentication_mechanisms.rst b/docsrc/sasl/authentication_mechanisms.rst new file mode 100644 index 00000000..ebf8a37e --- /dev/null +++ b/docsrc/sasl/authentication_mechanisms.rst @@ -0,0 +1,152 @@ +.. _authentication_mechanisms: + +Authentication Mechanisms +========================= + +EXTERNAL +-------- + +.. todo:: + Content needed here + +ANONYMOUS +--------- + +.. todo:: + Content needed here + +PLAIN +----- + +.. todo:: + Content needed here + +LOGIN +----- + +.. todo:: + Content needed here + +CRAM-MD5 +-------- + +.. todo:: + Content needed here + +DIGEST-MD5 +---------- + +.. todo:: + Content needed here + +SCRAM-SHA-1 +----------- + +.. todo:: + Content needed here + +GSSAPI +------ + +Not sure how to get GSSAPI going? Check out our :ref:`GSSAPI configuration guide `. + +.. todo:: + Content needed here + +GS2-KRB5 +-------- + +.. todo:: + Content needed here + +GS2-IAKERB +---------- + +.. todo:: + Content needed here + +NTLM +---- + +.. todo:: + Content needed here + +SRP +--- + +.. todo:: + Content needed here + +PSSDSS +------ + +.. todo:: + Content needed here + +OTP +--- + +.. todo:: + Content needed here + +Non-SASL Authentication +----------------------- + +.. todo:: + Content needed here + +This table shows what security flags and features are supported by each +of the mechanisms provided by the Cyrus SASL Library. + ++-------------+---------+----------------------------------------------------------------+---------------------------------------------+ +| | | Security Properties | Features | ++-------------+ +----------------------------------------------------------------+---------------------------------------------+ +| | MAX SSF | NOPLAIN | NOACTIVE | NODICT | FORWARD | NOANON | CRED | MUTUAL | CLT FIRST | SRV FIRST | SRV LAST | PROXY | ++-------------+---------+---------+----------+--------+---------+--------+------+--------+-----------+--------------+----------+-------+ +| ANONYMOUS | 0 | X | | | | | | | X | | | | ++-------------+---------+---------+----------+--------+---------+--------+------+--------+-----------+--------------+----------+-------+ +| CRAM-MD5 | 0 | X | | | | X | | | | X | | | ++-------------+---------+---------+----------+--------+---------+--------+------+--------+-----------+--------------+----------+-------+ +| DIGEST-MD5 | 128 | X | | | | X | | X | reauth | initial auth | X | X | ++-------------+---------+---------+----------+--------+---------+--------+------+--------+-----------+--------------+----------+-------+ +| EXTERNAL | 0 | X | | X | | X | | | X | | | X | ++-------------+---------+---------+----------+--------+---------+--------+------+--------+-----------+--------------+----------+-------+ +| GSSAPI | 56 | X | X | | | X | | X | X | | | X | ++-------------+---------+---------+----------+--------+---------+--------+------+--------+-----------+--------------+----------+-------+ +| KERBEROS_V4 | 56 | X | X | | | X | | X | | X | | X | ++-------------+---------+---------+----------+--------+---------+--------+------+--------+-----------+--------------+----------+-------+ +| LOGIN | 0 | | | | | X | | | | X | | | ++-------------+---------+---------+----------+--------+---------+--------+------+--------+-----------+--------------+----------+-------+ +| NTLM | 0 | X | | | | X | | | X | | | | ++-------------+---------+---------+----------+--------+---------+--------+------+--------+-----------+--------------+----------+-------+ +| OTP | 0 | X | | | X | X | | | X | | | X | ++-------------+---------+---------+----------+--------+---------+--------+------+--------+-----------+--------------+----------+-------+ +| PLAIN | 0 | | | | | X | | | X | | | X | ++-------------+---------+---------+----------+--------+---------+--------+------+--------+-----------+--------------+----------+-------+ +| SRP | 128 | X | X | X | X | X | | X | X | | X | X | ++-------------+---------+---------+----------+--------+---------+--------+------+--------+-----------+--------------+----------+-------+ + +Understanding this table: + +Security Properties: + +* **MAX SSF** - The maximum Security Strength Factor supported by the mechanism (roughly the number of bits of encryption provided, but may have other meanings, for example an SSF of 1 indicates integrity protection only, no encryption). +* **NOPLAIN** - Mechanism is not susceptable to simple passive (eavesdropping) attack. +* **NOACTIVE** - Protection from active (non-dictionary) attacks during authentication exchange. (Implies MUTUAL). +* **NODICT** - Not susceptable to passive dictionary attack. +* **NOFORWARD** - Breaking one session won't help break the next. +* **NOANON** - Don't permit anonymous logins. +* **CRED** - Mechanism can pass client credentials. +* **MUTUAL** - Supports mutual authentication (authenticates the server to the client) + +Features: + +* **CLTFIRST** - The client should send first in this mechanism. +* **SRVFIRST** - The server must send first in this mechanism. +* **SRVLAST** - This mechanism supports server-send-last configurations. +* **PROXY** - This mechanism supports proxy authentication. + +.. toctree:: + :hidden: + + gssapi diff --git a/docsrc/sasl/auxiliary_properties.rst b/docsrc/sasl/auxiliary_properties.rst new file mode 100644 index 00000000..e1b3e9a3 --- /dev/null +++ b/docsrc/sasl/auxiliary_properties.rst @@ -0,0 +1,40 @@ +Auxiliary Properties +==================== + +Auxiliary Properties and the Glue Layer +--------------------------------------- + +.. todo:: + Content needed here + +Passwords and other Data +------------------------ + +.. todo:: + Content needed here + +sasldb +------ + +.. todo:: + Content needed here + +ldapdb +------ + +.. todo:: + Content needed here + +sql +--- + +.. todo:: + Content needed here + +User Canonicalization +--------------------- + +.. todo:: + Content needed here + + diff --git a/docsrc/sasl/components.rst b/docsrc/sasl/components.rst new file mode 100644 index 00000000..f6bfa09b --- /dev/null +++ b/docsrc/sasl/components.rst @@ -0,0 +1,184 @@ +.. _components: + +========== +Components +========== + +As the SASL library is a 'glue layer' between many different parts of the +authentication system, there are a lot of different components +that often cause confusion to users of the library who are trying to +configure it for use on their system. This document will try to provide +some structure to all of these components, though you will also need +to read the :ref:`System Administration ` to have a full +understanding of how to install SASL on your system. + +The first thing to realize is that there is a difference between SASL, +the protocol, and Cyrus SASL, the library. The first is a specification +that describes how authentication mechanisms can be plugged into an application +protocol *on the wire*. The later is an implementation that aims +to make this easier for application developers to integrate authentication +mechanisms into their application in a generic way. It is quite possible +to have an application that uses SASL (the specification) without using +Cyrus SASL (the implementation). + +The remainder of this document will refer to components of the Cyrus +SASL implementation, though some of these will necessarily have a broader +scope. + +The Application +=============== + +The application is a client of the SASL library. It can be a client or server +application (or both, in the case of a proxy). It takes care of the +on-the-wire representation of the SASL negotiation, however it performs no +analysis of the exchange itself. It relies on the judgment of the SASL +library whether authentication has occurred or not. The application is also +responsible for determining if the authenticated user may authorize as another +user id (For more details on authentication and authorization identities +and their differences, see Cyrus SASL for System Administrators) + +Examples of applications are Cyrus IMAPd, OpenLDAP, Sendmail, Mutt, +sieveshell, cyradm, and many others. + +The SASL Glue Layer +=================== + +The first component of the SASL library is affectionately called the +``glue`` layer. It takes care of ensuring that the application and +the mechanisms can work together successfully. To this end, it does a +variety of basic tasks: + +* Loading of any plugins (more on these below) +* Ascertaining necessary security properties from the application to aid + in the choice of mechanism (or to limit the available mechanisms) +* Listing of available plugins to the application (mostly used on the server + side) +* Choosing the best mechanism from a list of available mechanisms + for a particular authentication attempt (client-side) +* Routing the authentication (and in the case of a mechanism with a security + layer, encrypted) data packets between the application and the + chosen mechanism. +* Providing information about the SASL negotiation back to the application + (authenticated user, requested authorization identity, security strength of + any negotiated security layer, and so on). + + +The Cyrus SASL implementation also provides several other services to +both its plugins and applications. Some of these are simply general utilities, +such as MIME Base-64 encoding and decoding, and random number generation. +Others are more specific to the task of authentication, such as providing +password verification services. Such services are capable of taking +a username and a plaintext password and saying ``yes`` or +``no``. Details of available password verification services are +discussed below. + +Finally, the glue code allows the mechanisms and applications access to +two special types of plugins, Auxiliary Property or ``auxprop`` +plugins, which provide a simple database interface and can return properties +about the user such as password, home directory, or mail +routing address, and Username Canonicalization, which might provide +site-specific ways to canonicalize a username or perform other tasks. + +In the Cyrus SASL Implementation, the glue code is entirely contained +within ``libsasl2.so`` (or ``libsasl2.a``) + +Plugins +======= + +Plugins: General +---------------- + +The Cyrus SASL architechure is very modular, using loadable modules for +things such as the mechanism profiles and the database access done by the +auxillary property plugins. This means that it is easy to limit what +parts are loaded by a given application, and that third parties can write +their own modules to provide services, just by adhering to the API description +in ``saslplug.h``. + +Plugins: SASL Mechanisms +------------------------ + +The simplest types of plugins to understand are those which provide +SASL mechanisms, such as CRAM-MD5, DIGEST-MD5, GSSAPI, PLAIN, SRP, and so on. +These mechanisms take care of both server-side and client-side parts +of the SASL negotiation. If the given mechanism supports a security layer +(that is, makes guarantees about privacy or integrity of data after the +negotiation is complete), the plugin provides that functionality as well. + +SASL mechanisms are generally defined by the IETF standards process, +however, some mechanisms are not (For example, NTLM). This is in contrast +to the other types of plugins, which provide database and username +canonicalization services to other plugins and thus aren't standardized in +their behavior (they are specific to our implementation). Password verifiers +are also an implementation detail (though saslauthd makes use of +standards such as PAM and LDAP to perform that verification) + +There are several types of mechanisms, in broad strokes we have: + +Password Verification Mechanisms + For example, PLAIN. These receive a raw password from the remote and then pass it into the glue code for + verification by a password verifier. These require the existence of an + outside security layer to hide the otherwise plaintext password from people + who might be snooping on the wire. These mechanisms do not require that + the server have access to a plaintext (or plaintext-equivalent) version + of the password. +Shared Secret Mechanisms + For these mechanisms, such as CRAM-MD5, DIGEST-MD5, and SRP, there is a shared secret between the server and client + (e.g. a password). However, in this case the password itself does not travel + on the wire. Instead, the client passes a server a token that proves that + it knows the secret (without actually sending the secret across the wire). + For these mechanisms, the server generally needs a plaintext equivalent of + the secret to be in local storage (not true for SRP). +Kerberos Mechanisms + Kerberos mechanisms use a trusted + third party to authenticate the client. These mechanisms don't require + the server to share any secret information with the client, it is all performed + through the Kerberos protocol. + + +Mechanism plugins are generally contained in a .so file that has a name +similar to the mechanism's name. Though, in a static compilation they +can also be a part of ``libsasl2.a`` + +Plugins: Auxiliary Property +--------------------------- + +Auxiliary Property (or auxprop) plugins provide a database service for the +glue layer (and through it, to the mechanisms and application). Cyrus SASL +ships with two auxprop plugins: SASLdb and SQL. Though they can be use +in much more generic ways, auxprop plugins are mostly only used by +shared secret mechanisms (or by the auxprop password verify) to access the +``userPassword`` attribute. This provides a plaintext copy of the +password that allows for authentication to take place. + +Like the mechanism plugins, these are named similarly to the databases +that they implement an interface for. + +Plugins: Username Canonicalization +---------------------------------- + +Username Canonicalization plugins are not widely used, however it may be +useful to use as a hook if your site has specific requirements for how userids +are presented to the applications. + +Password Verification Services +============================== + +As described above, the password verifiers take a username and plaintext +password, and say either ``yes`` or ``no``. It is not possible +to use them to verify hashes that might be provided by the shared secret +mechanisms. + +Password verifiers are selected using the ``pwcheck_method`` +SASL option. There are two main password verifiers provided with Cyrus SASL: + +auxprop + This uses an auxprop plugin to fetch the password and then + compares it with the client-provided copy to make the determination. +saslauthd + This calls out to the ``saslauthd`` daemon, which + also ships with the distribution. The ``saslauthd`` daemon has a number + of modules of its own, which allow it to do verification of passwords in + a variety of ways, including PAM, LDAP, against a Kerberos database, and so on. + This is how you would want to, for example, use the data contained in + ``/etc/shadow`` to authenticate users. diff --git a/docsrc/sasl/concepts.rst b/docsrc/sasl/concepts.rst new file mode 100644 index 00000000..74050254 --- /dev/null +++ b/docsrc/sasl/concepts.rst @@ -0,0 +1,63 @@ +Concepts +======== + +SASL +---- + +Simple Authentication and Security Layer (SASL) is a protocol developed by the Internet Engineering Task Force (IETF) for the purpose of providing an extensible and pluggable authentication framework, primarily for non-web related protocols. It is commonly used in email related protocols, such as SMTP, IMAP, and POP, along with XMPP, LDAP, and a few others. In doing so, various implementations of those protocols, such as the Cyrus IMAP or Dovecot servers, can support a wide range of authentication mechanisms with various email clients which implement the IMAP protocol, including Thunderbird, Outlook, and the Android mail client. + +RFC 4422 is the base framework specification for SASL. It provides guidance for protocol designers, server software implementations, and SASL mechanism designers. Protocol definitions, and SASL mechanism specifications in turn make use of this framework to independently support each other. That is, if a protocol were designed 5 years ago to make use of SASL, and a new mechanism were designed today, server implementations and client software could make use of that new mechanism without a change to the original server protocol spec. + +SASL Authentication Mechanisms +------------------------------ + +SASL mechanisms are plugable authentication methods that are developed independently of server protocols. For example, the Generic Security Service Application Program Interface (GSSAPI) mechanism, defined in RFC 4752, defines a network oriented protocol for authenticating a client to a server, using Kerberos version 5, a trusted 3rd party ticket based system. The GSSAPI mechanism should work with all clients and servers which implement support for it, regardless of the actual server protocol used (such as IMAP), given the protocol was designed for use with the SASL framework. + +A list of developed SASL mechanisms can be found at the `IANA registered SASL mechanisms `__ page. A more detailed discussion of these mechanisms can be found in :doc:`Authentication Mechanisms`. + +Security Layers +--------------- + +SASL Security Layers allow a server and client to negotiate integrity and confidentiality protection for a connection once it has been authenticated. It is only available for mechanisms which themselves are capable of providing such protection (such as GSSAPI). It is capable of being used to encrypt a connection over the public internet, and can be used as an alternative to TLS encryption. + +Channel Binding +--------------- + +.. todo:: + What's channel binding? + +Realms +------ + +.. todo:: + What are realms? + +Protocols +--------- + +.. todo:: + What protocols? + +Cyrus SASL +---------- + +.. todo:: + Something required here + +The Glue Library +---------------- + +.. todo:: + A bit stuck with this one too :) + +Auxiliary Properties +-------------------- + +.. todo:: + More properties... + +Plugins +------- + +.. todo:: + Plugins, plugins and plugins diff --git a/docsrc/sasl/developer/installation.rst b/docsrc/sasl/developer/installation.rst new file mode 100644 index 00000000..9baebc7c --- /dev/null +++ b/docsrc/sasl/developer/installation.rst @@ -0,0 +1,81 @@ +.. _sasldevinstallguide: + +=========================== +Cyrus SASL Developer Guide +=========================== + +.. todo: + This is all available at http://www.cyrusimap.org/docs/cyrus-sasl/2.1.25/install.php + +Compile from source +=================== + +Fetch the source +----------------- + +Fetch from git +############## + +If you're not familiar with Git, there are detailed instructions in the :ref:`Cyrus IMAPd GitHub guide `. + +Cyrus SASL is at https://github.com/cyrusimap/cyrus-sasl + +To contribute, we recommend `forking the code `_ then issuing a pull request when you're ready. + +Once forked on GitHub, you can obtain a copy by:: + + git clone https://github.com/YOUR-USERNAME/REPOSITORY-NAME.git + +You will then want to set your local copy to get its changes from the original repository, so it stays in sync. Use ``git remote -v`` to show the current origins of your clone which will currently be your fork:: + + git remote -v + origin https://github.com/YOUR_USERNAME/YOUR_FORK.git (fetch) + origin https://github.com/YOUR_USERNAME/YOUR_FORK.git (push) + +We want to set that instead to point to the primary original upstream repository:: + + git remote add upstream https://github.com/cyrusimap/cyrus-sasl.git + +Now we can check to see that the upstream is set:: + + git remote -v + origin https://github.com/YOUR_USERNAME/YOUR_FORK.git (fetch) + origin https://github.com/YOUR_USERNAME/YOUR_FORK.git (push) + upstream https://github.com/cyrusimap/cyrus-sasl.git (fetch) + upstream https://github.com/cyrusimap/cyrus-sasl.git (push) + +We recommend you create a topic branch and make your changes (don't forget to test!). Using a topic branch means you can keep your master +source in sync without affecting your changes. It also means that if your patch undergoes further revisions before inclusion, you +can easily do so. + + +Unpack from tarball +################### + +Cyrus SASL releases are available to download in tarball format from ftp://ftp.cyrusimap.org/cyrus-sasl/ + +Dependencies +------------ + +.. todo: + ?? Libraries + +Compiling +--------- + +:: + cd (source directory) + sh SMakefile + ./configure + make + make install + ln -s /usr/local/lib/sasl2 /usr/lib/sasl2 + + +Configuration +------------- + +`./configure ...` + +.. note: + If you tweak configure.ac or any of the .m4 files, you will have to delete configure and then compile again to create a new configure script. diff --git a/docsrc/sasl/developer/plugprog.rst b/docsrc/sasl/developer/plugprog.rst new file mode 100644 index 00000000..81b9952b --- /dev/null +++ b/docsrc/sasl/developer/plugprog.rst @@ -0,0 +1,347 @@ +.. _plugprog: + +========================= +Plugin Programmer's Guide +========================= + +.. note:: + + NOTE: This is a work in progress. Any contributions would be + *very* appreciated. + +.. contents:: + :local: + +Introduction +============ + +About this Guide +---------------- + +This guide gives a brief overview on the things that one +needs to know to write a :ref:`mechanism ` for the SASLv2 API (and thus +Cyrus SASLv2). Note that this page is a brief overview +and that the authoritative documentation are the header files +included in the SASL distribution. If you have any questions, please +feel free to contact the :ref:`Cyrus development team `. + +Please note that this guide is only intended for developers looking +to write mechanisms for the SASLv2 API, and that application programmers +should be reading the :ref:`Application Programming Guide ` instead. + + +What is SASL? +------------- + +A description of SASL is covered in detail in the +:ref:`programmer's guide `, which mechanism +developers should probably read first anyway to become familiar +with development using the SASL library. + +Common Section +============== + +Overview of Plugin Programming +------------------------------ + +The basic idea behind programming plugins for Cyrus SASL rests in +the ability to dlopen a shared library. Thus, all plugins should +be shared libraries. It is recommended that they are libtool +libraries for portability reasons (Cyrus SASL parses .la files to +get the appropriate name to dlopen), but they can have an extention +of .so as well. + +All plugins should live in the same directory +(generally /usr/lib/sasl2), which the glue code (that is, the interface +layer that sits between the plugins and the application) scans +when one of the init functions (sasl_server_init or sasl_client_init) +is called. Cyrus SASL then attempts to open each library and +run an initialization function. If the initialization function +succeeds, and the versions match, then the glue code determines +that the load was successful and the plugin is available for use. + +There are serveral types of plugins (note that a given plugin library +may contain any or all of the following in combination, though +such a plugin would be a beast!): + + +Mechanism Plugins + These plugins implement mechanisms + for authentication, and are the majority of the plugins included + with Cyrus SASL. Generally implementing both a client and a server + side they take care of the authentication process. +User Canonicalization Plugins + These plugins enable differing + ways of canonicalizing authentication and authorization IDs. +Auxiliary Property Plugins + These plugins allow auxilliary + properties about user accounts to be looked up, such as passwords. + Cyrus SASL includes a plugin to read sasldb files, for example. + + +Use of sasl_utils_t +------------------- + +Because of the way that shared library plugins are loaded for both +speed and namespace reasons, the symbol tables are not shared across +plugins. Thus, the only interface that the plugin should assume it +has to the outside world is through the ``sasl_utils_t`` structure (or +through links that it specifically requires). Likewise, the glue code +has no (and will use no) interface into the plugin other than the +contents of the structures that are passed back to it by the +initialization function. + +.. note:: + + Do not assume you have access to any + functions except through links that your library explicitly makes + or through what is provided via the ``sasl_utils_t`` structure. + +Error Reporting +--------------- + +Error reporting is very important for failed authentication tracking +and helping to debug installations or authentication problems. For +that reason, in addition to the standard SASL return codes, the +glue code provides an interface to its seterror function (via +``sasl_utils_t``). This function sets detailed error information for +a given connection. + +In order to ensure consistency of this information, it is the +responsibility of the deepest function with access to the sasl_conn_t +make the call to set the errdetail string. + +Memory Allocation +----------------- + +Memory allocation in SASLv2 follows the simple paradigm that **if you +allocate it, you free it**. This improves portability, and allows +for a large performance improvement over SASLv1. To prevent memory +leaks (especially in the mechanism plugins), please ensure that you +follow this paradigm. + +Client Send First / Server Send Last +------------------------------------ + +Mechanism plugins used to have to worry about the situation +where they needed clients to send first (or server to send last), yet +the protocol did not support it. Luckily, this is now handled by +the glue code, provided that the plugin declares the appropriate flags +in the structure returned by its init function. Thus, the step functions +will not have to worry about these issues and can be implemented +knowing they will be called only when the application actually has +data for them and/or will allow them to send data. These flags are as +follows: + +SASL_FEAT_WANT_CLIENT_FIRST + The mechanism has the client + side send first always. (e.g. PLAIN) +SASL_FEAT_SERVER_FIRST + The mechanism has the server side + send first always. (e.g. CRAM-MD5) + + +If neither flag is set, the mechanism will handle the client-send +first situation internally, because the client may or may not send +first. (e.g. DIGEST-MD5). In this case, the plugin must +intelligently check for the presence (or absence) of clientin/serverin +data. Note that the optional client send-first is only possible when the +protocol permits an initial response. + +The server send last situation is handled by the plugin intelligently +setting \*serverout when the step function returns SASL_OK. + +* For mechanisms + which never send last (e.g. PLAIN), \*serverout must be set to NULL. +* For + mechanisms which always send last (e.g. DIGEST-MD5), \*serverout must + point to the success data. +* For mechanisms in which the server may or + may not send last (e.g. SRP), \*serverout must be set accordingly. + +.. _plugprog-client: + +Client Plugins +============== + +Client-side mechanism plugins are generally included in the same +plugin with their :ref:`server ` counterpart, though +this is not a requirement. They take care of the client-side of the +SASL negotiation. For a simple example, see the ANONYMOUS plugin. +Client plugins must export ``sasl_client_plug_init`` which returns +a ``sasl_client_plug_t`` in order to load. The structure has +several functional members and a global context (which applies to +all connections using the plugin). The important ones are described +briefly here. + +mech_new + Called at the beginning of each connection, + (on a call to sasl_client_start), + + mech_new does mechanism-specific initialization, and if necessary + allocates a connection context (which the glue code keeps track + of for it). mech_new does not actually send any data to the client, + it simply allocates the context. + +mech_step + Called from ``sasl_client_start`` and + ``sasl_client_step``, this function does the actual work of + the client + side of the authentication. If authentication is successful, it + should return SASL_OK, otherwise it should return a valid SASL + error code (and call seterror). + + This should also set up the + oparams structure before returning SASL_OK, including any + security layer information (in the way of callbacks). + + Note + that as soon as the client has both the authentication and + authorization IDs, it MUST call the canon_user function provided + in its params structure (for both the authentication and + authorization IDs, with SASL_CU_AUTHID and SASL_CU_AUTHZID + respectively). + +mech_dispose + Called to dispose of a connection context. + This is only called when the connection will no longer be used + (e.g. when ``sasl_dispose`` is called) + +mech_free + Called when the sasl library is shutting down + (by ``sasl_client_done/sasl_server_done/sasl_done``). + Intended to free any global state of the plugin. + +.. _plugprog-server: + +Server Plugins +============== + +Server-side mechanism plugins are generally included in the same +plugin with their :ref:`client ` counterpart, though +this is not a requirement. They take care of the server-side of the +SASL negotiation, and are generally more complicated than their +client-side counterparts. For a simple example, see the ANONYMOUS +plugin. + +Server plugins must export ``sasl_server_plug_init`` which returns +a ``sasl_server_plug_t`` in order to load. The structure has +several functional members and a global context (which applies to +all connections using the plugin). The important ones are described +briefly here. + +mech_new + Called at the beginning of each connection, + (on a call to sasl_client_start), + + mech_new does mechanism-specific initialization, and if necessary + allocates a connection context (which the glue code keeps track + of for it). mech_new does not actually send any data to the client, + it simply allocates the context. + +mech_step + Called from ``sasl_server_start`` and + ``sasl_server_step``, this function does the actual work of + the server + side of the authentication. + + If authentication is successful, it + should return SASL_OK, otherwise it should return a valid SASL + error code (and call seterror). This should also set up the + oparams structure before returning SASL_OK, including any + security layer information (in the way of callbacks and SSF + information). + + Also, as soon + as the mechanism has computed both the authentication and the + authorization IDs, it MUST call the canon_user function provided + in the server params structure (for both the authentication and + authorization IDs, with SASL_CU_AUTHID and SASL_CU_AUTHZID + respectively). This action will also fill in its + propctx, so any auxiliary property *requests* + (for example, to lookup + the password) should be done before the request to canonicalize + the authentication id. Authorization ID lookups do not occur until + after the plugin returns success to the SASL library. + + Before returning SASL_OK, ``mech_step`` must fill in the + oparams fields for which it is responsible, that is, ``doneflag`` + (set to 1 to indicate a complete exchange), ``maxoutbuf``, or + the maximum output size it can do at once for a security layer, + ``mech_ssf`` or the supplied SSF of the security layer, + and ``encode``, ``decode``, ``encode_context``, + and ``decode_context``, + which are what the glue code will call on calls to ``sasl_encode``, + ``sasl_encodev``, and ``sasl_decode``. + +mech_dispose + Called to dispose of a connection context. + This is only called when the connection will no longer be used + (e.g. when ``sasl_dispose`` is called) + +mech_free + Called when the sasl library is shutting down + (by ``sasl_client_done/sasl_server_done/sasl_done``). + Intended to free any global state of the plugin. + +setpass + Called to set a user's password. This allows + mechanisms to support their own internal password or secret + database. + +mech_avail + Called by the first call to + ``sasl_listmech``, + it checks to see if the mechanism is available for the given + user, and MAY allocate a connection context (thus avoiding + a call to ``mech_new``). However it should not do this + without significant performance benefit as it forces the glue + code to keep track of extra contexts that may not be used. + +User Canonicalization (canon_user) Plugins +========================================== + +User Canonicalization plugins allow for nonstandard ways of +canonicalizing the username. They are subject to the following +requirements: + +* They must copy their output into the provided output buffers. +* The output buffers may be the same as the input buffers. +* They must function for the case which is only an authentication + ID (flags == SASL_CU_AUTHID) or only an authorization ID + (flags == SASL_CU_AUTHZID) or both + (flags == SASL_CU_AUTHID | SASL_CU_AUTHZID) + +User canonicalization plugins must export a ``sasl_canonuser_init`` +function which returns a ``sasl_canonuser_plug_t`` in order +to load successfully. They must implement at least one of +the ``canon_user_client`` or ``canon_user_server`` members +of the ``sasl_canonuser_plug_t``. The INTERNAL canon_user plugin +that is inside of the glue code implements both in the same way. + +Auxiliary Property (auxprop) Plugins +==================================== + +Perhaps the most exciting addition in SASLv2, Auxprop plugins +allow for an easy way to perform password and secret lookups (as well +as other information needed for authentication and authorization) +from directory services, and in the same request allow the application +to receive properties that it needs to provide the service. + +Auxprop plugins need to export the ``sasl_auxprop_init`` function +and pass back a ``sasl_auxprop_plug_t`` in order to load +successfully. The sasldb plugin included with the Cyrus SASL +distribution would be a good place to start. + +Interfacing with property contexts is extremely well documented in +``prop.h`` and so that is omitted here. The only important +note is to be sure that you are using the interfaces provided +through the ``sasl_utils_t`` structure and not calling +the functions directly. + +To successfully implement an auxprop plugin there is only one +required function to implement, that is the ``auxprop_lookup`` +member of the ``sasl_auxprop_plug_t``. This is called +just after canonicalization of the username, with the canonicalized +username. It can then do whatever lookups are necessary for any +of the requested auxiliary properties. diff --git a/docsrc/sasl/developer/programming.rst b/docsrc/sasl/developer/programming.rst new file mode 100644 index 00000000..9ddc0440 --- /dev/null +++ b/docsrc/sasl/developer/programming.rst @@ -0,0 +1,1101 @@ +.. _programming: + +============================== +Application Programmer's Guide +============================== + +.. note:: + + NOTE: This is a work in progress. Any contributions would be + *very* appreciated. + +.. contents:: + :local: + +Introduction +============ + +About this Guide +---------------- + +This guide gives a tutorial on the use of the Cyrus SASL library +for a client or server application. It complies with versions +including and after 2.0.0. The following pages should only be +considered a guide, not the final word on programming with the +Cyrus SASL library. Consult the header files in the distribution in +the case of ambiguities. + +What is SASL? +------------- + +SASL stands for Simple Authentication Security Layer and is +defined in :rfc:`2222`. That document is very difficult to understand however and +it should be unnecessary to consult it. + +Background +========== + +How did the world work before SASL? +----------------------------------- + +Before SASL, when a new protocol was written which required +authentication (users proving who they are to an entity), the +protocol had to allow explicitly for each individual authentication +mechanism. There had to be a distinct way to say "I want to log in +with Kerberos V4". There had to be another distinct way to say "I +want to log in with CRAM-MD5". There had to be yet a different way +to say "I want to log in anonymously," and so on. This was +not ideal for both the protocol and application writers. + +Additionally, many programmers were not very familiar with +security, so the protocol did support many mechanisms, or worse, +they were supported incorrectly. Moreover, when a new +authentication method was invented the protocol needed to be +modified to support that mechanism. + +This system also was not ideal for application writer. She had +to have a special case for each mechanism she wished her +application to support. Also, the mechanisms were difficult to +implement. Even with a good library, an understanding of how the +mechanism worked was still necessary. Finally if an application +used more than one protocol (for example a mail client might use +IMAP, POP, and SMTP) then "Kerberos V4 for IMAP", "Kerberos V4 for +POP", "Kerberos V4 for SMTP", "CRAM MD5 for IMAP", "CRAM-MD5 for +POP", etc... would need to be written. This could quickly create a +huge number of different mechanism-protocol pairs to implement. + +SASL to the rescue! +------------------- + +SASL hopefully solves all these problems. In practice it makes +many of them easier to deal with. + +Protocol designers simply have to support SASL (in particular +:rfc:`2222`). Consequently, any mechanism that supports SASL (just +about anything you would want to use does now) is supported by the +protocol. If a new authentication mechanism is invented the +protocol automatically supports it without any modifications. + +Application writers, instead of having to support every +mechanism for every protocol, only need to support SASL for every +protocol. Application writers do not need to understand the +authentication mechanisms at all: the SASL library handles all +that. Also with the Cyrus SASL library if a new mechanism is +invented you do not have rewrite your application at all. You may +not even have to restart your application if it is a long running +process. This is because the Cyrus SASL library loads each +mechanism from a shared library. Simply copying a shared library +into a directory will magically make your application support a new +mechanism. + +Cyrus SASL version 2 supports a much improved API over version +1, that allows for much smarter and faster memory allocation for +the mechanisms as well as the applications. It is also provides for +several new types of plugins to allow for greater overall +flexibility. Unfortunately, though similar, this new API is +completely incompatible with the old API, and applications will +need to be rewritten. + +Briefly +======= + +What is the Cyrus SASL library good for? +---------------------------------------- + +The Cyrus SASL library is good for applications that wish to use +protocols that support SASL authentication. An non-exhaustive list +of these are: IMAP, SMTP, ACAP, and LDAP. Also if you are making a +proprietary system and wish to support authentication it is a good +way of supporting many different authentication types. + +What does the Cyrus SASL library do? +------------------------------------ + +From a client point of view, the Cyrus SASL library, given a +list of mechanisms the server supports it will decide the best +mechanism to use and tell you what to send to the server at each +step of the authentication. From a server perspective, it handles +authentication requests from clients. + +What doesn't the Cyrus SASL library do? +--------------------------------------- + +The Cyrus SASL library is neither network nor protocol aware. It +is up to the application to send the data over the wire as well as +to send the data in the protocol specific manner. With IMAP this +means putting it in the form: ``+ [base64'ed data]\\r\\n``. LDAP +just sends data in binary via bind requests. The Cyrus SASL library +has utility base64 encode and decode routines to help with +this. + +Client-only Section +=================== + +A typical interaction from the client's perspective +--------------------------------------------------- + + +* A client makes a few calls (explained later) to initialize + SASL. + +* Every time the client application makes a new connection it + should make a new context that is kept for the life of the + connection. + +* Ask the server for the list of supported mechanisms + +* Feed this list to the library + +* Start the authentication with the mechanism the library + chose + +* The server will return some bytes + +* Give these to the library + +* The library returns some bytes to the application + +* Application sends these bytes over the network + +* repeat the last 4 steps until the server tells you that the + authentication is completed + + +How does this look in code +-------------------------- + +1. Initialize the library +######################### + +This is done once. + +.. code-block:: c + + int result; + + /* attempt to start sasl + * See the section on Callbacks and Interactions for an + * explanation of the variable callbacks + */ + + result=sasl_client_init(callbacks); + + /* check to see if that worked */ + if (result!=SASL_OK) [failure] + +2. Make a new SASL connection +############################# + +For every network connection, make a new SASL connection: + +.. code-block:: c + + /* The SASL context kept for the life of the connection */ + sasl_conn_t *conn; + + + /* client new connection */ + result=sasl_client_new("imap", /* The service we are using */ + serverFQDN, /* The fully qualified domain + name of the server we're + connecting to */ + NULL, NULL, /* Local and remote IP + address strings + (NULL disables mechanisms + which require this info)*/ + NULL, /* connection-specific + callbacks */ + 0, /* security flags */ + &conn); /* allocated on success */ + + /* check to see if that worked */ + if (result!=SASL_OK) [failure] + + +3. Get the mechanism list +######################### + +Next get the list of SASL mechanisms the server supports. This is +usually done through a capability command. Format the list as a +single string separated by spaces. Feed this string into SASL to +begin the authentication process. + +.. code-block:: c + + sasl_interact_t *client_interact=NULL; + const char *out, *mechusing; + unsigned outlen; + + do { + + result=sasl_client_start(conn, /* the same context from + above */ + mechlist, /* the list of mechanisms + from the server */ + &client_interact, /* filled in if an + interaction is needed */ + &out, /* filled in on success */ + &outlen, /* filled in on success */ + &mechusing); + + if (result==SASL_INTERACT) + { + [deal with the interactions. See interactions section below] + } + + + } while (result==SASL_INTERACT); /* the mechanism may ask us to fill + in things many times. result is + SASL_CONTINUE on success */ + if (result!=SASL_CONTINUE) [failure] + + +Note that you do not need to worry about the allocation and freeing +of the output buffer out. This is all handled inside of the +mechanism. It is important to note, however, that the output buffer +is not valid after the next call to ``sasl_client_start`` or +``sasl_client_step``. + +If this is successful send the protocol specific command to +start the authentication process. This may or may not allow for +initial data to be sent (see the documentation of the protocol to +see). + +4. Start authentication +####################### + +* For IMAP this might look like:: + + {tag} "AUTHENTICATE" {mechusing}\r\n + A01 AUTHENTICATE KERBEROS_V4\r\n + +* SMTP looks like:: + + "AUTH" {mechusing}[ {out base64 encoded}] + AUTH DIGEST-MD5 GHGJJGDDFDKHGHJG= + + +.. _client_authentication_step: + +5. Check Results +################ + +Read what the server sent back. It can be one of three +things: + +1. Authentication failure. Authentication process is halted. This + might look like ``A01 NO Authentication failure`` in IMAP or + ``501 Failed`` in SMTP. Either retry the authentication or + abort. + +2. Authentication success. We're now successfully authenticated. + This might look like ``A01 OK Authenticated successful`` in + IMAP or ``235 Authentication successful`` in SMTP. Go :ref:`here `. + +3. Another step in the authentication process is necessary. This + might look like ``+ HGHDS1HAFJ=`` in IMAP or ``334 + PENCeUxFREJoU0NnbmhNWitOMjNGNndAZWx3b29kLmlubm9zb2Z0LmNvbT4=`` + in SMTP. Note it could be an empty string such as ``+ \r\n`` + in IMAP. + + +Convert the continuation data to binary format (for example, this +may include base64 decoding it). Perform another step in the +authentication. + +.. code-block:: c + + do { + result=sasl_client_step(conn, /* our context */ + in, /* the data from the server */ + inlen, /* it's length */ + &client_interact, /* this should be + unallocated and NULL */ + &out, /* filled in on success */ + &outlen); /* filled in on success */ + + if (result==SASL_INTERACT) + { + [deal with the interactions. See below] + } + + + } while (result==SASL_INTERACT || result == SASL_CONTINUE); + + if (result!=SASL_OK) [failure] + + +Format the output (variable out of length outlen) in the protocol +specific manner and send it across the network to the server. + +Go :ref:`back to check results ` (this process +repeats until authentication either succeeds or fails. + +.. _client_authentication_success: + +6. Authentication Successful +############################ + +Before we're done we need to call sasl_client_step() one more +time to make sure the server isn't trying to fool us. Some +protocols include data along with the last step. If so this data +should be used here. If not use a length of zero. + +.. code-block:: c + + result=sasl_client_step(conn, /* our context */ + in, /* the data from the server */ + inlen, /* it's length */ + &client_interact, /* this should be unallocated and NULL */ + &out, /* filled in on success */ + &outlen); /* filled in on success */ + + if (result!=SASL_OK) [failure] + +Congratulations. You have successfully authenticated to the +server. + +Don't throw away the SASL connection object (sasl_conn_t \*) yet +though. If a security layer was negotiated you will need it to +encode and decode the data sent over the network. + +7. Cleaning up +############## + +When you are finally done with connection to server, dispose of +SASL connection. + +.. code-block:: c + + sasl_dispose(&conn); + + +If you are done with SASL forever (application quiting for +example): + +.. code-block:: c + + sasl_client_done(); + +Or if your application is both a SASL client and a SASL server: + +.. code-block:: c + + sasl_done(); + +But note that applications should be using sasl_client_done()/sasl_server_done() whenever possible. + +sasl_client_init +---------------- + +.. code-block:: c + + int sasl_client_init(const sasl_callback_t *callbacks) + +callbacks + List of :ref:`callbacks ` + +This function initializes the SASL library. This must be called +before any other SASL calls. + +sasl_client_new +--------------- + +.. code-block:: c + + int sasl_client_new(const char *service, + const char *serverFQDN, + const char *iplocalport, + const char *ipremoteport, + const sasl_callback_t *prompt_supp, + unsigned secflags, + sasl_conn_t **pconn) + +service + the service name being used. This usually is the + protocol name (e.g. "ldap") +serverFQDN + Fully qualified domain name of server +iplocalport and ipremoteport + a string of the format + "a.b.c.d;p" detailing the local or remote IP + and port, or NULL (which will disable + mechanisms that require this information) +prompt_supp + List of :ref:`callbacks ` specific to this + connection +secflags + security flags ORed together requested (e.g. + SASL_SEC_NOPLAINTEXT) +pconn + the SASL connection object allocated upon success + +This function creates a new SASL connection object. It should be +called once for every connection you want to authenticate for. + + +sasl_client_start +----------------- + +.. code-block:: c + + int sasl_client_start(sasl_conn_t *conn, + const char *mechlist, + sasl_interact_t **prompt_need, + const char **clientout, + unsigned *clientoutlen, + const char **mech); + +conn + the SASL connection object gotten from sasl_client_new() +mechlist + the list of mechanisms to try (separated by spaces) +prompt_need + filled in when a SASL_INTERACT is returned +clientout + filled in upon success with data to send to server +clientoutlen + length of that data +mech + filled in with mechanism being used + +This function starts an authentication session. It takes a list of +possible mechanisms (usually gotten from the server through a +capability command) and chooses the "best" mechanism to try. Upon +success clientout points at data to send to the server. + +sasl_client_step +---------------- + +.. code-block:: c + + int sasl_client_step(sasl_conn_t *conn, + const char *serverin, + unsigned serverinlen, + sasl_interact_t **prompt_need, + const char **clientout, + unsigned *clientoutlen); + +conn + the SASL connection object gotten from sasl_client_new() +serverin + data from the server +serverinlen + length of data from the server +prompt_need + filled in with a SASL_INTERACT is returned +clientout + filled in upon success with data to send to server +clientoutlen + length of that data + +This step preforms a step in the authentication process. It takes +the data from the server (serverin) and outputs data to send to the +server (clientout) upon success. SASL_CONTINUE is returned if +another step in the authentication process is necessary. SASL_OK is +returned if we're all done. + +Server-only Section +=================== + +A typical interaction from the server's perspective +--------------------------------------------------- + +The server makes a few Cyrus SASL calls for initialization. When it +gets a new connection it should make a new context for that +connection immediately. The client may then request a list of +mechanisms the server supports. The client also may request to +authenticate at some point. The client will specify the mechanism +it wishes to use. The server should negotiate this authentication +and keep around the context afterwards for encoding and decoding +the layers. + +How does this look in code? +--------------------------- + +Initialization +############## + +This is done once. The application name is used for +reading configuration information. + +.. code-block:: c + + int result; + + /* Initialize SASL */ + result=sasl_server_init(callbacks, /* Callbacks supported */ + "TestServer"); /* Name of the application */ + + +This should be called for each new connection. It probably should +be called right when the socket is accepted. + +.. code-block:: c + + sasl_conn_t *conn; + int result; + + /* Make a new context for this connection */ + result=sasl_server_new("smtp", /* Registered name of service */ + NULL, /* my fully qualified domain name; + NULL says use gethostname() */ + NULL, /* The user realm used for password + lookups; NULL means default to serverFQDN + Note: This does not affect Kerberos */ + NULL, NULL, /* IP Address information strings */ + NULL, /* Callbacks supported only for this connection */ + 0, /* security flags (security layers are enabled + * using security properties, separately) + &conn); + + +When a client requests the list of mechanisms supported by the +server. This particular call might produce the string: ``{PLAIN, +KERBEROS_V4, CRAM-MD5, DIGEST-MD5}`` + +.. code-block:: c + + result=sasl_listmech(conn, /* The context for this connection */ + NULL, /* not supported */ + "{", /* What to prepend the string with */ + ", ", /* What to separate mechanisms with */ + "}", /* What to append to the string */ + &result_string, /* The produced string. */ + &string_length, /* length of the string */ + &number_of_mechanisms); /* Number of mechanisms in + the string */ + + +When a client requests to authenticate: + +.. code-block:: c + + int result; + const char *out; + unsigned outlen; + + result=sasl_server_start(conn, /* context */ + mechanism_client_chose, + clientin, /* the optional string the client gave us */ + clientinlen, /* and it's length */ + &out, /* The output of the library. + Might not be NULL terminated */ + &outlen); + + if ((result!=SASL_OK) && (result!=SASL_CONTINUE)) + [failure. Send protocol specific message that says authentication failed] + else if (result==SASL_OK) + [authentication succeeded. Send client the protocol specific message + to say that authentication is complete] + else + [send data 'out' with length 'outlen' over the network in protocol + specific format] + +When a response is returned by the client. ``clientin`` is the +data from the client decoded from protocol specific format to a +string of bytes of length ``clientinlen``. This step may occur +zero or more times. An application must be able to deal with it +occurring an arbitrary number of times. + +.. code-block:: c + + int result; + + result=sasl_server_step(conn, + clientin, /* what the client gave */ + clientinlen, /* it's length */ + &out, /* allocated by library on success. + Might not be NULL terminated */ + &outlen); + + if ((result!=SASL_OK) && (result!=SASL_CONTINUE)) + [failure. Send protocol specific message that says authentication failed] + else if (result==SASL_OK) + [authentication succeeded. Send client the protocol specific message + to say that authentication is complete] + else + [send data 'out' with length 'outlen' over the network in protocol + specific format] + + +This continues until authentication succeeds. When the connection +is concluded, make a call to ``sasl_dispose`` as with the +client connection. + +sasl_server_init +---------------- + +.. code-block:: c + + int sasl_server_init(const sasl_callback_t *callbacks, + const char *appname); + +callbacks + A list of :ref:`callbacks ` supported by the application +appname + A string of the name of the application. This string + is what is used when loading configuration options. + +sasl_server_init() initializes the session. This should be the +first function called. In this function the shared library +authentication mechanisms are loaded. + +sasl_server_new +--------------- + +.. code-block:: c + + int sasl_server_new(const char *service, + const char *serverFQDN, + const char *user_realm, + const char *iplocalport, + const char *ipremoteport, + const sasl_callback_t *callbacks, + unsigned secflags, + sasl_conn_t **pconn); + +service + The name of the service you are supporting. This + might be "acap" or "smtp". This is used by Kerberos mechanisms and + possibly other mechanisms. It is also used for PAM + authentication. +serverFQDN + This is the fully qualified domain name of the + server (i.e. your hostname); if NULL, the library calls + ``gethostbyname()``. +user_realm + The realm the connected client is in. The Kerberos + mechanisms ignore this parameter and default to the local Kerberos + realm. A value of NULL makes the library default, usually to the + serverFQDN; a value of "" specifies that the client should specify + the realm; this also changes the semantics of "@" in a username for + mechanisms that don't support realms. +iplocalport and ipremoteport + a string of the format + "a.b.c.d;p" detailing the local or remote IP and port, or NULL + (which will disable mechanisms that require this information) +callbacks + Additional :ref:`callbacks ` that you wish only to apply to + this connection. +secflags + security flags. +pconn + Context. Filled in on success. + +sasl_server_start +----------------- + +.. code-block:: c + + int sasl_server_start(sasl_conn_t *conn, + const char *mech, + const char *clientin, + unsigned clientinlen, + const char **serverout, + unsigned *serveroutlen); + +conn + The context for the connection +mech + The authentication mechanism the client wishes to try + (e.g. ``KERBEROS_V4``) +clientin + Initial client challenge bytes. Note: some protocols + do not allow this. If this is the case passing NULL is valid +clientinlen + The length of the challenge. 0 if there is none. +serverout + allocated and filled in by the function. These are + the bytes that should be encoded as per the protocol and sent over + the network back to the client. +serveroutlen + length of bytes to send to client + +This function begins the authentication process with a client. If +the program returns SASL_CONTINUE that means ``serverout`` +should be sent to the client. If SASL_OK is returned that means +authentication is complete and the application should tell the +client the authentication was successful. Any other return code +means the authentication failed and the client should be notified +of this. + +sasl_server_step +---------------- + +.. code-block:: c + + int sasl_server_step(sasl_conn_t *conn, + const char *clientin, + unsigned clientinlen, + const char **serverout, + unsigned *serveroutlen); + +conn + The context for the connection +clientin + Data sent by the client. +clientinlen + The length of the client data. Note that this may be 0 +serverout + allocated and filled in by the function. These are + the bytes that should be encoded as per the protocol and sent over + the network back to the client. +serveroutlen + length of bytes to send to client. Note that this may be 0 + +This function preforms a step of the authentication. This may need +to be called an arbitrary number of times. If the program returns +SASL_CONTINUE that means ``serverout`` should be sent to the +client. If SASL_OK is returned that means authentication is +complete and the application should tell the client the +authentication was successful. Any other return code means the +authentication failed and the client should be notified of this. + +sasl_listmech +------------- + +.. code-block:: c + + int sasl_listmech(sasl_conn_t *conn, + const char *user, + const char *prefix, + const char *sep, + const char *suffix, + const char **result, + unsigned *plen, + unsigned *pcount); + +conn + The context for this connection +user + Currently not implemented +prefix + The string to prepend +sep + The string to separate mechanisms with +suffix + The string to end with +result + Resultant string +plen + Number of characters in the result string +pcount + Number of mechanisms listed in the result string + +This function is used to create a string with a list of SASL +mechanisms supported by the server. This string is often needed for +a capability statement. + +sasl_checkpass +-------------- + +.. code-block:: c + + int sasl_checkpass(sasl_conn_t *conn, + const char *user, + unsigned userlen, + const char *pass, + unsigned passlen); + +conn + The context for this connection +user + The user trying to check the password for +userlen + The user length +pass + The password +passlen + The password length + +This checks a plaintext password for a user. +Some protocols have legacy systems for plaintext authentication +where this might be used. + +Common Section +============== + +.. _callbacks: + +Callbacks and Interactions +-------------------------- + +When the application starts and calls sasl_client_init() you must +specify for what data you support callbacks and/or interactions. + +These are for the library getting information needed for +authentication from the application. This is needed for things like +authentication name and password. If you do not declare supporting +a callback you will not be able to use mechanisms that need that +data. + +A *callback* is for when you have the information before you +start the authentication. The SASL library calls a function you +specify and your function fills in the requested information. For +example if you had the userid of the user already for some reason. + +An *interaction* is usually for things you support but will need to +ask the user for (e.g. password). sasl_client_start() or +sasl_client_step() will return SASL_INTERACT. This will be a list +of sasl_interact_t's which contain a human readable string you can +prompt the user with, a possible computer readable string, and a +default result. The nice thing about interactions is you get them +all at once so if you had a GUI application you could bring up a +dialog box asking for authentication name and password together +instead of one at a time. + +Any memory that is given to the SASL library for the purposes of +callbacks and interactions must persist until the exchange +completes in either success or failure. That is, the data must +persist until ``sasl_client_start`` or +``sasl_client_step`` returns something other than +``SASL_INTERACT`` or ``SASL_CONTINUE``. + +Memory management + As in the rest of the SASLv2 API, + whoever allocates the memory is responsible for freeing it. In + almost all cases this should be fairly easy to manage, however a + slight exception where the interaction sasl_interact_t structure is + allocated and freed by the library, while the results are allocated + and freed by the application. As noted above, however, the + results may not be freed until after the exchange completes, in + either success or failure. + +For a detailed description of what each of the callback types +are see the sasl.h file. Here are some brief explanations: + +SASL_CB_AUTHNAME + the name of the user authenticating +SASL_CB_USER + the name of the user acting for. (for example + postman delivering mail for tmartin might have an AUTHNAME of + postman and a USER of tmartin) +SASL_CB_PASS + password for AUTHNAME +SASL_CB_GETREALM + Realm of the server + +An example of a way to handle callbacks: + +.. code-block:: c + + /* callbacks we support. This is a global variable at the + top of the program */ + static sasl_callback_t callbacks[] = { + { + SASL_CB_GETREALM, NULL, NULL /* we'll just use an interaction if this comes up */ + }, { + SASL_CB_USER, NULL, NULL /* we'll just use an interaction if this comes up */ + }, { + SASL_CB_AUTHNAME, &getauthname_func, NULL /* A mechanism should call getauthname_func + if it needs the authentication name */ + }, { + SASL_CB_PASS, &getsecret_func, NULL /* Call getsecret_func if need secret */ + }, { + SASL_CB_LIST_END, NULL, NULL + } + }; + + + static int getsecret_func(sasl_conn_t *conn, + void *context __attribute__((unused)), + int id, + sasl_secret_t **psecret) + { + [ask the user for their secret] + + [allocate psecret and insert the secret] + + return SASL_OK; + } + + static int getauthname_func(void *context, + int id, + const char **result, + unsigned *len) + { + if (id!=SASL_CB_AUTHNAME) return SASL_FAIL; + + [fill in result and len] + + return SASL_OK; + } + + +in the main program somewhere + +.. code-block:: c + + sasl_client_init(callbacks); + + +Security layers +--------------- + +All is well and good to securely authenticate, but if you don't +have some sort of integrity or privacy layer, anyone can hijack +your TCP session after authentication. If your application has +indicated that it can support a security layer, one might be +negotiated. + +To set that you support a security layer, set a security +property structure with ``max_ssf`` set to a non-zero +number: + +.. code-block:: c + + sasl_security_properties_t secprops; + + secprops.min_ssf = 0; + secprops.max_ssf = 256; + secprops.maxbufsize = /* SEE BELOW */; + + secprops.property_names = NULL; + secprops.property_values = NULL; + secprops.security_flags = SASL_SEC_NOANONYMOUS; /* as appropriate */ + + sasl_setprop(conn, SASL_SEC_PROPS, &secprops); + +The ``secprops`` variable will be copied during the call to +``sasl_setprop``, so you may free its memory immediately. The +SSF stands for "security strength factor" and is a +rough indication of how secure the connection is. A connection +supplying only integrity with no privacy would have an SSF of 1. A +connection secured by 56-bit DES would have an SSF of 56. + +To require a security layer, set ``min_ssf`` to the minimum +acceptable security layer strength. + +After authentication is successful, you can determine whether or +not a security layer has been negotiated by looking at the SASL_SSF +property: + +.. code-block:: c + + const int *ssfp; + + result = sasl_getprop(conn, SASL_SSF, (const **) &ssfp); + if (result != SASL_OK) { + /* ??? */ + } + if (*ssfp > 0) { + /* yay, we have a security layer! */ + } + +If a security layer has been negotiated, your application must +make use of the ``sasl_encode()`` and ``sasl_decode()`` +calls. All output must be passed through ``sasl_encode()`` +before being written to the wire; all input must be passed through +``sasl_decode()`` before being looked at by the application. +Your application must also be prepared to deal with +``sasl_decode()`` not returning any data in the rare case that +the peer application did something strange (by splitting a single +SASL blob into two seperate TCP packets). + +The only subtlety dealing with security layers is the maximum size +of data that can be passed through ``sasl_encode()`` or +``sasl_decode()``. This must be limited to make sure that only +a finite amount of data needs to be buffered. The simple rules to +follow: + +* Before starting authentication, set ``maxbufsize`` in your + security properties to be the buffer size that you pass to the + ``read()`` system call—that is, the amount of data + you're prepared to read at any one time. + +* After authentication finishes, use ``sasl_getprop()`` to + retrieve the ``SASL_MAXOUTBUF`` value, and call + ``sasl_encode()`` with chunks of data of that size or less. + ``sasl_encode()`` will throw an error if you call it with a + larger chunk of data, so be careful! + +Memory management + As usual, whoever allocates the memory + must free it. The SASL library will keep the data returned from + ``sasl_encode()`` until the next call to ``sasl_encode()`` + on that connection. (``sasl_decode()`` results persist until the + next call to ``sasl_decode()`` on that connection.) The + application must not attempt to free the memory returned from either + function. + +Internally + * your application sets SASL_SEC_PROPS with the buffer size X of + the amount of data it will be using to read() from the socket. + * libsasl passes this number to the mechanism. + * the mechanism passes this number to the other side. the other + side gives the corresponding read() size to our side. + * the mechanism subtracts the overhead of the layers from the + size retrieved from the other side and returns it to the + libsasl. + * libsasl then returns (via SASL_MAXOUTBUF) this number as the + maximum amount of plaintext material that can be encoded at any one + time, Y. + * sasl_encode() enforces the restriction of the length Y. + +Example applications that come with the Cyrus SASL library +========================================================== + +`sample-client` and `sample-server` +--------------------------------------- + +The sample client and server included with this distribution were +initially written to help debug mechanisms. They base64 encode all +the data and print it out on standard output. + +Make sure that you set the IP addresses, the username, the +authenticate name, and anything else on the command line (some +mechanisms depend on these being present). + +Also, sometimes you will receive a ``realm: Information +not available`` message, or similar; this is due to the fact +that some mechanisms do not support realms and therefore never set +it. + +Cyrus imapd v2.1.0 or later +--------------------------- + +The Cyrus IMAP server now incorporates SASLv2 for all its +authentication needs. It is a good example of a fairly large server +application. Also of interest is the prot layer, included in +libcyrus. This is a stdio-like interface that automatically takes +care of layers using a simple ``prot_setsasl()`` call. + +Cyrus imapd also sets a ``SASL_CB_PROXY_POLICY`` callback, +which should be of interest to many applications. + +`imtest`, from Cyrus 2.1.0 or later +------------------------------------- + +``imtest`` is an application included with Cyrus imapd. It is +a very simple IMAP client, but should be of interest to those +writing applications. It also uses the prot layer, but it is easy +to incorporate similar support without using the prot layer. +Likewise, there are other sample client applications that you can +look at including ``smtptest`` and ``pop3test`` in the +SASL distribution and the Cyrus IMAPd distribution, respectively. + +Miscellaneous Information +========================= + +Empty exchanges +--------------- + +Some SASL mechanisms intentionally send no data; an application +should be prepared to either send or receive an empty exchange. The +SASL profile for the protocol should define how to send an empty +string; make sure to send an empty string when requested, and when +receiving an empty string make sure that the ``inlength`` +passed in is 0. + +Note especially that the distinction between the empty string "" +and the lack of a string (NULL) is extremely important in many +cases (most notably, the client-send first scenario), and the +application must ensure that it is passing the correct values to +the SASL library at all times. + +Idle +---- + +While the implementation and the plugins correctly implement the +idle calls, none of them currently do anything. diff --git a/docsrc/sasl/developer/testing.rst b/docsrc/sasl/developer/testing.rst new file mode 100644 index 00000000..59016d63 --- /dev/null +++ b/docsrc/sasl/developer/testing.rst @@ -0,0 +1,95 @@ +.. _testing: + +======= +Testing +======= + +.. note:: + + This document is mainly useful for people doing libsasl development + or users having a lot of difficulty getting libsasl to work. + +Testing the CMU SASL Library with the included sample applications +================================================================== + +The CMU SASL library comes with two small sample programs: +sample-client and sample-server. Each of these programs dump base-64 +SASL iterations to STDOUT, and read the next iteration from STDIN. +Lines preceded by "C: " are from the client, and from "S: " are from +the server. + +This makes it fairly straightforward to test mechanisms; simply run +the sample-client on the "client" machine, and sample-server on the +"server" machine. + +Both programs take a -m MECH command line argument; this can be used +to force the mechanism used in the exchange. KERBEROS_V4 requires +that the IP addresses of both client and server be set, along with the +service name, and the server's fully-qualified hostname; these are +done through more command line arguments. + +Example +------- + +Here's the client side of an exchange. The mechanism selection code +chooses KERBEROS_V4; negotiation takes place, and the client is +authenticated. This is being run on the machine SPOOKY.ANDREW.CMU.EDU +(128.2.121.162), pretending to be talking to an "rcmd" service running +on port 23 (note the semicolons in the IP address. There is a strong +chance these will need to be escaped for proper interpretation by the shell): + +:: + + > ./sample-client -i local=128.2.121.162;23,remote=128.2.121.162;23 -s rcmd -n SPOOKY.ANDREW.CMU.EDU + Waiting for mechanism list from server... + S: UExBSU4gQU5PTllNT1VTIEtFUkJFUk9TX1Y0IERJR0VTVC1NRDUgQ1JBTS1NRDUgAAAAAED5EEA= + Choosing best mechanism from: PLAIN ANONYMOUS KERBEROS_V4 DIGEST-MD5 CRAM-MD5 + Using mechanism KERBEROS_V4 + Preparing initial. + Sending initial response... + C: S0VSQkVST1NfVjQA + Waiting for server reply... + S: hVQFjA== + Sending response... + C: BAYCQU5EUkVXLkNNVS5FRFUAOCDnIsZLQRdjLHXvzPNgpURYVj1iMqBIcTRaMpEQ8vWeYnfB+mTCVEa2URpkVgpzS1161MAX7ERzFV/EfGKlrAhGJCdN56mQ3eL2PzJlK7Z9ctKv4gKErcmV + Waiting for server reply... + S: BgcvFb63CLs= + Sending response... + C: ohBT+Jqab9zmDzclN7GSTw== + Negotiation complete + > + + +Here's the server side of the same dialog: + +:: + + > ./sample-server -s rcmd -i local=128.2.121.162;23,remote=128.2.121.162;23 + Generating client mechanism list... + Sending list of 5 mechanism(s) + S: UExBSU4gQU5PTllNT1VTIEtFUkJFUk9TX1Y0IERJR0VTVC1NRDUgQ1JBTS1NRDUgAAAAAED5EEA= + Waiting for client mechanism... + C: S0VSQkVST1NfVjQA + Sending response... + S: hVQFjA== + Waiting for client reply... + C: BAYCQU5EUkVXLkNNVS5FRFUAOCDnIsZLQRdjLHXvzPNgpURYVj1iMqBIcTRaMpEQ8vWeYnfB+mTCVEa2URpkVgpzS1161MAX7ERzFV/EfGKlrAhGJCdN56mQ3eL2PzJlK7Z9ctKv4gKErcmV + Sending response... + S: BgcvFb63CLs= + Waiting for client reply... + C: ohBT+Jqab9zmDzclN7GSTw== + Negotiation complete + Username: rob + Realm: ANDREW.CMU.EDU + SSF: 56 + > + + +Running the Testsuite application +================================= + +The Testsuite application in the utils directory tries out all the +functionality of libsasl against itself. When you run the application +it displays some requirments for running, such as being able to read +and write to the sasldb file. If this program is set up correctly and +still fails we'd like to hear about it at cyrus-bugs@andrew.cmu.edu. diff --git a/docsrc/sasl/faq.rst b/docsrc/sasl/faq.rst new file mode 100644 index 00000000..ac1651e8 --- /dev/null +++ b/docsrc/sasl/faq.rst @@ -0,0 +1,12 @@ +.. _sasl-faq: + +Frequently Asked Questions +========================== + +.. toctree:: + :maxdepth: 2 + :glob: + + faqs/* + +Looking for the :ref:`Cyrus IMAP FAQ `? \ No newline at end of file diff --git a/docsrc/sasl/faqs/authorize-vs-authenticate.rst b/docsrc/sasl/faqs/authorize-vs-authenticate.rst new file mode 100644 index 00000000..9a26d5f1 --- /dev/null +++ b/docsrc/sasl/faqs/authorize-vs-authenticate.rst @@ -0,0 +1,38 @@ +What is the difference between an Authorization ID and a Authentication ID? +--------------------------------------------------------------------------- + +**Authentication** is the act of proving who you are. "Hello, I'm Dave. To +prove it, here's my password: Foo." + +**Authorization** is the act of deciding +whether to grant access to resources. + +:: + + "I'd like to read Kellie's mail for her." + +In the example, I'm trying to read my wife's mail. I supply my own +username as the "authentication identifier", my own password (Or +biometric scan, or whatever else is required to prove I'm really me, +with whichever mechanism is in use), and my wife's username as the +"authorization identifier". + +At no point need I know my wife's password - instead, either Kellie or +an administrator needs to explicitly state that I am allowed in "as +Kellie". Once I've logged in, all the access checks are done against +Kellie, not against Dave, because I'm acting for her. To all intents and +purposes, after the authentication exchange itself, the server can +simply forget about who authenticated - it's not important any more - +and concentrate on who needs to be authorized. + +Another, more common example of the use of differing authentication +identifiers and authorization identifiers is in the design of many proxy +systems. You authenticate perfectly normally to the proxy, authorizing +as yourself. The proxy then authenticates to the master as itself, but +supplies you as the authorization identifier, thus getting all the right +access checks done at source, but not having to have access to your +authentication credentials. Finally, some mechanisms don't support +passing a distinct authorization identifier, and for most its optional, +and defaults to the case that most people are familiar with, where +authorization and authentication identifiers are the same. + diff --git a/docsrc/sasl/faqs/crammd5-digestmd5.rst b/docsrc/sasl/faqs/crammd5-digestmd5.rst new file mode 100644 index 00000000..84bf4d7b --- /dev/null +++ b/docsrc/sasl/faqs/crammd5-digestmd5.rst @@ -0,0 +1,14 @@ +Why do CRAM-MD5 and DIGEST-MD5 not work with CyrusSaslauthd? +------------------------------------------------------------ + +Saslauthd is only capable of verifying plaintext passwords (it takes a +plaintext password and a username and responds with "yes" or "no", +essentially). Therefore, since the plaintext password isn't passed from +client to server in DIGEST-MD5 and CRAM-MD5, Saslauthd can't verify the +password. + +Authentication in a CyrusSaslauthd-only environment will not only fail +with these mechanisms, it doesn't really make a lot of sense. You'll +want to use an AuxpropPlugin instead (for example, sasldb). + + diff --git a/docsrc/sasl/faqs/openldap-sasl-gssapi.rst b/docsrc/sasl/faqs/openldap-sasl-gssapi.rst new file mode 100644 index 00000000..8ece4e51 --- /dev/null +++ b/docsrc/sasl/faqs/openldap-sasl-gssapi.rst @@ -0,0 +1,81 @@ +How do I configure OpenLDAP +SASL+GSSAPI? +----------------------------------------- + +This article assumes that you have read and followed the SASL chapter of the `OpenLDAP Administrator's Guide `_. You should have a Kerberos server installed (such as Heimdal or MIT), and created all the appropriate principals (client and service) necessary. + +To verify that you have the Cyrus :ref:`GSSAPI ` mechanism properly installed, use the pluginviewer command. For instance:: + + server:~# pluginviewer | grep -i gssapi + CRAM-MD5 PLAIN NTLM GSSAPI OTP DIGEST-MD5 ANONYMOUS LOGIN EXTERNAL + Plugin "gssapiv2" [loaded], API version: 4 + SASL mechanism: GSSAPI, best SSF: 56, supports setpass: no + CRAM-MD5 PLAIN NTLM GSSAPI OTP DIGEST-MD5 ANONYMOUS LOGIN EXTERNAL + Plugin "gssapiv2" [loaded], API version: 4 + SASL mechanism: GSSAPI, best SSF: 56 + +Both your server and client systems will need to have this mechanism installed. If not, you may find the mechanism located in a binary package that you do not yet have installed, or you may need to recompile your Cyrus SASL installation. + +On your client system, search the Root DSE of the server to view advertised mechanisms:: + + client:~# ldapsearch -LLL -x -H ldap://ldap.example.org -s "base" -b "" supportedSASLMechanisms + dn: + supportedSASLMechanisms: DIGEST-MD5 + supportedSASLMechanisms: NTLM + supportedSASLMechanisms: GSSAPI + supportedSASLMechanisms: OTP + supportedSASLMechanisms: CRAM-MD5 + +If you received a No Such Object error, you may have an `ACL misconfiguration on your server `_. + +If you do not see GSSAPI listed, verify that the server can read the appropriate keytab. The default is ``/etc/krb5.keytab`` and is typically only readable by the root user. If your Kerberos library supports it, you can create a keytab in an alternate location, such as ``/etc/krb5.keytab-ldap``, with only your LDAP service principal, and read permissions for your OpenLDAP user. + +If your OpenLDAP server is looking for an unexpected principal within your keytab, use sasl-host and sasl-realm to influence which principal it will use (see the slapd.conf man page). + +For more control over how the SASL library operates within the OpenLDAP? server, you can create a slapd.conf SASL configuration. This is not the same configuration file as the OpenLDAP configuration (slapd.conf). The location of this file is dependent how on Cyrus SASL was compiled (via the ``--with-plugindir`` option during configure). It is the directory where your plugins are installed. + +For instance, if you create /usr/lib/sasl2/slapd.conf (assuming that is the correct location on your system) with the following contents:: + + keytab: /etc/krb5.keytab-ldap + mech_list: CRAM-MD5 DIGEST-MD5 GSSAPI + +then the server will search within /etc/krb5.keytab-ldap when initializing the GSSAPI plugin. The server will only offer the mechanisms listed in mech_list. If mech_list is not specified, the server will offer all the mechanisms available, and that it can initialize. + +Once you have verified that the server is advertising GSSAPI support, then try:: + + client:~# ldapsearch -LLL -Y GSSAPI -H ldap://ldap.example.org -s "base" -b "" supportedSASLMechanisms + SASL/GSSAPI authentication started + SASL username: host/client.example.org@EXAMPLE.ORG + SASL SSF: 56 SASL data security layer installed. + dn: + supportedSASLMechanisms: DIGEST-MD5 + supportedSASLMechanisms: NTLM + supportedSASLMechanisms: GSSAPI + supportedSASLMechanisms: OTP + supportedSASLMechanisms: CRAM-MD5 + +If you receive a list of mechanisms, then congratulations, you're done. + +If instead you receive an error, then it's possible that your client is requesting a service principal that mismatches what your server is using. + +Verify that you have received a TGT ticket from your kerberos server, and that you have also received a service principal ticket for the server (e.g. ldap/ldap.example.org@EXAMPLE.ORG). Use klist to verify:: + + client:~# klist + Credentials cache: FILE:/tmp/krb5cc_0 + Principal: host/client.example.org@EXAMPLE.ORG + Issued Expires Principal + Feb 22 11:00:02 Feb 22 21:00:01 krbtgt/EXAMPLE.ORG@EXAMPLE.ORG + Feb 22 11:24:39 Feb 22 21:00:01 ldap/ldap.example.org@EXAMPLE.ORG + +If not, then a network capture utility, such as wireshark, offers a good way to show you which service principal your client is requesting, and what errors are being returned by the server. + +If you wish to also view the interaction with the LDAP server with a capture utility, you will need to negotiate a SASL layer without encryption. You can specify ``-O maxssf=1`` in your client side command (ldapwhoami, ldapsearch etc.), e.g.:: + + client:~# ldapsearch -LLL -Y GSSAPI -H ldap://ldap.example.org -O maxssf=1 -s "base" -b "" supportedSASLMechanisms + +You might find it easier to specify defaults on your client system, to keep your commands shorter. See the man page for ldap.conf for details. You can specify the default server in your ldap.conf file:: + + URI ldap://ldap.example.org + +And you can specify the default mechanism in ~/.ldaprc (in your home directory): + + ASL_MECH GSSAPI diff --git a/docsrc/sasl/faqs/plaintextpasswords.rst b/docsrc/sasl/faqs/plaintextpasswords.rst new file mode 100644 index 00000000..5db69a1f --- /dev/null +++ b/docsrc/sasl/faqs/plaintextpasswords.rst @@ -0,0 +1,20 @@ +Why does CyrusSasl store plaintext passwords in its databases? +-------------------------------------------------------------- + +To operate with the CRAM-MD5 and DIGEST-MD5 mechanisms, Cyrus SASL +stores plaintext versions of the passwords in its secret database (an +AuxpropPlugin). + +This is typically regarded as insecure practice, however the alternative +is not much better. For CRAM-MD5 and DIGEST-MD5 to function, they must +have a plaintext equivalent locally in order to confirm the hash that +actually goes across a wire. This, if these equivalents were +compromised, it is trivially easy for an attacker to have access to any +account on the system. + +Note that for DIGEST-MD5 this isn't strictly true: the hash that DIGEST +can use limits the attack to only the realm for which the password +applies, but this is a questionable security gain for the increased +management hassles (you can't share them between mechanisms) that the +plaintext equivalents cause. + diff --git a/docsrc/sasl/faqs/rfcs.rst b/docsrc/sasl/faqs/rfcs.rst new file mode 100644 index 00000000..9c8e2851 --- /dev/null +++ b/docsrc/sasl/faqs/rfcs.rst @@ -0,0 +1,35 @@ +.. _faq-rfcs: + +=============== +RFCs and drafts +=============== + +* :rfc:`1321` - The MD5 Message-Digest Algorithm +* :rfc:`1939` - Post Office Protocol - Version 3 (APOP/sasl_checkapop) +* :rfc:`2104` - HMAC: Keyed-Hashing for Message Authentication +* :rfc:`2195` - IMAP/POP AUTHorize Extention for Simple Challenge/Response + +* `draft-ietf-sasl-crammd5-xx `_ - The CRAM-MD5 SASL Mechanism (CRAM-MD5) +* :rfc:`2222` - Simple Authentication and Security Layer (SASL) (KERBEROS_V4) + +* `draft-ietf-sasl-rfc2222bis `_ Simple Authentication and Security Layer (SASL) (EXTERNAL) - (which became :rfc:`4422` ) +* :rfc:`2243` - OTP Extended Responses +* :rfc:`2245` - Anonymous SASL Mechanism + +* `draft-ietf-sasl-anon `_ Anonymous SASL Mechanism (ANONYMOUS) (became :rfc:`4505`) +* :rfc:`2289` - A One-Time Password System +* :rfc:`2444` - The One-Time-Password SASL Mechanism (OTP) +* :rfc:`2595` - Using TLS with IMAP, POP, and ACAP + +* `draft-ietf-sasl-plain `_ Plain SASL Mechanism (PLAIN) +* :rfc:`2831` - Using Digest Authentication as a SASL Mechanism + +* `draft-ietf-sasl-rfc2831bis `_ - Using Digest Authentication as a SASL Mechanism (DIGEST-MD5) +* :rfc:`2945` - The SRP Authentication and Key Exchange System +* :rfc:`3174` - US Secure Hash Algorithm 1 (SHA1) +* `draft-burdis-cat-srp-sasl `_ - Secure Remote Password SASL Mechanism (SRP) +* `draft-ietf-sasl-gssapi `_ - SASL GSSAPI Mechanisms (GSSAPI) (became :rfc:`4752`) +* `draft-ietf-sasl-saslprep `_ 0 SASLprep: Stringprep profile for user names and passwords (became :rfc:`4013`) +* `draft-murchison-sasl-login `_ - The LOGIN SASL Mechanism (LOGIN) -- *obsolete* +* `draft-newman-sasl-passdss `_ - DSS Secured Password Authentication Mechanism (PASSDSS-3DES-1) +* `draft-newman-sasl-c-api `_ - The SASL C API (very rough draft) diff --git a/docsrc/sasl/faqs/upgrade-saslv2.rst b/docsrc/sasl/faqs/upgrade-saslv2.rst new file mode 100644 index 00000000..a13b402d --- /dev/null +++ b/docsrc/sasl/faqs/upgrade-saslv2.rst @@ -0,0 +1,22 @@ +Why am I having a problem running dbconverter-2 to upgrade from SASLv1 to SASLv2? +--------------------------------------------------------------------------------- + +The migration is documented in the official documentation. + +When migrating the ``/etc/sasldb`` database using the ``utils/dbconverter-2`` +utility, you may encounter the error message "Error opening password +file". This is usually due to the fact your SASL V1 library was compiled +using a different version of Berkeley DB than the SASL V2 library. You +can work around this by using Berkeley DB's db_upgrade utility (possibly +chaining the DB3 and DB4 upgrade utilities) to upgrade a copy of sasldb +prior to conversion using dbconverter-2. + +Here is the script we use at our installation, where SASL has to coexist with SASL2:: + + #!/bin/sh + cp /etc/sasldb /tmp/sasldb.$$ + /usr/local/BerkeleyDB.4/bin/db_upgrade /etc/sasldb + echo ""|/usr/local/sasl/sbin/dbconverter-2 + cp /tmp/sasldb.$$ /etc/sasldb + + diff --git a/docsrc/sasl/gssapi.rst b/docsrc/sasl/gssapi.rst new file mode 100644 index 00000000..59b02d34 --- /dev/null +++ b/docsrc/sasl/gssapi.rst @@ -0,0 +1,203 @@ +.. _gssapi: + +================================= +Configuring GSSAPI and Cyrus SASL +================================= + +This document was contributed by `Ken Hornstein `_ and updated +by `Alexey Melnikov `_. + +A couple of people have asked me privately, "Hey, how did you get the +GSSAPI mechanism to work? I tried, but the sample apps kept failing". +(The short answer: I'm a tenacious bastard). + +I figured that it couldn't hurt to give a quick explanation as to +how you get GSSAPI working with the sample apps, since it wasn't +obvious to me, and I consider myself not completely ignorant of GSSAPI +and Kerberos. + +Compile Cyrus SASL with GSSAPI +============================== + +Compile the Cyrus-SASL distribution with the GSSAPI plugin +for your favorite GSS-API mechanism. I personally use the GSSAPI +libraries included with the `MIT Kerberos 5 distribution `_; +`Heimdal `_ +and `CyberSafe `_ work as well. + +Start sample server +=================== + +The command-line used for +sample-server needs to specify the GSSAPI service name and the +location of the plug-ins. + +* On Unix: ``./sample-server -s host -p ../plugins/.libs`` +* On Windows: ``sample-server -s host -p ..\plugins`` + +In this example, I am using "host", which already exists on my +machine, but only root can read it, so I an running this as root. +If you want to use an alternate service name, you will need to +create that service in Kerberos, place it in a keytab readable by +you, and point your Kerberos library at it. + +* On Unix: Unix: both MIT Kerberos and Heimdal, use ``/etc/krb5.keytab`` on Unix by default, but this can be changed + by setting the ``KRB5_KTNAME`` environment variable; the default + for CyberSafe Kerberos is ``/krb5/v5srvtab`` for UNIX systems and can be + changed by setting the ``CSFC5KTNAME`` environment variable. +* On Windows: the default service key table location for CyberSafe is + ``C:\Program Files\CyberSafe\v5srvtab``, unless the + CyberSafe registry setting for the KeyTab key is set to an + alternate path. MIT Kerberos on Windows uses the keytab filename + krb5kt. + +You should get a response similar to: + +:: + + Generating client mechanism list... + Sending list of 3 mechanism(s) + S: R1NTQVBJIFBMQUlOIEFOT05ZTU9VUw== + +Note that later on (assuming everything works) you might need to paste +in lines that are longer than canonical input processing buffer on your +system. You can get around that by messing around with stty; while +the details vary from system to system, on Solaris you can do something +like: + +:: + + ( stty -icanon min 1 time 0 ; ./sample-server -s host -p ../plugins/.libs ) + +Obtain Kerberos ticket +====================== + +Obtain a Kerberos ticket for the user you want to authenticate as. + +:: + + kinit kenh + +Start up sample client +====================== + +You need to specify the service +name, the hostname, and the userid. An example might be + +:: + + ./sample-client -s host -n your.fqdn.here -u kenh -p ../plugins/.libs + +You should get a response similar to this: + +:: + + Waiting for mechanism list from server... + +Connect Server to Client +======================== + +Cut-and-paste the initial mechanism line from the server process +(this includes the `` S: `` ) into the client process. You +should get something similar to: + + +:: + + S: R1NTQVBJIFBMQUlOIEFOT05ZTU9VUw== + Choosing best mechanism from: GSSAPI PLAIN ANONYMOUS + Using mechanism GSSAPI + Preparing initial. + Sending initial response... + C: <.... lots of base 64 data ...> + Waiting for server reply... + +If GSSAPI isn't selected as the mechanism, there is a few things that +might have gone wrong: + +* The mechanism might not have been offered by the server. The decoded + mechanism list offered by the server appears in the "``Choosing best + mechanism``" line. If GSSAPI didn't appear in that list, then + something is wrong on the server. Make sure that you specified the + correct plugins directory. If the plugin directory is correct, but + the library fails to load, you might be running across a bug + in libtool on some platforms. If you have your Kerberos/gssapi + libraries not installed in the system library path, those libraries + are likely not able to be found when the SASL GSSAPI plugin loads. + + The solution varies from system to system; what I did was take + the linker line generated by libtool and run it by hand, adding + a ``-R/path/to/kerberos/libraries`` switch (this was on Solaris). + You can check with a system call tracer to see exactly what it is + trying to do. + +* The client doesn't know about the mechanism. The reasons for this + happening are the same as the server: check the -p switch, check + to make sure the correct libraries are being loaded with the GSSAPI + plugin. + + You can turn on a healthy amount of debugging information by changing + the definition in config.h of the VL macro to (and recompiling libsasl): + +:: + + #define VL(foo) printf foo; + +There is a possibility +you might get an error that looks like this: + + :: + + sample-client: Starting SASL negotiation: generic failure + +This can mean that you didn't provide all of the required information +to the sample-client (did you provide a service name with -s, the +hostname of the service with -n, and a username with -u ?), or that +GSSAPI has failed (unfortunately, on the client you cannot find out +the internal GSSAPI error; you will need to break out the debugger +for that). + +Connect Client to Server +======================== + +Cut and paste the client response (The *entire* line that begins +with C:, including the initial ``C:`` ) to the server +process. You should get a response back that starts with ``S:`` . +Cut and paste that to the client, and continue this +exchange until you either get ``Negotiation complete``, or an error. + +If you get an error on the server you should get a complete error +message (including the GSSAPI error string); on the client you +unfortunately will only probably get ``generic failure``, which will +again require the use of a debugger (but the VL macro should help +with this). + +One common thing that happens is that on your server you might see +the error: + +:: + + sample-server: Performing SASL negotiation: authentication failure + (Requested identity not authenticated identity) + +This comes from not having a requested identity (the -u option) that +matches the identity that you were authenticated to via the GSSAPI. +This is of course mechanism specific, but if for example you're using +Kerberos, the Cyrus SASL library strips out the @REALM from your +identity if you are in the same realm as the server. So if your +Kerberos identity is user\@SOME.REALM and the server is in SOME.REALM, +you need to specify "user" to the -u flag of the client. If you're +accessing a server in a foreign realm, you need to pass the full +principal name via the -u option to make this work correctly. + +If you complete the negotiation successfully, you should see something +that looks like (on both the client and server): + +:: + + Negotiation complete + Username: kenh + sample-server: realm: can't request info until later in exchange + SSF: 56 + +If you get to that, then you've done it, and GSSAPI works successfully! diff --git a/docsrc/sasl/installation.rst b/docsrc/sasl/installation.rst new file mode 100644 index 00000000..e865ebd9 --- /dev/null +++ b/docsrc/sasl/installation.rst @@ -0,0 +1,235 @@ +.. _installation: + +============ +Installation +============ + +Are you looking for the: + +* :ref:`Quick install ` guide (for experts), or +* :ref:`Detailed installation instructions ` + +.. _installation_quick: + +Quick install guide +=================== +You can install Cyrus SASL via packages or via tarball. + +Tarball installation +-------------------- + +Assuming an installation from tarball:: + + cd (directory it was untarred into) + ./configure + make + make install + ln -s /usr/local/lib/sasl2 /usr/lib/sasl2 + + +Contributors will want to `compile from source`_. + +.. _compile from source: developer/installation.html + +Unix package Installation +------------------------- + +Are you `upgrading from Cyrus SASLv1`_? + +Please see the file install.php for instructions on how to install this package. + +Note that the library can use the environment variable SASL_PATH to locate the directory where the mechanisms are; this should be a colon-separated list of directories containing plugins. Otherwise it will default to the value of `--with-plugindir` as supplied to `configure` (which itself defaults to `/usr/local/lib`). + +Extra information for :ref:`Mac OSX installation `. + +Extra information for :ref:`Windows installation `. This configuration has not been extensively tested. + +Configuration +------------- + +There are two main ways to configure the SASL library for a given application. The first (and typically easiest) is to make use of the application's configuration files. Provided the application supports it (via the `SASL_CB_GETOPT` callback), please refer to that documetation for how to supply SASL options. + +Alternatively, Cyrus SASL looks for configuration files in `/usr/lib/sasl/Appname.conf` where Appname is settable by the application (for example, Sendmail 8.10 and later set this to "Sendmail"). + +Configuration using the application's configuration files (via the getopt callback) will override those supplied by the SASL configuration files. + +For a detailed guide on configuring libsasl, please look at sysadmin.php and options.php + +.. _upgrading from Cyrus SASLv1: + + +.. _installation_detailed: + +Detailed installation guide +=========================== + +Before reading this section, please be sure you are comfortable with +the concepts presented in the :ref:`components ` guide +and in the :ref:`Quickstart ` guide. + +You will want to have answered the following questions about your intended +installation: + + +1. What mechanisms do you want to support? Are they plaintext (LOGIN, PLAIN), +shared secret (DIGEST-MD5, CRAM-MD5), or Kerberos (KERBEROS_V4, GSSAPI)? +Perhaps you will use some combination (generally plaintext with one of +the other two types). +2. Given the answer to the previous question, how will the mechanisms +perform user verification? + + * Kerberos mechanisms just need your existing Kerberos infrastructure. + * The shared secret mechanisms will need an auxprop plugin backend. + * The plaintext mechanisms can make do with saslauthd, Courier authdaemond (not included), *or* by using an auxprop plugin backend. + * To use Kerberos and Plaintext, you'll want to use saslauthd with a kerberos module for plaintext authentication. To use Shared Secret and plaintext, you'll want to use the auxprop plugin for password verification. + +3. If you are using an auxprop plugin, will you be using SASLdb (and +if so, Berkeley DB [recommended], GDBM, or NDBM?), LDAP or an SQL backend +(Postgres? MySQL?). +4. If you are using saslauthd, what module will you be using? LDAP? +Kerberos? PAM? +5. Also if you are using saslauthd, what communication (IPC) method do +you want to use? On most systems, the correct answer is the default +(unix sockets), but on Solaris you can use IPC doors, which have proven +to be more stable than equivilant Solaris systems using unix sockets. + +Once you have answered these questions, properly configuring a working +configuration of Cyrus SASL becomes easier. + +Requirements +------------ + +You'll need `GNU make `_. + +If you are using SASLdb, you will need to pick your backend. +libsasl2 can use `gdbm `_, `Berkeley db `_, or ndbm to implement its +user/password lookup. Most systems come with ndbm. + +If you are using SQL, you'll need to properly configure your server/tables, +and build the necessary client libraries on the system where you will be +building and using SASL. Currently we support `PostgreSQL `_ v7.2 (or higher) +and `MySQL `_. + +If you are using LDAPDB, you'll need SASL enabled `OpenLDAP `_ libraries. +v2.1.27 (or higher) or v2.2.6 (or higher) is supported. + +For Kerberos support, you'll need the `kerberos `_ libraries. + +For GSSAPI support you will need either `MIT Kerberos 5 `_, +the `Heimdal `_ or `CyberSafe `_. + +Build Configuration +------------------- + +Once you have answered all the necessary questions and installed +(and tested!) any required packages for your configuration, you are +ready to build SASL. Building SASL is done with the aid of +an autoconf ``configure`` script, which has a *lot* of options. +Be sure to read the output of ``configure --help`` to be sure you +aren't missing any. Note that an ``--enable-foo`` option has a counterpart ``--disable-foo`` +to not enable that feature. + +Some of the most important configuration options are those which allow +you to turn off the compilation of modules you do not need. This is often +the easiest way to solve compilation problems with Cyrus SASL. +If you're not going to need a particular mechanism, don't build it! Not +building them can also add performance improvements as it does take system +resources to load a given plugin, even if that plugin is otherwise unused +(even when it is disabled via the :option:`mech_list` option). + +As of this writing, modules that are enabled by default but may not +be applicable to all systems include CRAM-MD5, DIGEST-MD5, OTP, KERBEROS_V4, +GSSAPI, PLAIN, and ANONYMOUS. These can be disabled with:: + + ``--disable-cram``, + ``--disable-digest``, ``--disable-otp``, + ``--disable-krb4``, ``--disable-gssapi``, + ``--disable-plain``, and ``--disable-anon`` respecively. + +If you are using an SQL auxprop plugin, you may want to specify one or more +of ``--enable-sql``, ``--with-mysql=PATH``, and +``--with-pgsql=PATH``, note that PATH in the later two should be replaced +with the path where you installed the necessary client libraries. + +If you are using LDAPDB auxprop plugin, you will need to specify +``--enable-ldapdb`` and ``--with-ldap=PATH``. Warning: LDAPDB +auxprop plugin (and LDAP enabled saslauthd) introduces a circular dependency +between OpenLDAP and SASL. I.e., you must have OpenLDAP already built when +building LDAPDB in SASL. In order for LDAPDB to work at runtime, you must have +OpenLDAP already built with SASL support. One way to solve this issue is to +build Cyrus SASL first without ldap support, then build OpenLDAP, and then come +back to SASL and build LDAPDB. + +Given the myriad of ways that Berkeley DB can be installed on a system, +people useing it may want to look at the ``--with-bdb-libdir`` and +``--with-bdb-incdir`` as alternatives to ``--with-dbbase`` for +specifying the paths to the Berkeley DB Library and Include directories. + +In fact, if you're not planning on using SASLdb at all, it may be worth +your time to disable its use entirely with the ``--with-dblib=none`` +option. + +If you are planning on using LDAP with saslauthd, be sure to specify +the ``--with-ldap=PATH`` option to ``configure``. + +Building and Installation +------------------------- + +After configure runs, you should be able to build SASL just by +running ``make``. If this runs into problems, be sure that you +have disabled everything that your system doesn't need, and that you have +correctly specified paths to any dependencies you may have. + +To install the library, run ``make install`` as ``root`` followed by +``ln -s /usr/local/lib/sasl2 /usr/lib/sasl2`` (modified for your +installation path as appropriate). Be sure to do this last step or +SASL will not be able to locate your plugins! + +Compilation Hints +----------------- + +You may need to play with your CPPFLAGS and LDFLAGS if you're +using vendor compilers. We use ``gcc`` extensively, but you'll +probably have more luck if you use the same compiler for the library +as you do for your applications. You can see what compilers we use on +our platforms by looking at the "SMakefile". + +Application Configuration +------------------------- + +Plesae read about the :ref:`SASL Options ` to learn what +needs to be configured so that applications can successfully use the SASL +library. + +You will want to ensure that the settings of ``pwcheck_method`` +and ``auxprop_plugin`` match the decisions you made about your +authentication infrastructure. (For example, if you are using +saslauthd as a password verifier, you'll want to be sure to set +``pwcheck_method: saslauthd``). + +If you are using saslauthd, you will want to arrange for +``saslauthd -a pam`` (or ldap, or kerberos4, etc) to be run +at boot. If you are not going to be using saslauthd, then this is +not necessary. + +Many of these pieces are covered in more detail in the +:ref:`SASL System Administrator's Guide `. + +Supported platforms +=================== + +This has been tested under Linux 2.2, Linux 2.4, Solaris 2.7 and +Solaris 2.8. It should work under any platform where dynamic objects +can be linked against other dynamic objects, and where the dynamic +library file extension is ".so", or where libtool creates the .la +files correctly. There is also documentation for +:ref:`Win32 `, :ref:`MacOS X `, and +:ref:`OS/390 `. + +.. toctree:: + :hidden: + + developer/installation + macosx.rst + windows.rst + os390.rst diff --git a/docsrc/sasl/macosx.rst b/docsrc/sasl/macosx.rst new file mode 100644 index 00000000..1f2491cd --- /dev/null +++ b/docsrc/sasl/macosx.rst @@ -0,0 +1,211 @@ +.. _install-macos: + +========================================= +Building and using Cyrus SASL on Mac OS X +========================================= + +The Cyrus SASL v2 distribution now supports Mac OS X, including +applications written to Apple's Carbon and Cocoa interfaces, as well +as the standard Unix-like API. It includes the following +components: + +* A port of the Unix SASL library, which lives in ``/usr/local/lib/libsasl2.dylib`` + (or similar) and with plugins in ``/usr/lib/sasl`` (which should be a symlink to ``/usr/local/lib/sasl``). +* A framework which lives in + ``/Library/Frameworks/SASL2.framework``, and allows the use of the + ``-framework`` option to Apple's ``ld``, or linking with the + framework in Project Builder. This framework is in fact a wrapper for a + symlink to ``/usr/local/lib/libsasl2.dylib`` with the necessary + information to recognize it as a framework. This is what we expect many + Cocoa and Carbon Mach-O applications will want to use, and the framework + is required for CFBundle to work, which is used by the CFM glue library. +* A CFM glue library (``/Library/CFMSupport/SASL2GlueCFM``) which + can be linked in by Carbon CFM applications, that uses CFBundle to bind + the framework and thus load the Unix-level library. It automatically loads + the important functions at ``sasl_client_init`` or + ``sasl_server_init`` time; it also automatically makes sure memory + allocation works if you're using the metrowerks malloc; if you're not, + ``sasl_set_alloc`` works as usual. +* A Carbon port of the existing CFM library for Mac OS 9. Note that + this could probably be modified fairly easily to work on OS X, but + there's not much point. The CFM glue layer to the Unix library + supports many more functions, including the entire server API; also, + the Unix implementation is mostly independent of Kerberos + implementation, while the Mac OS 9 Carbon port specifically requires + MIT Kerberos for Macintosh 3.5 or later in order to get Kerberos + support. The Mac OS 9 code implements only the client API, but this is + mostly what is wanted from SASL on OS 9 anyway. + +If you are building a Carbon CFM application and intend it to run on +both OS 9 and OS X, you should link against the OS 9 Carbon SASL +library, since it exports fewer APIs (client side only, specifically) +than the OS X CFM glue. Your application should work seamlessly with +both libraries if you do this, despite the different implementations +underneath. + +If you need a Carbon CFM application to support server-side SASL +functionality, you need to link against the ``SASL2GlueCFM`` +library, but be aware that your application will not run on OS 9. + +Compiling and Using the Unix library +==================================== + +The Unix library is mostly ready to build on Mac OS X, but it does depend +on the ``dlcompat`` package in order to load its plugins. +``dlcompat-20010505`` is a relatively simple version known to work +with SASL; it is provided with the distribution in a tarball. You should +``make`` and ``make install`` the ``dlcompat`` library +(which probably goes into ``/usr/local/lib/libdl.dylib``) before +attempting to ``./configure`` the SASL distribution itself. SASL will +then pretend it's a real Unix ``libdl``, and link against it. + +Since there are, at this point, newer and far more complex versions of +dlcompat, you may prefer to use those instead if other software requires +their functionality. The dlcompat homepage is located on the `OpenDarwin `_ +site. Many users may want to install the ``/sw`` tree from `the Fink project `_ to get this, as +well as possibly newer autotools and other software. + +As of version 2.1.16, SASL uses and requires a recent version of GNU +autotools (autoconf, automake, and libtool) to build its configuration scripts. +If you are building from GIT, you will need to have the autotools installed +on your system. The version included with all releases of the developer tools +for OS X 10.2.x is too old for this; if you aren't using OS X 10.3 or later, +you should upgrade to more recent patchlevels of these tools. The easiest way +to do this is to install the Fink environment and then ``apt-get +install autoconf2.5 automake1.7 libtool14``. + +Recent versions of SASL ship with Kerberos v4 disabled by default. +If you need Kerberos v4 for some reason, and you are using MIT Kerberos +for Macintosh 4.0 or later, you should ``./configure`` with +the added options ``"--enable-krb4=/usr --without-openssl +--disable-digest"`` so that it finds the +correct location for the header files, and does not use OpenSSL or +build anything that depends on it (such as the digest-md5 plugin), +since OpenSSL provides its own DES routines which do not work with +Kerberos v4. + +.. warning:: + + Please read the "Known Problems" section at the end of + this document for more information on this issue. + +You must be root to make install, since ``/usr/local`` is only +modifiable by root. You need not enable the root account using +NetInfo; the recommended (but underdocumented) method is to use +``sudo -s`` from the Terminal window when you are logged into an +administrator's account, and enter the password for that account. When +building on Mac OS X, ``make install`` will automatically add the +framework to ``/Library/Frameworks``. + +This does not build the CFM glue library. Building the CFM glue +library requires Metrowerks CodeWarrior Pro 6 or later (tested with +6), and the files necessary to build it are in the +``mac/osx_cfm_glue`` folder. + +Changes to the Unix library to make it work on OS X +=================================================== + +This is provided for reference purposes only. The build system will +automatically take care of all of these issues when building on Darwin +or Mac OS X. + +* The random code supports the preferred way to generate random + numbers in Darwin. (In SASL v2, it does this on all unix-like + platforms that lack jrand48). *Note that Mac OS X "Jaguar", version + 10.2, + now has the standard jrand48 function, and that SASL will use this + instead + of the previous workaround.* +* Symbols which are dlopened have an underscore prefixed. (This + behavior is detected by configure in SASL v2.) +* Plugins are linked with the ``-module`` option to ``libtool``, + which causes the ``-bundle`` option to be + supplied to Apple's ``ld``. (This is done on all platforms in + SASL v2.) +* The MD5 symbols are renamed to avoid library conflicts. This + allows proper compilations against Heimdal and MIT's unix kerberos + distribution, and prevents crashes when linked against MIT Kerberos + for Macintosh (which also duplicates the symbols, but in a different + way). Note that the MD5 symbols have local names on all platforms with + SASL v2; this was only different in SASL v1. +* MIT Kerberos for Macintosh 4.0 and later are fully supported. This + was accomplished by using ``krb_get_err_text`` if available and + checking for additional names for the krb4 libraries. + +Changes to the Mac OS 9 projects to support Carbon +================================================== + +.. warning:: + + Please read these notes before you attempt to build SASL for OS 9 Carbon! + +* **Important!** You must make sure that all files have their + correct HFS filetype before starting to build this code! In + particular, all source and text files must be of type ``'TEXT'``, + which is not the default if you use the Mac OS X GIT client to check + out the projects. If you run into this problem, you may want to use a + utility such as FileTyper to recursively change the type on all + files. CodeWarrior is less picky about the projects' filetypes, but + setting them to filetype ``'MMPr'``, creator code ``'CWIE'`` + may be helpful in opening the projects from the Finder. Users on Mac OS + X familiar with the Unix ``find`` + command should be able to rig ``/Developer/Tools/SetFile`` + to do this job as well. +* Many of the important projects (for ``libdes``, ``libsasl``, + ``build_plugins``, and the sample client ``sc_shlb``) + have Carbon versions. +* Plugins are loaded from a ``Carbon`` subfolder of the ``SASL + v2`` folder in the Extensions folder. Plugins directly + in the ``SASL v2`` folder are considered to be for the Classic + libraries. +* Note that when using the ``build_plugins`` project, you must + generate the plugin init files using the ``makeinit.sh`` script in + the ``plugins`` directory. The easiest way to do this is to run the + script from a Unix shell, such as Mac OS X. You must then fix the + filetypes of the generated source files (see above). +* There is a new folder in ``CommonKClient`` called ``mac_kclient3`` + which contains code compatible with MIT's new `KClient + 3.0 `_ + API. This folder must be in your CodeWarrior access paths, the + old ``mac_kclient`` folder must not, and it must precede the + project's main folder. +* The kerberos4 plugin uses this new code. The kerberos4 plugin + also + statically links the Carbon ``libdes``, and no other part of + Carbon SASL uses ``libdes`` directly. *Your application should + **not** link against* ``libdes.shlb`` *under Carbon!* + (It causes problems due to DES symbols also existing in the MIT + Kerberos library, which loads first.) +* To build the projects, you should have the MIT Kerberos for + Macintosh 3.5 installation disk images mounted, since the access paths + include the absolute paths to the library directories from that + image. It's easier than you having to find the paths yourself, and + smaller than having to distribute the libraries with SASL. + +Known Problems +============== + +* The Kerberos v4 headers bundled with Mac OS X (and Kerberos for + Macintosh) are not compatible with OS X's OpenSSL headers. (Kerberos v4 + support is disabled by default.) If you actually need krb4 support, the + easiest solution is to build without using OpenSSL's + ``libcrypto``. To do this, specify the ``--without-openssl`` + option to ``configure``. As of version 2.1.18, this automatically + disables using ``libcrypto`` for DES as well. You will probably + also need to specify ``--disable-digest`` since the digestmd5 plugin + does not build against Kerberos v4's DES headers or library. Note that + this disables several features (digestmd5, NTLM, OTP) which require + OpenSSL. If both Kerberos v4 and functionality that requires OpenSSL are + needed, it is possible to build the Kerberos v4 plugin against + the correct K4 DES libraries, and everything else against OpenSSL; + however, we do not support that configuration. +* Versions of Cyrus SASL prior to 2.1.14 with support for Carbon + CFM applications on Mac OS X have a known bug involving the CFM glue + code (in ``mac/osx_cfm_glue``). If ``sasl_done`` is called + to unload the SASL library, and then one of the initialization + functions (such as ``sasl_client_init``) is called to + reinitialize it from the same process, the application will crash. A + fix for one obvious cause of this problem is included in 2.1.14; + however, as of this writing, it has not been tested. It is possible + that other bugs in Cyrus SASL, or deficiencies in Apple's libraries, + will make this fix insufficient to resolve this issue. diff --git a/docsrc/sasl/options.rst b/docsrc/sasl/options.rst new file mode 100644 index 00000000..f905a665 --- /dev/null +++ b/docsrc/sasl/options.rst @@ -0,0 +1,422 @@ +.. _options: + +======= +Options +======= + +This document contains information on what options are used by the +Cyrus SASL library and bundled mechanisms. The most commonly used +options (and those that are therefore most commonly misunderstood +are :option:`pwcheck_method` and :option:`auxprop_plugin`. Please ensure +that you have configured these correctly if things don't seem to +be working right. Additionally, :option:`mech_list` can be an easy +way to limit what mechanisms a given application will use. + +.. contents:: + :depth: 1 + :local: + +SASL Library +============ + +.. option:: authdaemon_path [] + + Path to Courier-IMAP authdaemond's unix socket. + + Default: /dev/null + +.. option:: auto_transition [yes|noplain|no] + + When set to 'yes' or 'noplain', + and when using an auxprop plugin, automatically transition + users to other mechs when they do a successful plaintext + authentication. When set to 'noplain', only non-plaintext secrets + will be written. *Note that the only mechanisms (as currently + implemented) which don't use plaintext secrets are + OTP and SRP.* + + Default: no + +.. option:: canon_user_plugin [] + + Name of canon_user plugin to use + + Default: INTERNAL + +.. option:: log_level [] + + **Numeric** Logging Level (see ``SASL_LOG_*`` in ``sasl.h`` + for values and descriptions) + + Default: 1 (SASL_LOG_ERR) + +.. option:: mech_list [] + + Whitespace separated list of mechanisms to allow (e.g. 'plain + otp'). Used to restrict the mechanisms to a subset of the installed + plugins. + + Default: empty (use all available plugins) + +.. option:: plugin_list [] + + Location of Plugin list (Unsupported) + + Default: none + +.. option:: pwcheck_method [] + + Whitespace separated list of mechanisms used to verify passwords, + used by sasl_checkpass. Possible values: 'auxprop', 'saslauthd', + 'pwcheck', 'authdaemond' [if compiled with --with-authdaemond]) + and 'alwaystrue' [if compiled with --enable-alwaystrue]) + + Default: auxprop + +.. option:: saslauthd_path [] + + Path to saslauthd run directory (**including** the "/mux" named pipe) + +Auxiliary Property Plugin +========================= + +.. option:: auxprop_plugin [] + + Name of auxiliary plugin to use, you may specify a space-separated + list of plugin names, and the plugins will be queried in order. + + Default: empty - queries all plugins. + +GSSAPI +====== + +.. option:: keytab [] + + Location of keytab file + + Default: /etc/krb5.keytab (system dependant) + +LDAPDB +====== + +.. option:: ldapdb_uri [] + + URI to the LDAP server. You can specify a space-separated list of URIs - + ldapi:// or ldaps://ldap1/ ldaps://ldap2/ + + Default: none + +.. option:: ldapdb_id [] + + ldap SASL authentication id + + Default: none + +.. option:: ldapdb_mech [] + + LDAP SASL mechanism for authentication. + + Default: none + +.. option:: ldapdb_pw [] + + LDAP password for SASL authentication id + + Default: none + +.. option:: ldapdb_rc [] + + The filename specified here will be put into the server's LDAPRC + environment variable, and libldap-specific config options may be set + in that ldaprc file. + + The main purpose behind this option is to allow + a client TLS certificate to be configured, so that SASL/EXTERNAL may + be used between the SASL server and the LDAP server. This is the most + optimal way to use this plugin when the servers are on separate machines. + + Default: none + +.. option:: ldapdb_starttls [try|demand] + + Use StartTLS. This option may be set to 'try' or 'demand'. + When set to "try" any failure in StartTLS is ignored. + When set to "demand" then any failure aborts the connection. + + Default: none + +.. option:: ldapdb_canon_attr [] + + Use the value of the specified attribute as the user's + canonical name. The attribute will be looked up in the user's LDAP + entry. This setting must be configured in order to use LDAPDB as + a canonuser plugin. + + Default: none + +Notes on LDAPDB +--------------- + +Unlike other LDAP-enabled plugins for other services that are common +on the web, this plugin does not require you to configure DN search +patterns to map usernames to LDAP DNs. This plugin requires SASL name +mapping to be configured on the target slapd. This approach keeps the +LDAP-specific configuration details in one place, the slapd.conf, and +makes the configuration of remote services much simpler. + +This plugin is not for use with slapd itself. When OpenLDAP is +built with SASL support, slapd uses its own internal auxprop and +canonuser module. + +By default, without configuring anything else, slapd will fail to load +the ldapdb module when it's present. This is as it should be. If you +don't like the "auxpropfunc: error -7" message that is sent to syslog +by slapd, you can stop it by creating /usr/lib/sasl2/slapd.conf with:: + + auxprop_plugin: slapd + +which will force the SASL library to ignore all other auxprop modules. + +Examples +-------- + +:: + + ldapdb_uri: ldap://ldap.example.com + ldapdb_id: root + ldapdb_pw: secret + ldapdb_mech: DIGEST-MD5 + ldapdb_canon_attr: uid + +The LDAP server must be configured to map the SASL authcId "root" into a DN +that has proxy authorization privileges to every account that is allowed to +login to this server. (See the OpenLDAP Admin Guide section 10 for +details.) + +:: + + ldapdb_uri: ldapi:// + ldapdb_mech: EXTERNAL + +This configuration assumes an LDAP server is on the same server that is +using SASL and the underlying OS is \*NIX based (ldapi:// requires UNIX domain +sockets). This is fast and secure, and needs no username or password to be +stored. The slapd.conf will need to map these usernames to LDAP DNs: + +:: + + sasl-regexp uidNumber=(.*)\\+gidNumber=(.*),cn=peercred,cn=external,cn=auth + ldap:///dc=example,dc=com??sub?(&(uidNumber=$1)(gidNumber=$2)) + + + sasl-regexp uid=(.*),cn=external,cn=auth + ldap:///dc=example,dc=com??sub?(uid=$1) + +NTLM +==== + +.. option:: ntlm_server [] + + Comma separated list of servernames (WinNT, Win2K, Samba, etc) to + which authentication will be proxied. + + Default: empty - perform authentication internally + +.. option:: ntlm_v2 [yes|no] + + (Client) Send NTLMv2 responses to the server. + + Default: no (send NTLMv1) + +OTP +=== + +.. option:: opiekeys [] + + Location of the opiekeys file + + Default: /etc/opiekeys + +.. option:: otp_mda [md4 | md5 | sha1] + + (Without opie) Message digest algorithm for one-time passwords, used by sasl_setpass + + Default: md5 + +Digest-md5 +========== + +.. option:: reauth_timeout [] + + Length in time (in minutes) that authentication info will be + cached for a fast reauth. A value of 0 will disable reauth. + + Default: 0 - reauth disabled. + +SASLDB +====== + +.. option:: sasldb_path [] + + Path to sasldb file + + Default: /etc/sasldb2 (system dependant) + +.. option:: sasldb_mapsize [] + + For sasldb with LMDB. Size of the memory map used by the DB. This is also the maximum possible + size of the database, so it must be set to a value large enough to contain + all the desired user records. + + Default: 1048576 bytes + +.. option:: sasldb_maxreaders [] + + For sasldb with LMDB. Maximum number of threads (or processes) that may concurrently read the + database. + + Default: 126 + +Notes on sasldb with LMDB +------------------------- + +The OpenLDAP LMDB library is an extremely compact, extremely high performance +B+tree database. The code for it is available in the regular OpenLDAP source +distributions and it is distributed under the terms of the OpenLDAP Public License. + +Full documentation, plus papers and presentations are available on +`the LMDB page `_. + +SQL Plugin +========== + +.. option:: sql_engine [] + + Name of SQL engine to use (possible values: 'mysql', 'pgsql', 'sqlite', 'sqlite3'). + + Default: mysql + +.. option:: sql_hostnames [] + + Comma separated list of SQL servers (in host[:port] format). + +.. option:: sql_user + + Username to use for authentication to the SQL server. + +.. option:: sql_passwd + + Password to use for authentication to the SQL server. + +.. option:: sql_database + + Name of the database which contains the auxiliary properties. + +.. option:: sql_select + + SELECT statement to use for fetching properties. This option is + **required** in order to use the SQL plugin. + +.. option:: sql_insert + + INSERT statement to use for creating properties for new users. + +.. option:: sql_update + + UPDATE statement to use for modifying properties. + +.. option: sql_usessl [yes | no] + + When set to 'yes', 'on', '1' or 'true', a secure connection will + be made to the SQL server. + + Default: no + +Notes on SQL +------------ + +The sql_insert and sql_update options are +optional and are only needed if you wish to allow the SASL library +(e.g., saslpasswd2) and plugins (e.g., OTP) to write properties to the +SQL server. If used, both statements MUST be provided so that +properties can be added, changed and deleted. + +NOTE: The columns for writable properites MUST accept NULL values. + +The SQL statements provided in the sql_select, +sql_insert and sql_update options can contain +arguments which will be substituted with the appropriate values. The +valid arguments are: + +%u + Username whose properties are being fetched/stored. +%p + Name of the property being fetched/stored. This could + technically be anything, but SASL authentication will try + userPassword and cmusaslsecretMECHNAME (where MECHNAME is the + name of a SASL mechanism). +%r + Realm to which the user belongs. This could be the + kerberos realm, the FQDN of the computer the SASL application is + running on or whatever is after the @ on a username. (read the + realm documentation). +%v + Value of the property being stored (INSERT or + UPDATE only!). This could technically be anything depending on + the property itself, but is generally a userPassword. + +Note: DO NOT put quotes around the entire SQL +statement, but each individual %u, %r and %v argument MUST be +quoted. + + +Examples +-------- + + + ``sql_select: SELECT %p FROM user_table WHERE username = '%u' and realm = '%r'`` + +would send the following statement to SQL for user "bovik" and +the default realm for the machine "madoka.surf.org.uk":: + + SELECT userPassword FROM user_table WHERE username = 'bovik' and + realm = 'madoka.surf.org.uk' + +:: + + sql_insert: INSERT INTO user_table (username, realm, %p) VALUES ('%u', '%r', '%v') + +would generate the following statement to SQL for user "bovik" in +realm "madoka.surf.org.uk" with userPassword "wert":: + + INSERT INTO user_table (username, realm, userPassword) VALUES + ('bovik', 'madoka.surf.org.uk', 'wert'); + + +Note that all substitutions do not have to be used. For instance, + +:: + + SELECT password FROM auth WHERE username = '%u' + +is a valid value for sql_select. + + + +SRP +=== + +.. option:: srp_mda [md5 | sha1 | rmd160] + + Message digest algorithm for SRP calculations + + Default: sha1 + +Kerberos V4 +=========== + +.. option:: srvtab [] + + Location of the srvtab file + + Default: /etc/srvtab diff --git a/docsrc/sasl/os390.rst b/docsrc/sasl/os390.rst new file mode 100644 index 00000000..4f9ac121 --- /dev/null +++ b/docsrc/sasl/os390.rst @@ -0,0 +1,56 @@ +.. _install-os390: + +======================================= +Building and Using Cyrus SASL on OS/390 +======================================= + +Cyrus SASLv2 can be made to build on OS/390 with some minimal changes. Here +are the suggestions provided by Howard Chu of the OpenLDAP project. + +Cyrus SASL must be compiled in ASCII mode. This can be accomplished with +a special invocation of c89. For ease of use, you can use a shell script +("acc" is a good name) and set the environment variable CC = acc before +configuring anything. The shell script is simple:: + + #! /bin/sh + exec /bin/c89 -Wc,CONVLIT\(ISO8859-1\) -Wc,LANGLVL\(EXTENDED\) -D__LIBASCII $* + +To build the source, you'll need to set these environment variables, at a minimum:: + + _C89_CCMODE=1 + CC=acc + CPP="c89 -E" + LD=c89 + CPPFLAGS=-D_ALL_SOURCE + +That should allow you to run configure and get a coherent build environment. Before you type "make" from the top level though, do this:: + + cd include + make CC=c89 + +In the include directory is a small program that generates an md5global.h +header file. This file must be generated in native EBCDIC. If you just +typed make from the top level, the program and header file would be +generated in ASCII, with an ASCII filename, which would be very confusing +and not very useful. + +In my initial tests I was able to use SASL/EXTERNAL to perform X.509-based +authentication with slapd. I have subsequently tested the DIGEST-MD5 +mechanism, using OpenLDAP's slapd for storage of the secrets. It worked +without any trouble. Note, I configured sasl --with-dblib=none to prevent +it from trying to use its own sasldb. This is simply because I haven't had +the time to fix the EBCDIC/ASCII dependencies in the rest of the SASL +library. Run as-is with a real database backend, the sasldb would try to +create ASCII-named database files, which would be very unpleasant. The +required fixes are trivial, but they are also numerous, and it is a very +time-consuming task to track down all the dependencies. + +Note that this minimal-effort port of SASL will probably only work in the +context of OpenLDAP (though it may work with other special-case auxprop plugins). + +No effort has been made to fix the ASCII filenames in +the library, this SASL library will be unable to create/parse/handle +native config files or database files. This is why I've only tested it +using secrets stored in slapd, and why I only tried SASL/EXTERNAL at +first. (EXTERNAL has no config parameters, and is part of libsasl2 itself, +so it doesn't need to be dynamically loaded from anywhere.) diff --git a/docsrc/sasl/pwcheck.rst b/docsrc/sasl/pwcheck.rst new file mode 100644 index 00000000..de081be7 --- /dev/null +++ b/docsrc/sasl/pwcheck.rst @@ -0,0 +1,174 @@ +Pwcheck +======= + +Auxprop +------- + +Auxprop-hashed +-------------- + +Saslauthd +--------- + +**What is saslauthd?** saslauthd is a daemon which validates + +``ldap_servers`` - ``ldap://localhost`` + + Specify a space separated list of LDAP server URIs of the form **ldap[si]://[name[:port]]**. See the ``ldap.conf`` *URI* option for formatting details. + +``ldap_bind_dn`` - none + + When simple authentication is desired, specify a distinguished name to use for a simple authenticated bind or a simple unauthenticated bind. Do not specify if an anonymous bind is desired. This option is ignored when the evaluated ``ldap_auth_method`` is ``fastbind``. + +``ldap_bind_pw`` - none + + ``ldap_bind_pw`` is an alias for ``ldap_password``. + +``ldap_password`` - none + + When simple authentication is desired, specify a password to perform an authenticated bind, or do not specify for an unauthenticated or anonymous bind. When SASL authentication is desired, specify a password to use where required by the underlying SASL mechanism. This option is ignored when the evaluated ``ldap_auth_method`` is ``fastbind``. + +``ldap_version`` - 3 + + Defaults to version *3*. If ``ldap_use_sasl`` or ``ldap_start_tls`` are enabled, this option will be ignored, and will conform to the default value. Version *3* **is** compatible with anonymous binds, simple authenticated binds and simple unauthenticated binds. Version *2* should only be necessary where required by the server. + +``ldap_search_base`` - none + + When ``ldap_auth_method`` is evaluated as *bind*, ``ldap_search_base`` will be used to search for the user's distinguished name. When ``ldap_auth_method`` is *custom*, ``ldap_search_base`` will be used to find the user's ``ldap_password_attr`` attribute. When ``ldap_auth_method`` is evaluated as *fastbind*, ``ldap_search_base`` is ignored. If ``ldap_search_base`` contains substitution tokens, they will be replaced as specified in the ``ldap_filter`` token expansion rules. + +``ldap_filter`` - uid=%u + + When ``ldap_auth_method`` is evaluated as *bind*, ``ldap_filter`` will be used to search for the user's distinguished name. When ``ldap_auth_method`` is *custom*, ``ldap_filter`` will become, after token expansion, the user's distinguished name. When ``ldap_auth_method`` is evaluated as *fastbind*, ``ldap_filter`` is ignored. + + The following tokens, when contained within the ``ldap_filter`` option, will be substituted with the specified values: + + ``%%`` + + is replaced with a literal %. + + ``%u`` + + is replaced with the userid to be authenticated. + + ``%U`` + + is replaced by the portion of the userid before the first @ character. If an @ character does not exist in the userid, then ``%U`` would function identically to ``%u``. For example, if the userid to be authenticated is *jsmith@example.org*, ``%u`` would be replaced by *jsmith@example.org* and ``%U`` would be replaced by *jsmith*. + + ``%d`` + + is replaced by the portion of the userid after the first @ character. If an @ character does not exist in the userid, ``%d`` will be replaced by the ``realm`` value passed to ``saslauthd``. If no ``realm`` value was passed to saslauthd, ``%d`` will be replaced by the configured ``ldap_default_realm``, or by an empty string if ``ldap_default_realm`` is not configured. + + ``%1-9`` + + Within a userid which contains an @ character, followed by a domain name, ``%1`` will be replaced by the top level domain, ``%2`` will be replaced by the secondary domain, ``%3`` will be replaced by the tertiary domain, up to and including ``%9`` which would be replaced by the ninth level domain. If no @ character exists in the userid, or if there is no domain name after the @ character, or if the specified hierarchical domain level does not exist, the option is replaced by the ``realm`` value passed to ``saslauthd``. Should no ``realm`` value exist in those scenarios, the option is replaced by the configured ``ldap_default_realm``, or by an empty string if ``ldap_default_realm`` has not been configured. + + For example, if the userid to be authenticated is *jsmith@example.org*, ``%1`` would be replaced by *org* and ``%2`` would be replaced by *example*. + + ``%s`` + + is replaced by the ``service`` option passed to ``saslauthd``, or by an empty string if no ``service`` option was passed. + + ``%r`` + + is replaced by the ``realm`` option passed to ``saslauthd``. If no ``realm`` value was passed to saslauthd, ``%r`` will be replaced by the configured ``ldap_default_realm``, or by an empty string if ``ldap_default_realm`` is not configured. + +``ldap_password_attr`` - userPassword + + When ``ldap_auth_method`` is evaluated as *custom*, ``ldap_password_attr`` specifies an attribute that will be requested and retrived. If successfully retrived, the authentication request will succeed if the ``ldap_password_attr`` attribute contains a supported password hash, and if the user submitted password matches the hash. When ``ldap_auth_method`` is *bind* or *fastbind*, ``ldap_password_attr`` is ignored. + + +``ldap_group_dn`` - none + + If ``ldap_group_dn`` is specified, group authorization must also succeed (in addition to the prior authentication step), for the user's authentication attempt to be successful. If ``ldap_group_dn`` contains substitution tokens, they will be replaced as specified in the ``ldap_filter`` token expansion rules. One additional token substitution is applicable to ``ldap_group_dn``: + + ``%D`` + + is replaced by the distinguished name that was specified, or evaluated, in the authentication step. If ``ldap_use_sasl`` is enabled, the distinguished name will be resolved by performing an ldapwhoami extended operation after a successful authentication. If ``ldap_group_dn`` is specified and ``ldap_use_sasl`` is enabled, but the ldap server does not support the ldapwhoami extended operation, or if the ldapwhoami extended operation fails, then the user's authentication attempt is unsuccessful. + + +``ldap_group_attr`` - uniqueMember + + ``ldap_group_attr`` is ignored unless ``ldap_group_dn`` is also specified and ``ldap_group_match_method`` is *attr*. ``ldap_group_attr`` specifies an attribute which contains the authenticating identity's dinstinguished name. See the ``ldap_group_match_method`` entry for additional details. + +``ldap_group_filter`` - none + +``ldap_group_search_base`` - defaults to the evaluated ``ldap_search_base`` + +``ldap_group_scope`` - *sub* + +``ldap_group_match_method`` - attr + +``ldap_default_realm`` - none + +``ldap_default_domain`` - none + + ``ldap_default_domain`` is an alias for ``ldap_default_realm``. + +``ldap_auth_method`` - bind + +``ldap_timeout`` - 5 + +``ldap_size_limit`` - 1 + +``ldap_time_limit`` - 5 + +``ldap_deref`` - never + +``ldap_referrals`` - no + +``ldap_restart`` - yes + +``ldap_scope`` - sub + +``ldap_use_sasl`` - no + +``ldap_id`` - none + +``ldap_sasl_authc_id`` - none + +``ldap_authz_id`` - none + + Does not make any sense to supply an authz identity when performing sasl/fastbind. + +``ldap_sasl_authz_id`` - none + + ``ldap_sasl_authz_id`` is an alias for ``ldap_authz_id``. + +``ldap_realm`` - none + +``ldap_sasl_realm`` - + +``ldap_mech`` - + + It doesn't make any sense to use a mech that does not require an authname and password, when using fastbind. + +``ldap_sasl_mech`` - + +``ldap_sasl_secprops`` - + +``ldap_start_tls`` - + +``ldap_tls_check_peer`` - + +``ldap_tls_cacert_file`` - + +``ldap_tls_cacert_dir`` - + +``ldap_tls_ciphers`` - + +``ldap_tls_cert`` - + +``ldap_tls_key`` - + +``ldap_debug`` - + +Authdaemon +---------- + +Alwaystrue +---------- + +Auto Transition +--------------- + + diff --git a/docsrc/sasl/quickstart.rst b/docsrc/sasl/quickstart.rst new file mode 100644 index 00000000..01b0b3cf --- /dev/null +++ b/docsrc/sasl/quickstart.rst @@ -0,0 +1,94 @@ +.. _quickstart: + +Quickstart guide +================ + +This document offers a general overview of the Cyrus SASL library. +The Cyrus SASL Libray provides applications with an implementation +of the Simple Authentication and Security Layer (RFC2222), and +several authentication mechanisms. Users interested in the "big picture" +of what is provided by the library should read about +:ref:`Cyrus SASL Components `. + +Features +-------- + +The following :ref:`authentication_mechanisms` are included in +this distribution: + +* ANONYMOUS +* CRAM-MD5 +* DIGEST-MD5 +* EXTERNAL +* GSSAPI (MIT Kerberos 5, Heimdal Kerberos 5 or CyberSafe) +* KERBEROS_V4 +* LOGIN +* NTLM (requires OpenSSL libcrypto) +* OTP (requires OpenSSL libcrypto) +* PLAIN +* SRP (work in progress; requires OpenSSL libcrypto) + + +The library also supports storing user secrets in either a hash +database (e.g. Berkeley DB, gdbm, ndbm), LDAP, or in a SQL database +(MySQL, Postgres). + + +Additionally, mechanisms such as PLAIN and LOGIN +(where the plaintext password is directly supplied by the client) +can perform direct password verification via the saslauthd daemon. This +allows the use of LDAP, PAM, and a variety of other password verification +routines. + +The sample directory in the code contains two programs which provide a reference +for using the library, as well as making it easy to test a mechanism +on the command line. See programming.html for more information. + +This library is believed to be thread safe **if**: + +* you supply mutex functions (see sasl_set_mutex()) +* you make no libsasl calls until sasl_client/server_init() completes +* no libsasl calls are made after sasl_done() is begun +* when using GSSAPI, you use a thread-safe GSS / Kerberos 5 library. + + +Typical Installation +-------------------- + +First, if you are upgrading from Cyrus SASLv1, please see upgrading.html. + +Please see the :ref:`installation guide ` for instructions +on how to install this package. + +Note that the library can use the environment variable SASL_PATH to locate the +directory where the mechanisms are; this should be a colon-separated +list of directories containing plugins. Otherwise it will default to the +value of ``--with-plugindir`` as supplied to ``configure`` (which +itself defaults to ``/usr/local/lib``). + +Looking to :ref:`Install on Mac OSX? ` + +Looking to :ref:`Install on Windows? ` + +Configuration +------------- + +There are two main ways to configure the SASL library for a given +application. The first (and typically easiest) is to make use +of the application's configuration files. Provided the application supports it +(via the ``SASL_CB_GETOPT`` callback), please refer to that documetation +for how to supply SASL options. + +Alternatively, Cyrus SASL looks for configuration files in +/usr/lib/sasl/Appname.conf where Appname is settable by the +application (for example, Sendmail 8.10 and later set this to +"Sendmail"). + +Configuration using the application's configuration files (via +the ``getopt`` callback) will override those supplied by +the SASL configuration files. + +For a detailed guide on configuring libsasl, please look at the +:ref:`Sysadmin guide ` and the information on :ref:`options `. diff --git a/docsrc/sasl/resources.rst b/docsrc/sasl/resources.rst new file mode 100644 index 00000000..663dc473 --- /dev/null +++ b/docsrc/sasl/resources.rst @@ -0,0 +1,15 @@ +.. _resources: + +=============================== +Other Documentation & Resources +=============================== + + +* `Using SASL: Pluggable Security `_ +* `Using SASL: CMU's Cyrus SASL Library `_ +* `Information on SASL mechanisms, profiles, servers and clients implementing SASL `_ +* `FAQ from Sendmail `_ +* `The Secure Remote Password Protocol `_ paper by Thomas Wu +* `TCL extensions for SASL `_ +* `The NTLM Authentication Protocol `_ (NTLM) +* `Common Internet File System (CIFS) Technical Reference `_ (SMB/NTLM) diff --git a/docsrc/sasl/sasl_migration.rst b/docsrc/sasl/sasl_migration.rst new file mode 100644 index 00000000..7cb4c657 --- /dev/null +++ b/docsrc/sasl/sasl_migration.rst @@ -0,0 +1,20 @@ +==================== +Cyrus SASL Migration +==================== + +When migrating the ``/etc/sasldb`` database using the ``utils/dbconverter-2`` +utility, you may encounter the error message "Error opening password +file". This is usually due to the fact your SASL V1 library was compiled +using a different version of Berkeley DB than the SASL V2 library. +You can work around this by using Berkeley DB's db_upgrade utility +(possibly chaining the DB3 and DB4 upgrade utilities) to upgrade a copy +of sasldb prior to conversion using dbconverter-2. + +Here is the script we use at our installation, where SASL has to +coexist with SASL2:: + + !/bin/sh + cp /etc/sasldb /tmp/sasldb.$$ + /usr/local/BerkeleyDB.4/bin/db_upgrade /etc/sasldb + echo ""|/usr/local/sasl/sbin/dbconverter-2 + cp /tmp/sasldb.$$ /etc/sasldb \ No newline at end of file diff --git a/docsrc/sasl/sysadmin.rst b/docsrc/sasl/sysadmin.rst new file mode 100644 index 00000000..73bd0ad2 --- /dev/null +++ b/docsrc/sasl/sysadmin.rst @@ -0,0 +1,455 @@ +.. _sysadmin: + +==================================== +Cyrus SASL for System Administrators +==================================== + +This document covers configuring SASL for system administrators, +specifically those administrators who are installing a server that +uses the Cyrus SASL library. You may want to read +:ref:`about components ` which presents an +overview of the Cyrus SASL distribution +and describes how the components interact, as well as the :ref:`installation guide ` + +.. _saslintro: + +What SASL is +============ + +SASL, the Simple Authentication and Security Layer, is a generic +mechanism for protocols to accomplish authentication. Since protocols +(such as SMTP or IMAP) use SASL, it is a natural place for code +sharing between applications. Some notable applications that use the +Cyrus SASL library include `Sendmail `_, +`Cyrus imapd `_, +and `OpenLDAP `_. + +Applications use the SASL library to tell them how to accomplish +the SASL protocol exchange, and what the results were. + +SASL is only a framework: specific SASL mechanisms govern the +exact protocol exchange. If there are n protocols and m different +ways of authenticating, SASL attempts to make it so only n plus m +different specifications need be written instead of n times m +different specifications. With the Cyrus SASL library, the mechanisms +need only be written once, and they'll work with all servers that use +it. + +.. _authid: + +Authentication and authorization identifiers +-------------------------------------------- + +An important concept to become familiar with is the difference between +an "authorization identifier" and an "authentication identifier". + +userid (user id, authorization id) + The userid is the + identifier an application uses to check allowable options. On my Unix + system, the user ``bovik`` (the account of Harry Q. Bovik) is + allowed to write to ``/home/bovik`` and its subdirectories but + not to ``/etc``. +authid (authentication id) + The authentication identifier is + the identifier that is being checked. "bovik"'s password might be + "qqqq", and the system will authenticate anyone who knows "qqqq" as + "bovik". + + However, it's possible to authenticate as one user but + *act as* another user. For instance, Harry might be away on + vacation and assign one of his graduate students, Jane, to read his + mail. He might then allow Jane to act as him merely by supplying her + password and her id as authentication but requesting authorization as + "bovik". So Jane might log in with an authentication identifier of + "jane" and an authorization id of "bovik" and her own (Jane's) + password. + + +Applications can set their own proxy policies; by default, the SASL +library will only allow the same user to act for another (that is, +userid must equal authid). See your application's documentation for +details about changing the default proxy/authorization policies. + +.. _realms: + +Realms +------ + +The Cyrus SASL library supports the concept of "realms". A realm is +an abstract set of users and certain mechanisms authenticate users in +a certain realm. + +In the simplest case, a single server on a single machine, the +realm might be the fully-qualified domain name of the server. If the +applications don't specify a realm to SASL, most mechanisms will +default to this. + +If a site wishes to share passwords between multiple machines, it +might choose it's authentication realm as a domain name, such as +"CMU.EDU". On the other hand, in order to prevent the entire site's +security from being compromised when one machine is compromised, each +server could have it's own realm. Certain mechanisms force the user +(client side) to manually configure what realm they're in, making it +harder for users to authenticate. + +A single site might support multiple different realms. This can +confuse applications that weren't written in anticipation of this; make +sure your application can support it before adding users from different +realms into your databases. + +To add users of different realms to sasldb, you can use the +``-u`` option to saslpasswd2. The SQL plugin has a way of +integrating the realm name into the query string with the '%r' macro. + +The Kerberos mechanisms treat the SASL realm as the Kerberos +realm. Thus, the realm for Kerberos mechanisms defaults to the +default Kerberos realm on the server. They may support cross-realm +authentication; check your application on how it deals with this. + +Realms will be passed to saslauthd as part of the saslauthd protocol, +however the way each saslauthd module deals with the situation is +different (for example, the LDAP plugin allows you to use the realm +to query the server, while the rimap and PAM plugins ignore it entirely). + +Realms are represented in a username string by any text followinhg +the '@' sign. So, usernames like rjs3@ANDREW.CMU.EDU, is user 'rjs3' +in the realm 'ANDREW.CMU.EDU'. If no realm is provided, the server's +FQDN is assumed (likewise when specifying a realm for saslpasswd2). + +.. _saslhow: + +How SASL works +============== + +How SASL works is governed by what mechanism the client and server +choose to use and the exact implementation of that mechanism. This +section describes the way these mechanisms act in the Cyrus SASL +implementation. + +The PLAIN mechanism, ``sasl_checkpass()``, and plaintext passwords +------------------------------------------------------------------ + +The PLAIN mechanism is not a secure method of authentication by +itself. It is intended for connections that are being encrypted by +another level. (For example, the IMAP command "STARTTLS" creates an +encrypted connection over which PLAIN might be used.) The PLAIN +mechanism works by transmitting a userid, an authentication id, and a +password to the server, and the server then determines whether that is +an allowable triple. + +The principal concern for system administrators is how the +authentication identifier and password are verified. The Cyrus SASL +library is flexible in this regard: + +auxprop + checks passwords agains the ``userPassword`` attribute + supplied by an auxiliary property plugin. For example, SASL ships + with a sasldb auxiliary property plugin, that can be used to + authenticate against the passwords stored in ``/etc/sasldb2``. + + Since other mechanisms also use this database for passwords, using + this method will allow SASL to provide a uniform password database to + a large number of mechanisms. +saslauthd + contacts the ``saslauthd`` daemon to to check passwords + using a variety of mechanisms. More information about the various invocations + of saslauthd can be can be found in ``saslauthd(8)``. Generally you + want something like ``saslauthd -a pam``. If plaintext authentications + seem to be taking some time under load, increasing the value of the ``-n`` + parameter can help. + + Saslauthd keeps its named socket in "/var/state/saslauthd" by default. + This can be overridden by specifying an alternate value to + --with-saslauthd=/foo/bar at compile time, or by passing the -m + parameter to saslauthd (along with setting the saslauthd_path SASL + option). Whatever directory this is, it must exist in order for + saslauthd to function. + + Once you configure (and start) ``saslauthd``, there is a + ``testsaslauthd`` program that can be built with ``make + testsaslauthd`` in the ``saslauthd`` subdirectory of the + source. This can be used to check that that the ``saslauthd`` + daemon is installed and running properly. An invocation like + ``testsaslauthd -u rjs3 -p 1234`` with appropriate values for the + username and password should do the trick. + + If you are using the PAM method to verify passwords with saslauthd, keep in + mind that your PAM configuration will need to be configured for each service + name that is using saslauthd for authentication. Common service names + are ``imap``, ``sieve``, and ``smtp``. +Courier-IMAP authdaemond + contacts Courier-IMAP's ``authdaemond`` daemon to check passwords. + This daemon is simliar in functionality to ``saslauthd``, and is shipped + separately with the `Courier `_ mail server. + + Note: this feature is **not** compiled in the library by default, and is + provided for sites with custom/special requirements only (because the + internal authentication protocol its not documented anywhere so it could + change at any time). We have tested against the authdaemond included with + Courier-IMAP 2.2.1. + + To enable ``authdaemond`` support, pass ``--with-authdaemon`` to the + configuration script, set pwcheck_method to ``authdaemond'' and point + authdaemond_path to ``authdaemond``'s unix socket. Optionally, you can + specify --with-authdaemond=PATH to the configure script so that + authdaemond_path points to a default, static, location. +pwcheck + checks passwords with the use of a separate, + helper daemon. This feature is for backwards-compatibility + only. New installations should use saslauthd. +write your own + Last, but not least, the most flexible method of authentication + for PLAIN is to write your own. If you do so, any application that + calls the ``sasl_checkpass()`` routine or uses PLAIN will + invoke your code. The easiest place to modify the plaintext + authentication routines is to modify the routine + ``_sasl_checkpass()`` in the file ``lib/server.c`` to + support a new method, and to add that method to + ``lib/checkpw.c``. Be sure to add a prototype in + ``lib/saslint.h``! + + However, the more flexible and preferred method of + adding a routine is to create a new saslauthd mechanism. + +The LOGIN mechanism (not to be confused with IMAP4's LOGIN command) +is an undocumented, unsupported mechanism. It's included in the Cyrus +SASL distribution for the sake of SMTP servers that might want to +interoperate with old clients. Do not enable this mechanism unless +you know you're going to need it. When enabled, it verifies passwords +the same way the PLAIN mechanism does. + +Shared secrets mechanisms +------------------------- + +The Cyrus SASL library also supports some "shared secret" +authentication methods: CRAM-MD5 and its successor DIGEST-MD5. These +methods rely on the client and the server sharing a "secret", usually +a password. The server generates a challenge and the client a +response proving that it knows the shared secret. This is much more +secure than simply sending the secret over the wire proving that the +client knows it. + +There's a downside: in order to verify such responses, the +server must keep passwords or password equivalents in a database; +if this database is compromised, it is the same as if all the +passwords for the realm are compromised. + +Put another way, *you cannot use saslauthd with these methods*. +If you do not wish to advertise these methods for that reason (i.e. you +are only using saslauthd for password verification), then either remove +the non-plaintext plugins (those other than login and plain) from the +plugin directory, or use the :option:`mech_list` option to disable them. + +For simplicity sake, the Cyrus SASL library stores plaintext +passwords only in the ``/etc/sasldb2`` database. These passwords +are then shared among all mechanisms which choose to use it. +Depending on the exact database method +used (gdbm, ndbm, or db) the file may have different suffixes or may +even have two different files (``sasldb.dir`` and +``sasldb.pag``). It is also possible for a server to define +it's own way of storing authentication secrets. Currently, no +application is known to do this. + +The principle problem for a system administrator is to make sure that +sasldb is properly protected. Only the servers that need to read it to +verify passwords should be able to. If there are any normal shell +users on the system, they must not be able to read it. + +This point is important, so we will repeat it: **sasldb stores the +plaintext versions of all of its passwords. If it is compromised so +are all of the passwords that it stores**. + +Managing password changes is outside the scope of the library. +However, system administrators should probably make a way of letting +user's change their passwords available to users. The +``saslpasswd2`` utility is provided to change the secrets in +sasldb. It does not affect PAM, ``/etc/passwd``, or any other +standard system library; it only affects secrets stored in sasldb. + +Finally, system administrators should think if they want to enable +"auto_transition". If set, the library will automatically create +secrets in sasldb when a user uses PLAIN to successfully authenticate. +However, this means that the individual servers, such as imapd, need +read/write access to sasldb, not just read access. By default, +"auto_transition" is set to false; set it to true to enable. (There's +no point in enabling this option if "pwcheck_method" is "auxprop", +and the sasldb plugin is installed, since you'll be transitioning from +a plaintext store to a plaintext store) + +Kerberos mechanisms +------------------- + +The Cyrus SASL library also comes with two mechanisms that make use of +Kerberos: KERBEROS_V4, which should be able to use any Kerberos v4 +implementation, and GSSAPI (tested against MIT Kerberos 5, Heimdal +Kerberos 5 and CyberSafe Kerberos 5). These mechanisms make use of the kerberos infrastructure +and thus have no password database. + +Applications that wish to use a kerberos mechanism will need access +to a service key, stored either in a :option:`srvtab` file (Kerberos 4) or a +:option:`keytab` file (Kerberos 5). + +The Kerberos 4 :option:`srvtab` file location is configurable; by default it is +``/etc/srvtab``, but this is modifiable by the "srvtab" option. +Different SASL applications can use different srvtab files. + +A SASL application must be able to read its srvtab or keytab file. + +You may want to consult the GSSAPI Tutorial.

    + +The OTP mechanism +----------------- + +The Cyrus SASL library also supports the One-Time-Password (OTP) +mechanism. This mechanism is similar to CRAM-MD5 and DIGEST-MD5 in +that is uses a shared secret and a challenge/response exchange. +However, OTP is more secure than the other shared secret mechanisms in +that the secret is used to generate a sequence of one-time (single +use) passwords which prevents reply attacks, and that secret need +not be stored on the system. These one-time passwords are stored in the +``/etc/sasldb2`` database. + +OTP via OPIE +############ + +For sites with an existing OTP infrastructure using OPIE, Cyrus SASL +can be configured to use OPIE v2.4 instead of using its own database +and server-side routines. + +OPIE should be configured with the ``--disable-user-locking`` +option if the SASL server application will not be running as "root". + +OPIE uses its own "opiekeys" database for storing the data necessary +for generating the server challenges. The location of the :option:`opiekeys` +file is configurable in SASL; by default it is ``/etc/opiekeys``, +but this is modifiable by the :option:`opiekeys` option. + +A SASL server application must be able to read and write the +opiekeys file. + +Auxiliary Properties +==================== + +SASLv2 introduces the concept of Auxilliary Properties. That is, the ability +for information related to authentication and authorization to all be looked +up at once from a directory during the authentication process. SASL Plugins +internally take advantage of this to do password lookups in directories +such as the SASLdb, LDAP or a SQL database. Applications can look up arbitrary properties through them. + +Note that this means that if your password database is in a SASLdb, and +you wish to use it for plaintext password lookups through the sasldb, you +will need to set the sasl :option:`pwcheck_method` to be ``auxprop``. + +How to set configuration options +================================ + +The Cyrus SASL library comes with a built-in configuration file +reader. However, it is also possible for applications to redefine +where the library gets it's configuration options from. + +.. _saslconf: + +The default configuration file +------------------------------ + +By default, the Cyrus SASL library reads its options from +``/usr/lib/sasl2/App.conf`` (where "App" is the application +defined name of the application). For instance, Sendmail reads its +configuration from ``/usr/lib/sasl2/Sendmail.conf`` and the +sample server application included with the library looks in +``/usr/lib/sasl2/sample.conf``. + +A standard Cyrus SASL configuration file looks like:: + + srvtab: /var/app/srvtab + pwcheck_method: saslauthd + +Application configuration +------------------------- + +Applications can redefine how the SASL library looks for configuration +information. Check your application's documentation for specifics. + +For instance, Cyrus imapd reads its sasl options from its own +configuration file, ``/etc/imapd.conf``, by prepending all SASL +options with ``sasl_``: the SASL option "pwcheck_method" is set +by changing "sasl_pwcheck_method" in ``/etc/imapd.conf``. + +Troubleshooting +=============== + +Why doesn't KERBEROS_V4 doesn't appear as an available mechanism? + Check that the ``srvtab`` file is readable by the + user running as the daemon. For Cyrus imapd, it must be readable by + the Cyrus user. By default, the library looks for the srvtab in + ``/etc/srvtab``, but it's configurable using the :option:`srvtab` + option. +Why doesn't OTP doesn't appear as an available mechanism? + If using OPIE, check that the ``opiekeys`` file is + readable by the user running the daemon. For Cyrus imapd, it must + be readable by the Cyrus user. By default, the library looks for the + opiekeys in ``/etc/opiekeys``, but it's configurable using the + :option:`opiekeys` option. +Why don't CRAM-MD5 and DIGEST-MD5 work with my old sasldb? + Because sasldb now stores plaintext passwords only, the old + sasldb is incompatible. +I'm having performance problems on each authentication, there is a noticeable slowdown when sasl initializes, what can I do? + libsasl reads from ``/dev/random`` as part of its + initialization. ``/dev/random`` is a "secure" source of entropy, + and will block your application until a sufficient amount of + randomness has been collected to meet libsasl's needs. + + To improve performance, you can change DEV_RANDOM in + ``config.h`` to be ``/dev/urandom`` and recompile + libsasl. ``/dev/urandom`` offers less secure random numbers but + should return immediately. The included mechanisms, besides OTP and + SRP, use random numbers only to generate nonces, so using + ``/dev/urandom`` is safe if you aren't using OTP or SRP. + + +I've converted the sasldb database to the new format. Why can't anybody authenticate? + sasldb is now a plugin module for the auxprop method. + Make sure you changed the /usr/lib/sasl2/\*.conf files to reflect + ``pwcheck_method: auxprop`` + + ...and if you're using cyrus-imapd, /etc/imapd.conf must reflect: + ``sasl_pwcheck_method: auxprop`` + +Is LOGIN supported? + The LOGIN mechanism is a non-standard, undocumented + plaintext mechanism. It's included in the SASL distribution purely + for sites that need it to interoperate with old clients; we don't + support it. Don't enable it unless you know you need it. + +Is NTLM supported? + The NTLM mechanism is a non-standard, undocumented + mechanism developed by Microsoft. It's included in the SASL + distribution purely for sites that need it to interoperate with + Microsoft clients (ie, Outlook) and/or servers (ie, Exchange); we + don't support it. Don't enable it unless you know you need it. + +How can I get a non-root application to check plaintext passwords? + Use the "saslauthd" daemon and setting "pwcheck_method" + to "saslauthd". + +I want to use Berkeley DB, but it's installed in ``/usr/local/BerkeleyDB.3.1`` and ``configure`` can't find it. + Try setting "CPPFLAGS" and "LDFLAGS" environment + variables before running ``configure``, like so:: + + env CPPFLAGS="-I/usr/local/BerkeleyDB.3.1/include" \ + LDFLAGS="-L/usr/local/BerkeleyDB.3.1/lib -R/usr/local/BerkeleyDB.3.1/lib" \ + ./configure --with-dblib=berkeley + +It's not working and won't tell me why! Help! + Check syslog output (usually stored in + ``/var/log``) for more information. You might want to change your + syslog configuration (usually ``/etc/syslogd.conf``) to log + "\*.debug" to a file while debugging a problem. + + The developers make heavy use of ``strace`` or ``truss`` + when debugging a problem that isn't outputting any useful + information. + +Is there a mailing list to discuss the Cyrus SASL library? + Check out our :ref:`contribution ` page for ways to get in touch + with us, including mailing lists and IRC. diff --git a/docsrc/sasl/upgrading.rst b/docsrc/sasl/upgrading.rst new file mode 100644 index 00000000..bf38fa3a --- /dev/null +++ b/docsrc/sasl/upgrading.rst @@ -0,0 +1,92 @@ +.. _upgrading-v1-v2: + +======================= +Upgrading from v1 to v2 +======================= + +This document covers issues with upgrading from SASLv1 to SASLv2. +To upgrade: + +* Install Cyrus SASL v2 as normal according to the :ref:`installation guide `. + This will overwrite + some manpages, but will not affect your current applications. Do NOT + attempt to make it use the same directories, otherwise old Cyrus SASLv1 + applications will no longer function. + +* Install your new Cyrus SASL v2 applications. Applications that + use Cyrus SASLv1 will *not* use the Cyrus SASL v2 + infrastructure (and vice-versa). + +* If you used ``/etc/sasldb`` for authentication, you'll need + to take the following steps to convert to using ``/etc/sasldb2`` + with Cyrus SASL v2: + + 1. run ``utils/dbconverter-2`` after installation. + 2. change the ``pwcheck_method`` in any config files to + ``auxprop`` + 3. (optional) add ``auxprop_plugin`` to the config files, + set to ``sasldb`` + +* If you used ``passwd``, ``shadow``, ``pam``, + ``kerberos_v4`` or ``sia`` as your ``pwcheck_method`` + in libsasl v1, you'll need to convert to using + ``saslauthd``. Arrange to start ``saslauthd -a + `` on boot. Change ``pwcheck_method`` in any + configuration files to ``saslauthd``. + +* If you used ``pwcheck`` with libsasl v1, you can either + continue to use ``pwcheck`` with libsasl v1 or you can switch to + ``saslauthd``, which offers more flexibility and a potentially + much more efficient implementation. + +* If you are continuing to use some libsasl v1 applications, read + onwards to understand the ramifications. + +* If you want to learn how to port applications from libsasl v1 to + libsasl v2, you should read the :ref:`converting applications guide `. + +Backwards Compatibility +======================= + +Cyrus SASLv2 is incompatible with applications that use +Cyrus SASLv1. This means that applications are unable to +simultaneously link both versions of the library, and developers are +encouraged to instead develop or upgrade their applications to link +against the new libsasl. + +Likewise, the format for the sasldb database has been completely +revamped. See :ref:`here ` for a discussion of the relevant +upgrade issues related to sasldb. All new passwords stored in the +sasldb database will be in plaintext, meaning that a compromised +sasldb will compromise all services with the same passwords. (This +situation isn't significantly worse, cryptographically speaking, than +the old method and allows the database to be easy to transition to +another format, when the need arises.) Mechanisms requiring a more +secure password database backend (e.g. SRP) should implement their own +or use alternate property names within sasldb. + +.. _coexist: + +Coexistence with SASLv1 +======================= + +The two library versions and the associated utilities should be able +to coexist on the same system. The man pages will be unable to +coexist (but luckily the new manpages are much better!). The libsasl +v2-specific utilities have had a "2" appended to their name for this +purpose (e.g. ``saslpasswd2``, ``sasldblistusers2``). The +new-style sasldb now defaults to the name ``/etc/sasldb2``, but +this is configurable. + +.. _upgrading-db: + +Database Upgrades +================= + +While there does not seem to be any conflict with the keys stored in +the database, it is not recommended for both versions of the library +to use the same database file. Included in the utils directory is a +program called ``dbconverter-2`` which will allow you to convert +from the old-format database to the new format. Note that if you continue to +run older applications that rely on Cyrus SASLv1, the databases for SASLv1 +and SASLv2 will not automatically be kept in sync. diff --git a/docsrc/sasl/windows.rst b/docsrc/sasl/windows.rst new file mode 100644 index 00000000..a6800a13 --- /dev/null +++ b/docsrc/sasl/windows.rst @@ -0,0 +1,170 @@ +.. _install-windows: + +============================== +Building Cyrus SASL on Windows +============================== + +Note, that Cyrus SASL on Windows is still laregely a "work in progress". +So far only the main library, plugins (SASLDB using SleepyCat, no MySQL) +and several applications (see the list below) can be built. In particular, +saslauthd doesn't compile on Windows. + +Prerequisites +============= + +Visual Studio. + We have tested Visual Studio 6 and Visual Studio 7 (.NET). + By default we are using Visual Studio 7 (both 2002 and 2003 versions were tested). If you want to use Visual Studio 6, + you need to remove the leading # character from the line containing ``#VCVER=6`` in win32/common.mak. + +The latest Platform SDK. + We are currently using March 2006. (The earliest tested version was November 2001.) + +SleepyCat + SleepyCat's include files and libraries are required to buil SASLDB plugin, + saslpasswd2.exe and sasldblistusers2.exe. We have tested SleepyCat 4.1.X-4.4.X. + +Cygwin (for building from GIT) + The `Cygwin `_ Unix-compatibility + environment to create the ``_init.c`` files needed for dynamic + loading. Cygwin is *not* required for building from our tar + distribution. + +Step by step +============ + +These directions assume that you've untarred the library or used GIT +and the sources are in ``C:\SASL``. + +Preparing to build (GIT only!) +------------------------------ + +Start a cygwin shell and create the dynamic loading stubs:: + + % cd /cygdrive/c/sasl/plugins + % sh makeinit.sh + +Building using NMake +-------------------- + +Open a "Windows 2000 build environment" from the SDK's Start Menu and +use ``nmake /f NTMakefile`` to build. + +To build a debug verison, use ``nmake /f NTMakefile +CFG=Debug``. For a production version, ``nmake /f NTMakefile +CFG=Release``. If you don't specify CFG parameter, production +version will be built by default. + +As Windows build requires SleepyCat, there are additional options +that have to be provided to NMake on the command line. +If SleepyCat sources are located in ``c:\packages\db\4.1.24`` +and built library in ``c:\packages\db\4.1.24\build_win32\Release_static``, +you should add something like +``DB_INCLUDE=c:\packages\db\4.1.24\build_win32`` +and ``DB_LIBPATH=c:\packages\db\4.1.24\build_win32\Release_static``. + +Also note, that the ``DB_LIB`` defines the name of the SleepyCat library +to link against. It defaults to libdb41s.lib. + +If you don't pass the parameters described above, NMake will pick the +defaults, which is probably not what you want. + +Another option of interest is ``STATIC``. +It specifies which version of the standard C library +to use. The default is "no", meaning that the standard C library +from the MSVCRT.DLL will be used. + +Example:: + + Targeting Windows 2000 and IE 5.0 RETAIL + + C:\Program Files\Microsoft SDK> cd \sasl + + C:\sasl> nmake /f NTMakefile DB_INCLUDE=c:\packages\db\4.1.24\build_win32 + DB_LIBPATH=c:\packages\db\4.1.24\build_win32\Release_static + + No configuration specified. Defaulting to Release. + Using MSVCRT.dll as C library by default. + Defaulting SleepyCat library name to libdb41s.lib. + Codegeneration defaulting to /MD. + + +SASL NTMakefile also understands "clean" target that you can use to clean all files generated by the compiler. + +:: + + C:\sasl> nmake /f NTMakefile clean + + Microsoft (R) Program Maintenance Utility Version 7.00.9466 + Copyright (C) Microsoft Corporation. All rights reserved. + + cd lib && nmake /f NTMakefile clean + + Microsoft (R) Program Maintenance Utility Version 7.00.9466 + Copyright (C) Microsoft Corporation. All rights reserved. + + No configuration specified. Defaulting to Release. + Using MSVCRT.dll as C library by default. + Defaulting SleepyCat library name to libdb41s.lib. + Defaulting SleepyCat include path to c:\work\isode\db\build_win32. + Defaulting SleepyCat library path to c:\work\isode\db\build_win32\Release_static. + + +Building additional plugins +--------------------------- + +Specify "GSSAPI=" parameter if you want to enable GSSAPI plugin. +Currently only =CyberSafe is supported and this will build the plugin +that links against CyberSafe Kerberos. + +GSSAPI depends on ``GSSAPI_INCLUDE`` and ``GSSAPI_LIBPATH`` parameters. +You can either specify them on the command line or edit the defaults in win32\common.mak + +Specify "SQL=" parameter if you want to enable SQL plugin. +Currently only =SQLITE is supported and this will build the plugin +that links against SQLITE (www.sqlite.org). + +SQL= depends on ``SQLITE_INCLUDES`` and ``SQLITE_LIBPATH`` parameters. +You can either specify them on the command line or edit the defaults in win32\common.mak + +Specify "NTLM=1" parameter if you want to enable NTLM plugin. +I.e. ``nmake /f NTMakefile NTLM=1`` + +Specify "SRP=1" parameter if you want to enable SRP plugin. +You can also specify "DO_SRP_SETPASS=1" if you want to enable SRP setpass functionality. + +Specify "OTP=1" parameter if you want to enable OTP plugin. + +NTLM, SRP and OTP plugins depend on OpenSSL. You can either specify +``OPENSSL_INCLUDE`` and ``OPENSSL_LIBPATH`` parameters on the command +line or edit the defaults in win32\common.mak +Note, that unless you are building one of those plugins, OpenSSL is not required! + +If you want to build multiple additional plugins at once, you can specify +multiple parameters described above, for example ``nmake /f NTMakefile NTLM=1 SRP=1 OPT=1`` + +Limitations +----------- + +Currently all plugins except KerberosV4 (kerberos4.c) and PASSDSS (passdss.c) can be built on Windows. +However limited testings was done for some plugins as listed below: + +* GSSAPI - tested using CyberSafe, +* SASLDB - only SleepyCat version can be built, +* SQL - using SQLITE, not tested + + +The following executables were built and tested (to some extent): + +* sample + + * sample-client + * sample-server + +* utils + + * sasldblistusers2 + * saslpasswd2 + * testsuite + * pluginviewer + * Note that saslauthd is *NOT* in this list. From ebd349ec1b310ee721b522044a039dac60a06ce7 Mon Sep 17 00:00:00 2001 From: Nicola Nye Date: Mon, 7 Nov 2016 16:03:04 +1100 Subject: [PATCH 247/796] [Docs] Tidying up the index, reduce duplication. --- docsrc/developers.rst | 10 ---------- docsrc/index.rst | 26 ++++++++++++-------------- docsrc/sasl/sasl_migration.rst | 20 -------------------- docsrc/sasl/sysadmin.rst | 6 +++--- docsrc/sasl/upgrading.rst | 21 +++++++++++++++++++++ 5 files changed, 36 insertions(+), 47 deletions(-) delete mode 100644 docsrc/developers.rst delete mode 100644 docsrc/sasl/sasl_migration.rst diff --git a/docsrc/developers.rst b/docsrc/developers.rst deleted file mode 100644 index d7e42cec..00000000 --- a/docsrc/developers.rst +++ /dev/null @@ -1,10 +0,0 @@ -========== -Developers -========== - - -.. toctree:: - :maxdepth: 2 - :glob: - - Contribute diff --git a/docsrc/index.rst b/docsrc/index.rst index 3778491b..9e353bec 100644 --- a/docsrc/index.rst +++ b/docsrc/index.rst @@ -51,18 +51,27 @@ be found within the source code. download sasl/quickstart sasl/installation - sasl/upgrading - sasl/appconvert + Contact Us .. toctree:: :maxdepth: 1 - :caption: Management + :caption: Configuration sasl/concepts sasl/components sasl/options sasl/sysadmin sasl/advanced + sasl/upgrading + sasl/appconvert + +.. toctree:: + :maxdepth: 1 + :caption: Developers + + sasl/developer/programming + sasl/developer/plugprog + sasl/developer/testing .. toctree:: :maxdepth: 1 @@ -72,15 +81,4 @@ be found within the source code. sasl/authentication_mechanisms sasl/pwcheck sasl/faq - sasl/sasl_migration sasl/resources - -.. toctree:: - :maxdepth: 1 - :caption: Developers - - contribute - developers - sasl/developer/programming - sasl/developer/plugprog - sasl/developer/testing diff --git a/docsrc/sasl/sasl_migration.rst b/docsrc/sasl/sasl_migration.rst deleted file mode 100644 index 7cb4c657..00000000 --- a/docsrc/sasl/sasl_migration.rst +++ /dev/null @@ -1,20 +0,0 @@ -==================== -Cyrus SASL Migration -==================== - -When migrating the ``/etc/sasldb`` database using the ``utils/dbconverter-2`` -utility, you may encounter the error message "Error opening password -file". This is usually due to the fact your SASL V1 library was compiled -using a different version of Berkeley DB than the SASL V2 library. -You can work around this by using Berkeley DB's db_upgrade utility -(possibly chaining the DB3 and DB4 upgrade utilities) to upgrade a copy -of sasldb prior to conversion using dbconverter-2. - -Here is the script we use at our installation, where SASL has to -coexist with SASL2:: - - !/bin/sh - cp /etc/sasldb /tmp/sasldb.$$ - /usr/local/BerkeleyDB.4/bin/db_upgrade /etc/sasldb - echo ""|/usr/local/sasl/sbin/dbconverter-2 - cp /tmp/sasldb.$$ /etc/sasldb \ No newline at end of file diff --git a/docsrc/sasl/sysadmin.rst b/docsrc/sasl/sysadmin.rst index 73bd0ad2..7a1e4356 100644 --- a/docsrc/sasl/sysadmin.rst +++ b/docsrc/sasl/sysadmin.rst @@ -1,8 +1,8 @@ .. _sysadmin: -==================================== -Cyrus SASL for System Administrators -==================================== +===================== +System Administrators +===================== This document covers configuring SASL for system administrators, specifically those administrators who are installing a server that diff --git a/docsrc/sasl/upgrading.rst b/docsrc/sasl/upgrading.rst index bf38fa3a..77025bd8 100644 --- a/docsrc/sasl/upgrading.rst +++ b/docsrc/sasl/upgrading.rst @@ -90,3 +90,24 @@ program called ``dbconverter-2`` which will allow you to convert from the old-format database to the new format. Note that if you continue to run older applications that rely on Cyrus SASLv1, the databases for SASLv1 and SASLv2 will not automatically be kept in sync. + + +Errors on migration +=================== + +When migrating the ``/etc/sasldb`` database using the ``utils/dbconverter-2`` +utility, you may encounter the error message "Error opening password +file". This is usually due to the fact your SASL V1 library was compiled +using a different version of Berkeley DB than the SASL V2 library. +You can work around this by using Berkeley DB's db_upgrade utility +(possibly chaining the DB3 and DB4 upgrade utilities) to upgrade a copy +of sasldb prior to conversion using dbconverter-2. + +Here is the script we use at our installation, where SASL has to +coexist with SASL2:: + + !/bin/sh + cp /etc/sasldb /tmp/sasldb.$$ + /usr/local/BerkeleyDB.4/bin/db_upgrade /etc/sasldb + echo ""|/usr/local/sasl/sbin/dbconverter-2 + cp /tmp/sasldb.$$ /etc/sasldb From 3712e0e1e533b5bcd2c9e6421754d9b8f2d339a2 Mon Sep 17 00:00:00 2001 From: Nicola Nye Date: Mon, 7 Nov 2016 16:12:07 +1100 Subject: [PATCH 248/796] [Docs] Need MAkefile to build the docs. --- docsrc/Makefile | 186 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 docsrc/Makefile diff --git a/docsrc/Makefile b/docsrc/Makefile new file mode 100644 index 00000000..82fd68d2 --- /dev/null +++ b/docsrc/Makefile @@ -0,0 +1,186 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = -n +SPHINXBUILD = sphinx-build +PAPER = +SOURCEDIR = . +BUILDDIR = build + +# Only need Perl2RST if building docs from Perl modules, which cyrus-sasl doesn't have +#PERL2RST = ../tools/perl2rst + +# User-friendly check for sphinx-build +ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) +$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) +endif + +# User-friendly check for perl2rst +#ifeq ($(shell which $(PERL2RST) >/dev/null 2>&1; echo $$?), 1) +#$(error The '$(PERL2RST)' command was not found. Make sure you have perl2rst installed, then set the PERL2RST environment variable to point to #the full path of the '$(PERL2RST)' script. It relies on Perl module Pod::POM::View::Restructured) +#endif + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(SOURCEDIR) +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(SOURCEDIR) + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/CyrusIMAP.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/CyrusIMAP.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/CyrusIMAP" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/CyrusIMAP" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +latexpdfja: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b cyrman $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." From 5beeb9fde2c1236851bb51254fd1e0a4f2d5e282 Mon Sep 17 00:00:00 2001 From: Ignacio Casal Quinteiro Date: Fri, 24 Jun 2016 14:57:15 +0200 Subject: [PATCH 249/796] Some fixes for distcheck saslmd5.h is already generated somewhere else so there is no need to point to it here. --- saslauthd/Makefile.am | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/saslauthd/Makefile.am b/saslauthd/Makefile.am index f38097cf..75dc1057 100644 --- a/saslauthd/Makefile.am +++ b/saslauthd/Makefile.am @@ -14,7 +14,7 @@ saslauthd_SOURCES = mechanisms.c globals.h \ auth_ldap.c auth_ldap.h cache.c cache.h cfile.c cfile.h \ krbtf.c krbtf.h utils.c utils.h \ ipc_unix.c ipc_doors.c saslauthd-main.c saslauthd-main.h \ - md5.c saslauthd_md5.h md5global.h + md5.c saslauthd_md5.h EXTRA_saslauthd_sources = getaddrinfo.c getnameinfo.c saslauthd_DEPENDENCIES = saslauthd-main.o $(LTLIBOBJS_FULL) saslauthd_LDADD = @SASL_KRB_LIB@ \ @@ -40,3 +40,6 @@ saslauthd.8: saslauthd.mdoc install-data-local: saslauthd.8 $(mkinstalldirs) $(DESTDIR)$(mandir)/man8 $(INSTALL_DATA) $(srcdir)/saslauthd.8 $(DESTDIR)$(mandir)/man8/saslauthd.8 + +uninstall-local: + -rm -rf $(DESTDIR)$(mandir)/man8/saslauthd.8 From 4322481be6622904e4e51b08b80bd99655229eab Mon Sep 17 00:00:00 2001 From: Ignacio Casal Quinteiro Date: Thu, 23 Jun 2016 11:43:11 +0200 Subject: [PATCH 250/796] Revert "Remove LIBSASL_API to sasldb" This reverts commit 1518b84c1a1adb1fce4c28da7bfce6bf69064016. The patch broke the msvc builds using nmake --- sasldb/sasldb.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sasldb/sasldb.h b/sasldb/sasldb.h index 06183ebd..0cef3b44 100644 --- a/sasldb/sasldb.h +++ b/sasldb/sasldb.h @@ -73,7 +73,7 @@ int _sasldb_putdata(const sasl_utils_t *utils, const char *data, size_t data_len); /* Should be run before any db access is attempted */ -int _sasl_check_db(const sasl_utils_t *utils, +LIBSASL_API int _sasl_check_db(const sasl_utils_t *utils, sasl_conn_t *conn); /* These allow iterating through the keys of the database */ @@ -84,15 +84,15 @@ typedef int (* sasldb_list_callback_t) (const char *authid, const char *property, void *rock); -sasldb_handle _sasldb_getkeyhandle(const sasl_utils_t *utils, +LIBSASL_API sasldb_handle _sasldb_getkeyhandle(const sasl_utils_t *utils, sasl_conn_t *conn); -int _sasldb_getnextkey(const sasl_utils_t *utils, +LIBSASL_API int _sasldb_getnextkey(const sasl_utils_t *utils, sasldb_handle handle, char *out, const size_t max_out, size_t *out_len); -int _sasldb_releasekeyhandle(const sasl_utils_t *utils, +LIBSASL_API int _sasldb_releasekeyhandle(const sasl_utils_t *utils, sasldb_handle handle); -int _sasldb_listusers(const sasl_utils_t *utils, +LIBSASL_API int _sasldb_listusers(const sasl_utils_t *utils, sasl_conn_t *context, sasldb_list_callback_t callback, void *callback_rock); From 474ab6233fad1f96166121a6332b5a3956f44a2c Mon Sep 17 00:00:00 2001 From: OBATA Akio Date: Thu, 25 Aug 2016 16:53:31 +0900 Subject: [PATCH 251/796] db_ndbm.c: Set "NOUSER" error message same as other db backend This change prevent logging "no user in db" error messages but set detailed error message for the case using ndbm as a sasldb backend. --- sasldb/db_ndbm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sasldb/db_ndbm.c b/sasldb/db_ndbm.c index 035ea1e0..d1496790 100644 --- a/sasldb/db_ndbm.c +++ b/sasldb/db_ndbm.c @@ -109,7 +109,9 @@ int _sasldb_getdata(const sasl_utils_t *utils, dkey.dsize = key_len; dvalue = dbm_fetch(db, dkey); if (! dvalue.dptr) { - utils->seterror(cntxt, 0, "no user in db"); + utils->seterror(cntxt, SASL_NOLOG, + "user: %s@%s property: %s not found in sasldb", + authid, realm, propName); result = SASL_NOUSER; goto cleanup; } From 06e8667fe3b3fe7a123643d40a809b49e81bc26b Mon Sep 17 00:00:00 2001 From: OBATA Akio Date: Thu, 25 Aug 2016 17:04:07 +0900 Subject: [PATCH 252/796] db_ndbm.c: Make sure to rise FAIL with db open error --- sasldb/db_ndbm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sasldb/db_ndbm.c b/sasldb/db_ndbm.c index d1496790..5d8f76cd 100644 --- a/sasldb/db_ndbm.c +++ b/sasldb/db_ndbm.c @@ -188,6 +188,7 @@ int _sasldb_putdata(const sasl_utils_t *utils, "SASL error opening password file. " "Do you have write permissions?\n"); utils->seterror(conn, 0, "Could not open db for write"); + result = SASL_FAIL; goto cleanup; } dkey.dptr = key; From db6706049985226e5a0ee4d7ed9a99b3db4ef01e Mon Sep 17 00:00:00 2001 From: OBATA Akio Date: Thu, 25 Aug 2016 17:06:07 +0900 Subject: [PATCH 253/796] db_ndbm.c: Fix warnings about incompatible callback types --- sasldb/db_ndbm.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sasldb/db_ndbm.c b/sasldb/db_ndbm.c index 5d8f76cd..a4d92ad8 100644 --- a/sasldb/db_ndbm.c +++ b/sasldb/db_ndbm.c @@ -92,7 +92,7 @@ int _sasldb_getdata(const sasl_utils_t *utils, } if (utils->getcallback(conn, SASL_CB_GETOPT, - &getopt, &cntxt) == SASL_OK) { + (sasl_callback_ft *)&getopt, &cntxt) == SASL_OK) { const char *p; if (getopt(cntxt, NULL, "sasldb_path", &p, NULL) == SASL_OK && p != NULL && *p != 0) { @@ -172,7 +172,7 @@ int _sasldb_putdata(const sasl_utils_t *utils, } if (utils->getcallback(conn, SASL_CB_GETOPT, - &getopt, &cntxt) == SASL_OK) { + (sasl_callback_ft *)&getopt, &cntxt) == SASL_OK) { const char *p; if (getopt(cntxt, NULL, "sasldb_path", &p, NULL) == SASL_OK && p != NULL && *p != 0) { @@ -237,7 +237,7 @@ int _sasl_check_db(const sasl_utils_t *utils, if(!utils) return SASL_BADPARAM; if (utils->getcallback(conn, SASL_CB_GETOPT, - &getopt, &cntxt) == SASL_OK) { + (sasl_callback_ft *)&getopt, &cntxt) == SASL_OK) { const char *p; if (getopt(cntxt, NULL, "sasldb_path", &p, NULL) == SASL_OK && p != NULL && *p != 0) { @@ -252,7 +252,7 @@ int _sasl_check_db(const sasl_utils_t *utils, } ret = utils->getcallback(NULL, SASL_CB_VERIFYFILE, - &vf, &cntxt); + (sasl_callback_ft *)&vf, &cntxt); if(ret != SASL_OK) { utils->seterror(conn, 0, "No verifyfile callback"); @@ -314,7 +314,7 @@ sasldb_handle _sasldb_getkeyhandle(const sasl_utils_t *utils, } if (utils->getcallback(conn, SASL_CB_GETOPT, - &getopt, &cntxt) == SASL_OK) { + (sasl_callback_ft *)&getopt, &cntxt) == SASL_OK) { const char *p; if (getopt(cntxt, NULL, "sasldb_path", &p, NULL) == SASL_OK && p != NULL && *p != 0) { From 737cd61c93e82562d1c299a00e5de738c8edb7db Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Mon, 7 Nov 2016 14:06:29 +0100 Subject: [PATCH 254/796] saslauthd: Fix indentation to silent GCC6 warnings [-Wmisleading-indentation] --- saslauthd/lak.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/saslauthd/lak.c b/saslauthd/lak.c index 17f58baf..d752f7b7 100644 --- a/saslauthd/lak.c +++ b/saslauthd/lak.c @@ -1378,8 +1378,8 @@ static int lak_group_member( } done:; - if (res) - ldap_msgfree(res); + if (res) + ldap_msgfree(res); if (group_dn) free(group_dn); if (group_filter) @@ -1391,7 +1391,7 @@ done:; if (dn_bv) ber_bvfree(dn_bv); - return rc; + return rc; } static int lak_auth_custom( From d74369f88988f5273a4f28d5fda9653c8067f1c0 Mon Sep 17 00:00:00 2001 From: Ken Murchison Date: Mon, 7 Nov 2016 11:05:02 -0500 Subject: [PATCH 255/796] index.html: update RFCs and I-Ds --- doc/index.html | 93 ++++++++++++++++++++++---------------------------- 1 file changed, 41 insertions(+), 52 deletions(-) diff --git a/doc/index.html b/doc/index.html index b09a8823..36824b61 100644 --- a/doc/index.html +++ b/doc/index.html @@ -47,58 +47,47 @@

    Documentation

    RFCs and drafts Other Documentation & Resources From a098dc7dfd762e1209d77f64a45909b79f0fe402 Mon Sep 17 00:00:00 2001 From: Ken Murchison Date: Mon, 7 Nov 2016 11:09:37 -0500 Subject: [PATCH 256/796] Remove all RFCs and I-Ds: simply link to IETF respository --- doc/draft-burdis-cat-srp-sasl-xx.txt | 2858 ------------------------- doc/draft-ietf-sasl-anon-xx.txt | 507 ----- doc/draft-ietf-sasl-crammd5-xx.txt | 434 ---- doc/draft-ietf-sasl-gssapi-xx.txt | 841 -------- doc/draft-ietf-sasl-plain-xx.txt | 507 ----- doc/draft-ietf-sasl-rfc2222bis-xx.txt | 1320 ------------ doc/draft-ietf-sasl-rfc2831bis-xx.txt | 2340 -------------------- doc/draft-ietf-sasl-saslprep-xx.txt | 339 --- doc/draft-murchison-sasl-login-xx.txt | 396 ---- doc/draft-newman-sasl-c-api-xx.txt | 1681 --------------- doc/draft-newman-sasl-passdss-xx.txt | 1122 ---------- doc/rfc1321.txt | 1179 ---------- doc/rfc1939.txt | 1291 ----------- doc/rfc2104.txt | 619 ------ doc/rfc2195.txt | 283 --- doc/rfc2222.txt | 899 -------- doc/rfc2243.txt | 563 ----- doc/rfc2245.txt | 283 --- doc/rfc2289.txt | 1403 ------------ doc/rfc2444.txt | 395 ---- doc/rfc2595.txt | 843 -------- doc/rfc2831.txt | 1515 ------------- doc/rfc2945.txt | 451 ---- doc/rfc3174.txt | 1235 ----------- 24 files changed, 23304 deletions(-) delete mode 100644 doc/draft-burdis-cat-srp-sasl-xx.txt delete mode 100644 doc/draft-ietf-sasl-anon-xx.txt delete mode 100644 doc/draft-ietf-sasl-crammd5-xx.txt delete mode 100644 doc/draft-ietf-sasl-gssapi-xx.txt delete mode 100644 doc/draft-ietf-sasl-plain-xx.txt delete mode 100644 doc/draft-ietf-sasl-rfc2222bis-xx.txt delete mode 100644 doc/draft-ietf-sasl-rfc2831bis-xx.txt delete mode 100644 doc/draft-ietf-sasl-saslprep-xx.txt delete mode 100644 doc/draft-murchison-sasl-login-xx.txt delete mode 100644 doc/draft-newman-sasl-c-api-xx.txt delete mode 100644 doc/draft-newman-sasl-passdss-xx.txt delete mode 100644 doc/rfc1321.txt delete mode 100644 doc/rfc1939.txt delete mode 100644 doc/rfc2104.txt delete mode 100644 doc/rfc2195.txt delete mode 100644 doc/rfc2222.txt delete mode 100644 doc/rfc2243.txt delete mode 100644 doc/rfc2245.txt delete mode 100644 doc/rfc2289.txt delete mode 100644 doc/rfc2444.txt delete mode 100644 doc/rfc2595.txt delete mode 100644 doc/rfc2831.txt delete mode 100644 doc/rfc2945.txt delete mode 100644 doc/rfc3174.txt diff --git a/doc/draft-burdis-cat-srp-sasl-xx.txt b/doc/draft-burdis-cat-srp-sasl-xx.txt deleted file mode 100644 index d784f823..00000000 --- a/doc/draft-burdis-cat-srp-sasl-xx.txt +++ /dev/null @@ -1,2858 +0,0 @@ - - - -Network K. Burdis -Internet-Draft Rhodes University -Expires: November 28, 2003 R. Naffah - Forge Research - May 30, 2003 - - - Secure Remote Password Authentication Mechanism - draft-burdis-cat-srp-sasl-08 - -Status of this Memo - - This document is an Internet-Draft and is in full conformance with - all provisions of Section 10 of RFC2026. - - Internet-Drafts are working documents of the Internet Engineering - Task Force (IETF), its areas, and its working groups. Note that other - groups may also distribute working documents as Internet-Drafts. - - Internet-Drafts are draft documents valid for a maximum of six months - and may be updated, replaced, or obsoleted by other documents at any - time. It is inappropriate to use Internet-Drafts as reference - material or to cite them other than as "work in progress." - - The list of current Internet-Drafts can be accessed at http:// - www.ietf.org/ietf/1id-abstracts.txt. - - The list of Internet-Draft Shadow Directories can be accessed at - http://www.ietf.org/shadow.html. - - This Internet-Draft will expire on November 28, 2003. - -Copyright Notice - - Copyright (C) The Internet Society (2003). All Rights Reserved. - -Abstract - - This document describes an authentication mechanism based on the - Secure Remote Password protocol (SRP-6) and how to use it with the - authentication frameworks Secure Authentication and Security Layer - (SASL), Generic Security Services Application Programming Interface - (GSS-API) and Extensible Authentication Protocol (EAP). This - mechanism performs mutual authentication and can provide a security - layer with replay detection, integrity protection and/or - confidentiality protection. - - - - - - -Burdis & Naffah Expires November 28, 2003 [Page 1] - -Internet-Draft SRP Authentication Mechanism May 2003 - - -Table of Contents - - 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 4 - 2. Conventions Used in this Document . . . . . . . . . . . . . 5 - 3. Data Element Formats . . . . . . . . . . . . . . . . . . . . 6 - 3.1 Scalar Numbers . . . . . . . . . . . . . . . . . . . . . . . 6 - 3.2 Multi-Precision Integers . . . . . . . . . . . . . . . . . . 6 - 3.3 Octet Sequences . . . . . . . . . . . . . . . . . . . . . . 7 - 3.4 Extended Octet Sequences . . . . . . . . . . . . . . . . . . 7 - 3.5 Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 - 3.6 Buffers . . . . . . . . . . . . . . . . . . . . . . . . . . 8 - 3.7 Data Element Size Limits . . . . . . . . . . . . . . . . . . 8 - 3.8 Unsigned Integers . . . . . . . . . . . . . . . . . . . . . 8 - 4. Protocol Description . . . . . . . . . . . . . . . . . . . . 9 - 4.1 Client Sends its Identity . . . . . . . . . . . . . . . . . 11 - 4.2 Server Agrees to Re-use Parameters of a Previous Session . . 11 - 4.3 Server Sends Protocol Elements . . . . . . . . . . . . . . . 12 - 4.4 Client Sends its Ephemeral Public Key and Evidence . . . . . 15 - 4.5 Server Verifies Client's Evidence and Sends its Evidence . . 17 - 5. Security Layer . . . . . . . . . . . . . . . . . . . . . . . 19 - 5.1 Cryptographic Primitives . . . . . . . . . . . . . . . . . . 20 - 5.1.1 Pseudo Random Number Generator . . . . . . . . . . . . . . . 20 - 5.1.2 Key Derivation Function . . . . . . . . . . . . . . . . . . 22 - 5.2 Confidentiality Protection . . . . . . . . . . . . . . . . . 23 - 5.3 Replay Detection . . . . . . . . . . . . . . . . . . . . . . 24 - 5.4 Integrity Protection . . . . . . . . . . . . . . . . . . . . 25 - 5.5 Summary of Security Layer Output . . . . . . . . . . . . . . 25 - 6. Discussion . . . . . . . . . . . . . . . . . . . . . . . . . 27 - 6.1 Mandatory Algorithms . . . . . . . . . . . . . . . . . . . . 27 - 6.2 Modulus and Generator Values . . . . . . . . . . . . . . . . 27 - 6.3 Replay Detection Sequence Number Counters . . . . . . . . . 27 - 6.4 Re-using the Parameters of a Previous Session . . . . . . . 28 - 7. SASL . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 - 7.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . 30 - 7.2 Mechanism Name . . . . . . . . . . . . . . . . . . . . . . . 30 - 7.3 Security Layer . . . . . . . . . . . . . . . . . . . . . . . 30 - 7.4 Profile Considerations . . . . . . . . . . . . . . . . . . . 30 - 7.5 Example . . . . . . . . . . . . . . . . . . . . . . . . . . 31 - 8. GSS-API . . . . . . . . . . . . . . . . . . . . . . . . . . 34 - 8.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . 34 - 8.2 Terminology . . . . . . . . . . . . . . . . . . . . . . . . 34 - 8.3 Initial Token . . . . . . . . . . . . . . . . . . . . . . . 34 - 8.4 Security Layer . . . . . . . . . . . . . . . . . . . . . . . 35 - 9. EAP . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 - 9.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . 36 - 9.2 Terminology . . . . . . . . . . . . . . . . . . . . . . . . 36 - 9.3 Method Details . . . . . . . . . . . . . . . . . . . . . . . 36 - 9.4 Security Claims . . . . . . . . . . . . . . . . . . . . . . 37 - - - -Burdis & Naffah Expires November 28, 2003 [Page 2] - -Internet-Draft SRP Authentication Mechanism May 2003 - - - 10. Security Considerations . . . . . . . . . . . . . . . . . . 40 - 11. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . 41 - Normative References . . . . . . . . . . . . . . . . . . . . 42 - Informative References . . . . . . . . . . . . . . . . . . . 44 - Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 46 - A. Modulus and Generator Values . . . . . . . . . . . . . . . . 47 - B. Changes since the previous draft . . . . . . . . . . . . . . 49 - Intellectual Property and Copyright Statements . . . . . . . 50 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Burdis & Naffah Expires November 28, 2003 [Page 3] - -Internet-Draft SRP Authentication Mechanism May 2003 - - -1. Introduction - - The Secure Remote Password (SRP) is a password-based, zero-knowledge, - authentication and key-exchange protocol developed by Thomas Wu. It - has good performance, is not plaintext-equivalent and maintains - perfect forward secrecy. It provides authentication (optionally - mutual authentication) and the negotiation of a shared context key - [SRP]. - - The mechanism described herein is based on the SRP-6 protocol, - described in [SRP-6] and [SRP-6i]. SRP-6 is an improved version of - the original SRP protocol (also called SRP-3) described in - [RFC-2945]. Due to the design of the mechanism, mutual - authentication is MANDATORY. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Burdis & Naffah Expires November 28, 2003 [Page 4] - -Internet-Draft SRP Authentication Mechanism May 2003 - - -2. Conventions Used in this Document - - o A hex digit is an element of the set: - - {0, 1, 2, 3, 4, 5, 6, 7, 8 , 9, A, B, C, D, E, F} - - A hex digit is the representation of a 4-bit string. Examples: - - 7 = 0111 - - A = 1010 - - o An octet is an 8-bit string. In this document an octet may be - written as a pair of hex digits. Examples: - - 7A = 01111010 - - 02 = 00000010 - - o All data is encoded and sent in network byte order (big-endian). - - o The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL - NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" - in this document are to be interpreted as described in [RFC-2119]. - - - - - - - - - - - - - - - - - - - - - - - - - - - -Burdis & Naffah Expires November 28, 2003 [Page 5] - -Internet-Draft SRP Authentication Mechanism May 2003 - - -3. Data Element Formats - - This section describes the encoding of the data elements used by the - mechanism described in this document. - -3.1 Scalar Numbers - - Scalar numbers are unsigned quantities. Using b[k] to refer to the - k-th octet being processed, the value of a two-octet scalar is: - - ((b[0] << 8) + b[1]), - - where << is the bit left-shift operator. The value of a four-octet - scalar is: - - ((b[0] << 24) + (b[1] << 16) + (b[2] << 8) + b[3]). - - -3.2 Multi-Precision Integers - - Multi-Precision Integers, or MPIs, are positive integers used to hold - large integers used in cryptographic computations. - - MPIs are encoded using a scheme inspired by that used by OpenPGP - - [RFC-2440] (section 3.2) - for encoding such entities: - - The encoded form of an MPI SHALL consist of two pieces: a - two-octet scalar that represents the length of the entity, in - octets, followed by a sequence of octets that contain the actual - integer. - - These octets form a big-endian number; A big-endian number can be - encoded by prefixing it with the appropriate length. - - Examples: (all numbers are in hexadecimal) - - The sequence of octets [00 01 01] encodes an MPI with the value - 1, while the sequence [00 02 01 FF] encodes an MPI with the - value of 511. - - Additional rule: - - * The length field of an encoded MPI describes the octet count - starting from the MPI's first non-zero octet, containing the - most significant non-zero bit. Thus, the encoding [00 02 01] - is not formed correctly; It should be [00 01 01]. - - We shall use the syntax mpi(A) to denote the encoded form of the - - - -Burdis & Naffah Expires November 28, 2003 [Page 6] - -Internet-Draft SRP Authentication Mechanism May 2003 - - - multi-precision integer A. Furthermore, we shall use the syntax - bytes(A) to denote the big-endian sequence of octets forming the - multi-precision integer with the most significant octet being the - first non-zero octet containing the most significant bit of A. - -3.3 Octet Sequences - - This mechanism generates, uses and exchanges sequences of octets; - e.g. output values of message digest algorithm functions. When such - entities travel on the wire, they shall be preceded by a one-octet - scalar quantity representing the count of following octets. - - Note that a zero-length octet sequence is encoded as a single 00 - octet. - - We shall use the syntax os(s) to denote the encoded form of the octet - sequence. Furthermore, we shall use the syntax bytes(s) to denote - the sequence of octets s, in big-endian order. - -3.4 Extended Octet Sequences - - Extended sequences of octets are exchanged when using the security - layer. When these sequences travel on the wire, they shall be - preceded by a four-octet scalar quantity representing the count of - following octets. - - We shall use the syntax eos(s) to denote the encoded form of the - extended octet sequence. Furthermore, we shall use the syntax - bytes(s) to denote the sequence of octets s, in big-endian order. - -3.5 Text - - The only character set for text is the UTF-8 encoding [RFC-2279] of - Unicode characters [ISO-10646]. All text MUST be in Unicode - Normalization Form KC [UNICODE-KC] without NUL characters. - - In addition, to avoid non-interoperability due to incompatible - normalisation techniques, the client MUST prepare strings using the - [SASLprep] profile of [RFC-3454] - - We shall use the syntax utf8(L) to denote the string L in UTF-8 - encoding, preceded by a two-octet scalar quantity representing the - count of following octets. Furthermore, we shall use the syntax - bytes(L) to denote the sequence of octets representing the UTF-8 - encoding of L, in big-endian order. - - Not that the empty string is encoded as the two octet sequence 00 00. - - - - -Burdis & Naffah Expires November 28, 2003 [Page 7] - -Internet-Draft SRP Authentication Mechanism May 2003 - - -3.6 Buffers - - In this mechanism data is exchanged between the client and server - using buffers. A buffer acts as an envelope for the sequence of data - elements sent by one end-point of the exchange, and expected by the - other. - - A buffer MAY NOT contain other buffers. It may only contain zero, - one or more data elements. - - A buffer shall be encoded as two fields: a four-octet scalar quantity - representing the count of following octets, and the concatenation of - the octets of the data element(s) contained in the buffer. - - We shall use the syntax {A|B|C} to denote a buffer containing A, B - and C in that order. For example: - - { mpi(N) | mpi(g) | utf8(L) } - - is a buffer containing, in the designated order, the encoded forms of - an MPI N, an MPI g and a Text L. - -3.7 Data Element Size Limits - - The following table details the size limit, in number of octets, for - each of the data element encodings described earlier. - - Data element type Header Size limit in octets - (octets) (excluding header) - ------------------------------------------------------------ - Octet Sequence 1 255 - MPI 2 65,535 - Text 2 65,535 - Extended Octet Sequence 4 2,147,483,383 - Buffer 4 2,147,483,643 - - An implementation MUST signal an exception if any size constraint is - violated. - -3.8 Unsigned Integers - - This mechanism uses unsigned integer values ranging from zero to - 4,294,967,296. - - When such entities travel on the wire, they shall be encoded as - 4-octet Scalar Numbers. We shall use the syntax uint(n) to denote - the encoding of an Unsigned Integer n. - - - - -Burdis & Naffah Expires November 28, 2003 [Page 8] - -Internet-Draft SRP Authentication Mechanism May 2003 - - -4. Protocol Description - - The following sections describe the sequence of data transmitted - between the client and server for SRP authentication, as well as the - extra control information exchanged to enable a client to request - whether or not replay detection, integrity protection and/or - confidentiality protection should be provided by a security layer. - There are two possible mechanism data exchanges during the - authentication phase: - - The following exchange occurs when a new session is negotiated - between the client and the server. It will also occur when the - client requests re-use of the parameters of a previous session and - either the server does not support such re-use or no longer considers - the previous session to be valid: - - Client Server - - --- { utf8(U) | utf8(I) | utf8(sid) | os(cn) } -------------> - - <------ { 00 | mpi(N) | mpi(g) | os(s) | mpi(B) | utf8(L) } --- - - --- { mpi(A) | os(M1) | utf8(o) | os(cIV) } ----------------> - - <------ { os(M2) | os(sIV) | utf8(sid) | uint(ttl) } --------- - - where: - - U is the authentication identity (username), - - I is the authorisation identity (userid), - - sid is the identifier of a previous session whose parameters the - client wishes to re-use, - - cn is the client's nonce used in deriving a new shared context - key from the shared context key of the previous session, - - 00 is an octet indicating that the previous session parameters - will NOT be re-used, - - N is the safe prime modulus, - - g is the generator, - - s is the user's password salt, - - B is the server's ephemeral public key, - - - -Burdis & Naffah Expires November 28, 2003 [Page 9] - -Internet-Draft SRP Authentication Mechanism May 2003 - - - L is the options list indicating available security services, - - A is the client's ephemeral public key, - - M1 is the client's evidence that the shared key K is known, - - o is the options list indicating chosen security services, - - cIV is the client's initial vector for the chosen encryption - algorithm, - - M2 is the server's evidence that the shared key K is known. - - sIV is the server's initial vector for the chosen encryption - algorithm, - - sid is the identifier the server gives to this session for - possible later re-use of the negotiated parameters, - - ttl is the time period for which this session's parameters may be - re-usable, - - The following exchange occurs when the client requests that the - parameters negotiated in a previous session be re-used in this - session, but with a newly derived shared context key, and the server - agrees: - - Client Server - - --- { utf8(U) | utf8(I) | utf8(sid) | os(cn) } --------------> - - <---------------------------------- { FF | os(sn) } ---------- - - where: - - U is the authentication identity (username), - - I is the authorisation identity (userid), - - sid is the identifier of a previous session whose parameters the - client wishes to re-use, - - cn is the client's nonce used in deriving a new shared context - key from the shared context key of the previous session, - - FF is an octet indicating that the previous session parameters - WILL be re-used, - - - - -Burdis & Naffah Expires November 28, 2003 [Page 10] - -Internet-Draft SRP Authentication Mechanism May 2003 - - - sn is the server's nonce used in deriving a new shared context - key from the shared context key of the previous session, - - -4.1 Client Sends its Identity - - The client determines its authentication identity U and authorisation - identity I, encodes them and sends them to the server. - - The semantics of both U and I are intended to be the same as - described in [SASL]. Specifically, the authentication identity U is - derived from the client's authentication credentials, and the - authorisation identity I is used by the server as the primary - identity for making access policy decisions. - - As a client might not have the same information as the server, - clients SHOULD NOT themselves try to derive authorisation identities - from authentication identities. When an authorisation identity is - not specified by the user the client SHOULD send an empty string - instead. - - If the client does not wish to re-use parameters negotiated in a - previous session then it sets sid to the empty string and cn to a - zero-length octet sequence. - - However, if the client does wish to attempt to re-use the parameters - negotiated in a previous session then it sets sid to the session - identifier for that session, and sets cn as follows: - - cn = prng() - - where: - - prng() is a random number generation function that outputs at - least 16 octets of data. - - See Section 6.4 for more information on re-using negotiated - parameters of a previous session. - - The client sends: - - { utf8(U) | utf8(I) | utf8(sid) | os(cn) } - - -4.2 Server Agrees to Re-use Parameters of a Previous Session - - If the server supports re-using the parameters negotiated in a - previous session and it considers the previous session, identified by - - - -Burdis & Naffah Expires November 28, 2003 [Page 11] - -Internet-Draft SRP Authentication Mechanism May 2003 - - - the session identifier (sid) received from the client, to be valid, - it responds as follows: - - The server sends the octet FF as the first element of the message to - indicate to the client that parameters of the previous session are - being re-used. It also generates a nonce (sn), which is later used - in deriving a new shared context key for this session: - - sn = prng() - - where: - - prng() is a random number generation function that outputs at - least 16 octets of data. - - Note that the server nonce (sn) MUST NOT be the same as the client - nonce (cn). - - The server sends: - - { FF | os(sn) } - - See Section 6.4 for more information on re-using negotiated - parameters of a previous session and deriving the new shared context - key. - -4.3 Server Sends Protocol Elements - - Otherwise, the server receives U and looks up the safe prime modulus - N, the generator g, the salt s, and the verifier v, to be used for - that identity. It uses the this information to generate its - ephemeral public key B as follows: - - b = prng(); - - B = ((3 * v) + (g ** b)) % N; - - where: - - prng() is a random number generation function, - - b is the MPI that will act as the server's private key, - - v is the stored password verifier value, - - g is the generator, - - N is the safe prime modulus, - - - -Burdis & Naffah Expires November 28, 2003 [Page 12] - -Internet-Draft SRP Authentication Mechanism May 2003 - - - * is the multiplication operator, - - + is the addition operator, - - ** is the exponentiation operator, - - % is the modulus operator, - - The server also creates an options list L, which consists of a - comma-separated list of option strings that specify the options the - server supports. This options list MUST NOT contain any whitespace - characters and all alphabetic characters MUST be in lowercase. When - used in digest calculations by the client the options list MUST be - used as received. - - The following option strings are defined: - - o "mda=" indicates that the server supports the designated - hash function as the underlying Message Digest Algorithm for the - designated user to be used for all SRP calculations - to compute - both client-side and server-side digests. The specified algorithm - MUST meet the requirements specified in section 3.2 of [RFC-2945]: - - "Any hash function used with SRP should produce an output of at - least 16 bytes and have the property that small changes in the - input cause significant nonlinear changes in the output." - - Note that in the interests of interoperability between client and - server implementations and with other SRP-based tools, both the - client and the server MUST support SHA-160 as an underlying - Message Digest Algorithm. While the server is not required to - list SHA-160 as an available underlying Message Digest Algorithm, - it must be able to do so. - - o "integrity=hmac-" indicates that the server supports - integrity protection using the HMAC algorithm [RFC-2104] with - as the underlying Message Digest Algorithm. Acceptable - MDA names are chosen from [SCAN] under the MessageDigest section. - A server SHOULD send such an option string for each HMAC algorithm - it supports. The server MUST advertise at least one integrity - protection algorithm and in the interest of interoperability the - server SHOULD advertise support for the HMAC-SHA-160 algorithm. - - o "replay_detection" indicates that the server supports replay - detection using sequence numbers. Replay detection SHALL NOT be - activated without also activating integrity protection. If the - replay detection option is offered (by the server) and/or chosen - (by the client) without explicitly specifying an integrity - - - -Burdis & Naffah Expires November 28, 2003 [Page 13] - -Internet-Draft SRP Authentication Mechanism May 2003 - - - protection option, then the default integrity protection option - "integrity=hmac-sha-160" is implied and SHALL be activated. - - o "confidentiality=" indicates that the server supports - confidentiality protection using the symmetric key block cipher - algorithm . The server SHOULD send such an option - string for each confidentiality protection algorithm it supports. - Note that in the interest of interoperability, if the server - offers confidentiality protection, it MUST send the option string - "confidentiality=aes" since it is then MANDATORY for it to provide - support for the [AES] algorithm. - - o "mandatory=[integrity|replay_detection|confidentiality]" is an - option only available to the server that indicates that the - specified security layer option is MANDATORY and MUST be chosen by - the client for use in the resulting security layer. If a server - specifies an option as mandatory in this way, it MUST abort the - connection if the specified option is not chosen by the client. - It doesn't make sense for the client to send this option since it - is only able to choose options that the server advertises. The - client SHOULD abort the connection if the server does not offer an - option that it requires. If this option is not specified then - this implies that no options are mandatory. The server SHOULD - always send the "mandatory=integrity" option indicating that - integrity protection is required. - - o "maxbuffersize=" indicates to the peer the - maximum number of raw bytes (excluding the buffer header) to be - processed by the security layer at a time, if one is negotiated. - The value of MUST NOT exceed the Buffer size - limit defined in section 3.7. If this option is not detected by a - client or server mechanism, then it shall operate its security - layer on the assumption that the maximum number of bytes that may - be sent, to the peer server or client mechanism respectively, is - the Buffer data size limit indicated in section 3.7. On the other - hand, if a recipient detects this option, it shall break any - octet-sequence longer than the designated limit into two or more - fragments, before sending them separately, in sequence, to the - peer. - - For example, if the server supports integrity protection using the - HMAC-SHA-160 and HMAC-MD5 algorithms, replay detection and no - confidentiality protection, the options list would be: - - mda=sha-1,integrity=hmac-sha-160,integrity=hmac-md5,replay_detection - - The server sends the octet 00 as the first element of the message to - indicate to the client that parameters from a previous session are - - - -Burdis & Naffah Expires November 28, 2003 [Page 14] - -Internet-Draft SRP Authentication Mechanism May 2003 - - - NOT being used. - - The server sends: - - { 00 | mpi(N) | mpi(g) | os(s) | mpi(B) | utf8(L) } - - -4.4 Client Sends its Ephemeral Public Key and Evidence - - The client receives the options list L from the server that specifies - the Message Digest Algorithm(s) available to be used for all SRP - calculations, the security service options the server supports, - including the maximum buffer size the server can handle, and the - server's ephemeral public key B. The client selects options from - this list and creates a new options list o that specifies the - selected Message Digest Algorithm to be used for SRP calculations and - the security services that will be used in the security layer. At - most one available Message Digest Algorithm name, one available - integrity protection algorithm and one available confidentiality - protection algorithm may be selected. In addition the client may - specify the maximum buffer size it can handle. The client MUST - include any option specified by the mandatory option. - - The client SHOULD always select an integrity protection algorithm - even if the server does not make it mandatory to do so. If the - client selects a confidentiality protection algorithm it SHOULD then - also select an integrity protection algorithm. - - The options list o MUST NOT contain any whitespace characters and all - alphabetic characters MUST be in lowercase. When used in digest - calculations by the server the options list MUST be used as received. - - The client generates its ephemeral public key A as follows: - - a = prng(); - - A = (g ** a) % N; - - where: - - a is the MPI that will act as the client's private key, - - The client also calculates the shared context key K, and calculates - the evidence M1 that proves to the server that it knows the shared - context key K, as well as the server's ephemeral public key B, the - user's authorisation identity I and the server's options list L. - - K, on the client's side is computed as follows: - - - -Burdis & Naffah Expires November 28, 2003 [Page 15] - -Internet-Draft SRP Authentication Mechanism May 2003 - - - x = H(s | H(U | ":" | p)); - - u = H(A | B); - - S = ((B - (3 * (g ** x))) ** (a + (u * x))) % N; - - K = H(S); - - where: - - s is the user's password salt, - - U is the authentication identity (username), - - p is the password value. - - A is the client's ephemeral public key, - - B is the server's ephemeral public key, - - g is the generator, - - N is the safe prime modulus, - - H() is the result of digesting the designated input/data with the - chosen underlying Message Digest Algorithm function. - - - is the subtraction operator, - - * is the multiplication operator, - - + is the addition operator, - - ** is the exponentiation operator, - - % is the modulus operator, - - M1 is computed as: - - H( bytes(H( bytes(N) )) ^ bytes( H( bytes(g) )) - | bytes(H( bytes(U) )) - | bytes(s) - | bytes(A) - | bytes(B) - | bytes(K) - | bytes(H( bytes(I) )) - | bytes(H( bytes(L) )) - ) - - - -Burdis & Naffah Expires November 28, 2003 [Page 16] - -Internet-Draft SRP Authentication Mechanism May 2003 - - - where: - - ^ is the bitwise XOR operator. - - All parameters received from the server that are used as input to a - digest operation MUST be used as received. - - If the client chooses to activate the Confidentiality Protection - service in the Security Layer, it MUST send the Initial Vector cIV - that the server will use to set up its encryption context. (See - Section 5.2 for details on the Confidentiality Protection service and - how cIV is generated.) However, this element MAY be a zero-length - octet stream if the server does not advertise the Confidentiality - Protection service or the client decides not to activate it. - - The client sends: - - { mpi(A) | os(M1) | utf8(o) | os(cIV) } - - -4.5 Server Verifies Client's Evidence and Sends its Evidence - - The server calculates the shared context key K, and verifies the - client's evidence M1. - - K, on the server's side is computed as follows: - - u = H(A | B); - - S = ((A * (v ** u)) ** b) % N; - - K = H(S); - - where: - - A is the client's ephemeral public key, - - B is the server's ephemeral public key, - - v is the stored password verifier value, - - b is the server's ephemeral private key, - - N is the safe prime modulus, - - H() is the result of digesting the designated input/data with the - chosen underlying Message Digest Algorithm function. - - - - -Burdis & Naffah Expires November 28, 2003 [Page 17] - -Internet-Draft SRP Authentication Mechanism May 2003 - - - * is the multiplication operator, - - ** is the exponentiation operator, - - % is the modulus operator, - - If the client chose to activate the Confidentiality Protection - service in the Security Layer then the server MUST send the Initial - Vector sIV that the client will use to set up its encryption context. - (See Section 5.2 for details on the Confidentiality Protection - service and how sIV is generated.) However, this element MAY be a - zero-length octet sequence if the client did not choose to activate - the Confidentiality Protection service. - - If the server's policy allows re-using the parameters of this session - then it sets sid to a unique identifier for this session and sets ttl - to the number of seconds for which the session MAY be valid. If the - server does not support re-using the parameters of this session then - it sets sid to the empty string and ttl to any value. See Section - 6.4 for more information on re-using negotiated parameters of a - previous session. - - The server computes its evidence M2, which proves to the client that - it knows the shared context key K, as well as U, I and o, as follows: - - H( bytes(A) - | bytes(M1) - | bytes(K) - | bytes(H( bytes(I) )) - | bytes(H( bytes(o) )) - | bytes(sid) - | ttl - ) - - All parameters received from the client that are used as input to a - digest operation MUST be used as received. - - The server sends: - - { os(M2) | os(sIV) | sid | ttl } - - - - - - - - - - - -Burdis & Naffah Expires November 28, 2003 [Page 18] - -Internet-Draft SRP Authentication Mechanism May 2003 - - -5. Security Layer - - Depending on the options offered by the server and chosen by the - client, the security layer may provide integrity protection, replay - detection, and/or confidentiality protection. - - The security layer can be thought of as a three-stage filter through - which the data flows from the output of one stage to the input of the - following one. The first input is the original data, while the last - output is the data after being subject to the transformations of this - filter. - - The data always passes through this three-stage filter, though any of - the stages may be inactive. Only when a stage is active would the - output be different from the input. In other words, if a stage is - inactive, the octet sequence at the output side is an exact duplicate - of the same sequence at the input side. - - Schematically, the three-stage filter security layer appears as - follows: - - +----------------------------+ - | | I/ p1 - p1 --->| Confidentiality protection |---+ - | | | A/ c - +----------------------------+ | - | - +------------------------------------+ - | - | +----------------------------+ - | | | I/ p2 - p2 +-->| Replay detection |---+ - | | | A/ p2 | q - +----------------------------+ | - | - +------------------------------------+ - | - | +----------------------------+ - | | | I/ p3 - p3 +-->| Integrity protection |---> - | | A/ p3 | C - +----------------------------+ - - where: - - p1, p2 and p3 are the input octet sequences at each stage, - - I/ denotes the output at the end of one stage if/when the stage is - - - -Burdis & Naffah Expires November 28, 2003 [Page 19] - -Internet-Draft SRP Authentication Mechanism May 2003 - - - inactive or disabled, - - A/ denotes the output at the end of one stage if/when the stage is - active or enabled, - - c is the encrypted (sender-side) or decrypted (receiver-side) - octet sequence. c1 shall denote the value computed by the sender, - while c2 shall denote the value computed by the receiver. - - q is a four-octet scalar quantity representing a sequence number, - - C is the Message Authentication Code. C1 shall denote the value - of the MAC as computed by the sender, while C2 shall denote the - value computed by the receiver. - - It is worth noting here that both client and server have their own - distinct security contexts, including distinct encryption and - decryption sub-contexts. In principal, nothing in this specification - should prevent an implementation from supporting asynchronous - connections. - -5.1 Cryptographic Primitives - -5.1.1 Pseudo Random Number Generator - - This mechanism requires random data to be generated for use in: - - 1. The CALG key material for both the client and server when the - Confidentiality Protection service is enabled. - - 2. The IALG key material for both the client and server when the - Integrity Protection service is enabled. - - The PRNG used in this specification is based on the pseudo-random - function described in section 5 of [UMAC]. It uses the [AES] - algorithm, in its 128-bit key size variant, as the underlying - symmetric key block cipher for its operations. - - A formal description of this PRNG follows: - - o Initialisation - - * SK: a 16-octet sequence (seeding key to AES) - - o Input - - * n: a positive integer - - - - -Burdis & Naffah Expires November 28, 2003 [Page 20] - -Internet-Draft SRP Authentication Mechanism May 2003 - - - o Output - - * Y: an n-octet sequence - - o Algorithm - - * (initialisation) - - 1. Initialise an AES instance for encryption with the first 16 - octets of SK as its user-supplied key material. Let "aes" - be that instance; i.e. aes = AES(SK, ENCRYPTION); - - 2. Initialise T to be an all-zero 16-octet long sequence; - - * (for every input) - - 1. Initialise "remaining" to n; - - 2. Initialise Y to be a 0-length octet sequence; - - 3. while (remaining > 0) do - - 1. T = aes(T); - - 2. Append m octets from T to Y, where m is the minimum of - 16 and remaining; - - 3. Subtract 16 from remaining; - - 4. return Y; - - In this document, "PRNG(key,n)" will refer to this algorithm, with - the initialisation parameter SK set to be the octets of the specified - key, returning n bits of pseudo-random data. For example, - "PRNG(K,n)" will refer to this algorithm, with the initialisation - parameters SK set to the shared context key K computed by the SRP - calculations (see Section 4.4 and Section 4.5), returning n bits of - pseudo-random data. - - This algorithm MAY also be used as part of the SRP calculations to - generate the required "a" and "b" parameters used in creating the - client and server ephemeral private keys ("A" and "B"), or to - generate the cn and sn parameters used in session re-use, or to - generate the initial vectors sIV and cIV used to set up the - encryption contexts. In this case the initialisation parameter SK can - be any 16-octet sequence (e.g. multiple representations of the - time-of-day). - - - - -Burdis & Naffah Expires November 28, 2003 [Page 21] - -Internet-Draft SRP Authentication Mechanism May 2003 - - - If the same PRNG instance is used for both these calculations and the - calculations in this specification, it MUST be re-initialised with - the shared context key K before any of the latter calculations are - performed. - -5.1.2 Key Derivation Function - - During the authentication phase, both parties compute the shared - context key K (see Section 4.4 for the client, and Section 4.5 for - the server sides respectively). The length of K is s bits, where "s" - is the output length of the chosen underlying Message Digest - Algorithm used in the SRP calculations (see "mda" option in Section - 4.3). - - When Confidentiality Protection is required, and the length of K is - not equal to the length of the user-supplied key material needed to - initialise the chosen Confidentiality Algorithm (CALG), the peers - MUST apply the Key Derivation Function (KDF) in order to obtain - enough data for this purpose. - - Similarly, when Integrity Protection is required, and the length of K - is not equal to the required length of the key material needed to - initialise the chosen Integrity Algorithm (IALG), the peers MUST - apply the Key Derivation Function (KDF) in order to obtain enough - data for this purpose too. - - If the KDF is required for both the key used with the CALG and the - key used with the IALG then it is first applied for the CALG key and - thereafter for the IALG key. - - We define this KDF as: - - Km = KDF(n) - - where: - - Km is the required key material, - - K is the shared context key, and - - n is the required length of Km. - - The following steps describe the KDF algorithm: - - If length of K is greater than or equal to n, then - - Let Km be the first n bytes of K; - - - - -Burdis & Naffah Expires November 28, 2003 [Page 22] - -Internet-Draft SRP Authentication Mechanism May 2003 - - - Else - - Let Km = PRNG(K, n); - - return Km - - -5.2 Confidentiality Protection - - The plaintext data octet sequence p1 is encrypted using the chosen - confidentiality algorithm (CALG) with key size m, initialised for - encryption with the key material Kc obtained as follows: - - Kc = KDF(m) - - c1 = CALG(Kc, ENCRYPTION)( bytes(p1) ) - - On the receiving side, the ciphertext data octet sequence p1 is - decrypted using the chosen confidentiality algorithm (CALG) - initialised for decryption, with the key Kc obtained by a similar - process: - - Kc = KDF(m) - - c2 = CALG(Kc, DECRYPTION)( bytes(p1) ) - - The designated CALG symmetric-key block cipher MUST be used in OFB - (Output Feedback Block) mode in the ISO variant, as described in - [HAC], algorithm 7.20. - - Let k be the block size of the chosen symmetric key block cipher - algorithm; e.g. for AES this is 128 bits or 16 octets. The OFB mode - used shall have a block size of k. - - It is recommended that block ciphers operating in OFB mode be used - with an Initial Vector (the mode's IV). In such a mode of operation - - OFB with key re-use - the IV need not be secret. For the mechanism - described in this document, the server MUST use cIV received from the - client as the Initial Vector when initialising its encryption - context, and the client MUST use sIV received from the server as the - Initial Vector when initialising its encryption context. These - Initial Vectors are generated as: - - cIV = prng(k); - - sIV = prng(k); - - where: - - - -Burdis & Naffah Expires November 28, 2003 [Page 23] - -Internet-Draft SRP Authentication Mechanism May 2003 - - - prng() is a random number generation function that outputs k - octets of data, - - k is the block size of the chosen symmetric key block cipher - algorithm - - The input data to the confidentiality protection algorithm shall be a - multiple of the symmetric key block cipher block size k. When the - input length is not a multiple of k octets, the data shall be padded - according to the following scheme (described in [PKCS7] which itself - is based on [RFC-1423]): - - Assuming the length of the input is l octets, (k - (l mod k)) - octets, all having the value (k - (l mod k)), shall be appended to - the original data. In other words, the input is padded at the - trailing end with one of the following sequences: - - - - 01 -- if l mod k = k-1 - 02 02 -- if l mod k = k-2 - ... - ... - ... - k k ... k k -- if l mod k = 0 - - The padding can be removed unambiguously since all input is padded - and no padding sequence is a suffix of another. This padding - method is well-defined if and only if k < 256 octets, which is the - case with symmetric block ciphers today, and in the forseeable - future. - - The output of this stage, when it is active, is: - - at the sending side: CALG(Kc, ENCRYPT)( bytes(p1) ) - - at the receiving side: CALG(Kc, DECRYPT)( bytes(p1) ) - - -5.3 Replay Detection - - A sequence number q is incremented every time a message is sent to - the peer. - - The output of this stage, when it is active, is: - - p2 | q - - - - -Burdis & Naffah Expires November 28, 2003 [Page 24] - -Internet-Draft SRP Authentication Mechanism May 2003 - - - At the other end, the receiver increments its instance of the - sequence number. This new value of the sequence number is then used - in the integrity protection transformation, which must also be active - as described in Section 4.3. See Section 6.3 for more details. - -5.4 Integrity Protection - - When the Integrity Protection stage is active, a message - authentication code C is computed using the chosen integrity - protection algorithm (IALG) as follows: - - o the IALG is initialised (once) with the key material Ki of size n - (the required key size of the chosen IALG); i.e. Ki = KDF(n), - - o the IALG is updated with every exchange of the sequence p3, - yielding the value C and a new IALG context for use in the - following exchange. - - At the other end, the receiver computes its version of C, using the - same transformation, and checks that its value is equal to that - received. If the two values do not agree, the receiver MUST signal an - exception and abort. - - The output of this stage, when it is active, is then: - - IALG(Ki)( bytes(p3) ) - - -5.5 Summary of Security Layer Output - - The following table shows the data exchanged by the security layer - peers, depending on the possible legal combinations of the three - security services in operation: - - CP IP RD Peer sends/receives - - I I I { eos(p) } - I A I { eos(p) | os( IALG(Ki)( bytes(p) ) ) } - I A A { eos(p) | os( IALG(Ki)( bytes(p) | bytes(q)) ) } - A I I { eos(c) } - A A I { eos(c) | os( IALG(Ki)( bytes(c) ) ) } - A A A { eos(c) | os( IALG(Ki)((bytes(c) | bytes(q)) )} - - where - - CP Confidentiality protection, - - IP Integrity protection, - - - -Burdis & Naffah Expires November 28, 2003 [Page 25] - -Internet-Draft SRP Authentication Mechanism May 2003 - - - RD Replay detection, - - I Security service is Inactive/disabled, - - A Security service is Active/enabled, - - p The original plaintext, - - q The sequence number. - - c The enciphered input obtained by either: - - CALG(Kc, ENCRYPT)( bytes(p) ) at the sender's side, or - - CALG(Kc, DECRYPT)( bytes(p) ) at the receiver's side - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Burdis & Naffah Expires November 28, 2003 [Page 26] - -Internet-Draft SRP Authentication Mechanism May 2003 - - -6. Discussion - -6.1 Mandatory Algorithms - - The algorithms specified as mandatory were chosen for utility and - availablity. We felt that a mandatory confidentiality and integrity - protection algorithm for the security layer and a mandatory Message - Digest Algorithm for SRP calculations should be specified to ensure - interoperability between implementations of this mechanism: - - o The SHA-160 Message Digest Algorithm was chosen as an underlying - algorithm for SRP calculations because this allows for easy - interoperability with other SRP-based tools that use the SRP-SHA1 - protocol described in section 3 of [RFC-2945] and create their - password files using this algorithm. - - o The HMAC algorithm was chosen as an integrity algorithm because it - is faster than MAC algorithms based on secret key encryption - algorithms [RFC-2847]. - - o AES was chosen as a symmetric-key block cipher because it has - undergone thorough scrutiny by the best cryptographers in the - world. - - Since confidentiality protection is optional, this mechanism should - be usable in countries that have strict controls on the use of - cryptography. - -6.2 Modulus and Generator Values - - It is RECOMMENDED that the server use values for the modulus N and - generator g chosen from those listed in Appendix A so that the client - can avoid expensive constraint checks, since these predefined values - already meet the constraints described in [RFC-2945]: - - "For maximum security, N should be a safe prime (i.e. a number of - the form N = 2q + 1, where q is also prime). Also, g should be a - generator modulo N (see [SRP] for details), which means that for - any X where 0 < X < N, there exists a value x for which g**x == X - (mod N). - - If other values are used for N and g then these values SHOULD undergo - the specified constraint checks. - -6.3 Replay Detection Sequence Number Counters - - The mechanism described in this document allows the use of a Replay - Detection security service that works by including sequence number - - - -Burdis & Naffah Expires November 28, 2003 [Page 27] - -Internet-Draft SRP Authentication Mechanism May 2003 - - - counters in the message authentication code (MAC) created by the - Integrity Protection service. As noted in Section 4.3 integrity - protection is always activated when the Replay Detection service is - activated. - - Both the client and the server keep two sequence number counters. - Each of these counters is a 32-bit unsigned integer initialised with - a Starting Value and incremented by an Increment Value with every - successful transmission of a data buffer through the security layer. - The Sent counter is incremented for each buffer sent through the - security layer. The Received counter is incremented for each buffer - received through the security layer. If the value of a sequence - number counter exceeds 2**32-1 it wraps around and starts from zero - again. - - When a sender sends a buffer it includes the value of its Sent - counter in the computation of the MAC accompanying each integrity - protected message. When a recipient receives a buffer it uses the - value of it's Received counter in its computation of the integrity - protection MAC for the received message. The recipient's Received - counter must be the same as the sender's Sent counter in order for - the received and computed MACs to match. - - This specification assumes that for each sequence number counter the - Starting Value is ZERO, and that the Increment Value is ONE. These - values do not affect the security or the intended objective of the - replay detection service, since they never travel on the wire. - -6.4 Re-using the Parameters of a Previous Session - - Re-using the parameters of a previous session enables the client and - server to avoid the overhead of the full authentication exchange - where the client and server communicate more than once during a - server-specified time period. - - Servers are not required to support re-using the parameters of the - current session in future sessions. If they do not wish to support - this then they send an empty string for the session identifier (sid). - However, if the server's policy allows for the parameters of the - current session to be re-used later, it generates a session - identifier (sid) that will uniquely identify the session within the - specified time period (ttl). The time period (ttl) is specified in - seconds and only gives an indication to the client how long the - session may be valid. The server is not required to ensure that the - session is valid for this time period. Note that a ttl of 0 indicates - an indeterminate time period. - - To avoid session hijacking, servers SHOULD NOT indicate that a - - - -Burdis & Naffah Expires November 28, 2003 [Page 28] - -Internet-Draft SRP Authentication Mechanism May 2003 - - - session may be re-used unless a security layer with integrity - protection and/or confidentiality protection has been negotiated. - - Clients are not required to support re-using the parameters of - previous sessions. If they do not wish to support it or they do not - wish to re-use the parameters of a previous session then they send - the empty string as the value for the session identifier (sid) and - send a zero-length octet sequence for the nonce (cn). If they do - support it and wish to use the parameters of a previous session then - they send the session identifier for this session that they - previously received from the server and calculate cn as described in - Section 4.1. - - If a client specifies a session id (sid) for a session that the - server still considers valid then the server sends the octet FF, to - indicate to the client that parameters of a previous session are - being re-used, and the nonce (sn) calculated as described in Section - 4.2. The client and server then calculate the new shared context key - Kn for this session as follows: - - Kn = H(K | cn | sn) - - where: - - K is the shared context key for the previous session identified - by sid. - - H() is the result of digesting the designated input/data with the - Message Digest Algorithm function negotiated in the previous - session identified by sid. - - Then, if the confidentiality and/or integrity protection services - were negotiated for the previous session, new keys for these services - are derived using the KDF for use in this session. (See Section - 5.1.2.) - - If the server does not support re-using parameters of previous - sessions or no longer considers the specified previous session to be - valid, it ignores the session id specified by the client and - continues the full authentication exchange. However, the first - element of the next buffer it sends is the octet 00, which indicates - to the client that no parameters of a previous session will be - re-used. - - - - - - - - -Burdis & Naffah Expires November 28, 2003 [Page 29] - -Internet-Draft SRP Authentication Mechanism May 2003 - - -7. SASL - -7.1 Overview - - SASL is described as follows [RFC-2222]: - - The Simple Authentication and Security Layer (SASL) is a method - for adding authentication support to connection-based protocols. - - This document describes a mechanism that can be used within the SASL - authentication framework. - -7.2 Mechanism Name - - The SASL mechanism name associated with this protocol is "SRP". - -7.3 Security Layer - - Section 3 of [RFC-2222] describes the operation of the security layer - as follows: - - "The security layer takes effect immediately following the last - response of the authentication exchange for data sent by the - client and the completion indication for data sent by the server. - Once the security layer is in effect, the protocol stream is - processed by the security layer into buffers of cipher-text. Each - buffer is transferred over the connection as a stream of octets - prepended with a four octet field in network byte order that - represents the length of the following buffer. The length of the - cipher-text buffer must be no larger than the maximum size that - was defined or negotiated by the other side." - - -7.4 Profile Considerations - - As mentioned briefly in [RFC-2222], and detailed in [SASL] a SASL - specification has three layers: (a) a protocol definition using SASL - known as the "Profile", (b) a SASL mechanism definition, and (c) the - SASL framework. - - Point (3) in section 5 of [SASL] ("Protocol profile requirements") - clearly states that it is the responsibility of the Profile to define - "...how the challenges and responses are encoded, how the server - indicates completion or failure of the exchange, how the client - aborts an exchange, and how the exchange method interacts with any - line length limits in the protocol." - - The username entity, referenced as U throughout this document, and - - - -Burdis & Naffah Expires November 28, 2003 [Page 30] - -Internet-Draft SRP Authentication Mechanism May 2003 - - - used by the server to locate the password data, is assumed to travel - "in the clear," meaning that no transformation is applied to its - contents. This assumption was made to allow the same SRP password - files to be used in this mechanism, as those used with other SRP - applications and tools. - - A Profile may decide, for privacy or other reason, to disallow such - information to travel in the clear, and instead use a hashed version - of U, or more generally a transformation function applied to U; i.e. - f(U). Such a Profile would require additional tools to add the - required entries to the SRP password files for the new value(s) of - f(U). It is worth noting too that if this is the case, and the same - user shall access the server through this mechanism as well as - through other SRP tools, then at least two entries, one with U and - the other with f(U) need to be present in the SRP password files if - those same files are to be used for both types of access. - -7.5 Example - - The example below uses SMTP authentication [RFC-2554]. The base64 - encoding of challenges and responses, as well as the reply codes - preceding the responses are part of the SMTP authentication - specification, not part of this SASL mechanism itself. - - "C:" and "S:" indicate lines sent by the client and server - respectively. - - S: 220 smtp.example.com ESMTP server ready - - C: EHLO zaau.example.com - - S: 250-smtp.example.com - S: 250 AUTH SRP CRAM-MD5 DIGEST-MD5 - - C: AUTH SRP AAAADAAEdGVzdAAEdGVzdA== - - with: - - U = "test" - - I = "test" - - S: 334 AAABygEArGvbQTJKmpvxZt5eE4lYL69ytmUZh+4H/DGSlD21YFCjcynLtKCZ - 7YGT4HV3Z6E91SMSq0sDMQ3Nf0ip2gT9UOgIOWntt2ewz2CVF5oWOrNmGgX71fqq6Ck - YqZYvC5O4Vfl5k+yXXuqoDXQK2/T/dHNZ0EHVwz6nHSgeRGsUdzvKl7Q6I/uAFna9IH - pDbGSB8dK5B4cXRhpbnTLmiPh3SFRFI7UksNV9Xqd6J3XS7PoDLPvb9S+zeGFgJ5AE5 - Xrmr4dOcwPOUymczAQce8MI2CpWmPOo0MOCca41+Onb+7aUtcgD2J965DXeI21SX1R1 - m2XjcvzWjvIPpxEfnkr/cwABAgqsi3AvmIqdEbREALhtZGE9U0hBLTEsbWFuZGF0b3J - - - -Burdis & Naffah Expires November 28, 2003 [Page 31] - -Internet-Draft SRP Authentication Mechanism May 2003 - - - 5PXJlcGxheSBkZXRlY3Rpb24scmVwbGF5IGRldGVjdGlvbixpbnRlZ3JpdHk9aG1hYy - 1zaGExLGludGVncml0eT1obWFjLW1kNSxjb25maWRlbnRpYWxpdHk9YWVzLGNvbmZpZ - GVudGlhbGl0eT1jYXN0NSxjb25maWRlbnRpYWxpdHk9Ymxvd2Zpc2gsbWF4YnVmZmVy - c2l6ZT0yMTQ3NDgzNjQz - - with: - - N = "21766174458617435773191008891802753781907668374255538511144 - 6432246898862353838409572109090130860564015713997172358072665816 - 4960647214841029141336415219736447718088739565548373811507267740 - 2235101762521901569820740293149529620419333266262073471054548368 - 7360395197024862265062488610602569718029849535611214426801576680 - 0076142998822245709041387397397017192709399211475176516806361476 - 1119615476233422096442783117971236371647333871414335895773474667 - 3089670508070055093204247996784170368679283167612722742303140675 - 4829113358247958306143957755934710196177140617368437852270348349 - 5337037655006751328447510550299250924469288819" - - g = "2" - - s = "814819216327401865851972" - - L = "mda=sha-1,mandatory=replay_detection,replay_detection,integ - rity=hmac-sha1,integrity=hmac-md5,confidentiality=aes,confidenti - ality=cast5,confidentiality=blowfish,maxbuffersize=2147483643" - - C: AAABYwEAAp5q/4zhXoTUzXBscozN97SWgfDcAImIk3lNHNvd0b+Dr7jEm6upXblZ - T5sL9mPgFsejlIh+B/eCu/HvzWCrXj6ylPZv8dy3LCH3LIORqQ45S7Lsbmrrg/dukDh - 4tZCJMLD4r3evzaY8KVhtJeLMVbeXuh4JljKP42Ll59Lzwf8jfPh4+4Lae1rpWUCL9D - ueKcY+nN+xNHTit/ynLATxwL93P6+GoGY4TkUbUBfjiI1+rAMvyMDMw5XozGy07FOEc - ++U0iPeXCQP4MT5FipOUoz8CYX7J1LbaXp2WJuFHlkyVXF7oCoyHbhld/5CfR3o6q/B - /x9+yZRqaHH+JfllOgBfbWRhPVNIQS0xLHJlcGxheSBkZXRlY3Rpb24saW50ZWdyaXR - 5PWhtYWMtbWQ1LGNvbmZpZGVudGlhbGl0eT1ibG93ZmlzaCxtYXhidWZmZXJzaXplPT - IxNDc0ODM2NDM= - - with: - - A = "33059541846712102497463123211304342021934496372587869281515 - 9695658237779884462777478850394977744553746930451895815615888405 - 0562780707370878253753979367019077142882237029766166623275718227 - 6555389834190840322081091599089081947324537907613924707058150037 - 7802790776231793962143786411792516760030102436603621046541729396 - 6890613394379900527412007068242559299422872893332111365840536495 - 1858834742328835373387573188369956379881606380890675411966073665 - 1106922002294035533470301541999274557200666703389531481794516625 - 4757418442215980634933876533189969562613241499465295849832999091 - 40398081321840949606581251320320995783959866" - - - - -Burdis & Naffah Expires November 28, 2003 [Page 32] - -Internet-Draft SRP Authentication Mechanism May 2003 - - - o = mda=sha-1,replay_detection,integrity=hmac-md5,confidentialit - y=blowfish,maxbuffersize=2147483643" - - S: 334 AAABAgEAOUKbXpnzMhziivGgMwm+FS8sKGSvjh5M3D+80RF/5z9rm0oPoi4+ - pF83fueWn4Hz9M+muF/22PHHZkHtlutDrtapj4OtirdxC21fS9bMtEh3F0whTX+3mPv - thw5sk11turandHiLvcUZOgcrAGIoDKcBPoGyBud+8bMgpkf/uGfyBM2nEX/hV+oGgg - X+LiHjmkxAJ3kewfQPH0eV9ffEuuyu8BUcBXkJsS6l7eWkuERSCttVOi/jS031c+CD/ - nuecUXYiF8IYzW03rbcwYhZzifmTi3VK9C8zG2K1WmGU+cDKlZMkyCPMmtCsxlbgE8z - SHCuCiOgQ35XhcA0Qa0C3Q== - - with: - - B: "722842847565031844205403087285424428589273458129750231766015 - 4465607827529853239240118185263492617243523916106658696965596526 - 8585300845435562962039149169549800169184521786717633959469278439 - 8771344445002432579509292115598435685062882631760796416554562980 - 8475896198325835507901319556929511421472132184990365213059654962 - 7218189966140113906545856088040473723048909402258929560823932725 - 2022154114087913895411927676707073040281136096806681758265221209 - 8822374723416364340410020172215773934302794679034424699999611678 - 9730443114919539575466941344964841591072763617954717789621871251 - 71089179399349194452686682517183909017223901" - - C: AAAAFRTkoju6xGP+zH89iaDWIFjfIKt5Kg== - - S: 235 Authentication successful. - - - - - - - - - - - - - - - - - - - - - - - - - -Burdis & Naffah Expires November 28, 2003 [Page 33] - -Internet-Draft SRP Authentication Mechanism May 2003 - - -8. GSS-API - -8.1 Overview - - The GSS-API is described as follows: - - The Generic Security Service Application Program Interface - (GSS-API), Version 2, as defined in [RFC-2078], provides security - services to callers in a generic fashion, supportable with a range - of underlying mechanisms and technologies and hence allowing - source-level portability of applications to different - environments. - - According to [RFC-2078] there are certain specifications related to - the GSS-API that are: - - "documents defining token formats, protocols, and procedures to be - implemented in order to realize GSS-API services atop particular - security mechanisms" - - This specification is such a document - it defines a security - mechanism that can be used with the GSS-API authentication framework. - -8.2 Terminology - - The tokens referred to in the GSS-API specification [RFC-2078] are - the same as the buffers referred to in this document. - -8.3 Initial Token - - [RFC-2078] states that: - - The first context-level token obtained from GSS_Init_sec_context() - is required to indicate at its very beginning a - globally-interpretable mechanism identifier, i.e., an Object - Identifier (OID) of the security mechanism. The remaining part of - this token as well as the whole content of all other tokens are - specific to the particular underlying mechanism used to support - the GSS-API. - - To satisfy this requirement and make use of the mechanism described - in this document as a GSS-API mechanism, the following octets must be - prefixed to the first buffer sent as part of the protocol described - in Section 4: - - [ 60 08 06 06 2B 06 01 05 05 08 ] - - Each octet is written as a pair of hex digits - see Section 2. - - - -Burdis & Naffah Expires November 28, 2003 [Page 34] - -Internet-Draft SRP Authentication Mechanism May 2003 - - - These octets represent the encoding of the GSS-API mechanism - identifier as per section 3.1 of [RFC-2078]. The OID for this - mechanism is iso.org.dod.internet.security.mechanisms.srp - (1.3.6.1.5.5.8). - - Note that it is not possible to make this requirement part of the - security protocol itself, because other authentication frameworks - have different requirements for the initial octets in a mechanism - buffer. - -8.4 Security Layer - - This mechanism does not provide distinct replay detection and - sequencing services as part of the security layer. Both of these - services are provided through the use of sequence numbers in - integrity protected messages. If a GSS-API caller sets either the - replay_det_req_flag or the sequence_req_flag (section 1.2.3 of - [RFC-2078]) then this selects the "replay_detection" security - service. - - This mechanism does not make use of any channel binding data (section - 1.1.6 of [RFC-2078]). - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Burdis & Naffah Expires November 28, 2003 [Page 35] - -Internet-Draft SRP Authentication Mechanism May 2003 - - -9. EAP - -9.1 Overview - - The Extensible Authentication Protocol (EAP) [RFC-2284] is an - authentication framework that supports multiple authentication - mechanisms. It is used with link layer protocols such as PPP and the - IEEE-802 wired and wireless protocols. - -9.2 Terminology - - EAP uses the following terms to describe the entities involved in the - authentication exchange [rfc2284bis]: - - Authenticator: The entity that initiates EAP authentication in order - to authenticate a Peer. - - Peer: The entity that responds to requests from the Authenticator. - - In this document, the Server corresponds to the Authenticator and the - Client corresponds to the Peer. - -9.3 Method Details - - The EAP authentication method described in this document has the - following properties: - - Method Name: SRP - - Method Type: 7 - - As described in section 2 of [rfc2284bis] the EAP authentication - exchange is initiated by the Authenticator sending a Request packet - to the peer with a Type field indicating the type of request. The - Peer responds with a corresponding Reply packet, and the - Authenticator and Peer exchange additional corresponding Request and - Reply packets until the Authenticator deems that the authentication - exchange is successful and complete, whereafter the Authenticator - sends a Success packet. However, if at any time the Authenticator - deems the authentication exchange to be unsuccessful it sends a - Failure packet to indicate this. - - When using this authentication method, the Type field in all Request - and Reply packets is set to 7 and the Type Data is as described in - Section 4 and the rest of this document. The diagrams below - illustrate the EAP packet exchanges for this authentication method. - - The following exchange occurs when a new session is negotiated - - - -Burdis & Naffah Expires November 28, 2003 [Page 36] - -Internet-Draft SRP Authentication Mechanism May 2003 - - - between the client and the server. It will also occur when the - client requests re-use of the parameters of a previous session and - either the server does not support such re-use or no longer considers - the previous session to be valid: - - Peer (client) Authenticator (server) - - <------------ Request [ 7, { } ] ---------------------------- - - ---- Reply [ 7, { U, I, sid, cn } ] -------------------------> - - <------------ Request [ 7, { 00, N, g, s, B, L } ] ---------- - - ---- Reply [ 7, { A, M1, o, cIV } ] ------------------------> - - <------------ Request [ 7, { M2, sIV, sid, ttl } ] ---------- - - ---- Reply [ 7, { } ] --------------------------------------> - - The following exchange occurs when the client requests that the - parameters negotiated in a previous session be re-used in this - session, but with a newly derived shared context key, and the server - agrees: - - Peer (client) Authenticator (server) - - <----------------------------- Request [ 7, { } ] ----------- - - --------- Reply [ 7, { U, I, sid, cn } ] -------------------> - - <----------------------------- Request [ 7, { FF, sn } ] ---- - - --------- Reply [ 7, { } ] ---------------------------------> - - If a security layer is negotiated then the payloads of all subsequent - lower layer packets sent over the link are protected using the - negotiated security services. - -9.4 Security Claims - - As required by section 7.2 of [rfc2284bis], these are the security - claims made by this authentication method indicating the level of - security provided: - - Intended Use: Wired networks, including PPP, PPPOE, and IEEE-802 - wired media. Use over the Internet or with wireless media only - when the recommended security layer has been negotiated. - - - - -Burdis & Naffah Expires November 28, 2003 [Page 37] - -Internet-Draft SRP Authentication Mechanism May 2003 - - - Mechanism: Passphrase - - Mutual authentication: Yes. This mechanism requires mutual - authentication. - - Integrity protection: Yes. The calculations of evidence that the - shared context key is known - M1 sent by the client and M2 sent by - the server - include the protocol elements received from the - other party, so any modification by a third party will be - detected. SRP itself is resistent to known active and passive - attacks - see [SRP]. - - Replay protection: Yes. Both the client and the server randomly - generate ephemeral private keys (a and b) that are used in the SRP - calculations, but are not publicly revealed. New ephemeral - private keys are generated for each session making replay attacks - infeasible. - - Confidentiality: No. - - Key Derivation: No. - - Dictionary attack protection: Yes. From [SRP]: "An attacker with - neither the user's password nor the host's password file cannot - mount a dictionary attack on the password". - - Fast reconnect: Yes. An optional, optimised alternate authentication - exchange is available where the parameters of a previously - negotiated session are re-used, but with a newly derived shared - context key - see Section 6.4. - - Man-in-the-Middle resistance: Yes. The calculations of evidence - M1 - sent by the client and M2 sent by the server - include the - protocol elements received from the other party, so any - modification by a third party will be detected. SRP itself is - resistent to known active attacks, including man-in-the-middle - attacks - see [SRP]. - - Acknowledged result indications: Yes. When the client receives M2 - from the server it knows that the server has verified that the - evidence (M1) it presented to prove its knowledge of the shared - context key is correct, so it knows that it is authenticated to - the server. When the server receives the empty response from the - client at the end of the authentication exchange, it knows that - the client has verified that the evidence (M2) it presented to - prove its knowledge of the shared context key is correct, so it - knows that it is authenticated to the client. Similarly for - session re-use where the client receives the server nonce (sn) - - - -Burdis & Naffah Expires November 28, 2003 [Page 38] - -Internet-Draft SRP Authentication Mechanism May 2003 - - - from the server, and the server receives the final empty response - from the client. - - Key hierarchy: N/A - - Key strength: The shared context key (K) negotiated between the - client and server has a length of s, where "s" is the output - length of the chosen underlying Message Digest Algorithm used in - the SRP calculations (see "mda" option in Section 4.3). For - example, the recommended Message Digest Algorithm SHA-160 has an - output length of 160 bits, so in this case the length of K would - be 160 bits. Keys for the confidentiality and integrity - protection services are derived from K - see Section 5.1.2 - and - have sizes appropriate for the algorithms being used. Note that - all Message Digest Algorithms used with this mechanism MUST have - an output of at least 16 bytes (see "mda" option in Section 4.3), - which means that the shared context key will always have a length - of at least 128 bits. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Burdis & Naffah Expires November 28, 2003 [Page 39] - -Internet-Draft SRP Authentication Mechanism May 2003 - - -10. Security Considerations - - This mechanism relies on the security of SRP, which bases its - security on the difficulty of solving the Diffie-Hellman problem in - the multiplicative field modulo a large safe prime. See section 4 - "Security Considerations" of [RFC-2945], section 4 "Security - analysis" of [SRP], and [SRP-6i]. - - This mechanism also relies on the security of the HMAC algorithm and - the underlying hash function when integrity protection is used. - Section 6 "Security" of [RFC-2104] discusses these security issues in - detail. Weaknesses found in MD5 do not impact HMAC-MD5 [DOBBERTIN]. - - U, I, A and o, sent from the client to the server, and N, g, s, B and - L, sent from the server to the client, could be modified by an - attacker before reaching the other party. For this reason, these - values are included in the respective calculations of evidence (M1 - and M2) to prove that each party knows the shared context key K. - This allows each party to verify that these values were received - unmodified. - - The use of integrity protection is RECOMMENDED to detect message - tampering and to avoid session hijacking after authentication has - taken place. - - Replay attacks may be avoided through the use of sequence numbers, - because sequence numbers make each integrity protected message - exchanged during a session different, and each session uses a - different key. - - Research [KRAWCZYK] shows that the order and way of combining message - encryption (Confidentiality Protection) and message authentication - (Integrity Protection) are important. This mechanism follows the EtA - (encrypt-then-authenticate) method and is "generically secure". - - This mechanism uses a Pseudo-Random Number Generator (PRNG) for - generating some of its parameters. Section 5.1.1 describes a - securely seeded, cryptographically strong PRNG implementation for - this purpose. - - - - - - - - - - - - -Burdis & Naffah Expires November 28, 2003 [Page 40] - -Internet-Draft SRP Authentication Mechanism May 2003 - - -11. Acknowledgements - - The following people provided valuable feedback in the preparation of - this document: - - Stephen Farrell - - Sam Hartman - - Timothy Martin - - Alexey Melnikov - - Ken Murchison - - Magnus Nystrom - - David Taylor - - Thomas Wu - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Burdis & Naffah Expires November 28, 2003 [Page 41] - -Internet-Draft SRP Authentication Mechanism May 2003 - - -Normative References - - [RFC-2078] - Linn, J., "Generic Security Service Application Program - Interface, Version 2", RFC 2078, January 1997, . - - [RFC-2104] - Krawczyk, H., "HMAC: Keyed-Hashing for Message - Authentication", RFC 2104, February 1997, . - - [RFC-2119] - Bradner, S., "Key words for use in RFCs to Indicate - Requirement Levels", BCP 0014, RFC 2119, March 1997, - . - - [RFC-2222] - Myers, J., "Simple Authentication and Security Layer - (SASL)", RFC 2222, October 1997, . - - [RFC-2284] - Blunk, L. and J. Vollbrecht, "PPP Extensible - Authentication Protocol (EAP)", RFC 2284, March 1998, - . - - [rfc2284bis] - Blunk, L., Vollbrecht, J., Aboba, B., Carlson, J. and H. - Levkowetz, "Extensible Authentication Protocol (EAP), work - in progress", May 2003, . - - [RFC-2945] - Wu, T., "The SRP Authentication and Key Exchange System", - RFC 2945, September 2000, . - - [RFC-3454] - Hoffman, P. and M. Blanchet, "Preparation of - Internationalized Strings ("stringprep")", RFC 3454, - December 2002, . - - [SASL] Myers, J., "Simple Authentication and Security Layer - (SASL)", April 2002, . - - [SASLprep] - - - -Burdis & Naffah Expires November 28, 2003 [Page 42] - -Internet-Draft SRP Authentication Mechanism May 2003 - - - Zeilenga, K., "SASLprep: Stringprep profile for user names - and passwords, work in progress", May 2003, . - - [SRP] Wu, T., "The Secure Remote Password Protocol, Proceedings - of the 1998 Internet Society Network and Distributed - System Security Symposium, San Diego, CA, Mar 1998, pp. - 97-111", March 1998, . - - [SRP-6i] Wu, T., "SRP-6: Improvements and Refinements to the Secure - Remote Password Protocol", October 2002, . - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Burdis & Naffah Expires November 28, 2003 [Page 43] - -Internet-Draft SRP Authentication Mechanism May 2003 - - -Informative References - - [AES] National Institute of Standards and Technology, "Rijndael: - NIST's Selection for the AES", December 2000, . - - [DOBBERTIN] - Dobbertin, H., "The Status of MD5 After a Recent Attack", - December 1996, . - - [HAC] Menezes, A., van Oorschot, P. and S. Vanstone, "Handbook - of Applied Cryptography", CRC Press, Inc., ISBN - 0-8493-8523-7, 1997, . - - [ISO-10646] - International Standards Organization, "International - Standard --Information technology-- Universal - Multiple-Octet Coded Character Set (UCS) -- Part 1 - Architecture and Basic Multilingual Plane. UTF-8 is - described in Annex R, adopted but not yet published. - UTF-16 is described in Annex Q, adopted but not yet - published.", ISO/IEC 10646-1, 1993. - - [KRAWCZYK] - Krawczyk, H., "The order of encryption and authentication - for protecting communications (Or: how secure is SSL?)", - June 2001, . - - [PKCS7] RSA Data Security, Inc., "PKCS #7: Cryptographic Message - Syntax Standard", Version 1.5, November 1993, . - - [RFC-1423] - Balenson, D., "Privacy Enhancement for Internet Electronic - Mail: Part III: Algorithms, Modes, and Identifiers", RFC - 1423, February 1993, . - - [RFC-2279] - Yergeau, F., "UTF-8, a transformation format of Unicode - and ISO 10646", RFC 2279, January 1998, . - - [RFC-2440] - Callas, J., Donnerhacke, L., Finney, H. and R. Thayer, - "OpenPGP Message Format", RFC 2440, November 1998, . - - [RFC-2554] - Myers, J., "SMTP Service Extension for Authentication", - RFC 2554, March 1999. - - [RFC-2629] - Rose, M., "Writing I-Ds and RFCs using XML", RFC 2629, - June 1999, . - - [RFC-2847] - Eisler, M., "LIPKEY - A Low Infrastructure Public Key - Mechanism Using SPKM", RFC 2847, June 2000, . - - [SCAN] Hopwood, D., "Standard Cryptographic Algorithm Naming", - June 2000, . - - [SRP-6] Wu, T., "SRP Protocol Design", October 2002, . - - [SRPimpl] Wu, T., "SRP: The Open Source Password Authentication - Standard", March 1998, . - - [UMAC] Black, J., Halevi, S., Krawczyk, H., Krovetz, T. and P. - Rogaway, "UMAC: Fast and Secure Message Authentication, - Advances in Cryptology - CRYPTO '99. Lecture Notes in - Computer Science, vol. 1666, Springer-Verlag, 1999, pp. - 216-233", October 2000, . - - [UNICODE] The Unicode Consortium, "The Unicode Standard, Version - 3.2.0, is defined by The Unicode Standard, Version 3.0, as - amended by the Unicode Standard Annex #27: Unicode 3.1 and - by the Unicode Standard Annex #28: Unicode 3.2.", March - 2002, . - - [UNICODE-KC] - Durst, D., "Unicode Standard Annex #15: Unicode - Normalization Forms.", March 2001, . - - - - - - - - - - -Burdis & Naffah Expires November 28, 2003 [Page 45] - -Internet-Draft SRP Authentication Mechanism May 2003 - - -Authors' Addresses - - Keith Burdis - Rhodes University - Computer Science Department - Grahamstown 6139 - ZA - - EMail: keith@rucus.ru.ac.za - - - Raif S. Naffah - Forge Research Pty. Limited - Suite 116, Bay 9 - Locomotive Workshop, - Australian Technology Park - Cornwallis Street - Eveleigh, NSW 1430 - AU - - EMail: raif@forge.com.au - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Burdis & Naffah Expires November 28, 2003 [Page 46] - -Internet-Draft SRP Authentication Mechanism May 2003 - - -Appendix A. Modulus and Generator Values - - Modulus N and generator g values for various modulus lengths are - given below. In each case the modulus is a large safe prime and the - generator is a primitve root of GF(n) [RFC-2945]. These values are - taken from software developed by Tom Wu and Eugene Jhong for the - Stanford SRP distribution [SRPimpl]. - - [264 bits] - Modulus (base 16) = - 115B8B692E0E045692CF280B436735C77A5A9E8A9E7ED56C965F87DB5B2A2 - ECE3 - Generator = 2 - - [384 bits] - Modulus (base 16) = - 8025363296FB943FCE54BE717E0E2958A02A9672EF561953B2BAA3BAACC3E - D5754EB764C7AB7184578C57D5949CCB41B - Generator = 2 - - [512 bits] - Modulus (base 16) = - D4C7F8A2B32C11B8FBA9581EC4BA4F1B04215642EF7355E37C0FC0443EF75 - 6EA2C6B8EEB755A1C723027663CAA265EF785B8FF6A9B35227A52D86633DB - DFCA43 - Generator = 2 - - [640 bits] - Modulus (base 16) = - C94D67EB5B1A2346E8AB422FC6A0EDAEDA8C7F894C9EEEC42F9ED250FD7F0 - 046E5AF2CF73D6B2FA26BB08033DA4DE322E144E7A8E9B12A0E4637F6371F - 34A2071C4B3836CBEEAB15034460FAA7ADF483 - Generator = 2 - - [768 bits] - Modulus (base 16) = - B344C7C4F8C495031BB4E04FF8F84EE95008163940B9558276744D91F7CC9 - F402653BE7147F00F576B93754BCDDF71B636F2099E6FFF90E79575F3D0DE - 694AFF737D9BE9713CEF8D837ADA6380B1093E94B6A529A8C6C2BE33E0867 - C60C3262B - Generator = 2 - - [1024 bits] - Modulus (base 16) = - EEAF0AB9ADB38DD69C33F80AFA8FC5E86072618775FF3C0B9EA2314C9C256 - 576D674DF7496EA81D3383B4813D692C6E0E0D5D8E250B98BE48E495C1D60 - 89DAD15DC7D7B46154D6B6CE8EF4AD69B15D4982559B297BCF1885C529F56 - 6660E57EC68EDBC3C05726CC02FD4CBF4976EAA9AFD5138FE8376435B9FC6 - - - -Burdis & Naffah Expires November 28, 2003 [Page 47] - -Internet-Draft SRP Authentication Mechanism May 2003 - - - 1D2FC0EB06E3 - Generator = 2 - - [1280 bits] - Modulus (base 16) = - D77946826E811914B39401D56A0A7843A8E7575D738C672A090AB1187D690 - DC43872FC06A7B6A43F3B95BEAEC7DF04B9D242EBDC481111283216CE816E - 004B786C5FCE856780D41837D95AD787A50BBE90BD3A9C98AC0F5FC0DE744 - B1CDE1891690894BC1F65E00DE15B4B2AA6D87100C9ECC2527E45EB849DEB - 14BB2049B163EA04187FD27C1BD9C7958CD40CE7067A9C024F9B7C5A0B4F5 - 003686161F0605B - Generator = 2 - - [1536 bits] - Modulus (base 16) = - 9DEF3CAFB939277AB1F12A8617A47BBBDBA51DF499AC4C80BEEEA9614B19C - C4D5F4F5F556E27CBDE51C6A94BE4607A291558903BA0D0F84380B655BB9A - 22E8DCDF028A7CEC67F0D08134B1C8B97989149B609E0BE3BAB63D4754838 - 1DBC5B1FC764E3F4B53DD9DA1158BFD3E2B9C8CF56EDF019539349627DB2F - D53D24B7C48665772E437D6C7F8CE442734AF7CCB7AE837C264AE3A9BEB87 - F8A2FE9B8B5292E5A021FFF5E91479E8CE7A28C2442C6F315180F93499A23 - 4DCF76E3FED135F9BB - Generator = 2 - - [2048 bits] - Modulus (base 16) = - AC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC3192943DB56 - 050A37329CBB4A099ED8193E0757767A13DD52312AB4B03310DCD7F48A9DA - 04FD50E8083969EDB767B0CF6095179A163AB3661A05FBD5FAAAE82918A99 - 62F0B93B855F97993EC975EEAA80D740ADBF4FF747359D041D5C33EA71D28 - 1E446B14773BCA97B43A23FB801676BD207A436C6481F1D2B9078717461A5 - B9D32E688F87748544523B524B0D57D5EA77A2775D2ECFA032CFBDBF52FB3 - 786160279004E57AE6AF874E7303CE53299CCC041C7BC308D82A5698F3A8D - 0C38271AE35F8E9DBFBB694B5C803D89F7AE435DE236D525F54759B65E372 - FCD68EF20FA7111F9E4AFF73 - Generator = 2 - - - - - - - - - - - - - - - -Burdis & Naffah Expires November 28, 2003 [Page 48] - -Internet-Draft SRP Authentication Mechanism May 2003 - - -Appendix B. Changes since the previous draft - - Removed specific references to SASL in the main document, instead - isolating them to their own section. - - Added sections describing how the mechanism can be used with the - GSS-API and EAP authentication frameworks. - - Adopted SRP-6 exchange for the base protocol. - - Mandated the use of SASLprep profile for text based information. - - Added an optional, optimised alternate authentication exchange where - the parameters of a previously negotiated session are re-used, but - with a newly derived shared context key. - - TODO: Regenerate SASL example. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Burdis & Naffah Expires November 28, 2003 [Page 49] - -Internet-Draft SRP Authentication Mechanism May 2003 - - -Intellectual Property Statement - - The IETF takes no position regarding the validity or scope of any - intellectual property or other rights that might be claimed to - pertain to the implementation or use of the technology described in - this document or the extent to which any license under such rights - might or might not be available; neither does it represent that it - has made any effort to identify any such rights. Information on the - IETF's procedures with respect to rights in standards-track and - standards-related documentation can be found in BCP-11. Copies of - claims of rights made available for publication and any assurances of - licenses to be made available, or the result of an attempt made to - obtain a general license or permission for the use of such - proprietary rights by implementors or users of this specification can - be obtained from the IETF Secretariat. - - The IETF invites any interested party to bring to its attention any - copyrights, patents or patent applications, or other proprietary - rights which may cover technology that may be required to practice - this standard. Please address the information to the IETF Executive - Director. - - -Full Copyright Statement - - Copyright (C) The Internet Society (2003). All Rights Reserved. - - This document and translations of it may be copied and furnished to - others, and derivative works that comment on or otherwise explain it - or assist in its implementation may be prepared, copied, published - and distributed, in whole or in part, without restriction of any - kind, provided that the above copyright notice and this paragraph are - included on all such copies and derivative works. However, this - document itself may not be modified in any way, such as by removing - the copyright notice or references to the Internet Society or other - Internet organizations, except as needed for the purpose of - developing Internet standards in which case the procedures for - copyrights defined in the Internet Standards process must be - followed, or as required to translate it into languages other than - English. - - The limited permissions granted above are perpetual and will not be - revoked by the Internet Society or its successors or assignees. - - This document and the information contained herein is provided on an - "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING - TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING - BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION - - - -Burdis & Naffah Expires November 28, 2003 [Page 50] - -Internet-Draft SRP Authentication Mechanism May 2003 - - - HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - - -Acknowledgement - - Funding for the RFC Editor function is currently provided by the - Internet Society. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Burdis & Naffah Expires November 28, 2003 [Page 51] - - diff --git a/doc/draft-ietf-sasl-anon-xx.txt b/doc/draft-ietf-sasl-anon-xx.txt deleted file mode 100644 index bcff00a0..00000000 --- a/doc/draft-ietf-sasl-anon-xx.txt +++ /dev/null @@ -1,507 +0,0 @@ - - - - - - -INTERNET-DRAFT Editor: Kurt D. Zeilenga -Intended Category: Standards Track OpenLDAP Foundation -Expires in six months 30 June 2003 -Obsoletes: RFC 2245 - - - The Anonymous SASL Mechanism - - - -Status of Memo - - This document is an Internet-Draft and is in full conformance with all - provisions of Section 10 of RFC2026. - - This document is intended to be, after appropriate review and - revision, submitted to the RFC Editor as a Standards Track document. - Distribution of this memo is unlimited. Technical discussion of this - document will take place on the IETF SASL mailing list - . Please send editorial comments directly to the - document editor . - - Internet-Drafts are working documents of the Internet Engineering Task - Force (IETF), its areas, and its working groups. Note that other - groups may also distribute working documents as Internet-Drafts. - Internet-Drafts are draft documents valid for a maximum of six months - and may be updated, replaced, or obsoleted by other documents at any - time. It is inappropriate to use Internet-Drafts as reference - material or to cite them other than as ``work in progress.'' - - The list of current Internet-Drafts can be accessed at - . The list of - Internet-Draft Shadow Directories can be accessed at - . - - Copyright (C) The Internet Society (2003). All Rights Reserved. - - Please see the Full Copyright section near the end of this document - for more information. - - -Abstract - - It is common practice on the Internet to permit anonymous access to - various services. Traditionally, this has been done with a plain text - password mechanism using "anonymous" as the user name and optional - trace information, such as an email address, as the password. As - plain text login commands are not permitted in new IETF protocols, a - - - -Zeilenga Anonymous SASL Mechanism [Page 1] - -INTERNET-DRAFT draft-ietf-sasl-anon-02.txt 30 June 2003 - - - new way to provide anonymous login is needed within the context of the - Simple Authentication and Security Layer (SASL) framework. - - -Conventions - - The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", - "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this - document are to be interpreted as described in [Keywords]. - - -1. Anonymous SASL mechanism - - This document defines an anonymous mechanism for the Simple - Authentication and Security Layer ([SASL]) framework. The name - associated with this mechanism is "ANONYMOUS". - - This document replaces RFC 2245. Changes since RFC 2245 are detailed - in Appendix A. - - The mechanism consists of a single message from the client to the - server. The client sends optional trace information in the form of a - string of [UTF-8] encoded [Unicode] characters prepared in accordance - with [StringPrep] and the "trace" stringprep profile defined in - Section 2 of this document. The trace information, which has no - semantical value, should take one of three forms: an Internet email - address, an opaque string which does not contain the '@' (U+0040) - character and can be interpreted by the system administrator of the - client's domain, or nothing. For privacy reasons, an Internet email - address or other information identifying the user should only be used - with permission from the user. - - A server which permits anonymous access will announce support for the - ANONYMOUS mechanism, and allow anyone to log in using that mechanism, - usually with restricted access. - - This mechanism does not provide a security layer. - - A formal grammar for the client message using Augmented BNF [ABNF] is - provide below as a tool for understanding this technical - specification. - - message = [ email / token ] - ;; MUST be prepared in accordance with Section 2 - - UTF1 = %x00-3F / %x41-7F ;; less '@' (U+0040) - UTF2 = %xC2-DF UTF0 - UTF3 = %xE0 %xA0-BF UTF0 / %xE1-EC 2(UTF0) / - - - -Zeilenga Anonymous SASL Mechanism [Page 2] - -INTERNET-DRAFT draft-ietf-sasl-anon-02.txt 30 June 2003 - - - %xED %x80-9F UTF0 / %xEE-EF 2(UTF0) - UTF4 = %xF0 %x90-BF 2(UTF0) / %xF1-F3 3(UTF0) / - %xF4 %x80-8F 2(UTF0) - UTF0 = %x80-BF - - TCHAR = UTF1 / UTF2 / UTF3 / UTF4 - ;; any UTF-8 encoded Unicode character - ;; except '@' (U+0040) - - email = addr-spec - ;; as defined in [IMAIL], except with no free - ;; insertion of linear-white-space, and the - ;; local-part MUST either be entirely enclosed in - ;; quotes or entirely unquoted - - token = 1*255TCHAR - - Note to implementors: - The production is restricted to 255 UTF-8 encoded Unicode - characters. As the encoding of a characters uses a sequence of 1 - to 4 octets, a token may be long as 1020 octets. - - -2. The "trace" profile of "Stringprep" - - This section defines the "trace" profile of [StringPrep]. This - profile is designed for use with the SASL ANONYMOUS Mechanism. - Specifically, the client MUST prepare the production in - accordance with this profile. - - The character repertoire of this profile is Unicode 3.2 [Unicode]. - - No mapping is required by this profile. - - No Unicode normalization is required by this profile. - - The list of unassigned code points for this profile is that provided - in appendix A of [RFC 3454]. Unassigned code points are not - prohibited. - - Characters from the following tables of [StringPrep] are prohibited: - - C.2.1 (ASCII control characters) - - C.2.2 (Non-ASCII control characters) - - C.3 (Private use characters) - - C.4 (Non-character code points) - - C.5 (Surrogate codes) - - C.6 (Inappropriate for plain text) - - C.8 (Change display properties are deprecated) - - - -Zeilenga Anonymous SASL Mechanism [Page 3] - -INTERNET-DRAFT draft-ietf-sasl-anon-02.txt 30 June 2003 - - - - C.9 (Tagging characters) - - No additional characters are prohibited. - - This profile requires bidirectional character checking per Section 6 - of [StringPrep]. - - -3. Example - - Here is a sample ANONYMOUS login between an IMAP client and server. - In this example, "C:" and "S:" indicate lines sent by the client and - server respectively. If such lines are wrapped without a new "C:" or - "S:" label, then the wrapping is for editorial clarity and is not part - of the command. - - Note that this example uses the IMAP profile [IMAP4] of SASL. The - base64 encoding of challenges and responses, as well as the "+ " - preceding the responses are part of the IMAP4 profile, not part of - SASL itself. Newer profiles of SASL will include the client message - with the AUTHENTICATE command itself so the extra round trip below - (the server response with an empty "+ ") can be eliminated. - - In this example, the user's opaque identification token is "sirhc". - - S: * OK IMAP4 server ready - C: A001 CAPABILITY - S: * CAPABILITY IMAP4 IMAP4rev1 AUTH=DIGEST-MD5 AUTH=ANONYMOUS - S: A001 OK done - C: A002 AUTHENTICATE ANONYMOUS - S: + - C: c2lyaGM= - S: A003 OK Welcome, trace information has been logged. - - -4. Security Considerations - - The ANONYMOUS mechanism grants access to information by anyone. For - this reason it should be disabled by default so the administrator can - make an explicit decision to enable it. - - If the anonymous user has any write privileges, a denial of service - attack is possible by filling up all available space. This can be - prevented by disabling all write access by anonymous users. - - If anonymous users have read and write access to the same area, the - server can be used as a communication mechanism to anonymously - exchange information. Servers which accept anonymous submissions - - - -Zeilenga Anonymous SASL Mechanism [Page 4] - -INTERNET-DRAFT draft-ietf-sasl-anon-02.txt 30 June 2003 - - - should implement the common "drop box" model which forbids anonymous - read access to the area where anonymous submissions are accepted. - - If the anonymous user can run many expensive operations (e.g., an IMAP - SEARCH BODY command), this could enable a denial of service attack. - Servers are encouraged to reduce the priority of anonymous users or - limit their resource usage. - - While servers may impose a limit on the number of anonymous users, it - is noted that such limits enable denial of service attacks and should - be used with caution. - - The trace information is not authenticated so it can be falsified. - This can be used as an attempt to get someone else in trouble for - access to questionable information. Administrators trying to trace - abuse need to realize this information may be falsified. - - A client which uses the user's correct email address as trace - information without explicit permission may violate that user's - privacy. Information about who accesses an anonymous archive on a - sensitive subject (e.g., sexual abuse) has strong privacy needs. - Clients should not send the email address without explicit permission - of the user and should offer the option of supplying no trace token -- - thus only exposing the source IP address and time. Anonymous proxy - servers could enhance this privacy, but would have to consider the - resulting potential denial of service attacks. - - Anonymous connections are susceptible to man in the middle attacks - which view or alter the data transferred. Clients and servers are - encouraged to support external integrity and encryption mechanisms. - - Protocols which fail to require an explicit anonymous login are more - susceptible to break-ins given certain common implementation - techniques. Specifically, Unix servers which offer user login may - initially start up as root and switch to the appropriate user id after - an explicit login command. Normally such servers refuse all data - access commands prior to explicit login and may enter a restricted - security environment (e.g., the Unix chroot(2) function) for anonymous - users. If anonymous access is not explicitly requested, the entire - data access machinery is exposed to external security attacks without - the chance for explicit protective measures. Protocols which offer - restricted data access should not allow anonymous data access without - an explicit login step. - - General [SASL] security considerations apply to this mechanism. - - [StringPrep] security considerations as well as [Unicode] security - considerations discussed in [StringPrep] apply to this mechanism. - - - -Zeilenga Anonymous SASL Mechanism [Page 5] - -INTERNET-DRAFT draft-ietf-sasl-anon-02.txt 30 June 2003 - - - [UTF-8] security considerations also apply. - - -5. IANA Considerations - - It is requested that the SASL Mechanism registry [IANA-SASL] entry for - the ANONYMOUS mechanism be updated to reflect that this document now - provides its technical specification. - - To: iana@iana.org - Subject: Updated Registration of SASL mechanism ANONYMOUS - - SASL mechanism name: ANONYMOUS - Security considerations: See RFC XXXX. - Published specification (optional, recommended): RFC XXXX - Person & email address to contact for further information: - Kurt Zeilenga - Chris Neuman - Intended usage: COMMON - Author/Change controller: IESG - Note: Updates existing entry for ANONYMOUS - - - It is requested that the [Stringprep] profile "trace", first defined - in this RFC, be registered: - - To: iana@iana.org - Subject: Initial Registration of Stringprep "trace" profile - - Stringprep profile: trace - Published specification: RFC XXXX - Person & email address to contact for further information: - Kurt Zeilenga - - -6. Acknowledgment - - This document is a revision of RFC 2245 by Chris Newman. Portions of - the grammar defined in Section 1 were borrowed from [UTF-8] by - Francois Yergeau. - - This document is a product of the IETF SASL WG. - - -7. Normative References - - [ABNF] Crocker, D. and P. Overell, "Augmented BNF for Syntax - Specifications: ABNF", RFC 2234, November 1997. - - - -Zeilenga Anonymous SASL Mechanism [Page 6] - -INTERNET-DRAFT draft-ietf-sasl-anon-02.txt 30 June 2003 - - - [IMAIL] Crocker, D., "Standard for the Format of Arpa Internet - Text Messages", STD 11, RFC 822, August 1982. - - [Keywords] Bradner, S., "Key words for use in RFCs to Indicate - Requirement Levels", BCP 14, RFC 2119, March 1997 - - [SASL] Myers, J., "Simple Authentication and Security Layer - (SASL)", draft-myers-saslrev-xx.txt, a work in progress. - - [StringPrep] Hoffman P. and M. Blanchet, "Preparation of - Internationalized Strings ('stringprep')", RFC 3454, - December 2002. - - [Unicode] The Unicode Consortium, "The Unicode Standard, Version - 3.2.0" is defined by "The Unicode Standard, Version 3.0" - (Reading, MA, Addison-Wesley, 2000. ISBN 0-201-61633-5), - as amended by the "Unicode Standard Annex #27: Unicode - 3.1" (http://www.unicode.org/reports/tr27/) and by the - "Unicode Standard Annex #28: Unicode 3.2" - (http://www.unicode.org/reports/tr28/). - - [UTF-8] Yergeau, F., "UTF-8, a transformation - format of ISO 10646", draft-yergeau-rfc2279bis, a work - in progress. - - -8. Informative References - - [IMAP4] Crispin, M., "Internet Message Access Protocol - Version - 4rev1", RFC 2060, December 1996. - - [IANA-SASL] IANA, "SIMPLE AUTHENTICATION AND SECURITY LAYER (SASL) - MECHANISMS", http://www.iana.org/assignments/sasl- - mechanisms. - - -9. Editor's Address - - Kurt Zeilenga - OpenLDAP Foundation - - Email: kurt@OpenLDAP.org - - -Appendix A. Changes since RFC 2245 - - This appendix is non-normative. - - - - -Zeilenga Anonymous SASL Mechanism [Page 7] - -INTERNET-DRAFT draft-ietf-sasl-anon-02.txt 30 June 2003 - - - RFC 2245 allows the client to send optional trace information in the - form of a human readable string. RFC 2245 restricted this string to - US-ASCII. As the Internet is international, this document uses a - string restricted to UTF-8 encoded Unicode characters. A "stringprep" - profile is defined to precisely define which Unicode characters are - allowed in this string. While the string remains restricted to 255 - characters, the encoded length of each character may now range from 1 - to 4 octets. - - Additionally, a number of editorial changes were made. - - - -Intellectual Property Rights - - The IETF takes no position regarding the validity or scope of any - intellectual property or other rights that might be claimed to pertain - to the implementation or use of the technology described in this - document or the extent to which any license under such rights might or - might not be available; neither does it represent that it has made any - effort to identify any such rights. Information on the IETF's - procedures with respect to rights in standards-track and - standards-related documentation can be found in BCP-11. Copies of - claims of rights made available for publication and any assurances of - licenses to be made available, or the result of an attempt made to - obtain a general license or permission for the use of such proprietary - rights by implementors or users of this specification can be obtained - from the IETF Secretariat. - - The IETF invites any interested party to bring to its attention any - copyrights, patents or patent applications, or other proprietary - rights which may cover technology that may be required to practice - this standard. Please address the information to the IETF Executive - Director. - - - -Full Copyright - - Copyright (C) The Internet Society (2003). All Rights Reserved. - - This document and translations of it may be copied and furnished to - others, and derivative works that comment on or otherwise explain it - or assist in its implmentation may be prepared, copied, published and - distributed, in whole or in part, without restriction of any kind, - provided that the above copyright notice and this paragraph are - included on all such copies and derivative works. However, this - document itself may not be modified in any way, such as by removing - - - -Zeilenga Anonymous SASL Mechanism [Page 8] - -INTERNET-DRAFT draft-ietf-sasl-anon-02.txt 30 June 2003 - - - the copyright notice or references to the Internet Society or other - Internet organizations, except as needed for the purpose of - developing Internet standards in which case the procedures for - copyrights defined in the Internet Standards process must be followed, - or as required to translate it into languages other than English. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Zeilenga Anonymous SASL Mechanism [Page 9] - diff --git a/doc/draft-ietf-sasl-crammd5-xx.txt b/doc/draft-ietf-sasl-crammd5-xx.txt deleted file mode 100644 index 85bda721..00000000 --- a/doc/draft-ietf-sasl-crammd5-xx.txt +++ /dev/null @@ -1,434 +0,0 @@ - - -Network Working Group L. Nerenberg, Editor -Internet Draft: The CRAM-MD5 SASL Mechanism Orthanc Systems -Document: draft-ietf-sasl-crammd5-01.txt November 2003 - - - - The CRAM-MD5 SASL Mechanism - - -Status of this Memo - - This document is an Internet Draft and is in full conformance with - all provisions of Section 10 of RFC 2026. - - Internet Drafts are working documents of the Internet Engineering - Task Force (IETF), its areas, and its working groups. Note that - other groups may also distribute working documents as Internet - Drafts. - - Internet Drafts are draft documents valid for a maximum of six - months and may be updated, replaced, or obsoleted by other docu- - ments at any time. It is inappropriate to use Internet Drafts as - reference material or to cite them other than as "work in - progress." - - The list of current Internet Drafts can be accessed at - http://www.ietf.org/ietf/1id-abstracts.txt The list of Internet - Draft Shadow Directories can be accessed at - http://www.ietf.org/shadow.html. - - Copyright 2003, The Internet Society. All Rights Reserved. - - Please see the Copyright section near the end of this document for - more information. - -Abstract - - This document defines a simple challenge-response authentication - mechanism, using a keyed-hash digest, for use with the Simple - Authentication and Security Layer (SASL). - -1. Conventions Used in this Document - - The key words "MUST", "MUST NOT", "SHOULD", "SHOULD NOT", and "MAY" - in this document are to be interpreted as defined in [KEYWORD]. - - -2. CRAM-MD5 Authentication Mechanism - - This document defines a simple challenge-response [SASL] authenti- - cation mechanism, using a [KEYED-MD5] digest, for use with [SASL]. - The mechanism name associated with CRAM-MD5 is 'CRAM-MD5'. - - This mechanism does not provide a security layer. - - - -Nerenberg draft-ietf-sasl-crammd5-01.txt [Page 1] - -Internet Draft CRAM-MD5 SASL Mechanism November 2003 - - - The data encoded in the challenge contains a presumptively arbi- - trary string of random digits, a time-stamp, and the fully-quali- - fied primary host name of the server. - - The client makes note of the data and then responds with a string - consisting of the user name, a space, and a "digest." The latter - is computed by applying the keyed MD5 algorithm from [KEYED-MD5] - where the key is a shared secret and the digested text is the chal- - lenge (including angle-brackets). The client MUST NOT interpret or - attempt to validate the contents of the challenge in any way. - - This shared secret is a string known only to the client and server. - The "digest" parameter itself is a 16-octet value which is sent in - hexadecimal format, using lower-case US-ASCII characters. - - When the server receives this client response, it verifies the - digest provided. Since the user name may contain the space charac- - ter, the server MUST scan the client response from right to left; - the first space character encountered separates the digest from the - user name. If the digest is correct, the server should consider - the client authenticated and respond appropriately. - - The client MUST prepare the user name and shared secret strings - using the [SASLPrep] profile of the [StringPrep] algorithm. The - resulting values MUST be encoded as UTF-8 [UTF8]. - - -2.1. Formal Syntax - - The following syntax specification uses the augmented Backus-Naur - Form (ABNF) as specified in [ABNF], and incorporates by reference - the Core Rules defined in that document. - - challenge = "<" 1*DIGIT "." 1*DIGIT "@" hostname ">" - - digest = 32(DIGIT / %x61-66) - ; A hexadecimal string using only lower-case - ; letters - - hostname = 1*(ALPHA / DIGIT) *("." / "-" / ALPHA / DIGIT) - - response = user SP digest - - user = 1*OCTET - - -2.2. Examples - - The examples in this section do NOT form part of the specification. - Where conflicts exist between the examples and the formal grammar - or specification text, the latter are authoritative. - - These examples show the use of the CRAM-MD5 mechanism with the - IMAP4 AUTHENTICATE command [IMAP4]. The base64 encoding of the - - - -Nerenberg draft-ietf-sasl-crammd5-01.txt [Page 2] - -Internet Draft CRAM-MD5 SASL Mechanism November 2003 - - - challenges and responses is part of the IMAP4 AUTHENTICATE command, - not part of the CRAM-MD5 specification itself. - - S: * OK [CAPABILITY IMAP4rev1 STARTTLS LOGINDISABLED AUTH=CRAM-MD5] - C: A0001 AUTHENTICATE CRAM-MD5 - S: + PDE4OTYuNjk3MTcwOTUyQHBvc3RvZmZpY2UucmVzdG9uLm1jaS5uZXQ+ - C: dGltIGI5MTNhNjAyYzdlZGE3YTQ5NWI0ZTZlNzMzNGQzODkw - S: A0001 OK CRAM-MD5 authentication successful - - In this example, the shared secret is the string - - tanstaaftanstaaf - - Hence, the Keyed MD5 digest is produced by calculating - - MD5((tanstaaftanstaaf XOR opad), - MD5((tanstaaftanstaaf XOR ipad), - <1896.697170952@postoffice.example.net>)) - - where ipad and opad are as defined in [KEYED-MD5] and the string - shown in the challenge is the base64 encoding of - <1896.697170952@postoffice.reston.mci.net>. The shared secret is - null-padded to a length of 64 bytes. If the shared secret is longer - than 64 bytes, the MD5 digest of the shared secret is used as a 16 - byte input to the keyed MD5 calculation. - - This produces a digest value (in hexadecimal) of - - b913a602c7eda7a495b4e6e7334d3890 - - The user name is then prepended to it, forming - - tim b913a602c7eda7a495b4e6e7334d3890 - - Which is then base64 encoded to meet the requirements of the IMAP4 - AUTHENTICATE command (or the similar POP3 AUTH command), yielding - - dGltIGI5MTNhNjAyYzdlZGE3YTQ5NWI0ZTZlNzMzNGQzODkw - - - -3. References - -3.1. Normative References - -[ABNF] - Crocker, D., P. Overell, "Augmented BNF for Syntax Specifications: - ABNF", RFC2234, Internet Mail Consortium and Demon Internet Ltd., - November 1997. - -[KEYED-MD5] - Krawczyk, Bellare, Canetti, "HMAC: Keyed-Hashing for Message - Authentication", RFC 2104, IBM and UCSD, February 1997. - - - - -Nerenberg draft-ietf-sasl-crammd5-01.txt [Page 3] - -Internet Draft CRAM-MD5 SASL Mechanism November 2003 - - -[KEYWORD] - Bradner, S., "Key words for use in RFCs to Indicate Requirement - Levels", BCP 14, RFC2119, Harvard University, March 1997. - -[MD5] - Rivest, R., "The MD5 Message Digest Algorithm", RFC 1321, MIT Labo- - ratory for Computer Science and RSA Data Security, Inc., April - 1992. - -[SASL] - Myers, J., "Simple Authentication and Security Layer (SASL)," RFC - 2222, Netscape Communications, October 1997. - -[SASLPrep] - Zeilenga, K., "SASL String Preparation Profiles", draft-ietf-sasl- - saslprep (work in progress) - -[StringPrep] - Hoffman, P., M. Blanchet, "Preparation of Internationalized Strings - (stringprep)", RFC 3454, IMC and Viagenie, December 2002. - -[UTF8] - Yergeau, F., "UTF-8, a transformation format of ISO 10646", RFC - 2279, Alis Technologies, January 1998. - -3.2. Informative References - -[IMAP4] - Crispin, M., "Internet Message Access Protocol - Version 4rev1," - RFC 3501, University of Washington, March 2003. - - -4. Security Considerations - - It is conjectured that use of the CRAM-MD5 authentication mechanism - provides replay protection for a session. - - This mechanism does not obscure the user name in any way. Accord- - ingly, a server that implements both a clear-text password command - and this authentication type should not allow both methods of - access for a given user name. - - Keyed MD5 is chosen for this application because of the greater - security imparted to authentication of short messages. In addition, - the use of the techniques described in [KEYED-MD5] for pre-computa- - tion of intermediate results make it possible to avoid explicit - clear-text storage of the shared secret on the server system by - instead storing the intermediate results which are known as "con- - texts." While the saving, on the server, of the MD5 "context" is - marginally better than saving the shared secrets in clear-text, it - is not sufficient to protect the secrets if the server itself is - compromised. Consequently, servers that store the secrets or con- - texts must both be protected to a level appropriate to the poten- - tial information value in the data and services protected by this - - - -Nerenberg draft-ietf-sasl-crammd5-01.txt [Page 4] - -Internet Draft CRAM-MD5 SASL Mechanism November 2003 - - - mechanism. In other words, techniques like this one involve a - trade-off between vulnerability to network sniffing and I/O buffer - snooping and vulnerability of the server host's databases. If one - believes that the host and its databases are subject to compromise, - and the network is not, this technique (and all others like it) is - unattractive. It is perhaps even less attractive than clear-text - passwords, which are typically stored on hosts in one-way hash - form. On the other hand, if the server databases are perceived as - reasonably secure, and one is concerned about client-side or net- - work interception of the passwords (secrets), then this (and simi- - lar) techniques are preferable to clear-text passwords by a wide - margin. - - As the length of the shared secret increases, so does the diffi- - culty of deriving it. - - While there are now suggestions in the literature that the use of - MD5 and keyed MD5 in authentication procedures probably has a lim- - ited effective lifetime, the technique is now widely deployed and - widely understood. It is believed that this general understanding - may assist with the rapid replacement, by CRAM-MD5, of the current - uses of permanent clear-text passwords in many protocols. This - document has been deliberately written to permit easy upgrading to - use SHA (or whatever alternatives emerge) when they are considered - to be widely available and adequately safe. - - Even with the use of CRAM-MD5, users are still vulnerable to active - attacks. An example of an increasingly common active attack is - 'TCP Session Hijacking' as described in CERT Advisory CA-95:01. - - CRAM-MD5 does not authenticate the server and does not include a - client-supplied nonce. As a result, it is possible to construct a - server with a fixed challenge string that has pre-computed the - hashes for all possible passwords up to a certain length (or from a - dictionary). Such a server could then immediately determine the - user's password if it is sufficiently short. - - -5. IANA Considerations - - The SASL Mechanism Registry entry for CRAM-MD5 must be updated to - reference this specification. - - -6. Contributors - - The CRAM-MD5 mechanism was originally specified in RFC 2095, - IMAP/POP AUTHorize Extension for Simple Challenge/Response. The - authors of that document -- John C. Klensin, Paul Krumviede, and - Randy Catoe -- are to be credited with the design and specification - of CRAM-MD5. This memo serves only to re-state CRAM-MD5 within the - formal context of SASL, which specification it preceded by several - months. - - - - -Nerenberg draft-ietf-sasl-crammd5-01.txt [Page 5] - -Internet Draft CRAM-MD5 SASL Mechanism November 2003 - - -7. Intellectual Property - - The IETF takes no position regarding the validity or scope of any - intellectual property or other rights that might be claimed to per- - tain to the implementation or use of the technology described in - this document or the extent to which any license under such rights - might or might not be available; neither does it represent that it - has made any effort to identify any such rights. Information on - the IETF's procedures with respect to rights in standards-track and - standards-related documentation can be found in BCP-11. Copies of - claims of rights made available for publication and any assurances - of licenses to be made available, or the result of an attempt made - to obtain a general license or permission for the use of such pro- - prietary rights by implementers or users of this specification can - be obtained from the IETF Secretariat. - - The IETF invites any interested party to bring to its attention any - copyrights, patents or patent applications, or other proprietary - rights which may cover technology that may be required to practice - this standard. Please address the information to the IETF Execu- - tive Director. - - -8. Editors' Address - - Lyndon Nerenberg - Orthanc Systems - 1606 - 10770 Winterburn Road - Edmonton, Alberta - Canada T5S 1T6 - Email: lyndon+rfc-crammd5@orthanc.ca - - - - - - - - - - - - - - - - - - - - - - - - - - -Nerenberg draft-ietf-sasl-crammd5-01.txt [Page 6] - -Internet Draft CRAM-MD5 SASL Mechanism November 2003 - - -9. Full Copyright Statement - - Copyright 2003, The Internet Society. All Rights Reserved. - - This document and translations of it may be copied and furnished to - others, and derivative works that comment on or otherwise explain - it or assist in its implementation may be prepared, copied, pub- - lished and distributed, in whole or in part, without restriction of - any kind, provided that the above copyright notice and this para- - graph are included on all such copies and derivative works. How- - ever, this document itself may not be modified in any way, such as - by removing the copyright notice or references to the Internet - Society or other Internet organizations, except as needed for the - purpose of developing Internet standards in which case the proce- - dures for copyrights defined in the Internet Standards process must - be followed, or as required to translate it into languages other - than English. The limited permissions granted above are perpetual - and will not be revoked by the Internet Society or its successors - or assigns. - - This document and the information contained herein is provided on - an "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGI- - NEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, - INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE - INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WAR- - RANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Nerenberg draft-ietf-sasl-crammd5-01.txt [Page 7] - - diff --git a/doc/draft-ietf-sasl-gssapi-xx.txt b/doc/draft-ietf-sasl-gssapi-xx.txt deleted file mode 100644 index bc37a498..00000000 --- a/doc/draft-ietf-sasl-gssapi-xx.txt +++ /dev/null @@ -1,841 +0,0 @@ - - -SASL Working Group A. Melnikov -Internet-Draft Isode -Expires: May 22, 2004 November 22, 2003 - - - SASL GSSAPI mechanisms - draft-ietf-sasl-gssapi-00 - -Status of this Memo - - This document is an Internet-Draft and is in full conformance with - all provisions of Section 10 of RFC2026. - - Internet-Drafts are working documents of the Internet Engineering - Task Force (IETF), its areas, and its working groups. Note that - other groups may also distribute working documents as Internet- - Drafts. - - Internet-Drafts are draft documents valid for a maximum of six months - and may be updated, replaced, or obsoleted by other documents at any - time. It is inappropriate to use Internet-Drafts as reference - material or to cite them other than as "work in progress." - - The list of current Internet-Drafts can be accessed at http:// - www.ietf.org/ietf/1id-abstracts.txt. - - The list of Internet-Draft Shadow Directories can be accessed at - http://www.ietf.org/shadow.html. - - This Internet-Draft will expire on May 22, 2004. - -Copyright Notice - - Copyright (C) The Internet Society (2003). All Rights Reserved. - -Abstract - - The Simple Authentication and Security Layer [SASL] is a method for - adding authentication support to connection-based protocols. This - document describes the method for using the Generic Security Service - Application Program Interface [GSSAPI] in the Simple Authentication - and Security Layer [SASL]. - - This document replaces section 7.2 of RFC 2222 [SASL], the definition - of the "GSSAPI" SASL mechanism. - - - - - - - -Melnikov Expires May 22, 2004 [Page 1] - -Internet-Draft SASL GSSAPI mechanisms November 2003 - - -Table of Contents - - 1. Conventions Used in this Document . . . . . . . . . . . . . . 3 - 2. Introduction and Overview . . . . . . . . . . . . . . . . . . 4 - 2.1 Example . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 - 3. SPNEGO . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 - 4. Specification common to all GSSAPI mechanisms . . . . . . . . 6 - 4.1 Client side of authentication protocol exchange . . . . . . . 6 - 4.2 Server side of authentication protocol exchange . . . . . . . 7 - 4.3 Security layer . . . . . . . . . . . . . . . . . . . . . . . . 8 - 5. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 9 - 6. Security Considerations . . . . . . . . . . . . . . . . . . . 11 - 7. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . 12 - Normative References . . . . . . . . . . . . . . . . . . . . . 13 - Informative References . . . . . . . . . . . . . . . . . . . . 14 - Author's Address . . . . . . . . . . . . . . . . . . . . . . . 14 - Full Copyright Statement . . . . . . . . . . . . . . . . . . . 15 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Melnikov Expires May 22, 2004 [Page 2] - -Internet-Draft SASL GSSAPI mechanisms November 2003 - - -1. Conventions Used in this Document - - The key words "MUST", "MUST NOT", "SHOULD", "SHOULD NOT", and "MAY" - in this document are to be interpreted as defined in "Key words for - use in RFCs to Indicate Requirement Levels" [KEYWORDS]. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Melnikov Expires May 22, 2004 [Page 3] - -Internet-Draft SASL GSSAPI mechanisms November 2003 - - -2. Introduction and Overview - - Each and every GSSAPI mechanism used within SASL is implicitly - registered by this specification. - - For backwards compatibility with existing implementations of Kerberos - V5 and SPNEGO under SASL, the SASL mechanism name for the Kerberos V5 - GSSAPI mechanism [KRB5GSS] is "GSSAPI" and the SASL mechanism for the - SPNEGO GSSAPI mechanism [SPNEGO] is "GSS-SPNEGO". The SASL mechanism - name for any other GSSAPI mechanism is the concatenation of "GSS-" - and the Base32 [BASE-ENCODING] encoding of the first ten bytes of the - MD5 hash [MD5] of the ASN.1 DER encoding [ASN1] of the GSSAPI - mechanism's OID. The Base32 rules on padding characters and - characters outside of the base32 alphabet are not relevant to this - use of Base32. - - SASL mechanism names starting with "GSS-" are reserved for SASL - mechanisms which conform to this document. - - The specification of all SASL mechanisms conforming to this document - is in the "Specification common to all GSSAPI mechanisms" section of - this document. - - The IESG is considered to be the owner of all SASL mechanisms which - conform to this document. This does NOT necessarily imply that the - IESG is considered to be the owner of the underlying GSSAPI - mechanism. - -2.1 Example - - The OID for the SPKM-1 mechanism [SPKM1] is 1.3.6.1.5.5.1. The ASN.1 - DER encoding of this OID is 06 06 2b 06 01 05 05 01. The MD5 hash of - the ASN.1 DER encoding is 57 ee 81 82 4e ac 4d b0 e6 50 9f 60 1f 46 - 8a 30. The Base32 encoding of the first ten bytes of this is - "K7XIDASOVRG3BZSQ". Thus the SASL mechanism name for the SPKM-1 - GSSAPI mechanism is "GSS-K7XIDASOVRG3BZSQ". - - - - - - - - - - - - - - - -Melnikov Expires May 22, 2004 [Page 4] - -Internet-Draft SASL GSSAPI mechanisms November 2003 - - -3. SPNEGO - - Use of the Simple and Protected GSS-API Negotiation Mechanism - [SPNEGO] underneath SASL introduces subtle interoperability problems - and security considerations. To address these, this section places - additional requirements on implementations which support SPNEGO - underneath SASL. - - A client which supports, for example, the Kerberos V5 GSSAPI - mechanism only underneath SPNEGO underneath the "GSS-SPNEGO" SASL - mechanism will not interoperate with a server which supports the - Kerberos V5 GSSAPI mechanism only underneath the "GSSAPI" SASL - mechanism. - - Since SASL is capable of negotiating amongst GSSAPI mechanisms, the - only reason for a server or client to support the "GSS-SPNEGO" - mechanism is to allow a policy of only using mechanisms below a - certain strength if those mechanism's negotiation is protected. In - such a case, a client or server would only want to negotiate those - weaker mechanisms through SPNEGO. In any case, there is no down- - negotiation security consideration with using the strongest mechanism - and set of options the implementation supports, so for - interoperability that mechanism and set of options MUST be negotiable - without using the "GSS-SPNEGO" mechanism. - - If a client's policy is to first prefer GSSAPI mechanism X, then non- - GSSAPI mechanism Y, then GSSAPI mechanism Z, and if a server supports - mechanisms Y and Z but not X, then if the client attempts to - negotiate mechanism X by using the "GSS-SPNEGO" SASL mechanism, it - may end up using mechanism Z when it should have used mechanism Y. - For this reason, implementations MUST exclude from SPNEGO those - GSSAPI mechanisms which are weaker than the strongest non-GSSAPI SASL - mechanism advertised by the server. - - - - - - - - - - - - - - - - - - -Melnikov Expires May 22, 2004 [Page 5] - -Internet-Draft SASL GSSAPI mechanisms November 2003 - - -4. Specification common to all GSSAPI mechanisms - - Each SASL mechanism which uses a GSSAPI mechanism uses the following - specification. - - The implementation MAY set any GSSAPI flags or arguments not - mentioned in this specification as is necessary for the - implementation to enforce its security policy. - -4.1 Client side of authentication protocol exchange - - The client calls GSS_Init_sec_context, passing in - input_context_handle of 0 (initially), mech_type of the GSSAPI - mechanism for which this SASL mechanism is registered, chan_binding - of NULL, and targ_name equal to output_name from GSS_Import_Name - called with input_name_type of GSS_C_NT_HOSTBASED_SERVICE and - input_name_string of "service@hostname" where "service" is the - service name specified in the protocol's profile, and "hostname" is - the fully qualified host name of the server. If the client will be - requesting a security layer, it MUST also supply to the - GSS_Init_sec_context a mutual_req_flag of TRUE, a sequence_req_flag - of TRUE, and an integ_req_flag of TRUE. If the client will be - requesting a security layer providing confidentiality protection, it - MUST also supply to the GSS_Init_sec_context a conf_req_flag of TRUE. - The client then responds with the resulting output_token. If - GSS_Init_sec_context returns GSS_S_CONTINUE_NEEDED, then the client - should expect the server to issue a token in a subsequent challenge. - The client must pass the token to another call to - GSS_Init_sec_context, repeating the actions in this paragraph. - - When GSS_Init_sec_context returns GSS_S_COMPLETE, the client examines - the context to ensure that it provides a level of protection - permitted by the client's security policy. If the context is - acceptable, the client takes the following actions: If the last call - to GSS_Init_sec_context returned an output_token, then the client - responds with the output_token, otherwise the client responds with no - data. The client should then expect the server to issue a token in a - subsequent challenge. The client passes this token to GSS_Unwrap and - interprets the first octet of resulting cleartext as a bit-mask - specifying the security layers supported by the server and the second - through fourth octets as the network byte order maximum size - output_message to send to the server (if the resulting cleartext is - not 4 octets long, the client fails the negotiation). The client - then constructs data, with the first octet containing the bit-mask - specifying the selected security layer, the second through fourth - octets containing in network byte order the maximum size - output_message the client is able to receive, and the remaining - octets containing the authorization identity, encoded according to - - - -Melnikov Expires May 22, 2004 [Page 6] - -Internet-Draft SASL GSSAPI mechanisms November 2003 - - - the application profile specification. The authorization identity is - not NUL-terminated. The client passes the data to GSS_Wrap with - conf_flag set to FALSE, and responds with the generated - output_message. The client can then consider the server - authenticated. - -4.2 Server side of authentication protocol exchange - - The server passes the initial client response to - GSS_Accept_sec_context as input_token, setting input_context_handle - to 0 (initially), mech_type of the GSSAPI mechanism for which this - SASL mechanism is registered, chan_binding of NULL, and - acceptor_cred_handle equal to output_cred_handle from - GSS_Acquire_cred called with desired_name equal to output_name from - GSS_Import_name with input_name_type of GSS_C_NT_HOSTBASED_SERVICE - and input_name_string of "service@hostname" where "service" is the - service name specified in the protocol's profile, and "hostname" is - the fully qualified host name of the server. If - GSS_Accept_sec_context returns GSS_S_CONTINUE_NEEDED, the server - returns the generated output_token to the client in challenge and - passes the resulting response to another call to - GSS_Accept_sec_context, repeating the actions in this paragraph. - - When GSS_Accept_sec_context returns GSS_S_COMPLETE, the server - examines the context to ensure that it provides a level of protection - permitted by the server's security policy. If the context is - acceptable, the server takes the following actions: If the last call - to GSS_Accept_sec_context returned an output_token, the server - returns it to the client in a challenge and expects a reply from the - client with no data. Whether or not an output_token was returned - (and after receipt of any response from the client to such an - output_token), the server then constructs 4 octets of data, with the - first octet containing a bit-mask specifying the security layers - supported by the server and the second through fourth octets - containing in network byte order the maximum size output_token the - server is able to receive. The server must then pass the plaintext - to GSS_Wrap with conf_flag set to FALSE and issue the generated - output_message to the client in a challenge. The server must then - pass the resulting response to GSS_Unwrap and interpret the first - octet of resulting cleartext as the bit-mask for the selected - security layer, the second through fourth octets as the network byte - order maximum size output_message to send to the client, and the - remaining octets as the authorization identity. The server must - verify that the src_name is authorized to authenticate as the - authorization identity. After these verifications, the - authentication process is complete. - - - - - -Melnikov Expires May 22, 2004 [Page 7] - -Internet-Draft SASL GSSAPI mechanisms November 2003 - - -4.3 Security layer - - The security layers and their corresponding bit-masks are as follows: - - 1 No security layer - 2 Integrity protection. - Sender calls GSS_Wrap with conf_flag set to FALSE - 4 Confidentiality protection. - Sender calls GSS_Wrap with conf_flag set to TRUE - - Other bit-masks may be defined in the future; bits which are not - understood must be negotiated off. - - Note that SASL negotiates the maximum size of the output_message to - send. Implementations can use the GSS_Wrap_size_limit call to - determine the corresponding maximum size input_message. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Melnikov Expires May 22, 2004 [Page 8] - -Internet-Draft SASL GSSAPI mechanisms November 2003 - - -5. IANA Considerations - - The IANA is advised that SASL mechanism names starting with "GSS-" - are reserved for SASL mechanisms which conform to this document. The - IANA is directed to place a statement to that effect in the sasl- - mechanisms registry. - - Family of SASL mechanisms: YES - - Prefix: GSS- - - Security considerations: RFC [THIS-DOC] - - Published Specification: RFC [THIS-DOC] - - Person & email address to contact for further information: Alexey - Melnikov - - Intended usage: COMMON - - Author/Change controller: iesg@ietf.org - - The IANA is directed to modify the existing registration for "GSSAPI" - as follows. - - Family of SASL mechanisms: NO - - SASL mechanism name: GSSAPI - - Security considerations: ? - - Published Specification: RFC [THIS-DOC] - - Person & email address to contact for further information: Alexey - Melnikov - - Intended usage: COMMON - - Author/Change controller: iesg@ietf.org - - Additional Information: This mechanism is for the Kerberos V5 - mechanism of GSSAPI. Other GSSAPI mechanisms use other SASL - mechanism names, as described in this mechanism's published - specification. - - The IANA is directed to modify the existing registration for "GSS- - SPNEGO" as follows. - - - - -Melnikov Expires May 22, 2004 [Page 9] - -Internet-Draft SASL GSSAPI mechanisms November 2003 - - - Family of SASL mechanisms: NO - - SASL mechanism name: GSS-SPNEGO - - Security considerations: See the "SPNEGO" section of RFC [THIS-DOC]. - - Published Specification: RFC [THIS-DOC] - - Person & email address to contact for further information: Alexey - Melnikov - - Intended usage: LIMITED USE - - Author/Change controller: iesg@ietf.org - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Melnikov Expires May 22, 2004 [Page 10] - -Internet-Draft SASL GSSAPI mechanisms November 2003 - - -6. Security Considerations - - Security issues are discussed throughout this memo. - - When a server or client supports multiple authentication mechanisms, - each of which has a different security strength, it is possible for - an active attacker to cause a party to use the least secure mechanism - supported. To protect against this sort of attack, a client or - server which supports mechanisms of different strengths should have a - configurable minimum strength that it will use. It is not sufficient - for this minimum strength check to only be on the server, since an - active attacker can change which mechanisms the client sees as being - supported, causing the client to send authentication credentials for - its weakest supported mechanism. - - The client's selection of a SASL mechanism is done in the clear and - may be modified by an active attacker. It is important for any new - SASL mechanisms to be designed such that an active attacker cannot - obtain an authentication with weaker security properties by modifying - the SASL mechanism name and/or the challenges and responses. - - [SPNEGO] has protection against many of these down-negotiation - attacks, SASL does not itself have such protection. The section - titled "SPNEGO" mentions considerations of choosing negotiation - through SASL versus SPNEGO. - - The integrity protection provided by the security layer is useless to - the client unless the client also requests mutual authentication. - Therefore, a client wishing to benefit from the integrity protection - of a security layer MUST pass to the GSS_Init_sec_context call a - mutual_req_flag of TRUE. - - When constructing the input_name_string, the client should not - canonicalize the server's fully qualified domain name using an - insecure or untrusted directory service. - - Additional security considerations are in the [SASL] and [GSSAPI] - specifications. - - - - - - - - - - - - - -Melnikov Expires May 22, 2004 [Page 11] - -Internet-Draft SASL GSSAPI mechanisms November 2003 - - -7. Acknowledgements - - This document is a revision of RFC 2222 written by John G. Myers. - He also contributed significantly to this revision. - - Thank you to Lawrence Greenfield for converting text of this draft to - XML format. - - Contributions of many members of the SASL mailing list are gratefully - acknowledged. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Melnikov Expires May 22, 2004 [Page 12] - -Internet-Draft SASL GSSAPI mechanisms November 2003 - - -Normative References - - [ASN1] International Organization for Standardization, - "Information Processing Systems - Open Systems - Interconnection - Specification of Abstract Syntax - Notation One (ASN.1)", ISO Standard 8824, December - 1990. - - [BASE-ENCODING] Josefsson, S., "The Base16, Base32, and Base64 Data - Encodings", RFC 3548, July 2003. - - [GSSAPI] Linn, J., "Generic Security Service Application - Program Interface Version 2, Update 1", RFC 2743, - January 2000. - - [KEYWORDS] Bradner, S., "Key words for use in RFCs to Indicate - Requirement Levels", BCP 14, RFC 2119, March 1997. - - [KRB5GSS] Linn, J., "The Kerberos Version 5 GSS-API - Mechanism", RFC 1964, June 1996. - - [MD5] Rivest, R., "The MD5 Message-Digest Algorithm", RFC - 1321, April 1992. - - [SASL] Myers, J., "Simple Authentication and Security Layer - (SASL)", RFC 2222, October 1997. - - [SASL(rev)] Melnikov, A., "Simple Authentication and Security - Layer (SASL)", draft-ietf-sasl-rfc2222bis (work in - progress), October 2003. - - [SPNEGO] Baize, E. and D. Pinkas, "The Simple and Protected - GSS-API Negotiation Mechanism", RFC 2478, December - 1998. - - - - - - - - - - - - - - - - - -Melnikov Expires May 22, 2004 [Page 13] - -Internet-Draft SASL GSSAPI mechanisms November 2003 - - -Informative References - - [SPKM1] Adams, C., "The Simple Public-Key GSS-API Mechanism (SPKM)", - RFC 2025, October 1996. - - [UTF8] Yergeau, F., "UTF-8, a transformation format of ISO 10646", - RFC 2279, January 1998. - - -Author's Address - - Alexey Melnikov (Ed.) - Isode Limited - 5 Castle Business Village - 36 Station Road - Hampton, Middlesex TW12 2BX - UK - - EMail: Alexey.Melnikov@isode.com - URI: http://www.melnikov.ca/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Melnikov Expires May 22, 2004 [Page 14] - -Internet-Draft SASL GSSAPI mechanisms November 2003 - - -Full Copyright Statement - - Copyright (C) The Internet Society (2003). All Rights Reserved. - - This document and translations of it may be copied and furnished to - others, and derivative works that comment on or otherwise explain it - or assist in its implementation may be prepared, copied, published - and distributed, in whole or in part, without restriction of any - kind, provided that the above copyright notice and this paragraph are - included on all such copies and derivative works. However, this - document itself may not be modified in any way, such as by removing - the copyright notice or references to the Internet Society or other - Internet organizations, except as needed for the purpose of - developing Internet standards in which case the procedures for - copyrights defined in the Internet Standards process must be - followed, or as required to translate it into languages other than - English. - - The limited permissions granted above are perpetual and will not be - revoked by the Internet Society or its successors or assigns. - - This document and the information contained herein is provided on an - "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING - TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING - BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION - HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - -Acknowledgement - - Funding for the RFC Editor function is currently provided by the - Internet Society. - - - - - - - - - - - - - - - - - - - -Melnikov Expires May 22, 2004 [Page 15] - - diff --git a/doc/draft-ietf-sasl-plain-xx.txt b/doc/draft-ietf-sasl-plain-xx.txt deleted file mode 100644 index fa1fbce7..00000000 --- a/doc/draft-ietf-sasl-plain-xx.txt +++ /dev/null @@ -1,507 +0,0 @@ - - - - - - -INTERNET-DRAFT Editor: Kurt D. Zeilenga -Intended Category: Standards Track OpenLDAP Foundation -Expires in six months 27 October 2003 -Updates: RFC 2595 - - - The Plain SASL Mechanism - - - -Status of Memo - - This document is an Internet-Draft and is in full conformance with all - provisions of Section 10 of RFC2026. - - This document is intended to be, after appropriate review and - revision, submitted to the RFC Editor as a Standards Track document. - Distribution of this memo is unlimited. Technical discussion of this - document will take place on the IETF SASL mailing list - . Please send editorial comments directly to the - document editor . - - Internet-Drafts are working documents of the Internet Engineering Task - Force (IETF), its areas, and its working groups. Note that other - groups may also distribute working documents as Internet-Drafts. - Internet-Drafts are draft documents valid for a maximum of six months - and may be updated, replaced, or obsoleted by other documents at any - time. It is inappropriate to use Internet-Drafts as reference - material or to cite them other than as ``work in progress.'' - - The list of current Internet-Drafts can be accessed at - . The list of - Internet-Draft Shadow Directories can be accessed at - . - - Copyright (C) The Internet Society (2003). All Rights Reserved. - - Please see the Full Copyright section near the end of this document - for more information. - - -Abstract - - This document defines a simple clear-text user/password Simple - Authentication and Security Layer (SASL) mechanism called the PLAIN - mechanism. The PLAIN mechanism is intended to be used, in combination - with data confidentiality services provided by a lower layer, in - protocols which lack a simple password authentication command. - - - -Zeilenga Plain SASL Mechanism [Page 1] - -INTERNET-DRAFT draft-ietf-sasl-plain-03.txt 27 October 2003 - - -Conventions - - The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", - "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this - document are to be interpreted as described in [Keywords]. - - -1. Background and Intended Usage - - Clear-text passwords are simple, interoperate with almost all existing - operating system authentication databases, and are useful for a smooth - transition to a more secure password-based authentication mechanism. - The drawback is that they are unacceptable for use over an unencrypted - network connection. - - This document defines the PLAIN Simple Authentication and Security - Layer ([SASL]) mechanism for use in protocols with no clear-text login - command (e.g., [ACAP] or [SMTP-AUTH]). - - The name associated with this mechanism is "PLAIN". - - The PLAIN SASL mechanism does not provide a security layer. This - mechanism MUST NOT be used without adequate security protection as the - mechanism affords no integrity nor confidentiality protection itself. - The PLAIN SASL mechanism MUST NOT be advertised unless a strong - encryption layer, such as provided by Transport Layer Security - ([TLS]), is active or backwards compatibility dictates otherwise. - - This document updates RFC 2595, replacing Section 6. Changes since - RFC 2595 are detailed in Appendix A. - - -2. PLAIN SASL mechanism - - The mechanism consists of a single message from the client to the - server. The client sends the authorization identity (identity to - login as), followed by a NUL (U+0000) character, followed by the - authentication identity (identity whose password will be used), - followed by a NUL (U+0000) character, followed by the clear-text - password. The client leaves the authorization identity empty if it - wishes the server to derive the authorization identity from the - authentication identity. - - The formal grammar for the client message using Augmented BNF [ABNF] - follows. - - message = [authzid] NUL authcid NUL passwd - authcid = 1*SAFE ; MUST accept up to 255 octets - - - -Zeilenga Plain SASL Mechanism [Page 2] - -INTERNET-DRAFT draft-ietf-sasl-plain-03.txt 27 October 2003 - - - authzid = 1*SAFE ; MUST accept up to 255 octets - passwd = 1*SAFE ; MUST accept up to 255 octets - NUL = %x00 - - SAFE = UTF1 / UTF2 / UTF3 / UTF4 - ;; any UTF-8 encoded Unicode character except NUL - - UTF1 = %x01-7F ;; except NULL - UTF2 = %xC2-DF UTF0 - UTF3 = %xE0 %xA0-BF UTF0 / %xE1-EC 2(UTF0) / - %xED %x80-9F UTF0 / %xEE-EF 2(UTF0) - UTF4 = %xF0 %x90-BF 2(UTF0) / %xF1-F3 3(UTF0) / - %xF4 %x80-8F 2(UTF0) - UTF0 = %x80-BF - - The authorization identity (authzid), authentication identity - (authcid) and password (passwd) SHALL be transferred as [UTF-8] - encoded strings of [Unicode] characters. As NUL (U+0000) is used as a - deliminator, the NUL (U+0000) MUST NOT appear in authzid, authcid, or - passwd productions. - - The form of the authzid production is specific to the - application-level protocol's SASL profile [SASL]. The authcid and - passwd productions are form-free. Use of non-visible characters or - characters which a user may be unable to enter on some keyboards is - discouraged. - - Servers MUST be capable of accepting authzid, authcid, and passwd - productions up to and including 255 octets. It is noted that the - UTF-8 encoding of a Unicode character may be as long as 4 octets. - - Upon receipt of the message, the server will verify the presented - authentication identity (authcid) and password (passwd) with the - system authentication database and verify the authentication - credentials permit the client to login as the (presented or derived) - authorization identity. If both steps succeed, the user is - authenticated. - - The presented authentication identity and password strings are not to - be compared directly with stored strings. The server SHALL first - prepare authentication identity and password strings using the - [SASLPrep] profile of the [StringPrep] algorithm. If preparation - fails or results in an empty string, verification SHALL fail. If the - server stores only the hash of expected string, that string MUST be - prepared before generation of the hash. - - When the no authorization identity is provided, the server SHALL - derive the authorization identity from the prepared representation of - - - -Zeilenga Plain SASL Mechanism [Page 3] - -INTERNET-DRAFT draft-ietf-sasl-plain-03.txt 27 October 2003 - - - the provided authentication identity string. This ensures that the - derivation of different representations of the authentication identity - produce the same authorization identity. - - The verification function (using hashed password) can be written (in - pseudo-code): - - boolean Verify(string authzid, string authcid, string passwd) { - string pAuthcid = SASLprep(authcid); # prepare authcid - string pPasswd = SASLprep(passwd); # prepare passwd - if (pAuthcid == NULL || pPasswd == NULL) { - return false; # preparation failed - } - if (pAuthcid == "" || pPasswd == "") { - return false; # empty prepared string - } - - storedHash = FetchPasswordHash(pAuthcid); - if (storedHash == NULL || storedHash == "") { - return false; # error or unknown authcid - } - - if (!Compare(storedHash, Hash(pPassword))) { - return false; # incorrect password - } - - if (authzid == NULL) { - authzid = DeriveAuthzid(pAuthcid); - if (authzid == NULL || authzid == "") { - return false; # could not derive authzid - } - } - - if (!Authorize(pAuthcid, authzid)) { - return false; # not authorized - } - - return true; - } - - Also note that the second parameter provided to the Authorize function - is not prepared by this code. The application-level SASL profile - should be consulted to determine what, if any, preparation is - necessary. - - The server MAY also use the credentials to initialize any new - authentication database, such as one suitable for [CRAM-MD5] or - [DIGEST-MD5]. - - - -Zeilenga Plain SASL Mechanism [Page 4] - -INTERNET-DRAFT draft-ietf-sasl-plain-03.txt 27 October 2003 - - -4. Example - - Here is an example of how this might be used to initialize a CRAM-MD5 - authentication database using the Application Configuration Access - Protocol ([ACAP]). "C:" and "S:" indicate lines sent by the client - and server respectively and represents a single NUL (U+0000) - character. - - S: * ACAP (SASL "CRAM-MD5") (STARTTLS) - C: a001 AUTHENTICATE "CRAM-MD5" - S: + "<1896.697170952@postoffice.reston.mci.net>" - C: "tim b913a602c7eda7a495b4e6e7334d3890" - S: a001 NO (TRANSITION-NEEDED) - "Please change your password, or use TLS to login" - C: a002 STARTTLS - S: a002 OK "Begin TLS negotiation now" - - S: * ACAP (SASL "CRAM-MD5" "PLAIN" "EXTERNAL") - C: a003 AUTHENTICATE "PLAIN" {21+} - C: timtanstaaftanstaaf - S: a003 OK CRAM-MD5 password initialized - - - -5. Security Considerations - - The PLAIN mechanism relies on the TLS encryption layer for security. - When used without TLS, it is vulnerable to a common network - eavesdropping attack. Therefore PLAIN MUST NOT be advertised or used - unless a suitable TLS encryption layer is active or backwards - compatibility dictates otherwise. - - When the PLAIN mechanism is used, the server gains the ability to - impersonate the user to all services with the same password regardless - of any encryption provided by TLS or other network privacy mechanisms. - While many other authentication mechanisms have similar weaknesses, - stronger SASL mechanisms address this issue. Clients are encouraged - to have an operational mode where all mechanisms which are likely to - reveal the user's password to the server are disabled. - - General SASL security considerations apply to this mechanism. - "stringprep" and Unicode [StringPrep] security considerations also - apply, as do [UTF-8] security considerations. - - -6. IANA Considerations - - It is requested that the SASL Mechanism registry [IANA-SASL] entry for - - - -Zeilenga Plain SASL Mechanism [Page 5] - -INTERNET-DRAFT draft-ietf-sasl-plain-03.txt 27 October 2003 - - - the PLAIN mechanism be updated to reflect that this document now - provides its technical specification. - - To: iana@iana.org - Subject: Updated Registration of SASL mechanism PLAIN - - SASL mechanism name: PLAIN - Security considerations: See RFC XXXX. - Published specification (optional, recommended): RFC XXXX - Person & email address to contact for further information: - Kurt Zeilenga - IETF SASL WG - Intended usage: COMMON - Author/Change controller: IESG - Note: Updates existing entry for PLAIN - - -7. Acknowledgment - - This document is a revision of RFC 2595 by Chris Newman. Portions of - the grammar defined in Section 2 were borrowed from [UTF-8] by - Francois Yergeau. - - This document is a product of the IETF SASL WG. - - -8. Normative References - - [ABNF] Crocker, D. and P. Overell, "Augmented BNF for Syntax - Specifications: ABNF", RFC 2234, November 1997. - - [Keywords] Bradner, S., "Key words for use in RFCs to Indicate - Requirement Levels", BCP 14, RFC 2119, March 1997 - - [SASL] Melnikov, A. (Editor), "Simple Authentication and - Security Layer (SASL)", - draft-ietf-sasl-rfc2222bis-xx.txt, a work in progress. - - [StringPrep] Hoffman P. and M. Blanchet, "Preparation of - Internationalized Strings ('stringprep')", - draft-hoffman-rfc3454bis-xx.txt, a work in progress. - - [Unicode] The Unicode Consortium, "The Unicode Standard, Version - 3.2.0" is defined by "The Unicode Standard, Version 3.0" - (Reading, MA, Addison-Wesley, 2000. ISBN 0-201-61633-5), - as amended by the "Unicode Standard Annex #27: Unicode - 3.1" (http://www.unicode.org/reports/tr27/) and by the - "Unicode Standard Annex #28: Unicode 3.2" - - - -Zeilenga Plain SASL Mechanism [Page 6] - -INTERNET-DRAFT draft-ietf-sasl-plain-03.txt 27 October 2003 - - - (http://www.unicode.org/reports/tr28/). - - [UTF-8] Yergeau, F., "UTF-8, a transformation format of ISO - 10646", draft-yergeau-rfc2279bis-xx.txt, a work in - progress. - - [TLS] Dierks, T. and, E. Rescorla, "The TLS Protocol Version - 1.1", draft-ietf-tls-rfc2246-bis-xx.txt, a work in - progress. - - -9. Informative References - - [ACAP] Newman, C. and J. Myers, "ACAP -- Application - Configuration Access Protocol", RFC 2244, November 1997. - [CRAM-MD5] Nerenberg, L., "The CRAM-MD5 SASL Mechanism", - draft-ietf-sasl-crammd5-xx.txt, a work in progress. - - [DIGEST-MD5] Leach, P., C. Newman, and A. Melnikov, "Using Digest - Authentication as a SASL Mechanism", - draft-ietf-sasl-rfc2831bis-xx.txt, a work in progress. - - [IANA-SASL] IANA, "SIMPLE AUTHENTICATION AND SECURITY LAYER (SASL) - MECHANISMS", http://www.iana.org/assignments/sasl- - mechanisms. - - [SMTP-AUTH] Myers, J., "SMTP Service Extension for Authentication", - RFC 2554, March 1999. - - - -10. Editor's Address - - Kurt Zeilenga - OpenLDAP Foundation - - Email: kurt@OpenLDAP.org - - -Appendix A. Changes since RFC 2595 - - This appendix is non-normative. - - This document replaces Section 6 of RFC 2595. - - The specification details how the server is to compare client-provided - character strings with stored character strings. - - - - -Zeilenga Plain SASL Mechanism [Page 7] - -INTERNET-DRAFT draft-ietf-sasl-plain-03.txt 27 October 2003 - - - The ABNF grammar was updated. In particular, the grammar now allows - LINE FEED (U+000A) and CARRIAGE RETURN (U+000D) characters in the - authzid, authcid, passwd productions. However, whether these control - characters may be used depends on the string preparation rules - applicable to the production. For passwd and authcid productions, - control characters are prohibited. For authzid, one must consult the - application-level SASL profile. - - - -Intellectual Property Rights - - The IETF takes no position regarding the validity or scope of any - intellectual property or other rights that might be claimed to pertain - to the implementation or use of the technology described in this - document or the extent to which any license under such rights might or - might not be available; neither does it represent that it has made any - effort to identify any such rights. Information on the IETF's - procedures with respect to rights in standards-track and - standards-related documentation can be found in BCP-11. Copies of - claims of rights made available for publication and any assurances of - licenses to be made available, or the result of an attempt made to - obtain a general license or permission for the use of such proprietary - rights by implementors or users of this specification can be obtained - from the IETF Secretariat. - - The IETF invites any interested party to bring to its attention any - copyrights, patents or patent applications, or other proprietary - rights which may cover technology that may be required to practice - this standard. Please address the information to the IETF Executive - Director. - - - -Full Copyright - - Copyright (C) The Internet Society (2003). All Rights Reserved. - - This document and translations of it may be copied and furnished to - others, and derivative works that comment on or otherwise explain it - or assist in its implmentation may be prepared, copied, published and - distributed, in whole or in part, without restriction of any kind, - provided that the above copyright notice and this paragraph are - included on all such copies and derivative works. However, this - document itself may not be modified in any way, such as by removing - the copyright notice or references to the Internet Society or other - Internet organizations, except as needed for the purpose of - developing Internet standards in which case the procedures for - - - -Zeilenga Plain SASL Mechanism [Page 8] - -INTERNET-DRAFT draft-ietf-sasl-plain-03.txt 27 October 2003 - - - copyrights defined in the Internet Standards process must be followed, - or as required to translate it into languages other than English. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Zeilenga Plain SASL Mechanism [Page 9] - diff --git a/doc/draft-ietf-sasl-rfc2222bis-xx.txt b/doc/draft-ietf-sasl-rfc2222bis-xx.txt deleted file mode 100644 index ecadd4bf..00000000 --- a/doc/draft-ietf-sasl-rfc2222bis-xx.txt +++ /dev/null @@ -1,1320 +0,0 @@ - - - - - - -Network Working Group A. Melnikov -Internet Draft Editor -Document: draft-ietf-sasl-rfc2222bis-03.txt October 2003 - Expires in six months - - - Simple Authentication and Security Layer (SASL) - -Status of this Memo - - This document is an Internet Draft and is in full conformance with - all provisions of Section 10 of RFC 2026. - - Internet Drafts are working documents of the Internet Engineering - Task Force (IETF), its Areas, and its Working Groups. Note that - other groups may also distribute working documents as Internet - Drafts. Internet Drafts are draft documents valid for a maximum of - six months. Internet Drafts may be updated, replaced, or obsoleted - by other documents at any time. It is not appropriate to use - Internet Drafts as reference material or to cite them other than as - ``work in progress''. - - The list of current Internet-Drafts can be accessed at - http://www.ietf.org/ietf/1id-abstracts.txt - - The list of Internet-Draft Shadow Directories can be accessed at - http://www.ietf.org/shadow.html. - - A revised version of this draft document will be submitted to the RFC - editor as a Draft Standard for the Internet Community. Discussion - and suggestions for improvement are requested. Distribution of this - draft is unlimited. - - When published as an RFC this document will obsolete RFC 2222. - - - - - - - - - - - - - - - - - -A. Melnikov FORMFEED[Page i] - - - - - -Internet DRAFT SASL 18 October 2003 - - -1. Abstract - - The Simple Authentication and Security Layer (SASL) provides a method - for adding authentication support with an optional security layer to - connection-based protocols. It also describes a structure for - authentication mechanisms. The result is an abstraction layer - between protocols and authentication mechanisms such that any SASL- - compatible authentication mechanism can be used with any SASL- - compatible protocol. - - This document describes how a SASL authentication mechanism is - structured, describes how a protocol adds support for SASL, defines - the protocol for carrying a security layer over a connection, and - defines the EXTERNAL SASL authentication mechanism. - -2. Organization of this document - -2.1. How to read this document - - This document is written to serve two different audiences, protocol - designers using this specification to support authentication in their - protocol, and implementors of clients or servers for those protocols - using this specification. - - The sections "Overview", "Authentication Mechanisms", "Protocol - Profile Requirements", "Specific Issues", and "Security - Considerations" cover issues that protocol designers need to - understand and address in profiling this specification for use in a - specific protocol. - - Implementors of a protocol using this specification need the - protocol-specific profiling information in addition to the - information in this document. - -2.2. Conventions used in this document - - In examples, "C:" and "S:" indicate lines sent by the client and - server respectively. - - The key words "MUST", "MUST NOT", "SHOULD", "SHOULD NOT", and "MAY" - in this document are to be interpreted as defined in "Key words for - use in RFCs to Indicate Requirement Levels" [KEYWORDS]. - - Character names in this document use the notation for code points and - names from the Unicode Standard [Unicode]. For example, the letter - "a" may be represented as either or . - - - - - -A. Melnikov FORMFEED[Page 2] - - - - - -Internet DRAFT SASL 18 October 2003 - - -3. Overview - - The Simple Authentication and Security Layer (SASL) is a method for - adding authentication support to connection-based protocols. - - The SASL specification has three layers, as indicated in the diagram - below. At the top, a protocol definition using SASL specifies a - profile, including a command for identifying and authenticating a - user to a server and for optionally negotiating a security layer for - subsequent protocol interactions. At the bottom, a SASL mechanism - definition specifies an authentication mechanism. The SASL - framework, specified by this document, constrains the behavior of - protocol profiles and mechanisms, separating protocol from mechanism - and defining how they interact. - - SMTP Protocol LDAP Protocol Etc - Profile Profile . . . - ----- | -----// - | // - SASL framework - / | \ - /----- | -----\ - EXTERNAL DIGEST-MD5 Etc - SASL mechanism SASL mechanism . . . - - This separation between the definition of protocols and the - definition of authentication mechanisms is crucial. It permits an - authentication mechanism to be defined once, making it usable by any - SASL protocol profile. In many implementations, the same SASL - mechanism code is used for multiple protocols. - -4. Authentication mechanisms - - SASL mechanisms are named by strings, from 1 to 20 characters in - length, consisting of upper-case ASCII [ASCII] letters, digits, - hyphens, and/or underscores. SASL mechanism names must be registered - with the Internet Assigned Numbers Authority (IANA). IETF standards - track documents may direct the IANA to reserve a portion of the SASL - mechanism namespace and may specify different registration criteria - for the reserved portion; the GSSAPI mechanism specification [SASL- - GSSAPI] does this. Procedures for registering new SASL mechanisms are - given in the section 8. - - The "sasl-mech" rule below defines the syntax of a SASL mechanism - name. This uses the Augmented Backus-Naur Form (ABNF) notation as - specified in [ABNF] and the ABNF core rules as specified in Appendix - A of the ABNF specification [ABNF]. - - - - -A. Melnikov FORMFEED[Page 3] - - - - - -Internet DRAFT SASL 18 October 2003 - - - sasl-mech = 1*20mech-char - mech-char = %x41-5A / DIGIT / "-" / "_" - ; mech names restricted to uppercase ASCII letters, - ; digits, "-" and "_" - - -4.1. Authentication protocol exchange - - A SASL mechanism is responsible for conducting an authentication - protocol exchange. This consists of a series of server challenges - and client responses, the contents of which are specific to and - defined by the mechanism. To the protocol, the challenges and - responses are opaque binary tokens of arbitrary length. The - protocol's profile then specifies how these binary tokens are then - encoded for transfer over the connection. - - After receiving an authentication command or any client response, a - server mechanism may issue a challenge, indicate failure, or indicate - completion. The server mechanism may return additional data with a - completion indication. The protocol's profile specifies how each of - these is then represented over the connection. - - After receiving a challenge, a client mechanism may issue a response - or abort the exchange. The protocol's profile specifies how each of - these is then represented over the connection. - - During the authentication protocol exchange, the mechanism performs - authentication, transmits an authorization identity (frequently known - as a userid) from the client to server, and negotiates the use of a - mechanism-specific security layer. If the use of a security layer is - agreed upon, then the mechanism must also define or negotiate the - maximum security layer buffer size that each side is able to receive. - -4.2. Authorization identities and proxy authentication - - An authorization identity is a string of zero or more ISO 10646 - [ISO-10646] coded characters. The NUL character is not - permitted in authorization identities. The meaning of an - authorization identity of the empty string (zero length) is defined - below in this section. The authorization identity is used by the - server as the primary identity for making access policy decisions. - - The character encoding scheme used (see [CHARSET-POLICY] for IETF - policy regarding character sets in IETF protocols) for transmitting - an authorization identity over protocol is specified in each - authentication mechanism (with the authentication mechanism's data - being further restricted/encoded by the protocol profile). - Authentication mechanisms SHOULD encode these and other strings in - - - -A. Melnikov FORMFEED[Page 4] - - - - - -Internet DRAFT SASL 18 October 2003 - - - UTF-8 [UTF-8]. While some legacy mechanisms are incapable of - transmitting an authorization identity other than the empty string, - newly defined mechanisms are expected to be capable of carrying the - entire Unicode repertoire (with the exception of the NUL character). - An authorization identity of the empty string and an absent - authorization identity MUST be treated as equivalent. However, - mechanisms SHOULD NOT allow both. That is, a mechanism which provides - an optional field for an authorization identity, SHOULD NOT allow - that field, when present, to be empty. - - The identity derived from the client's authentication credentials is - known as the "authentication identity". With any mechanism, - transmitting an authorization identity of the empty string directs - the server to derive an authorization identity from the client's - authentication identity. - - If the authorization identity transmitted during the authentication - protocol exchange is not the empty string, this is typically referred - to as "proxy authentication". This feature permits agents such as - proxy servers to authenticate using their own credentials, yet - request the access privileges of the identity for which they are - proxying. - - The server makes an implementation defined policy decision as to - whether the authentication identity is permitted to have the access - privileges of the authorization identity and whether the - authorization identity is permitted to receive service. If it is - not, the server indicates failure of the authentication protocol - exchange. - - As a client might not have the same information as the server, - clients SHOULD NOT derive authorization identities from - authentication identities. Instead, clients SHOULD provide no (or - empty) authorization identity when the user has not provided an - authorization identity. - - The server MUST verify that a received authorization identity is in - the correct form. Profiles whose authorization identities are simple - user names (e.g. IMAP [RFC 3501]) SHOULD use "SASLPrep" profile - [SASLPrep] of the "stringprep" algorithm [StringPrep] to prepare - these names for matching. The profiles MAY use a stringprep profile - that is more strict than "SASLPrep". If the preparation of the - authorization identity fails or results in an empty string, the - server MUST fail the authentication exchange. The only exception to - this rule is when the received authorization identity is already the - empty string. - - - - - -A. Melnikov FORMFEED[Page 5] - - - - - -Internet DRAFT SASL 18 October 2003 - - -4.3. Security layers - - If use of a security layer is negotiated by the authentication - protocol exchange, the security layer is applied to all subsequent - data sent over the connection (until another security layer or no - security layer is negotiated; see also section 6.3). The security - layer takes effect immediately following the last response of the - authentication exchange for data sent by the client and the - completion indication for data sent by the server. - - Once the security layer is in effect, the protocol stream is - processed by the security layer into buffers of security encoded - data. Each buffer of security encoded data is transferred over the - connection as a stream of octets prepended with a four octet field in - network byte order that represents the length of the following - buffer. The length of the security encoded data buffer MUST be no - larger than the maximum size that was either defined in the mechanism - specification or negotiated by the other side during the - authentication protocol exchange. Upon the receipt of a data buffer - which is larger than the defined/negotiated maximal buffer size, the - receiver SHOULD close the connection. This might be a sign of an - attack or a buggy implementation. - -4.4. Character string issues - - Authentication mechanisms SHOULD encode character strings in UTF-8 - [UTF-8] (see [CHARSET-POLICY] for IETF policy regarding character - sets in IETF protocols). In order to avoid noninteroperability due - to differing normalizations, when a mechanism specifies that a string - authentication identity or password used as input to a cryptographic - function (or used for comparison) it SHOULD specify that the string - first be prepared using the "SASLPrep" profile [SASLPrep] of the - "stringprep" algorithm [StringPrep]. There are three entities that - has to deal with this issue: a client (upon getting user input or - retrieving a value from configuration), a server (upon receiving the - value from the client) and a utility that is able to store - passwords/hashes in a database that can be later used by the server. - The preparation must be done by the client and the utility and may be - done by the server. If preparation fails or results in an empty - string, the entity doing the preparation SHALL fail the - authentication exchange. - - -5. Protocol profile requirements - - In order to use this specification, a protocol definition MUST supply - the following information: - - - - -A. Melnikov FORMFEED[Page 6] - - - - - -Internet DRAFT SASL 18 October 2003 - - - A service name, to be selected from the IANA registry of "service" - elements for the GSSAPI host-based service name form [GSSAPI]. This - service name is made available to the authentication mechanism. - - The registry is available at the URL - . - - A definition of the command to initiate the authentication protocol - exchange. This command must have as a parameter the name of the - mechanism being selected by the client. - - The command SHOULD have an optional parameter giving an initial - response. This optional parameter allows the client to avoid a round - trip when using a mechanism which is defined to have the client send - data first. When this initial response is sent by the client and the - selected mechanism is defined to have the server start with an - initial challenge, the command fails. See section 6.1 of this - document for further information. - - A definition of the method by which the authentication protocol - exchange is carried out, including how the challenges and responses - are encoded, how the server indicates completion or failure of the - exchange, how the client aborts an exchange, and how the exchange - method interacts with any line length limits in the protocol. - - The exchange method SHOULD allow the server to include an optional - data ("optional challenge") with a success notification. This allows - the server to avoid a round trip when using a mechanism which is - defined to have the server send additional data along with the - indication of successful completion. See section 6.2 of this - document for further information. - - In addition, a protocol profile SHOULD specify a mechanism through - which a client may obtain the names of the SASL mechanisms available - to it. This is typically done through the protocol's extensions or - capabilities mechanism. - - Identification of the octet where any negotiated security layer - starts to take effect, in both directions. - - Specify if the protocol supports "multiple authentications" (see - section 6.3). - - If both TLS and SASL security layer are allowed to be negotiated by - the protocol, the protocol profile MUST define in which order they - are applied to a cleartext data sent over the connection. - - A protocol profile MAY further refine the definition of an - - - -A. Melnikov FORMFEED[Page 7] - - - - - -Internet DRAFT SASL 18 October 2003 - - - authorization identity by adding additional syntactic restrictions - and protocol-specific semantics. A protocol profile MUST specify the - form of the authorization identity (since it is protocol specific, as - opposed to the authentication identity, which is mechanism specific) - and how authorization identities are to be compared. Profiles whose - authorization identities are simple user names (e.g. IMAP [RFC 3501]) - SHOULD use "SASLPrep" profile [SASLPrep] of the "stringprep" - algorithm [StringPrep] to prepare these names for matching. The - profiles MAY use a stringprep profile that is more strict than - SASLPrep. - - A protocol profile SHOULD NOT attempt to amend the definition of - mechanisms or make mechanism-specific encodings. This breaks the - separation between protocol and mechanism that is fundamental to the - design of SASL. Likewise, SASL mechanisms SHOULD be profile neutral. - -6. Specific issues - -6.1. Client sends data first - - Some mechanisms specify that the first data sent in the - authentication protocol exchange is from the client to the server. - - If a protocol's profile permits the command which initiates an - authentication protocol exchange to contain an initial client - response, this parameter SHOULD be used with such mechanisms. - - If the initial client response parameter is not given, or if a - protocol's profile does not permit the command which initiates an - authentication protocol exchange to contain an initial client - response, then the server issues a challenge with no data. The - client's response to this challenge is then used as the initial - client response. (The server then proceeds to send the next - challenge, indicates completion, or indicates failure.) - -6.2. Server returns success with additional data - - Some mechanisms may specify that additional data be sent to the - client along with an indication of successful completion of the - exchange. This data would, for example, authenticate the server to - the client. - - If a protocol's profile does not permit this additional data to be - returned with a success indication, then the server issues the data - as a server challenge, without an indication of successful - completion. The client then responds with no data. After receiving - this empty response, the server then indicates successful completion - (with no additional data). - - - -A. Melnikov FORMFEED[Page 8] - - - - - -Internet DRAFT SASL 18 October 2003 - - - Client implementors should be aware of an additional failure case - that might occur when the profile supports sending the additional - data with success. Imagine that an active attacker is trying to - impersonate the server and sends faked data, which should be used to - authenticate the server to the client, with success. (A similar - situation can happen when either the server and/or the client has a - bug and they calculate different responses.) After checking the data, - the client will think that the authentication exchange has failed, - however the server will think that the authentication exchange has - completed successfully. At this point the client can not abort the - authentication exchange, it SHOULD close the connection instead. - However, if the profile did not support sending of additional data - with success, the client could have aborted the exchange at the very - last step of the authentication exchange. - -6.3. Multiple authentications - - Unless otherwise stated by the protocol's profile, only one - successful SASL negotiation may occur in a protocol session. In this - case, once an authentication protocol exchange has successfully - completed, further attempts to initiate an authentication protocol - exchange fail. - - If a profile explicitly permits multiple successful SASL negotiations - to occur, then in no case may multiple security layers be - simultaneously in effect. If a security layer is in effect and a - subsequent SASL negotiation selects a second security layer, then the - second security layer replaces the first. If a security layer is in - effect and a subsequent SASL negotiation selects no security layer, - the original security layer MUST be removed. The next paragraphs - explain why this is important. - - Let's assume that the protected resources on a server are partitioned - into a set of protection spaces, each with its own authentication - mechanisms and/or authorization database. Let's use the term "realm" - to reference any such protected space. Conceptually, realm is a named - collection of user's accounts. For example, a proxy/frontend can use - different realms for different servers/backends it represents. - - Now consider the following scenario. A client has already - authenticated and established a security layer with "Realm A" which - is managed by the server AA. Now the same client authenticates to - "Realm B" (managed by the server BB) without negotiating a new - security layer, while the security layer negotiated with "Realm A" - remains in effect. The server BB is now able observe how known - cleartext is encrypted. This scenario enables the server BB to make - guesses about previously observed ciphertext between the client and - the server AA using the server's SASL engine as an oracle. This - - - -A. Melnikov FORMFEED[Page 9] - - - - - -Internet DRAFT SASL 18 October 2003 - - - scenario is illustrated below: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -A. Melnikov FORMFEED[Page 10] - - - - - -Internet DRAFT SASL 18 October 2003 - - - +---------+ +---------+ - | | | | - | Realm B | | Realm A | - | | | | - +---------+ +---------+ - | ^ | - | : +-----------+ | - Traffic from | : | Encryption| | Traffic from A - B to client +-------->| end point |<-------+ to client - : | (SSL/SASL)| - : +-----------+ - : | - : | - : +---+ - : | | - : | | - : | | Encryption tunnel, e.g. SASL or SSL, - : | | between the server - (1) Recording +---------:| | and a single client only. - encrypted | | Separate tunnels to different - traffic between | | clients. - Realm A and client +---+ - | - | - +-----------> Traffic to clients - -7. The EXTERNAL mechanism - - The mechanism name associated with external authentication is - "EXTERNAL". - - The client sends an initial response with the UTF-8 encoding of the - authorization identity. The form of the authorization identity is - further restricted by the application-level protocol's SASL profile. - - The server uses information, external to SASL, to determine whether - the client is authorized to authenticate as the authorization - identity. If the client is so authorized, the server indicates - successful completion of the authentication exchange; otherwise the - server indicates failure. - - The system providing this external information may be, for example, - IPSec or TLS. However, the client can make no assumptions as to what - information the server can use in determining client authorization. - E.g., just because TLS was established, doesn't mean that the server - will use the information provided by TLS. - - If the client sends the empty string as the authorization identity - - - -A. Melnikov FORMFEED[Page 11] - - - - - -Internet DRAFT SASL 18 October 2003 - - - (thus requesting that the authorization identity be derived from the - client's authentication credentials), the authorization identity is - to be derived from authentication credentials which exist in the - system that is providing the external authentication. - -7.1. Formal syntax - - The following syntax specification uses the augmented Backus-Naur - Form (BNF) notation as specified in [ABNF]. This uses the ABNF core - rules as specified in Appendix A of the ABNF specification [ABNF]. - Non-terminals referenced but not defined below are as defined by - [UTF-8]. - - The "extern-init-resp" rule below defines the initial response sent - from client to server. - - extern-init-resp = *( UTF8-char-no-nul ) - - UTF8-char-no-nul = UTF8-1-no-nul / UTF8-2 / UTF8-3 / UTF8-4 - - UTF8-1-no-nul = %x01-7F - - -7.2. Example - - The following is an example of an EXTERNAL authentication in the SMTP - protocol [SMTP]. In this example, the client is proxy - authenticating, sending the authorization id "fred". The server has - determined the client's identity through IPsec and has a security - policy that permits that identity to proxy authenticate as any other - identity. - - To the protocol profile, the four octet sequence "fred" is an opaque - binary data. The SASL protocol profile for SMTP [SMTP-AUTH] specifies - that server challenges and client responses are encoded in BASE64 - [BASE64]; the BASE64 encoding of "fred" is "ZnJlZA==". - - S: 220 smtp.example.com ESMTP server ready - C: EHLO jgm.example.com - S: 250-smtp.example.com - S: 250 AUTH DIGEST-MD5 EXTERNAL - C: AUTH EXTERNAL ZnJlZA== - S: 235 Authentication successful. - -8. IANA Considerations - - - - - - -A. Melnikov FORMFEED[Page 12] - - - - - -Internet DRAFT SASL 18 October 2003 - - -8.1. Guidelines for IANA - - - It is requested that IANA updates the SASL mechanisms registry as - follows: - - - Change the "Intended usage" of the KERBEROS_V4 and SKEY mechanism - registrations to OBSOLETE. Change the "Published specification" - of the EXTERNAL mechanism to this document. Updated registration - is provided in Section 8.6. - -8.2. Registration procedure - - - Registration of a SASL mechanism is done by filling in the template - in section 8.5 and sending it via electronic mail to . - IANA has the right to reject obviously bogus registrations, but will - perform no review of claims made in the registration form. SASL - mechanism registrations are currently available at the URL - . - - There is no naming convention for SASL mechanisms; any name that - conforms to the syntax of a SASL mechanism name can be registered. - An IETF Standards Track document may reserve a portion of the SASL - mechanism namespace ("family of SASL mechanisms") for its own use, - amending the registration rules for that portion of the namespace. - Each family of SASL mechanisms MUST be identified by a prefix. - - While the registration procedures do not require it, authors of SASL - mechanisms are encouraged to seek community review and comment - whenever that is feasible. Authors may seek community review by - posting a specification of their proposed mechanism as an Internet- - Draft. SASL mechanisms intended for widespread use should be - standardized through the normal IETF process, when appropriate. - -8.3. Comments on SASL mechanism registrations - - Comments on registered SASL mechanisms should first be sent to the - "owner" of the mechanism and/or to the SASL WG mailing list. - Submitters of comments may, after a reasonable attempt to contact the - owner, request IANA to attach their comment to the SASL mechanism - registration itself. If IANA approves of this, the comment will be - made accessible in conjunction with the SASL mechanism registration - itself. - - - - - - -A. Melnikov FORMFEED[Page 13] - - - - - -Internet DRAFT SASL 18 October 2003 - - -8.4. Change control - - Once a SASL mechanism registration has been published by IANA, the - author may request a change to its definition. The change request - follows the same procedure as the registration request. - - The owner of a SASL mechanism may pass responsibility for the SASL - mechanism to another person or agency by informing IANA; this can be - done without discussion or review. - - The IESG may reassign responsibility for a SASL mechanism. The most - common case of this will be to enable changes to be made to - mechanisms where the author of the registration has died, moved out - of contact or is otherwise unable to make changes that are important - to the community. - - SASL mechanism registrations may not be deleted; mechanisms which are - no longer believed appropriate for use can be declared OBSOLETE by a - change to their "intended use" field; such SASL mechanisms will be - clearly marked in the lists published by IANA. - - The IESG is considered to be the owner of all SASL mechanisms which - are on the IETF standards track. - -8.5. Registration template - - - Subject: Registration of SASL mechanism X - - Family of SASL mechanisms: (YES or NO) - - SASL mechanism name (or prefix for the family): - - Security considerations: - - Published specification (optional, recommended): - - Person & email address to contact for further information: - - Intended usage: - - (One of COMMON, LIMITED USE or OBSOLETE) - - Owner/Change controller: - - (Any other information that the author deems interesting may be - added below this line.) - - - - -A. Melnikov FORMFEED[Page 14] - - - - - -Internet DRAFT SASL 18 October 2003 - - -8.6. The EXTERNAL mechanism registration - - It is requested that the SASL Mechanism registry [IANA-SASL] entry - for the EXTERNAL mechanism be updated to reflect that this document - now provides its technical specification. - - - Subject: Updated Registration of SASL mechanism EXTERNAL - - Family of SASL mechanisms: NO - - SASL mechanism name: EXTERNAL - - Security considerations: See RFC XXXX, section 9. - - Published specification (optional, recommended): RFC XXXX - - Person & email address to contact for further information: - Alexey Melnikov - - Intended usage: COMMON - - Owner/Change controller: IESG - - Note: Updates existing entry for EXTERNAL - -9. Security considerations - - Security issues are discussed throughout this memo. - - The mechanisms that support integrity protection are designed such - that the negotiation of the security layer and authorization identity - is integrity protected. When the client selects a security layer - with at least integrity protection, this protects against an active - attacker hijacking the connection and modifying the authentication - exchange to negotiate a plaintext connection. - - When a server or client supports multiple authentication mechanisms, - each of which has a different security strength, it is possible for - an active attacker to cause a party to use the least secure mechanism - supported. To protect against this sort of attack, a client or - server which supports mechanisms of different strengths should have a - configurable minimum strength that it will use. It is not sufficient - for this minimum strength check to only be on the server, since an - active attacker can change which mechanisms the client sees as being - supported, causing the client to send authentication credentials for - its weakest supported mechanism. - - - - -A. Melnikov FORMFEED[Page 15] - - - - - -Internet DRAFT SASL 18 October 2003 - - - The client's selection of a SASL mechanism is done in the clear and - may be modified by an active attacker. It is important for any new - SASL mechanisms to be designed such that an active attacker cannot - obtain an authentication with weaker security properties by modifying - the SASL mechanism name and/or the challenges and responses. - - Any protocol interactions prior to authentication are performed in - the clear and may be modified by an active attacker. In the case - where a client selects integrity protection, it is important that any - security-sensitive protocol negotiations be performed after - authentication is complete. Protocols should be designed such that - negotiations performed prior to authentication should be either - ignored or revalidated once authentication is complete. - - When use of a security layer is negotiated by the authentication - protocol exchange, the receiver should handle gracefully any security - encoded data buffer larger than the defined/negotiated maximal size. - In particular, it must not blindly allocate the amount of memory - specified in the buffer size field, as this might cause the "out of - memory" condition. If the receiver detects a large block, it SHOULD - close the connection. - - "stringprep" and Unicode security considerations apply to - authentication identities, authorization identities and passwords. - - The EXTERNAL mechanism provides no security protection; it is - vulnerable to spoofing by either client or server, active attack, and - eavesdropping. It should only be used when external security - mechanisms are present and have sufficient strength. - -10. References - -10.1. Normative References - - [ABNF] Crocker, Overell, "Augmented BNF for Syntax Specifications: - ABNF", RFC 2234, November 1997 - - [ASCII] American National Standards Institute, "Code Extension - Techniques for Use with the 7-bit Coded Character Set of American - National Standard Code (ASCII) for Information Interchange", FIPS PUB - 35, 1974 - - [CHARSET-POLICY] Alvestrand, "IETF Policy on Character Sets and - Languages", RFC 2277, January 1998 - - [GSSAPI] Linn, "Generic Security Service Application Program - Interface, Version 2, Update 1", RFC 2743, January 2000 - - - - -A. Melnikov FORMFEED[Page 16] - - - - - -Internet DRAFT SASL 18 October 2003 - - - [ISO-10646] "Universal Multiple-Octet Coded Character Set (UCS) - - Architecture and Basic Multilingual Plane", ISO/IEC 10646-1 : 1993. - - [KEYWORDS] Bradner, "Key words for use in RFCs to Indicate - Requirement Levels", RFC 2119, March 1997 - - [Unicode] The Unicode Consortium, "The Unicode Standard, Version - 3.2.0" is defined by "The Unicode Standard, Version 3.0" (Reading, - MA, Addison-Wesley, 2000. ISBN 0-201-61633-5), as amended by the - "Unicode Standard Annex #27: Unicode 3.1" - (http://www.unicode.org/reports/tr27/) and by the "Unicode Standard - Annex #28: Unicode 3.2" (http://www.unicode.org/reports/tr28/). - - [Stringprep] P. Hoffman, M. Blanchet, "Preparation of - Internationalized Strings ("stringprep")", RFC 3454, December 2002. - - [SASLPrep] Zeilenga, K., "SASLprep: Stringprep profile for user names - and passwords", Work in progress, draft-ietf-sasl-saslprep-XX.txt. - - [UTF-8] Yergeau, "UTF-8, a transformation format of ISO 10646", work - in progress (draft-yergeau-rfc2279bis-XX) that replaces RFC 2279, - Janyary 1998 - -10.2. Informative References - - <> [SASL-GSSAPI] Myers, J., "SASL GSSAPI - mechanisms", work in progress, draft-ietf-cat-sasl-gssapi-XX.txt, - September 2000 - - [SASL-DIGEST] Leach, P., Newman, C., Melnikov, A., "Using Digest - Authentication as a SASL Mechanism", work in progress, draft-ietf- - sasl-rfc2831bis-XX.txt, replaces RFC 2831 - - [SASL-OTP] Newman, C., "The One-Time-Password SASL Mechanism", RFC - 2444, October 1998 - - [SMTP] Klensin, J., "Simple Mail Transfer Protocol", RFC 2821, April - 2001 - - [SMTP-AUTH] Myers, J., "SMTP Service Extension for Authentication", - RFC 2554, March 1999 - - [BASE64] Josefsson, S., "The Base16, Base32, and Base64 Data - Encodings", RFC 3548, July 2003 - - [RFC-INSTRUCTIONS] Postel, Reynolds, "Instructions to RFC Authors", - RFC 2223, October 1997 - - - - -A. Melnikov FORMFEED[Page 17] - - - - - -Internet DRAFT SASL 18 October 2003 - - - [IANA-SASL] IANA, "SIMPLE AUTHENTICATION AND SECURITY LAYER (SASL) - MECHANISMS", http://www.iana.org/assignments/sasl-mechanisms. - -11. Editor's Address - - Alexey Melnikov - Isode - - Email: Alexey.Melnikov@isode.com - -12. Acknowledgments - - This document is a revision of RFC 2222 written by John G. Myers. He - also contributed significantly to this revision. - - Magnus Nystrom provided the ASCII art used in Section 6.3. - - Definition of realm was extracted from RFC 2617 ("HTTP - Authentication: Basic and Digest Access Authentication"). - - Contributions of many members of the SASL mailing list are gratefully - acknowledged, in particular Kurt D. Zeilenga, Peter Saint-Andre, Rob - Siemborski, Jeffrey Hutzelman and Hallvard B Furuseth for - proofreading the document and various editorial suggestions. - - -13. Full Copyright Statement - - Copyright (C) The Internet Society (2003). All Rights Reserved. - - This document and translations of it may be copied and furnished to - others, and derivative works that comment on or otherwise explain it - or assist in its implementation may be prepared, copied, published - and distributed, in whole or in part, without restriction of any - kind, provided that the above copyright notice and this paragraph are - included on all such copies and derivative works. However, this - document itself may not be modified in any way, such as by removing - the copyright notice or references to the Internet Society or other - Internet organizations, except as needed for the purpose of - developing Internet standards in which case the procedures for - copyrights defined in the Internet Standards process must be - followed, or as required to translate it into languages other than - English. - - The limited permissions granted above are perpetual and will not be - revoked by the Internet Society or its successors or assigns. - - This document and the information contained herein is provided on an - - - -A. Melnikov FORMFEED[Page 18] - - - - - -Internet DRAFT SASL 18 October 2003 - - - "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING - TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING - BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION - HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - -Acknowledgement - - Funding for the RFC Editor function is currently provided by the - Internet Society. - -Appendix A. Relation of SASL to transport security - - Questions have been raised about the relationship between SASL and - various services (such as IPsec and TLS) which provide a secured - connection. - - Two of the key features of SASL are: - - The separation of the authorization identity from the identity in - the client's credentials. This permits agents such as proxy - servers to authenticate using their own credentials, yet request - the access privileges of the identity for which they are proxying. - - Upon successful completion of an authentication exchange, the - server knows the authorization identity the client wishes to use. - This allows servers to move to a "user is authenticated" state in - the protocol. - - These features are extremely important to some application protocols, - yet Transport Security services do not always provide them. To - define SASL mechanisms based on these services would be a very messy - task, as the framing of these services would be redundant with the - framing of SASL and some method of providing these important SASL - features would have to be devised. - - Sometimes it is desired to enable within an existing connection the - use of a security service which does not fit the SASL model. (TLS is - an example of such a service.) This can be done by adding a command, - for example "STARTTLS", to the protocol. Such a command is outside - the scope of SASL, and should be different from the command which - starts a SASL authentication protocol exchange. - - In certain situations, it is reasonable to use SASL underneath one of - these Transport Security services. The transport service would - secure the connection, either service would authenticate the client, - and SASL would negotiate the authorization identity. The SASL - negotiation would be what moves the protocol from "unauthenticated" - - - -A. Melnikov FORMFEED[Page 19] - - - - - -Internet DRAFT SASL 18 October 2003 - - - to "authenticated" state. The "EXTERNAL" SASL mechanism is - explicitly intended to handle the case where the transport service - secures the connection and authenticates the client and SASL - negotiates the authorization identity. - -Appendix B. Changes since RFC 2222 - - The GSSAPI mechanism was removed. It is now specified in a separate - document [SASL-GSSAPI]. - - The "KERBEROS_V4" mechanism defined in RFC 2222 is obsolete and has - been removed. - - The "SKEY" mechanism described in RFC 2222 is obsolete and has been - removed. It has been replaced by the OTP mechanism [SASL-OTP]. - - The overview has been substantially reorganized and clarified. - - Clarified the definition and semantics of the authorization identity. - - Prohibited the NUL character in authorization identities. - - Added a section on character string issues. - - The word "must" in the first paragraph of the "Protocol profile - requirements" section was changed to "MUST". - - Specified that protocol profiles SHOULD provide a way for clients to - discover available SASL mechanisms. - - Made the requirement that protocol profiles specify the semantics of - the authorization identity optional to the protocol profile. - Clarified that such a specification is a refinement of the definition - in the base SASL spec. - - Added a requirement discouraging protocol profiles from breaking the - separation between protocol and mechanism. - - Mentioned that standards track documents may carve out their own - portions of the SASL mechanism namespace and may amend registration - rules for the portion. However registration of individual SASL - mechanisms is still required. - - Specified that the authorization identity in the EXTERNAL mechanism - is encoded in UTF-8. - - Added a statement that a protocol profile SHOULD allow challenge data - to be sent with a success indication. - - - -A. Melnikov FORMFEED[Page 20] - - - - - -Internet DRAFT SASL 18 October 2003 - - - Added a security consideration for the EXTERNAL mechansim. - - Clarified sections concerning success with additional data. - - Cleaned up IANA considerations/registrations and assembled them in - one place. - - Updated references and split them into Informative and Normative. - - Added text to the Security Considerations section regarding handling - of extremely large SASL blocks. - - Replaced UTF-8 ABNF with the reference to the UTF-8 document. - - Added text about SASLPrep for authentication identities and - passwords. Described where SASLPrep preparation should take place. - - Added paragraph about verifying authorization identities. - - This document requires to drop a security layer on reauthentication - when no security layer is negotiated. This differs from RFC 2222, - which required to keep the last security layer in this case. - - Added a protocol profile requirement to specify interaction between - SASL and TLS security layers. - - Added a protocol profile requirement to specify if it supports - reauthentication. - - Removed the text that seemed to suggest that SASL security layer must - not be used when TLS is available. - - - - - - - - - - - - - - - - - - - - -A. Melnikov FORMFEED[Page 21] - - - - - -Internet DRAFT SASL 18 October 2003 - - - Status of this Memo .......................................... i - 1. Abstract ............................................... 2 - 2. Organization of this document .......................... 2 - 2.1. How to read this document .............................. 2 - 2.2. Conventions used in this document ...................... 2 - 3. Overview ............................................... 3 - 4. Authentication mechanisms .............................. 3 - 4.1. Authentication protocol exchange ....................... 4 - 4.2. Authorization identities and proxy authentication ...... 4 - 4.3. Security layers ........................................ 6 - 4.4. Character string issues ................................ 6 - 5. Protocol profile requirements .......................... 6 - 6. Specific issues ........................................ 8 - 6.1. Client sends data first ................................ 8 - 6.2. Server returns success with additional data ............ 8 - 6.3. Multiple authentications ............................... 9 - 7. The EXTERNAL mechanism ................................ 11 - 7.1. Formal syntax ......................................... 12 - 7.2. Example ............................................... 12 - 8. IANA Considerations ................................... 12 - 8.1. Guidelines for IANA ................................... 13 - 8.2. Registration procedure ................................ 13 - 8.3. Comments on SASL mechanism registrations .............. 13 - 8.4. Change control ........................................ 14 - 8.5. Registration template ................................. 14 - 8.6. The EXTERNAL mechanism registration ................... 15 - 9. Security considerations ................................ 15 - 10. References ........................................... 16 - 10.1. Normative References ................................. 16 - 10.2. Informative References ............................... 17 - 11. Editor's Address ...................................... 18 - 12. Acknowledgments ....................................... 18 - 13. Full Copyright Statement .............................. 18 - Appendix A. Relation of SASL to transport security .......... 19 - Appendix B. Changes since RFC 2222 .......................... 20 - - - - - - - - - - - - - - - - -A. Melnikov FORMFEED[Page ii] - - diff --git a/doc/draft-ietf-sasl-rfc2831bis-xx.txt b/doc/draft-ietf-sasl-rfc2831bis-xx.txt deleted file mode 100644 index dd3b9b0f..00000000 --- a/doc/draft-ietf-sasl-rfc2831bis-xx.txt +++ /dev/null @@ -1,2340 +0,0 @@ - - - - - - -INTERNET-DRAFT P. Leach -Obsoletes: 2831 Microsoft -Intended category: Standards track C. Newman - Sun Microsystems - A. Melnikov - Isode - June 2003 - - Using Digest Authentication as a SASL Mechanism - draft-ietf-sasl-rfc2831bis-02.txt - -Status of this Memo - - This document is an Internet-Draft and is in full conformance with - all provisions of Section 10 of RFC 2026. - - Internet-Drafts are working documents of the Internet Engineering - Task Force (IETF), its areas, and its working groups. Note that other - groups may also distribute working documents as Internet-Drafts. - - Internet-Drafts are draft documents valid for a maximum of six months - and may be updated, replaced, or obsoleted by other documents at any - time. It is inappropriate to use Internet-Drafts as reference - material or to cite them other than as "work in progress." - - The list of current Internet-Drafts can be accessed at - http://www.ietf.org/ietf/1id-abstracts.txt - - The list of Internet-Draft Shadow Directories can be accessed at - http://www.ietf.org/shadow.html. - -Copyright Notice - - Copyright (C) The Internet Society (2003). All Rights Reserved. - -Abstract - - This specification defines how HTTP Digest Authentication [Digest] - can be used as a SASL [RFC 2222] mechanism for any protocol that has - a SASL profile. It is intended both as an improvement over CRAM-MD5 - [RFC 2195] and as a convenient way to support a single authentication - mechanism for web, mail, LDAP, and other protocols. - - - - - - - - - -Leach & Newman Expires: December 2003 [Page 1] - - - - - -INTERNET DRAFT Digest SASL Mechanism June 2003 - - -Table of Contents - - 1 INTRODUCTION.....................................................3 - 1.1 CONVENTIONS AND NOTATION......................................3 - 1.2 REQUIREMENTS..................................................4 - 2 AUTHENTICATION...................................................5 - 2.1 INITIAL AUTHENTICATION........................................5 - 2.1.1 Step One...................................................5 - 2.1.2 Step Two...................................................9 - 2.1.3 Step Three................................................16 - 2.2 SUBSEQUENT AUTHENTICATION....................................17 - 2.2.1 Step one..................................................17 - 2.2.2 Step Two..................................................17 - 2.3 INTEGRITY PROTECTION.........................................18 - 2.4 CONFIDENTIALITY PROTECTION...................................18 - 3 SECURITY CONSIDERATIONS.........................................21 - 3.1 AUTHENTICATION OF CLIENTS USING DIGEST AUTHENTICATION........21 - 3.2 COMPARISON OF DIGEST WITH PLAINTEXT PASSWORDS................21 - 3.3 REPLAY ATTACKS...............................................21 - 3.4 ONLINE DICTIONARY ATTACKS....................................22 - 3.5 OFFLINE DICTIONARY ATTACKS...................................22 - 3.6 MAN IN THE MIDDLE............................................22 - 3.7 CHOSEN PLAINTEXT ATTACKS.....................................22 - 3.8 CBC MODE ATTACKS............................................. - 3.9 SPOOFING BY COUNTERFEIT SERVERS..............................23 - 3.10 STORING PASSWORDS...........................................23 - 3.11 MULTIPLE REALMS.............................................24 - 3.12 SUMMARY.....................................................24 - 4 EXAMPLE.........................................................24 - 5 REFERENCES......................................................26 - 5.1 NORMATIVE REFERENCES.........................................26 - 5.2 INFORMATIVE REFERENCES.......................................27 - 6 AUTHORS' ADDRESSES..............................................28 - 7 ABNF............................................................29 - 7.1 AUGMENTED BNF................................................29 - 7.2 BASIC RULES..................................................31 - 8 SAMPLE CODE.....................................................33 - 9 INTEROPERABILITY CONSIDERATIONS.................................34 - 9.1 Implementing DES cipher in CBC mode..........................34 - 10 ACKNOWLEDGEMENTS..............................................34 - 11 FULL COPYRIGHT STATEMENT.......................................35 - Appendix A: Changes from 2831.....................................36 - Appendix B: Open Issues...........................................37 - - - - - - - - -Leach & Newman Expires: December 2003 [Page 2] - - - - - -INTERNET DRAFT Digest SASL Mechanism June 2003 - - -1 Introduction - - This specification describes the use of HTTP Digest Access - Authentication as a SASL mechanism. The authentication type - associated with the Digest SASL mechanism is "DIGEST-MD5". - - This specification is intended to be upward compatible with the - "md5-sess" algorithm of HTTP/1.1 Digest Access Authentication - specified in [Digest]. The only difference in the "md5-sess" - algorithm is that some directives not needed in a SASL mechanism have - had their values defaulted. - - There is one new feature for use as a SASL mechanism: integrity - protection on application protocol messages after an authentication - exchange. - - Also, compared to CRAM-MD5, DIGEST-MD5 prevents chosen plaintext - attacks, and permits the use of third party authentication servers, - mutual authentication, and optimized reauthentication if a client has - recently authenticated to a server. - -1.1 Conventions and Notation - - This specification uses the same ABNF notation and lexical - conventions as HTTP/1.1 specification; see section 7. - - Let { a, b, ... } be the concatenation of the octet strings a, b, ... - - Let ** denote the power operation. - - Let H(s) be the 16 octet MD5 hash [RFC 1321] of the octet string s. - - Let KD(k, s) be H({k, ":", s}), i.e., the 16 octet hash of the string - k, a colon and the string s. - - Let HEX(n) be the representation of the 16 octet MD5 hash n as a - string of 32 hex digits (with alphabetic characters always in lower - case, since MD5 is case sensitive). - - Let HMAC(k, s) be the 16 octet HMAC-MD5 [RFC 2104] of the octet - string s using the octet string k as a key. - - - - - - - - - - -Leach & Newman Expires: December 2003 [Page 3] - - - - - -INTERNET DRAFT Digest SASL Mechanism June 2003 - - - Let unq(X) be the value of the quoted-string X without the - surrounding quotes and with all escape characters "\\" removed. For - example for the quoted-string "Babylon" the value of unq("Babylon") - is Babylon; for the quoted string "ABC\"123\\" the value of - unq("ABC\"123\\") is ABC"123\. - - The value of a quoted string constant as an octet string does not - include any terminating null character. - -1.2 Requirements - - The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", - "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this - document are to be interpreted as described in RFC 2119 [RFC 2119]. - - An implementation is not compliant if it fails to satisfy one or more - of the MUST level requirements for the protocols it implements. An - implementation that satisfies all the MUST level and all the SHOULD - level requirements for its protocols is said to be "unconditionally - compliant"; one that satisfies all the MUST level requirements but - not all the SHOULD level requirements for its protocols is said to be - "conditionally compliant." - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Leach & Newman Expires: December 2003 [Page 4] - - - - - -INTERNET DRAFT Digest SASL Mechanism June 2003 - - -2 Authentication - - The following sections describe how to use Digest as a SASL - authentication mechanism. - -2.1 Initial Authentication - - If the client has not recently authenticated to the server, then it - must perform "initial authentication", as defined in this section. If - it has recently authenticated, then a more efficient form is - available, defined in the next section. - -2.1.1 Step One - - The server starts by sending a challenge. The data encoded in the - challenge contains a string formatted according to the rules for a - "digest-challenge" defined as follows: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Leach & Newman Expires: December 2003 [Page 5] - - - - - -INTERNET DRAFT Digest SASL Mechanism June 2003 - - - digest-challenge = - 1#( realm | nonce | qop-options | stale | server_maxbuf | charset - algorithm | cipher-opts | auth-param ) - - realm = "realm" "=" <"> realm-value <"> - realm-value = qdstr-val - nonce = "nonce" "=" <"> nonce-value <"> - nonce-value = *qdtext - qop-options = "qop" "=" <"> qop-list <"> - qop-list = 1#qop-value - qop-value = "auth" | "auth-int" | "auth-conf" | - token - stale = "stale" "=" "true" - server_maxbuf = "maxbuf" "=" maxbuf-value - maxbuf-value = 1*DIGIT - charset = "charset" "=" "utf-8" - algorithm = "algorithm" "=" "md5-sess" - cipher-opts = "cipher" "=" <"> 1#cipher-value <"> - cipher-value = "3des" | "des" | "rc4-40" | "rc4" | - "rc4-56" | "aes" | token - auth-param = token "=" ( token | quoted-string ) - - The meanings of the values of the directives used above are as - follows: - - realm - Mechanistically, a string which can enable users to know which - username and password to use, in case they might have different - ones for different servers. Conceptually, it is the name of a - collection of accounts that might include the user's account. This - string should contain at least the name of the host performing the - authentication and might additionally indicate the collection of - users who might have access. An example might be - "registered_users@gotham.news.example.com". This directive is - optional; if not present, the client SHOULD solicit it from the - user or be able to compute a default; a plausible default might be - the realm supplied by the user when they logged in to the client - system. Multiple realm directives are allowed, in which case the - user or client must choose one as the realm for which to supply to - username and password. - - If at least one realm is present and the charset directive is also - specified (which means that realm(s) are encoded as UTF-8), the - client should prepare each instance of realm using the "SASLPrep" - profile [SASLPrep] of the "stringprep" algorithm [StringPrep]. If - preparation of a realm instance fails or results in an empty - string, the client should abort the authentication exchange. - - - - -Leach & Newman Expires: December 2003 [Page 6] - - - - - -INTERNET DRAFT Digest SASL Mechanism June 2003 - - - nonce - A server-specified data string which MUST be different each time a - digest-challenge is sent as part of initial authentication. It is - recommended that this string be base64 or hexadecimal data. Note - that since the string is passed as a quoted string, the - double-quote character is not allowed unless escaped (see section - 7.2). The contents of the nonce are implementation dependent. The - security of the implementation depends on a good choice. It is - RECOMMENDED that it contain at least 64 bits of entropy. The nonce - is opaque to the client. This directive is required and MUST - appear exactly once; if not present, or if multiple instances are - present, the client should abort the authentication exchange. - - qop-options - A quoted string of one or more tokens indicating the "quality of - protection" values supported by the server. The value "auth" - indicates authentication; the value "auth-int" indicates - authentication with integrity protection; the value "auth-conf" - indicates authentication with integrity protection and encryption. - This directive is optional; if not present it defaults to "auth". - The client MUST ignore unrecognized options; if the client - recognizes no option, it should abort the authentication exchange. - - stale - The "stale" directive is not used in initial authentication. See - the next section for its use in subsequent authentications. This - directive may appear at most once; if multiple instances are - present, the client should abort the authentication exchange. - - server_maxbuf ("maximal ciphertext buffer size") - A number indicating the size of the largest buffer the server is - able to receive when using "auth-int" or "auth-conf". The value - MUST be bigger than 16 and smaller or equal to 16777215 (i.e. - 2**24-1). If this directive is missing, the default value is - 65536. This directive may appear at most once; if multiple - instances are present, the client MUST abort the authentication - exchange. - - Let call "maximal cleartext buffer size" (or "maximal sender - size") the maximal size of a cleartext buffer that, after being - transformed by integrity (section 2.3) or confidentiality (section - 2.4) protection function, will produce a SASL block of the maxbuf - size. As it should be clear from the name, the sender MUST never - pass a block of data bigger than the "maximal sender size" through - the selected protection function. This will guaranty that the - receiver will never get a block bigger than the maxbuf. - - - - - -Leach & Newman Expires: December 2003 [Page 7] - - - - - -INTERNET DRAFT Digest SASL Mechanism June 2003 - - - charset - This directive, if present, specifies that the server supports - UTF-8 [UTF-8] encoding for the username, realm and password. If - present, the username, realm and password are in Unicode, prepared - using the "SASLPrep" profile [SASLPrep] of the "stringprep" - algorithm [StringPrep] and than encoded as UTF-8 [UTF-8]. If not - present, the username, realm and password MUST be encoded in ISO - 8859-1 [ISO-8859] (of which US-ASCII [USASCII] is a subset). The - directive is needed for backwards compatibility with HTTP Digest, - which only supports ISO 8859-1. This directive may appear at most - once; if multiple instances are present, the client should abort - the authentication exchange. - - Note, that this directive doesn't affect authorization id - ("authzid"). - - algorithm - This directive is required for backwards compatibility with HTTP - Digest, which supports other algorithms. This directive is - required and MUST appear exactly once; if not present, or if - multiple instances are present, the client should abort the - authentication exchange. - - cipher-opts - A list of ciphers that the server supports. This directive must be - present exactly once if "auth-conf" is offered in the - "qop-options" directive, in which case the "3des" cipher is - mandatory-to-implement. The client MUST ignore unrecognized - options; if the client recognizes no option, it should abort the - authentication exchange. See section 2.4 for more detailed - description of the ciphers. - - des - the Data Encryption Standard (DES) cipher [FIPS] in cipher - block chaining (CBC) mode with a 56 bit key. - - 3des - the "triple DES" cipher in CBC mode with EDE - (Encrypt,Decrypt,Encrypt) with the same key for each E stage - (aka "two keys mode") for a total key length of 112 bits. - - rc4, rc4-40, rc4-56 - the RC4 cipher with a 128 bit, 40 bit, and 56 bit key, - respectively. - - aes - the Advanced Encryption Standard (AES) cipher [AES] in cipher - block chaining (CBC) mode with a 128 bit key. This mode - - - -Leach & Newman Expires: December 2003 [Page 8] - - - - - -INTERNET DRAFT Digest SASL Mechanism June 2003 - - - requires an Initialization Vector (IV) that has the same size - as the block size. - - auth-param - This construct allows for future extensions; it may appear more - than once. The client MUST ignore any unrecognized directives. - - For use as a SASL mechanism, note that the following changes are made - to "digest-challenge" from HTTP: the following Digest options (called - "directives" in HTTP terminology) are unused (i.e., MUST NOT be sent, - and MUST be ignored if received): - - opaque - domain - - The size of a digest-challenge MUST be less than 2048 bytes. - -2.1.2 Step Two - - The client makes note of the "digest-challenge" and then responds - with a string formatted and computed according to the rules for a - "digest-response" defined as follows: - - digest-response = 1#( username | realm | nonce | cnonce | - nonce-count | qop | digest-uri | response | - client_maxbuf | charset | cipher | authzid | - auth-param ) - - username = "username" "=" <"> username-value <"> - username-value = qdstr-val - cnonce = "cnonce" "=" <"> cnonce-value <"> - cnonce-value = *qdtext - nonce-count = "nc" "=" nc-value - nc-value = 8LHEX - client_maxbuf = "maxbuf" "=" maxbuf-value - qop = "qop" "=" qop-value - digest-uri = "digest-uri" "=" <"> digest-uri-value <"> - digest-uri-value = serv-type "/" host [ "/" serv-name ] - serv-type = 1*ALPHA - serv-name = host - response = "response" "=" response-value - response-value = 32LHEX - LHEX = "0" | "1" | "2" | "3" | - "4" | "5" | "6" | "7" | - "8" | "9" | "a" | "b" | - "c" | "d" | "e" | "f" - cipher = "cipher" "=" cipher-value - authzid = "authzid" "=" <"> authzid-value <"> - - - -Leach & Newman Expires: December 2003 [Page 9] - - - - - -INTERNET DRAFT Digest SASL Mechanism June 2003 - - - authzid-value = qdstr-val - - The 'host' non-terminal is defined in [RFC 2732] as - - host = hostname | IPv4address | IPv6reference - ipv6reference = "[" IPv6address "]" - - where IPv6address and IPv4address are defined in [RFC 2373] - and 'hostname' is defined in [RFC 2396]. - - username - The user's name in the specified realm, encoded according to the - value of the "charset" directive. This directive is required and - MUST be present exactly once; otherwise, authentication fails. - - Upon the receipt of this value and if the charset directive is - also specified (which means that the username is encoded as - UTF-8), the server MUST prepare the username using the "SASLPrep" - profile [SASLPrep] of the "stringprep" algorithm [StringPrep]. If - preparation of the username fails or results in an empty string, - the server MUST fail the authentication exchange. - - realm - The realm containing the user's account, encoded according to the - value of the "charset" directive. This directive is required if - the server provided any realms in the - "digest-challenge", in which case it may appear exactly once and - its value SHOULD be one of those realms. If the directive is - missing, "realm-value" will set to the empty string when computing - A1 (see below for details). - - If realm was provided by the client and if the charset directive - was also specified (which means that the realm is encoded as - UTF-8), the server MUST prepare the realm using the "SASLPrep" - profile [SASLPrep] of the "stringprep" algorithm [StringPrep]. If - preparation of the realm fails or results in an empty string, the - server MUST fail the authentication exchange. - - nonce - The server-specified data string received in the preceding digest- - challenge. This directive is required and MUST be present exactly - once; otherwise, authentication fails. - - - - - - - - - -Leach & Newman Expires: December 2003 [Page 10] - - - - - -INTERNET DRAFT Digest SASL Mechanism June 2003 - - - cnonce - A client-specified data string which MUST be different each time a - digest-response is sent as part of initial authentication. The - cnonce-value is an opaque quoted string value provided by the - client and used by both client and server to avoid chosen - plaintext attacks, and to provide mutual authentication. The - security of the implementation depends on a good choice. It is - RECOMMENDED that it contain at least 64 bits of entropy. This - directive is required and MUST be present exactly once; otherwise, - authentication fails. - - nonce-count - The nc-value is the hexadecimal count of the number of requests - (including the current request) that the client has sent with the - nonce value in this request. For example, in the first request - sent in response to a given nonce value, the client sends - "nc=00000001". The purpose of this directive is to allow the - server to detect request replays by maintaining its own copy of - this count - if the same nc-value is seen twice, then the request - is a replay. See the description below of the construction of the - response value. This directive is required and MUST be present - exactly once; otherwise, authentication fails. - - qop - Indicates what "quality of protection" the client accepted. If - present, it may appear exactly once and its value MUST be one of - the alternatives in qop-options. If not present, it defaults to - "auth". These values affect the computation of the response. Note - that this is a single token, not a quoted list of alternatives. - - serv-type - Indicates the type of service, such as "http" for web service, - "ftp" for FTP service, "smtp" for mail delivery service, etc. The - service name as defined in the SASL profile for the protocol see - section 4 of [RFC 2222], registered in the IANA registry of - "service" elements for the GSSAPI host-based service name form - [RFC 2078]. - - host - The DNS host name or IP (IPv4 or IPv6) address for the service - requested. The DNS host name must be the fully-qualified - canonical name of the host. The DNS host name is the preferred - form; see notes on server processing of the digest-uri. - - - - - - - - -Leach & Newman Expires: December 2003 [Page 11] - - - - - -INTERNET DRAFT Digest SASL Mechanism June 2003 - - - serv-name - Indicates the name of the service if it is replicated. The service - is considered to be replicated if the client's service-location - process involves resolution using standard DNS lookup operations, - and if these operations involve DNS records (such as SRV [RFC - 2052], or MX) which resolve one DNS name into a set of other DNS - names. In this case, the initial name used by the client is the - "serv-name", and the final name is the "host" component. For - example, the incoming mail service for "example.com" may be - replicated through the use of MX records stored in the DNS, one of - which points at an SMTP server called "mail3.example.com"; it's - "serv-name" would be "example.com", it's "host" would be - "mail3.example.com". If the service is not replicated, or the - serv-name is identical to the host, then the serv-name component - MUST be omitted. - - digest-uri - Indicates the principal name of the service with which the client - wishes to connect, formed from the serv-type, host, and serv-name. - For example, the FTP service on "ftp.example.com" would have a - "digest-uri" value of "ftp/ftp.example.com"; the SMTP server from - the example above would have a "digest-uri" value of - "SMTP/mail3.example.com/example.com". - - Servers SHOULD check that the supplied value is correct. This will - detect accidental connection to the incorrect server, as well as some - redirection attacks. It is also so that clients will be trained to - provide values that will work with implementations that use a shared - back-end authentication service that can provide server - authentication. - - The serv-type component should match the service being offered. The - host component should match one of the host names of the host on - which the service is running, or it's IP address. Servers SHOULD NOT - normally support the IP address form, because server authentication - by IP address is not very useful; they should only do so if the DNS - is unavailable or unreliable. The serv-name component should match - one of the service's configured service names. - - This directive may appear at most once; if multiple instances are - present, the client should abort the authentication exchange. - - Note: In the HTTP use of Digest authentication, the digest-uri is the - URI (usually a URL) of the resource requested -- hence the name of - the directive. - - - - - - -Leach & Newman Expires: December 2003 [Page 12] - - - - - -INTERNET DRAFT Digest SASL Mechanism June 2003 - - - response - A string of 32 hex digits computed as defined below, which proves - that the user knows a password. This directive is required and - MUST be present exactly once; otherwise, authentication fails. - - client_maxbuf - A number indicating the size of the largest ciphertext buffer the - client is able to receive when using "auth-int" or "auth-conf". If - this directive is missing, the default value is 65536. This - directive may appear at most once; if multiple instances are - present, the server MUST abort the authentication exchange. If the - value is less or equal to 16 or bigger than 16777215 (i.e. - 2**24-1), the server MUST abort the authentication exchange. - - Upon processing/sending of the client_maxbuf value both the server - and the client calculate their "maximal ciphertext buffer size" as - the minimum of the server_maxbuf (Step One) and the client_maxbuf - (Step Two). The "maximal sender size" can be calculated by - subtracting 16 from the calculated "maximal ciphertext buffer - size". - - When sending a block of data the client/server MUST NOT pass more - than the "maximal sender size" bytes of data to the selected - protection function (2.3 or 2.4). - - charset - This directive, if present, specifies that the client has used - UTF-8 [UTF-8] encoding for the username, realm and password. If - present, the username, realm and password are in Unicode, prepared - using the "SASLPrep" profile [SASLPrep] of the "stringprep" - algorithm [StringPrep] and than encoded as UTF-8 [UTF-8]. If not - present, the username and password must be encoded in ISO 8859-1 - [ISO-8859] (of which - US-ASCII [USASCII] is a subset). The client should send this - directive only if the server has indicated it supports UTF-8 - [UTF-8]. The directive is needed for backwards compatibility with - HTTP Digest, which only supports ISO 8859-1. - - Note, that this directive doesn't affect authorization id - ("authzid"). - - LHEX - 32 hex digits, where the alphabetic characters MUST be lower case, - because MD5 is not case insensitive. - - cipher - The cipher chosen by the client. This directive MUST appear - exactly once if "auth-conf" is negotiated; if required and not - - - -Leach & Newman Expires: December 2003 [Page 13] - - - - - -INTERNET DRAFT Digest SASL Mechanism June 2003 - - - present, authentication fails. - - authzid - The "authorization ID" directive is optional. If present, and the - authenticating user has sufficient privilege, and the server - supports it, then after authentication the server will use this - identity for making all accesses and access checks. If the client - specifies it, and the server does not support it, then the - response-value calculated on the server will not match the one - calculated on the client and authentication will fail. - - The authzid MUST NOT be an empty string. - - The authorization identifier MUST NOT be converted to ISO 8859-1 - even if the authentication identifier ("username") is converted - for compatibility as directed by "charset" directive. - - The server SHOULD verify the correctness of an authzid as - specified by the corresponding SASL protocol profile. - - The size of a digest-response MUST be less than 4096 bytes. - -2.1.2.1 Response-value - - The definition of "response-value" above indicates the encoding for - its value -- 32 lower case hex characters. The following definitions - show how the value is computed. - - Although qop-value and components of digest-uri-value may be - case-insensitive, the case which the client supplies in step two is - preserved for the purpose of computing and verifying the - response-value. - - response-value = - HEX( KD ( HEX(H(A1)), - { nonce-value, ":" nc-value, ":", - cnonce-value, ":", qop-value, ":", HEX(H(A2)) })) - - If authzid is specified, then A1 is - - - A1 = { H( { unq(username-value), ":", unq(realm-value), ":", passwd } ), - ":", nonce-value, ":", cnonce-value, ":", unq(authzid-value) } - - If authzid is not specified, then A1 is - - - A1 = { H( { unq(username-value), ":", unq(realm-value), ":", passwd } ), - - - -Leach & Newman Expires: December 2003 [Page 14] - - - - - -INTERNET DRAFT Digest SASL Mechanism June 2003 - - - ":", nonce-value, ":", cnonce-value } - - where - - passwd = *OCTET - - The "username-value", "realm-value" and "passwd" are encoded - according to the value of the "charset" directive. If "charset=UTF-8" - is present, and all the characters of "username-value" are, after - preparing using the "SASLPrep" profile [SASLPrep] of the "stringprep" - algorithm [StringPrep], in the ISO 8859-1 character set, then it must - be converted to ISO 8859-1 before being hashed. The same - transformation has to be done for "realm-value" and "passwd". This is - so that authentication databases that store the hashed username, - realm and password (which is common) can be shared compatibly with - HTTP, which specifies ISO 8859-1. A sample implementation of this - conversion is in section 8. - - If the "qop" directive's value is "auth", then A2 is: - - A2 = { "AUTHENTICATE:", digest-uri-value } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Leach & Newman Expires: December 2003 [Page 15] - - - - - -INTERNET DRAFT Digest SASL Mechanism June 2003 - - - If the "qop" value is "auth-int" or "auth-conf" then A2 is: - - A2 = { "AUTHENTICATE:", digest-uri-value, - ":00000000000000000000000000000000" } - - Note that "AUTHENTICATE:" must be in upper case, and the second - string constant is a string with a colon followed by 32 zeros. - - These apparently strange values of A2 are for compatibility with - HTTP; they were arrived at by setting "Method" to "AUTHENTICATE" and - the hash of the entity body to zero in the HTTP digest calculation of - A2. - - Also, in the HTTP usage of Digest, several directives in the - "digest-challenge" sent by the server have to be returned by the - client in the "digest-response". These are: - - opaque - algorithm - - These directives are not needed when Digest is used as a SASL - mechanism (i.e., MUST NOT be sent, and MUST be ignored if received). - -2.1.3 Step Three - - The server receives and validates the "digest-response". The server - checks that the nonce-count is "00000001". If it supports subsequent - authentication (see section 2.2), it saves the value of the nonce and - the nonce-count. It sends a message formatted as follows: - - response-auth = "rspauth" "=" response-value - - where response-value is calculated as above, using the values sent in - step two, except that if qop is "auth", then A2 is - - A2 = { ":", digest-uri-value } - - And if qop is "auth-int" or "auth-conf" then A2 is - - A2 = { ":", digest-uri-value, ":00000000000000000000000000000000" } - - Compared to its use in HTTP, the following Digest directives in the - "digest-response" are unused: - - nextnonce - qop - cnonce - nonce-count - - - -Leach & Newman Expires: December 2003 [Page 16] - - - - - -INTERNET DRAFT Digest SASL Mechanism June 2003 - - -2.2 Subsequent Authentication - - If the client has previously authenticated to the server, and - remembers the values of username, realm, nonce, nonce-count, cnonce, - and qop that it used in that authentication, and the SASL profile for - a protocol permits an initial client response, then it MAY perform - "subsequent authentication", as defined in this section. - -2.2.1 Step one - - The client uses the values from the previous authentication and sends - an initial response with a string formatted and computed according to - the rules for a "digest-response", as defined above, but with a - nonce-count one greater than used in the last "digest-response". - -2.2.2 Step Two - - The server receives the "digest-response". If the server does not - support subsequent authentication, then it sends a - "digest-challenge", and authentication proceeds as in initial - authentication. If the server has no saved nonce and nonce-count from - a previous authentication, then it sends a "digest-challenge", and - authentication proceeds as in initial authentication. Otherwise, the - server validates the "digest-response", checks that the nonce-count - is one greater than that used in the previous authentication using - that nonce, and saves the new value of nonce-count. - - If the response is invalid, then the server sends a - "digest-challenge", and authentication proceeds as in initial - authentication (and should be configurable to log an authentication - failure in some sort of security audit log, since the failure may be - a symptom of an attack). The nonce-count MUST NOT be incremented in - this case: to do so would allow a denial of service attack by sending - an out-of-order nonce-count. - - If the response is valid, the server MAY choose to deem that - authentication has succeeded. However, if it has been too long since - the previous authentication, or for any o including the next - subsequent authentication, between the client and the server MUST be - integrity protected. Using as a base session key the value of H(A1) - as defined above the client and server calculate a pair of message - integrity keys as follows. - - The key for integrity protecting messages from client to server is: - - Kic = MD5({H(A1), - "Digest session key to client-to-server signing key magic constant"}) - - - - -Leach & Newman Expires: December 2003 [Page 17] - - - - - -INTERNET DRAFT Digest SASL Mechanism June 2003 - - - The key for integrity protecting messages from server to client is: - - Kis = MD5({H(A1), - "Digest session key to server-to-client signing key magic constant"}) - - where MD5 is as specified in [RFC 1321]. If message integrity is - negotiated, a MAC block for each message is appended to the message. - The MAC block is 16 bytes: the first 10 bytes of the HMAC-MD5 [RFC - 2104] of the message, a 2-byte message type number in network byte - order with value 1, and the 4-byte sequence number in network byte - order. The message type is to allow for future extensions such as - rekeying. - - MAC(Ki, SeqNum, msg) = (HMAC(Ki, {SeqNum, msg})[0..9], 0x0001, - SeqNum) - - where Ki is Kic for messages sent by the client and Kis for those - sent by the server. The sequence number (SeqNum) is an unsigned - number initialized to zero after initial or subsequent - authentication, and incremented by one for each message - sent/successfully verified. (Note, that there are two independent - counters for sending and receiving.) The sequence number wraps around - to 0 after 2**32-1. - - Upon receipt, MAC(Ki, SeqNum, msg) is computed and compared with the - received value; the message is discarded if they differ. The - receiver's sequence counter is incremented if they match. - -2.4 Confidentiality Protection - - If the server sent a "cipher-opts" directive and the client responded - with a "cipher" directive, then subsequent messages between the - client and the server MUST be confidentiality protected. Using as a - base session key the value of H(A1) as defined above the client and - server calculate a pair of message integrity keys as follows. - - The key for confidentiality protecting messages from client to server - is: - - Kcc = MD5({H(A1)[0..n-1], - "Digest H(A1) to client-to-server sealing key magic constant"}) - - The key for confidentiality protecting messages from server to client - is: - - Kcs = MD5({H(A1)[0..n-1], - "Digest H(A1) to server-to-client sealing key magic constant"}) - - - - -Leach & Newman Expires: December 2003 [Page 18] - - - - - -INTERNET DRAFT Digest SASL Mechanism June 2003 - - - where MD5 is as specified in [RFC 1321]. For cipher "rc4-40" n is 5; - for "rc4-56" n is 7; for the rest n is 16. The key for the "rc4-*" - and "aes" ciphers is all 16 bytes of Kcc or Kcs; the key for "des" is - the first 7 bytes; the key for "3des" is the first 14 bytes. - - The IV used to send/receive the initial buffer of security encoded - data for "des" and "3des" is the last 8 bytes of Kcc or Kcs. For all - subsequent buffers the last 8 bytes of the ciphertext of the buffer - NNN is used as the IV for the buffer (NNN + 1). - - The IV for the "aes" cipher in CBC mode for messages going from the - client to the server (IVc) consists of 16 bytes calculated as - follows: - - IVc = MD5({Kcc, "aes-128"}) - - The IV for the "aes" cipher in CBC mode for messages going from the - server to the client (IVs) consists of 16 bytes calculated as - follows: - - IVs = MD5({Kcs, "aes-128"}) - - The IV is XOR'd with the first plaintext block before it is encrypted - with "aes". Then for successive blocks, the previous ciphertext - block is XOR'd with the current plaintext, before it is encrypted. - - rc4 cipher state MUST NOT be reset before sending/receiving a next - buffer of security encoded data. - - The MAC block is a variable length padding prefix followed by 16 - bytes formatted as follows: the first 10 bytes of the HMAC-MD5 [RFC - 2104] of the message, a 2-byte message type number in network byte - order with value 1, and the 4-byte sequence number in network byte - order. If the blocksize of the chosen cipher is not 1 byte, the - padding prefix is one or more octets each containing the number of - padding bytes, such that total length of the encrypted part of the - message is a multiple of the blocksize. The padding and first 10 - bytes of the MAC block are encrypted with the chosen cipher along - with the message. - - SEAL(Ki, Kc, SeqNum, msg) = - {CIPHER(Kc, {msg, pad, HMAC(Ki, {SeqNum, msg})[0..9]}), 0x0001, - SeqNum} - - where CIPHER is the chosen cipher, Ki and Kc are Kic and Kcc for - messages sent by the client and Kis and Kcs for those sent by the - server. The sequence number (SeqNum) is an unsigned number - initialized to zero after initial or subsequent authentication, and - - - -Leach & Newman Expires: December 2003 [Page 19] - - - - - -INTERNET DRAFT Digest SASL Mechanism June 2003 - - - incremented by one for each message sent/successfully verified. - (Note, that there are two independent counters for sending and - receiving.) The sequence number wraps around to 0 after 2**32-1. - - Upon receipt, the message is decrypted, HMAC(Ki, {SeqNum, msg}) is - computed and compared with the received value; the padding is - verified. The message is discarded if the received and the - calculated HMACs differ and/or the padding is invalid. See also - section 3.8 for important information about MAC and padding - verification. The receiver's sequence counter is then compared with - the received SeqNum value; the message is discarded if they differ. - The receiver's sequence counter is incremented if they match. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Leach & Newman Expires: December 2003 [Page 20] - - - - - -INTERNET DRAFT Digest SASL Mechanism June 2003 - - -3 Security Considerations - - General SASL security considerations apply to this mechanism. - "stringprep" and Unicode security considerations also apply. - - Detailed discussion of other DIGEST-MD5 specific security issues is - below. - -3.1 Authentication of Clients using Digest Authentication - - Digest Authentication does not provide a strong authentication - mechanism, when compared to public key based mechanisms, for example. - However, since it prevents chosen plaintext attacks, it is stronger - than (e.g.) CRAM-MD5, which has been proposed for use with ACAP [RFC - 2244], POP and IMAP [RFC 2195]. It is intended to replace the much - weaker and even more dangerous use of plaintext passwords; however, - since it is still a password based mechanism it avoids some of the - potential deployabilty issues with public-key, OTP or similar - mechanisms. - - Digest Authentication offers no confidentiality protection beyond - protecting the actual password. All of the rest of the challenge and - response are available to an eavesdropper, including the user's name - and authentication realm. - -3.2 Comparison of Digest with Plaintext Passwords - - The greatest threat to the type of transactions for which these - protocols are used is network snooping. This kind of transaction - might involve, for example, online access to a mail service whose use - is restricted to paying subscribers. With plaintext password - authentication an eavesdropper can obtain the password of the user. - This not only permits him to access anything in the database, but, - often worse, will permit access to anything else the user protects - with the same password. - -3.3 Replay Attacks - - Replay attacks are defeated if the client or the server chooses a - fresh nonce for each authentication, as this specification requires. - - As a security precaution, the server, when verifying a response from - the client, must use the original server nonce ("nonce") it sent, not - the one returned by the client in the response, as it might have been - modified by an attacker. - - To prevent some redirection attacks it is recommended that the server - verifies that the "serv-type" part of the "digest-uri" matches the - - - -Leach & Newman Expires: December 2003 [Page 21] - - - - - -INTERNET DRAFT Digest SASL Mechanism June 2003 - - - service name and that the hostname/IP address belongs to the server. - -3.4 Online dictionary attacks - - If the attacker can eavesdrop, then it can test any overheard - nonce/response pairs against a (potentially very large) list of - common words. Such a list is usually much smaller than the total - number of possible passwords. The cost of computing the response for - each password on the list is paid once for each challenge. - - The server can mitigate this attack by not allowing users to select - passwords that are in a dictionary. - -3.5 Offline dictionary attacks - - If the attacker can choose the challenge, then it can precompute the - possible responses to that challenge for a list of common words. Such - a list is usually much smaller than the total number of possible - passwords. The cost of computing the response for each password on - the list is paid just once. - - Offline dictionary attacks are defeated if the client chooses a fresh - nonce for each authentication, as this specification requires. - -3.6 Man in the Middle - - Digest authentication is vulnerable to "man in the middle" (MITM) - attacks. Clearly, a MITM would present all the problems of - eavesdropping. But it also offers some additional opportunities to - the attacker. - - A possible man-in-the-middle attack would be to substitute a weaker - qop scheme for the one(s) sent by the server; the server will not be - able to detect this attack. For this reason, the client should always - use the strongest scheme that it understands from the choices - offered, and should never choose a scheme that does not meet its - minimum requirements. - - A man-in-the-middle attack may also make the client and the server - that agreed to use confidentiality protection to use different (and - possibly weaker) cipher's. This is because the chosen cipher is not - used in the shared secret calculation. - -3.7 Chosen plaintext attacks - - A chosen plaintext attack is where a MITM or a malicious server can - arbitrarily choose the challenge that the client will use to compute - the response. The ability to choose the challenge is known to make - - - -Leach & Newman Expires: December 2003 [Page 22] - - - - - -INTERNET DRAFT Digest SASL Mechanism June 2003 - - - cryptanalysis much easier [MD5]. - - However, Digest does not permit the attack to choose the challenge as - long as the client chooses a fresh nonce for each authentication, as - this specification requires. - -3.8 CBC Mode attacks - - The following attack can be launched when the connection uses - Confidentiality protection with ciphers in CBC mode. If bad padding - is treated differently from bad MACs when decrypting a DIGEST-MD5 - buffer of security encoded data, the attacker may be able to launch - Vaudenay's attack on padding. - - An error logfile will suffice to launch the attack if it reveals the - type of error -- even if file permissions prevent the attacker from - actually reading the file (the file length increase cause by the - attack is likely to reveal which of the two errors occured). - - A different approach to distinguish these two error cases and launch - the attack is to examine the timing of error responses: if the MAC - verification is skipped when bad padding has been found, the error - will appear quicker in the case of incorrect block cipher padding - than in the case of an incorrect MAC. - - A countermeasure is to compute a MAC of the plaintext anyway, even if - the usual padding removal step fails because of incorrect padding, to - obtain (nearly) uniform timing. - -3.9 Spoofing by Counterfeit Servers - - If a user can be led to believe that she is connecting to a host - containing information protected by a password she knows, when in - fact she is connecting to a hostile server, then the hostile server - can obtain challenge/response pairs where it was able to partly - choose the challenge. There is no known way that this can be - exploited. - -3.10 Storing passwords - - Digest authentication requires that the authenticating agent (usually - the server) store some data derived from the user's name and password - in a "password file" associated with a given realm. Normally this - might contain pairs consisting of username and H({ username-value, - ":", realm-value, ":", passwd }), which is adequate to compute H(A1) - as described above without directly exposing the user's password. - - The security implications of this are that if this password file is - - - -Leach & Newman Expires: December 2003 [Page 23] - - - - - -INTERNET DRAFT Digest SASL Mechanism June 2003 - - - compromised, then an attacker gains immediate access to documents on - the server using this realm. Unlike, say a standard UNIX password - file, this information need not be decrypted in order to access - documents in the server realm associated with this file. On the other - hand, decryption, or more likely a brute force attack, would be - necessary to obtain the user's password. This is the reason that the - realm is part of the digested data stored in the password file. It - means that if one Digest authentication password file is compromised, - it does not automatically compromise others with the same username - and password (though it does expose them to brute force attack). - - There are two important security consequences of this. First the - password file must be protected as if it contained plaintext - passwords, because for the purpose of accessing documents in its - realm, it effectively does. - - A second consequence of this is that the realm string should be - unique among all realms that any single user is likely to use. In - particular a realm string should include the name of the host doing - the authentication. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Leach & Newman Expires: December 2003 [Page 24] - - - - - -INTERNET DRAFT Digest SASL Mechanism June 2003 - - -3.11 Multiple realms - - Use of multiple realms may mean both that compromise of a the - security database for a single realm does not compromise all - security, and that there are more things to protect in order to keep - the whole system secure. - -3.11 Summary - - By modern cryptographic standards Digest Authentication is weak, - compared to (say) public key based mechanisms. But for a large range - of purposes it is valuable as a replacement for plaintext passwords. - Its strength may vary depending on the implementation. - - -4 Example - - This example shows the use of the Digest SASL mechanism with the - IMAP4 AUTHENTICATE command [RFC 3501]. - - In this example, "C:" and "S:" represent a line sent by the client or - server respectively including a CRLF at the end. Linebreaks and - indentation within a "C:" or "S:" are editorial and not part of the - protocol. The password in this example was "secret". Note that the - base64 encoding of the challenges and responses is part of the IMAP4 - AUTHENTICATE command, not part of the Digest specification itself. - - S: * OK elwood.innosoft.com PMDF IMAP4rev1 V6.0-9 - C: c CAPABILITY - S: * CAPABILITY IMAP4 IMAP4rev1 ACL LITERAL+ NAMESPACE QUOTA - UIDPLUS AUTH=CRAM-MD5 AUTH=DIGEST-MD5 AUTH=PLAIN - S: c OK Completed - C: a AUTHENTICATE DIGEST-MD5 - S: + cmVhbG09ImVsd29vZC5pbm5vc29mdC5jb20iLG5vbmNlPSJPQTZNRzl0 - RVFHbTJoaCIscW9wPSJhdXRoIixhbGdvcml0aG09bWQ1LXNlc3MsY2hh - cnNldD11dGYtOA== - C: Y2hhcnNldD11dGYtOCx1c2VybmFtZT0iY2hyaXMiLHJlYWxtPSJlbHdvb2 - QuaW5ub3NvZnQuY29tIixub25jZT0iT0E2TUc5dEVRR20yaGgiLG5jPTAw - MDAwMDAxLGNub25jZT0iT0E2TUhYaDZWcVRyUmsiLGRpZ2VzdC11cmk9Im - ltYXAvZWx3b29kLmlubm9zb2Z0LmNvbSIscmVzcG9uc2U9ZDM4OGRhZDkw - ZDRiYmQ3NjBhMTUyMzIxZjIxNDNhZjcscW9wPWF1dGg= - S: + cnNwYXV0aD1lYTQwZjYwMzM1YzQyN2I1NTI3Yjg0ZGJhYmNkZmZmZA== - C: - S: a OK User logged in - --- - - The base64-decoded version of the SASL exchange is: - - - - -Leach & Newman Expires: December 2003 [Page 25] - - - - - -INTERNET DRAFT Digest SASL Mechanism June 2003 - - - S: realm="elwood.innosoft.com",nonce="OA6MG9tEQGm2hh",qop="auth", - algorithm=md5-sess,charset=utf-8 - C: charset=utf-8,username="chris",realm="elwood.innosoft.com", - nonce="OA6MG9tEQGm2hh",nc=00000001,cnonce="OA6MHXh6VqTrRk", - digest-uri="imap/elwood.innosoft.com", - response=d388dad90d4bbd760a152321f2143af7,qop=auth - S: rspauth=ea40f60335c427b5527b84dbabcdfffd - - The password in this example was "secret". - - This example shows the use of the Digest SASL mechanism with the - ACAP, using the same notational conventions and password as in the - previous example. Note that ACAP does not base64 encode and uses - fewer round trips that IMAP4. - - S: * ACAP (IMPLEMENTATION "Test ACAP server") (SASL "CRAM-MD5" - "DIGEST-MD5" "PLAIN") - C: a AUTHENTICATE "DIGEST-MD5" - S: + {94} - S: realm="elwood.innosoft.com",nonce="OA9BSXrbuRhWay",qop="auth", - algorithm=md5-sess,charset=utf-8 - C: {206} - C: charset=utf-8,username="chris",realm="elwood.innosoft.com", - nonce="OA9BSXrbuRhWay",nc=00000001,cnonce="OA9BSuZWMSpW8m", - digest-uri="acap/elwood.innosoft.com", - response=6084c6db3fede7352c551284490fd0fc,qop=auth - S: a OK (SASL {40} - S: rspauth=2f0b3d7c3c2e486600ef710726aa2eae) "AUTHENTICATE - Completed" - --- - - The server uses the values of all the directives, plus knowledge of - the users password (or the hash of the user's name, server's realm - and the user's password) to verify the computations above. If they - check, then the user has authenticated. - - - - - - - - - - - - - - - - -Leach & Newman Expires: December 2003 [Page 26] - - - - - -INTERNET DRAFT Digest SASL Mechanism June 2003 - - -5 References - -5.1 Normative references - - [Digest] Franks, J., et al., "HTTP Authentication: Basic and Digest - Access Authentication", RFC 2617, June 1999. - - [ISO-8859] ISO-8859. International Standard--Information Processing-- - 8-bit Single-Byte Coded Graphic Character Sets -- - Part 1: Latin alphabet No. 1, ISO-8859-1:1987. - Part 2: Latin alphabet No. 2, ISO-8859-2, 1987. - Part 3: Latin alphabet No. 3, ISO-8859-3, 1988. - Part 4: Latin alphabet No. 4, ISO-8859-4, 1988. - Part 5: Latin/Cyrillic alphabet, ISO-8859-5, 1988. - Part 6: Latin/Arabic alphabet, ISO-8859-6, 1987. - Part 7: Latin/Greek alphabet, ISO-8859-7, 1987. - Part 8: Latin/Hebrew alphabet, ISO-8859-8, 1988. - Part 9: Latin alphabet No. 5, ISO-8859-9, 1990. - - [RFC 822] Crocker, D., "Standard for The Format of ARPA Internet - Text Messages," STD 11, RFC 822, August 1982. - - [RFC 1321] Rivest, R., "The MD5 Message-Digest Algorithm", RFC 1321, - April 1992. - - [RFC 2052] Gulbrandsen, A. and P. Vixie, "A DNS RR for specifying the - location of services (DNS SRV)", RFC 2052, October 1996. - - [RFC 2104] Krawczyk, H., Bellare, M. and R. Canetti, "HMAC: Keyed- - Hashing for Message Authentication", RFC 2104, February - 1997. - - [RFC 2119] Bradner, S., "Key words for use in RFCs to Indicate - Requirement Levels", BCP 14, RFC 2119, March 1997. - - [RFC 2222] Myers, J., "Simple Authentication and Security Layer - (SASL)", RFC 2222, October 1997. - - [Stringprep] Hoffman, P., Blanchet, M., "Preparation of - Internationalized Strings ("stringprep")", RFC 3454, - December 2002. - - [Unicode] The Unicode Consortium, "The Unicode Standard, Version - 3.2.0", defined by: The Unicode Standard, Version 3.0 - (Reading, MA, Addison-Wesley, 2000. ISBN 0-201-61633-5), - as amended by the Unicode Standard Annex #28: Unicode 3.2 - (http://www.unicode.org/reports/tr28/tr28-3.html). - - - - -Leach & Newman Expires: December 2003 [Page 27] - - - - - -INTERNET DRAFT Digest SASL Mechanism June 2003 - - - [UTF-8] Yergeau, "UTF-8, a transformation format of ISO 10646", RFC - 2279, Janyary 1998. - - [USASCII] US-ASCII. Coded Character Set - 7-Bit American Standard - Code for Information Interchange. Standard ANSI X3.4-1986, - ANSI, 1986. - - [SASLPrep] Zeilenga, K., "SASLprep: Stringprep profile for user names - and passwords", Work in progress, draft-ietf-sasl- - saslprep-XX.txt. - - [RFC 2732] Hinden, R., Carpenter, B., Masinter, L., "Format for - Literal IPv6 Addresses in URL's", RFC 2732, December 1999. - - [RFC 2373] Hinden, R., Deering, S., "IP Version 6 Addressing - Architecture", RFC 2373, July 1998. - - [RFC 2396] Berners-Lee, T., Fielding, R., Masinter, L., "Uniform - Resource Identifiers (URI): Generic Syntax", RFC 2396, - August 1998. - - [FIPS] National Institute of Standards and Technology, "DES Modes of - Operation", http://www.itl.nist.gov/fipspubs/fip81.htm, - December 1980. - - [AES] Daemen, J., Rijmen, V., "The Rijndael Block Cipher", - http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf, - 3rd September 1999. - - -5.2 Informative references - - [RFC 2195] Klensin, J., Catoe, R. and P. Krumviede, "IMAP/POP - AUTHorize Extension for Simple Challenge/Response", RFC - 2195, September 1997. - - [MD5] Kaliski, B.,Robshaw, M., "Message Authentication with MD5", - CryptoBytes, Sping 1995, RSA Inc, - (http://www.rsa.com/rsalabs/pubs/cryptobytes/spring95/md5.htm) - - [RFC 2078] Linn, J., "Generic Security Service Application Program - Interface, Version 2", RFC 2078, January 1997. - - [RFC 3501] Crispin, M., "Internet Message Access Protocol - Version - 4rev1", RFC 3501, March 2003. - - [RFC 2244] Newman, C., Myers, J., "ACAP -- Application Configuration - Access Protocol", RFC 2244, November 1997. - - - -Leach & Newman Expires: December 2003 [Page 28] - - - - - -INTERNET DRAFT Digest SASL Mechanism June 2003 - - - [RFC 2616] Fielding, R., Gettys, J., Mogul, J., Frystyk, H., - Masinter, L., Leach, P., Berners-Lee, T., "Hypertext - Transfer Protocol -- HTTP/1.1", RFC 2616, June 1999. - - [TLS-CBC] Moeller, B., "Security of CBC Ciphersuites in SSL/TLS: - Problems and Countermeasures", - http://www.openssl.org/~bodo/tls-cbc.txt. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Leach & Newman Expires: December 2003 [Page 29] - - - - - -INTERNET DRAFT Digest SASL Mechanism June 2003 - - -6 Authors' Addresses - - Paul Leach - Microsoft - 1 Microsoft Way - Redmond, WA 98052, USA - - EMail: paulle@microsoft.com - - - Chris Newman - Sun Microsystems - 1050 Lakes Drive - West Covina, CA 91790, USA - - EMail: Chris.Newman@Sun.COM - - - Alexey Melnikov - Isode - 28 Gloucester Road, - Teddington, Middlesex, TW11 0NU, UK - - Email: mel@isode.com - - - - - - - - - - - - - - - - - - - - - - - - - - - -Leach & Newman Expires: December 2003 [Page 30] - - - - - -INTERNET DRAFT Digest SASL Mechanism June 2003 - - -7 ABNF - - What follows is the definition of the notation as is used in the - HTTP/1.1 specification [RFC 2616] and the HTTP authentication - specification [Digest]; it is reproduced here for ease of reference. - Since it is intended that a single Digest implementation can support - both HTTP and SASL-based protocols, the same notation is used in both - to facilitate comparison and prevention of unwanted differences. - Since it is cut-and-paste from the HTTP specifications, not all - productions may be used in this specification. It is also not quite - legal ABNF; again, the errors were copied from the HTTP - specifications. - -7.1 Augmented BNF - - All of the mechanisms specified in this document are described in - both prose and an augmented Backus-Naur Form (BNF) similar to that - used by RFC 822 [RFC 822]. Implementers will need to be familiar with - the notation in order to understand this specification. - - The augmented BNF includes the following constructs: - - name = definition - The name of a rule is simply the name itself (without any - enclosing "<" and ">") and is separated from its definition by the - equal "=" character. White space is only significant in that - indentation of continuation lines is used to indicate a rule - definition that spans more than one line. Certain basic rules are - in uppercase, such as SP, LWS, HT, CRLF, DIGIT, ALPHA, etc. Angle - brackets are used within definitions whenever their presence will - facilitate discerning the use of rule names. - - "literal" - Quotation marks surround literal text. Unless stated otherwise, - the text is case-insensitive. - - rule1 | rule2 - Elements separated by a bar ("|") are alternatives, e.g., "yes | - no" will accept yes or no. - - (rule1 rule2) - Elements enclosed in parentheses are treated as a single element. - Thus, "(elem (foo | bar) elem)" allows the token sequences - "elem foo elem" and "elem bar elem". - - *rule - The character "*" preceding an element indicates repetition. The - full form is "*element" indicating at least and at most - - - -Leach & Newman Expires: December 2003 [Page 31] - - - - - -INTERNET DRAFT Digest SASL Mechanism June 2003 - - - occurrences of element. Default values are 0 and infinity so - that "*(element)" allows any number, including zero; "1*element" - requires at least one; and "1*2element" allows one or two. - - [rule] - Square brackets enclose optional elements; "[foo bar]" is - equivalent to "*1(foo bar)". - - N rule - Specific repetition: "(element)" is equivalent to - "*(element)"; that is, exactly occurrences of (element). - Thus 2DIGIT is a 2-digit number, and 3ALPHA is a string of three - alphabetic characters. - - #rule - A construct "#" is defined, similar to "*", for defining lists of - elements. The full form is "#element" indicating at least - and at most elements, each separated by one or more commas - (",") and OPTIONAL linear white space (LWS). This makes the usual - form of lists very easy; a rule such as - ( *LWS element *( *LWS "," *LWS element )) - can be shown as - 1#element - Wherever this construct is used, null elements are allowed, but do - not contribute to the count of elements present. That is, - "(element), , (element) " is permitted, but counts as only two - elements. Therefore, where at least one element is required, at - least one non-null element MUST be present. Default values are 0 - and infinity so that "#element" allows any number, including zero; - "1#element" requires at least one; and "1#2element" allows one or - two. - - ; comment - A semi-colon, set off some distance to the right of rule text, - starts a comment that continues to the end of line. This is a - simple way of including useful notes in parallel with the - specifications. - - implied *LWS - The grammar described by this specification is word-based. Except - where noted otherwise, linear white space (LWS) can be included - between any two adjacent words (token or quoted-string), and - between adjacent words and separators, without changing the - interpretation of a field. At least one delimiter (LWS and/or - separators) MUST exist between any two tokens (for the definition - of "token" below), since they would otherwise be interpreted as a - single token. - - - - -Leach & Newman Expires: December 2003 [Page 32] - - - - - -INTERNET DRAFT Digest SASL Mechanism June 2003 - - -7.2 Basic Rules - - The following rules are used throughout this specification to - describe basic parsing constructs. The US-ASCII coded character set - is defined by ANSI X3.4-1986 [USASCII]. - - OCTET = - CHAR = - UPALPHA = - LOALPHA = - ALPHA = UPALPHA | LOALPHA - DIGIT = - CTL = - CR = - LF = - SP = - HT = - <"> = - TEXTCHAR = - CRLF = CR LF - - All linear white space, including folding, has the same semantics as - SP. A recipient MAY replace any linear white space with a single SP - before interpreting the field value or forwarding the message - downstream. - - LWS = [CRLF] 1*( SP | HT ) - - The TEXT rule is only used for descriptive field contents and values - that are not intended to be interpreted by the message parser. Words - of TEXT contains characters either from ISO-8859-1 [ISO-8859] - character set or UTF-8 [UTF-8]. - - TEXT = - - A CRLF is allowed in the definition of TEXT only as part of a header - field continuation. It is expected that the folding LWS will be - replaced with a single SP before interpretation of the TEXT value. - - Hexadecimal numeric characters are used in several protocol elements. - - HEX = "A" | "B" | "C" | "D" | "E" | "F" - | "a" | "b" | "c" | "d" | "e" | "f" | DIGIT - - Many HTTP/1.1 header field values consist of words separated by LWS - or special characters. These special characters MUST be in a quoted - - - -Leach & Newman Expires: December 2003 [Page 33] - - - - - -INTERNET DRAFT Digest SASL Mechanism June 2003 - - - string to be used within a parameter value. - - token = 1*TOKENCHAR - separators = "(" | ")" | "<" | ">" | "@" - | "," | ";" | ":" | "\" | <"> - | "/" | "[" | "]" | "?" | "=" - | "{" | "}" | SP | HT - TOKENCHAR = - - A string of text is parsed as a single word if it is quoted using - double-quote marks. - - quoted-string = ( <"> qdstr-val <"> ) - qdstr-val = *( qdtext | quoted-pair ) - qdtext = and "\"> - - Note that LWS is NOT implicit between the double-quote marks (<">) - surrounding a qdstr-val and the qdstr-val; any LWS will be considered - part of the qdstr-val. This is also the case for quotation marks - surrounding any other construct. - - The backslash character ("\") MAY be used as a single-character - quoting mechanism only within qdstr-val and comment constructs. - - quoted-pair = "\" CHAR - - The value of this construct is CHAR. Note that an effect of this rule - is that backslash itself MUST be quoted. - - - - - - - - - - - - - - - - - - - - - - - -Leach & Newman Expires: December 2003 [Page 34] - - - - - -INTERNET DRAFT Digest SASL Mechanism June 2003 - - -8 Sample Code - - The sample implementation in [Digest] also applies to DIGEST-MD5. - - The following code implements the conversion from UTF-8 to 8859-1 if - necessary. - - /* if the string is entirely in the 8859-1 subset of UTF-8, then - * translate to 8859-1 prior to MD5 - */ - void MD5_UTF8_8859_1(MD5_CTX *ctx, const unsigned char *base, - int len) - { - const unsigned char *scan, *end; - unsigned char cbuf; - - end = base + len; - for (scan = base; scan < end; ++scan) { - if (*scan > 0xC3) break; /* abort if outside 8859-1 */ - if (*scan >= 0xC0 && *scan <= 0xC3) { - if (++scan == end || *scan < 0x80 || *scan > 0xBF) - break; - } - } - /* if we found a character outside 8859-1, don't alter string - */ - if (scan < end) { - MD5Update(ctx, base, len); - return; - } - - /* convert to 8859-1 prior to applying hash - */ - do { - for (scan = base; scan < end && *scan < 0xC0; ++scan) - ; - if (scan != base) MD5Update(ctx, base, scan - base); - if (scan + 1 >= end) break; - cbuf = ((scan[0] & 0x3) << 6) | (scan[1] & 0x3f); - MD5Update(ctx, &cbuf, 1); - base = scan + 2; - } while (base < end); - } - - - - - - - - -Leach & Newman Expires: December 2003 [Page 35] - - - - - -INTERNET DRAFT Digest SASL Mechanism June 2003 - - -9 Interoperability considerations - - 9.1 Implementing DES cipher in CBC mode - - Several cryptographic libraries (Ebones, OpenSSL) provide a convenience - function des_cbc_encrypt for implementing DES cipher in CBC mode. - There is a documented bug in this function: the function doesn't update - IV before returning. If an implementation uses this function to implement - DES cipher in CBC mode, it MUST update IV by copying the last 8 bytes of - the des_cbc_encrypt's output to the IV buffer. - Note that the function des_ede2_cbc_encrypt that may be used to implement - 3DES (in "two keys mode") in CBC mode works as expected. - - Care must be taken when configuring the DES keys for most DES - libraries. This specification gives 56 bits for the DES key (or 112 - bits for the 3DES key); libraries generally expect the key to be given - in a 64 bit (128 bit for 3DES) form. - - The following C function can be used to convert a 56 bit DES key into a - form acceptable for the libraries. The low order bit in each byte - would contain parity information and will be corrected by the library. - - /* slide the first 7 bytes of 'inbuf' into the high seven bits of the - first 8 bytes of 'keybuf'. 'keybuf' better be 8 bytes long or longer. */ - void slidebits(unsigned char *keybuf, unsigned char *inbuf) - { - keybuf[0] = inbuf[0]; - keybuf[1] = (inbuf[0]<<7) | (inbuf[1]>>1); - keybuf[2] = (inbuf[1]<<6) | (inbuf[2]>>2); - keybuf[3] = (inbuf[2]<<5) | (inbuf[3]>>3); - keybuf[4] = (inbuf[3]<<4) | (inbuf[4]>>4); - keybuf[5] = (inbuf[4]<<3) | (inbuf[5]>>5); - keybuf[6] = (inbuf[5]<<2) | (inbuf[6]>>6); - keybuf[7] = (inbuf[6]<<1); - } - -10 Acknowledgements - - The following people had substantial contributions to the development - and/or refinement of this document: - - Lawrence Greenfield John Gardiner Myers Simon Josefsson RL Bob Morgan - Jeff Hodges Claus Assmann Tony Hansen Sam Hartman - - as well as other members of the SASL mailing list. - - The text used is section 3.8 was taken from [TLS-CBC] by Bodo - Moeller. - - - -Leach & Newman Expires: December 2003 [Page 36] - - - - - -INTERNET DRAFT Digest SASL Mechanism June 2003 - - -11 Full Copyright Statement - - Copyright (C) The Internet Society (2003). All Rights Reserved. - - This document and translations of it may be copied and furnished to - others, and derivative works that comment on or otherwise explain it - or assist in its implementation may be prepared, copied, published - and distributed, in whole or in part, without restriction of any - kind, provided that the above copyright notice and this paragraph are - included on all such copies and derivative works. However, this - document itself may not be modified in any way, such as by removing - the copyright notice or references to the Internet Society or other - Internet organizations, except as needed for the purpose of - developing Internet standards in which case the procedures for - copyrights defined in the Internet Standards process must be - followed, or as required to translate it into languages other than - English. - - The limited permissions granted above are perpetual and will not be - revoked by the Internet Society or its successors or assigns. - - This document and the information contained herein is provided on an - "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING - TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING - BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION - HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - -Acknowledgement - - Funding for the RFC Editor function is currently provided by the - Internet Society. - - - - - - - - - - - - - - - - - - - -Leach & Newman Expires: December 2003 [Page 37] - - - - - -INTERNET DRAFT Digest SASL Mechanism June 2003 - - -Appendix A: Changes from 2831 - - 1). Fixed various typos in formulas. - - 2). Dropped DES as mandatory to implement cipher (3DES is mandatory - to implement). - - 3). Tighten ABNF. Fixed some bugs. - - 4). Clarified nc-value verification and which side is aborting - exchange. - - 5). Added text saying that for interoperability - username/password/realm MUST be prepared using the "SASLPrep" profile - [SASLPrep] of the "stringprep" algorithm [StringPrep]. - - 6). Clarified that unquoted version of the username, etc. used in A1 - calculation. - - 7). Various cleanup to References section. Split all references to - Normative and Informative. - - 8). Added minimal and maximal limits on maxbuf. Clarified how to - calculate max sender size. - - 9). Change ABNF for host to allow for IPv6 addresses. ABNF now - references RFC 2373 and RFC 2396. - - 10). Added DES cipher interoperability section. - - 11). Added man-in-the-middle considerations for ciphers. - - 12). Clarified how sequence counters are modified. - - 13). Addition warnings about preventing reply/redirection attacks. - - 14). Specified that "charset" directive affects "realm" and doesn't - affect - "authzid". - - 15). Removed text that described that "authzid" is in Unicode in - Normalization - Form KC, encoded as UTF-8. - - 16). Clarified that rc4 state is not reset between two sent/received - buffers - of encoded data. - - - - -Leach & Newman Expires: December 2003 [Page 38] - - - - - -INTERNET DRAFT Digest SASL Mechanism June 2003 - - - 17). Clarified that for DES/3DES the IV for the next buffer of - encoded data is - the last 8 bytes of the ciphertext. - - 18). Clarified how "maximal sender size" is calculated. - - 19). Prohibit an empty authzid. - - 20). Added AES cipher defined in "AES Ciphersuite for DIGEST-MD5 SASL - mechanism" - document (expired draft-ietf-sasl-digest-aes-00.txt). - - 21). Minor text clarifications. - -Appendix B: Open Issues/ToDo List - - 1). The latest revision prohibits escaped characters in nonce/cnonce. - This is different - from HTTP Digest. Any objections? - - 2). Do we need/want a new stringprep profile for "realm"? - - 3). What to do about CBC mode attack that affects TLS document and - DIGEST-MD5 as well? - - One of the proposals is to drop DES/3DES ciphers and define a new one - (e.g. AES) in such a way that is not susceptible to this kind of - attack. - - AES cipher has to be fixed to prevent this attack. - - 4). Add reference to CBC mode attack: - - This problem is described in LASEC Memo "Password Interception in a - SSL/TLS Channel" by Brice Canvel, published 2003-02-20: - http://lasecwww.epfl.ch/memo_ssl.shtml - - 5). Normative vs. Informative references must be carefully rechecked. - - - - - - - - - - - - - -Leach & Newman Expires: December 2003 [Page 39] - - diff --git a/doc/draft-ietf-sasl-saslprep-xx.txt b/doc/draft-ietf-sasl-saslprep-xx.txt deleted file mode 100644 index fd0f6b86..00000000 --- a/doc/draft-ietf-sasl-saslprep-xx.txt +++ /dev/null @@ -1,339 +0,0 @@ - - - - - - -INTERNET-DRAFT Kurt D. Zeilenga -Intended Category: Standards Track OpenLDAP Foundation -Expires in six months 27 October 2003 - - - SASLprep: Stringprep profile for user names and passwords - - - -Status of Memo - - This document is an Internet-Draft and is in full conformance with all - provisions of Section 10 of RFC 2026. - - This document is intended to be, after appropriate review and - revision, submitted to the RFC Editor as a Standards Track document. - Distribution of this memo is unlimited. Technical discussion of this - document will take place on the IETF SASL mailing list - . Please send editorial comments directly to the - document editor . - - Internet-Drafts are working documents of the Internet Engineering Task - Force (IETF), its areas, and its working groups. Note that other - groups may also distribute working documents as Internet-Drafts. - Internet-Drafts are draft documents valid for a maximum of six months - and may be updated, replaced, or obsoleted by other documents at any - time. It is inappropriate to use Internet-Drafts as reference - material or to cite them other than as ``work in progress.'' - - The list of current Internet-Drafts can be accessed at - . The list of - Internet-Draft Shadow Directories can be accessed at - . - - Copyright (C) The Internet Society (2003). All Rights Reserved. - - Please see the Full Copyright section near the end of this document - for more information. - - -Abstract - - This document describes how to prepare Unicode strings representing - user names and passwords for comparison. The document defines the - "SASLprep" profile of the "stringprep" algorithm to be used for both - user names and passwords. This profile is intended to be used by - Simple Authentication and Security Layer (SASL) mechanisms (such as - PLAIN, CRAM-MD5, and DIGEST-MD5) as well as other protocols exchanging - - - -Zeilenga SASLprep [Page 1] - -INTERNET-DRAFT draft-ietf-sasl-saslprep-04.txt 27 October 2003 - - - user names and/or passwords. - - -1. Introduction - - The use of simple user names and passwords in authentication and - authorization is pervasive on the Internet. To increase the - likelihood that user name and password input and comparison work in - ways that make sense for typical users throughout the world, this - document defines rules for preparing internationalized user names and - passwords for comparison. For simplicity and implementation ease, a - single algorithm is defined for both user names and passwords. - - This document defines the "SASLprep" profile of the "stringprep" - algorithm [StringPrep]. - - The profile is designed for use in Simple Authentication and Security - Layer ([SASL]) mechanisms such as [PLAIN]. It may be applicable - elsewhere simple user names and passwords are used. This profile is - not intended to be used for arbitrary text. This profile is also not - intended to be used to prepare identity strings which are not simple - user names (e.g., e-mail addresses, domain names, distinguished - names). - - -2. The SASLprep profile - - This section defines the "SASLprep" profile. This profile is intended - to be used to prepare strings representing simple user names and - passwords. - - This profile uses Unicode 3.2, as defined in [StringPrep, A.1]. - - Character names in this document use the notation for code points and - names from the Unicode Standard [Unicode]. For example, the letter - "a" may be represented as either or . - In the lists of mappings and the prohibited characters, the "U+" is - left off to make the lists easier to read. The comments for character - ranges are shown in square brackets (such as "[CONTROL CHARACTERS]") - and do not come from the standard. - - Note: a glossary of terms used in Unicode can be found in [Glossary]. - Information on the Unicode character encoding model can be found in - [CharModel]. - - -2.1. Mapping - - - - -Zeilenga SASLprep [Page 2] - -INTERNET-DRAFT draft-ietf-sasl-saslprep-04.txt 27 October 2003 - - - This profile specifies: - - non-ASCII space characters [StringPrep, C.1.2] be mapped to SPACE - (U+0020), and - - - the "commonly mapped to nothing" characters [StringPrep, B.1] be - mapped to nothing. - - - -2.2. Normalization - - This profile specifies using Unicode normalization form KC, as - described in Section 4 of [StringPrep]. - - -2.3. Prohibited Output - - This profile specifies the following characters: - - - Non-ASCII space characters [StringPrep, C.1.2], - - ASCII control characters [StringPrep, C.2.1], - - Non-ASCII control characters [StringPrep, C.2.2], - - Private Use [StringPrep, C.3], - - Non-character code points [StringPrep, C.4], - - Surrogate code points [StringPrep, C.5], - - Inappropriate for plain text [StringPrep, C.6], - - Inappropriate for canonical representation [StringPrep, C.7], - - Change display properties or are deprecated [StringPrep, C.8], and - - Tagging characters [StringPrep, C.9]. - - are prohibited output. - - -2.4. Bidirectional characters - - This profile specifies checking bidirectional strings as described in - [StringPrep, Section 6]. - - -2.5. Unassigned Code Points - - This profile specifies [StringPrep, A.1] table as its list of - unassigned code points. - - -3. Security Considerations - - This profile is intended to used to prepare simple user names and - - - -Zeilenga SASLprep [Page 3] - -INTERNET-DRAFT draft-ietf-sasl-saslprep-04.txt 27 October 2003 - - - passwords for comparison. It is not intended to be used for to - prepare identities which are not simple user names (e.g., - distinguished names and domain names). Nor is the profile intended to - be used for simple user names which require different handling. - Protocols (or applications of those protocols) which have - application-specific identity forms and/or comparison algorithms - should use mechanisms specifically designed for these forms and - algorithms. - - User names and passwords should be protected from eavesdropping. - - General "stringprep" and Unicode security considerations apply. Both - are discussed in [StringPrep]. - - -4. IANA Considerations - - This document details the "SASLprep" profile of [StringPrep] protocol. - Upon Standards Action the profile should be registered in the - stringprep profile registry. - - Name of this profile: SASLprep - RFC in which the profile is defined: This RFC - Indicator whether or not this is the newest version of the - profile: This is the first version of the SASPprep profile. - - -5. Acknowledgment - - This document borrows text from "Preparation of Internationalized - Strings ('stringprep')" and "Nameprep: A Stringprep Profile for - Internationalized Domain Names", both by Paul Hoffman and Marc - Blanchet. - - This document is a product of the IETF SASL WG. - - -6. Normative References - - [StringPrep] Hoffman P. and M. Blanchet, "Preparation of - Internationalized Strings ('stringprep')", - draft-hoffman-rfc3454bis-xx.txt, a work in progress. - - [SASL] Melnikov, A. (Editor), "Simple Authentication and - Security Layer (SASL)", - draft-ietf-sasl-rfc2222bis-xx.txt, a work in progress. - - [Unicode] The Unicode Consortium, "The Unicode Standard, Version - - - -Zeilenga SASLprep [Page 4] - -INTERNET-DRAFT draft-ietf-sasl-saslprep-04.txt 27 October 2003 - - - 3.2.0" is defined by "The Unicode Standard, Version 3.0" - (Reading, MA, Addison-Wesley, 2000. ISBN 0-201-61633-5), - as amended by the "Unicode Standard Annex #27: Unicode - 3.1" (http://www.unicode.org/reports/tr27/) and by the - "Unicode Standard Annex #28: Unicode 3.2" - (http://www.unicode.org/reports/tr28/). - - -7. Informative References - - [Glossary] The Unicode Consortium, "Unicode Glossary", - . - - [CharModel] Whistler, K. and M. Davis, "Unicode Technical Report - #17, Character Encoding Model", UTR17, - , August - 2000. - - [CRAM-MD5] Nerenberg, L., "The CRAM-MD5 SASL Mechanism", - draft-ietf-sasl-crammd5-xx.txt, a work in progress. - - [DIGEST-MD5] Leach, P., C. Newman, and A. Melnikov, "Using Digest - Authentication as a SASL Mechanism", - draft-ietf-sasl-rfc2831bis-xx.txt, a work in progress. - - [PLAIN] Zeilenga, K. (Editor), "The Plain SASL Mechanism", - draft-ietf-sasl-plain-xx.txt, a work in progress. - - -8. Editor's Address - - Kurt Zeilenga - OpenLDAP Foundation - - Email: kurt@OpenLDAP.org - - -Intellectual Property Rights - - The IETF takes no position regarding the validity or scope of any - intellectual property or other rights that might be claimed to pertain - to the implementation or use of the technology described in this - document or the extent to which any license under such rights might or - might not be available; neither does it represent that it has made any - effort to identify any such rights. Information on the IETF's - procedures with respect to rights in standards-track and - standards-related documentation can be found in BCP-11. Copies of - claims of rights made available for publication and any assurances of - - - -Zeilenga SASLprep [Page 5] - -INTERNET-DRAFT draft-ietf-sasl-saslprep-04.txt 27 October 2003 - - - licenses to be made available, or the result of an attempt made to - obtain a general license or permission for the use of such proprietary - rights by implementors or users of this specification can be obtained - from the IETF Secretariat. - - The IETF invites any interested party to bring to its attention any - copyrights, patents or patent applications, or other proprietary - rights which may cover technology that may be required to practice - this standard. Please address the information to the IETF Executive - Director. - - -Full Copyright - - Copyright (C) The Internet Society (2003). All Rights Reserved. - - This document and translations of it may be copied and furnished to - others, and derivative works that comment on or otherwise explain it - or assist in its implmentation may be prepared, copied, published and - distributed, in whole or in part, without restriction of any kind, - provided that the above copyright notice and this paragraph are - included on all such copies and derivative works. However, this - document itself may not be modified in any way, such as by removing - the copyright notice or references to the Internet Society or other - Internet organizations, except as needed for the purpose of - developing Internet standards in which case the procedures for - copyrights defined in the Internet Standards process must be followed, - or as required to translate it into languages other than English. - - - - - - - - - - - - - - - - - - - - - - - -Zeilenga SASLprep [Page 6] - diff --git a/doc/draft-murchison-sasl-login-xx.txt b/doc/draft-murchison-sasl-login-xx.txt deleted file mode 100644 index e6ffc297..00000000 --- a/doc/draft-murchison-sasl-login-xx.txt +++ /dev/null @@ -1,396 +0,0 @@ - - - - - - - -Internet Draft K. Murchison -Category: Informational M. Crispin -Expires: March 2, 2004 28 August 2003 - - - The LOGIN SASL Mechanism - - - - -Status of this Memo - - This document is an Internet-Draft and is subject to all provisions - of Section 10 of RFC2026. - - Internet-Drafts are working documents of the Internet Engineering - Task Force (IETF), its areas, and its working groups. Note that - other groups may also distribute working documents as - Internet-Drafts. - - Internet-Drafts are draft documents valid for a maximum of six months - and may be updated, replaced, or obsoleted by other documents at any - time. It is inappropriate to use Internet-Drafts as reference - material or to cite them other than as "work in progress." - - The list of current Internet-Drafts can be accessed at - http://www.ietf.org/1id-abstracts.html - - The list of Internet-Draft Shadow Directories can be accessed at - http://www.ietf.org/shadow.html - - -Copyright Notice - - Copyright (C) The Internet Society 2003. All Rights Reserved. - - -Abstract - - This document documents the obsolete clear-text user/password Simple - Authentication and Security Layer (SASL) mechanism called the LOGIN - mechanism. The LOGIN mechanism was intended to be used, in - combination with data confidentiality services provided by a lower - layer, in protocols which lack a simple password authentication - command. - - - - - - -Expires: March 2, 2004 Murchison [Page 1] - -Internet Draft LOGIN SASL Mechanism August 28, 2004 - - - -Conventions Used in the Document - - The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", - "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this - document are to be interpreted as described in [KEYWORDS]. - - -1. Background and Intended Usage - - This document documents the obsolete LOGIN Simple Authentication and - Security Layer ([SASL]) mechanism which was in use in protocols with - no clear-text login command (e.g., [SMTP-AUTH]). - - Note: The LOGIN SASL mechanism is obsoleted in favor of the PLAIN - SASL mechanism ([PLAIN]). The LOGIN mechanism is documented here - only for the purpose of backwards compatibility with legacy software. - Clients SHOULD implement the PLAIN SASL mechanism and use it whenever - offered by a server. The LOGIN SASL mechanism SHOULD NOT be used by - a client when other plaintext mechanisms are offered by a server. - - The name associated with this mechanism is "LOGIN". - - The LOGIN SASL mechanism does not provide a security layer. This - mechanism MUST NOT be used without adequate security protection as - the mechanism affords no integrity nor confidentiality protection - itself. The LOGIN SASL mechanism MUST NOT be advertised or used in - any configuration that prohibits the PLAIN mechanism or plaintext - LOGIN (or USER/PASS) command that sends passwords in the clear. - - -2. LOGIN SASL Mechanism - - The authorization identity is the same string as the "username" in - the traditional (non-SASL) LOGIN or USER commands; the authorization - authenticator is the same string as the traditional "password". The - authentication identity is the same as the authorization identity in - this mechanism. - - Only US-ASCII printable characters SHOULD be used in the username and - password to permit maximal interoperability. If non-US-ASCII - characters are used in a username, they MUST use UTF-8. Passwords - MAY contain arbitrary binary data excluding NUL, CR and LF - characters. However, if a password is supplied to the client as a - sequence of characters (e.g., a password dialog box), those - characters MUST be encoded as UTF-8. - - The username MUST be less than 64 characters in length. - - - -Expires: March 2, 2004 Murchison [Page 2] - -Internet Draft LOGIN SASL Mechanism August 28, 2004 - - -2.1. Client side of authentication protocol exchange - - The client expects the server to issue a challenge. The client then - responds with the authorization identity. The client then expects - the server to issue a second challenge. The client then responds - with the authorization authenticator. The contents of both - challenges SHOULD be ignored. - - -2.2. Server side of authentication protocol exchange - - The server issues the string "User Name" in challenge, and receives a - client response. This response is recorded as the authorization - identity. The server then issues the string "Password" in challenge, - and receives a client response. This response is recorded as the - authorization authenticator. The server must verify that the - authorization authenticator permits login as the authorization - identity. - - Note: There is at least one widely deployed client which requires - that the challenge strings transmitted by the server be "Username:" - and "Password:" respectively. For this reason, server - implementations MAY send these challenge strings instead of those - listed above. - - -2.3. Example - - This example shows the use of the LOGIN mechanism with the SMTP AUTH - command [SMTP-AUTH] under the protection of SMTP STARTTLS [SMTP-TLS]. - The user name is "tim" and the password is "tanstaaftanstaaf". The - base64 encoding of the challenges and responses is part of the SMTP - AUTH command, not part of the LOGIN specification itself. "C:" and - "S:" indicate lines sent by the client and server respectively. - - S: 220 smtp.example.com ESMTP server ready - C: EHLO test.example.com - S: 250-smtp.example.com - S: 250-STARTTLS - S: 250 AUTH CRAM-MD5 - C: STARTTLS - S: 220 Ready to start TLS - - C: EHLO test.example.com - S: 250-smtp.example.com - S: 250 AUTH LOGIN CRAM-MD5 - C: AUTH LOGIN - S: 334 VXNlciBOYW1lAA== - - - -Expires: March 2, 2004 Murchison [Page 3] - -Internet Draft LOGIN SASL Mechanism August 28, 2004 - - - C: dGlt - S: 334 UGFzc3dvcmQA - C: dGFuc3RhYWZ0YW5zdGFhZg== - S: 235 Authentication successful. - - -3. - Security Considerations - - The LOGIN mechanism relies upon an underlying encryption layer or - other secure channel for security. When used without an encryption - layer or secure channel, it is vulnerable to a common network - eavesdropping attack. Therefore the LOGIN mechanism MUST NOT be - advertised or used in any configuration that prohibits the PLAIN - mechanism or a plaintext LOGIN (or USER/PASS) command that sends - passwords in the clear. - - -4. - IANA Considerations - - The registration for the LOGIN SASL mechanism follows: - - SASL mechanism name: LOGIN - Security Considerations: See section 3 of this memo - Published specification: this memo - Person & email address to contact for futher information: - See section 7 of this memo - Intended usage: OBSOLETE - Owner/Change controller: See section 7 of this memo - - -5. - References - - -5.1. - Normative References - - - [KEYWORDS] Bradner, S., "Key words for use in RFCs to Indicate - Requirement Levels", Harvard University, RFC 2119, March 1997. - - - [SASL] Melnikov, A., Ed., "Simple Authentication and Security Layer - (SASL)", Isode, draft-ietf-sasl-rfc2222bis-xx.txt, Work In - Progress. - - - - -Expires: March 2, 2004 Murchison [Page 4] - -Internet Draft LOGIN SASL Mechanism August 28, 2004 - - -5.2. Informative References - - - [PLAIN] Zeilenga, Kurt D., Ed., "The Plain SASL Mechanism", - OpenLDAP Foundation, draft-ietf-sasl-plain-xx.txt, Work In - Progress. - - - [SMTP-AUTH] Myers, J., "SMTP Service Extension for Authentication", - Netscape Communications, RFC 2554, March 1999. - - - [SMTP-TLS] Hoffman, P., "SMTP Service Extension for Secure SMTP - over Transport Layer Security", Internet Mail Consortium, RFC - 3207, February 2002. - - - -6. Acknowledgments - - Thanks to Rob Siemborski for his input and feedback on this document. - - -7. - Author's Address - - Kenneth Murchison - Oceana Matrix Ltd. - 21 Princeton Place - Orchard Park, NY 14127 - - Phone: (716) 662-8973 - - EMail: ken@oceana.com - - - - - Mark R. Crispin - Networks and Distributed Computing - University of Washington - 4545 15th Avenue NE - Seattle, WA 98105-4527 - - Phone: (206) 543-5762 - - EMail: MRC@CAC.Washington.EDU - - - - -Expires: March 2, 2004 Murchison [Page 5] - -Internet Draft LOGIN SASL Mechanism August 28, 2004 - - -8. - Intellectual Property Considerations - - The IETF takes no position regarding the validity or scope of any - intellectual property or other rights that might be claimed to - pertain to the implementation or use of the technology described in - this document or the extent to which any license under such rights - might or might not be available; neither does it represent that it has - made any effort to identify any such rights. Information on the - IETF's procedures with respect to rights in standards-track and - standards-related documentation can be found in BCP-11. Copies of - claims of rights made available for publication and any assurances of - licenses to be made available, or the result of an attempt made to - obtain a general license or permission for the use of such proprietary - rights by implementors or users of this specification can be obtained - from the IETF Secretariat. - - The IETF invites any interested party to bring to its attention any - copyrights, patents or patent applications, or other proprietary - rights which may cover technology that may be required to practice - this standard. Please address the information to the IETF Executive - Director. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Expires: March 2, 2004 Murchison [Page 6] - -Internet Draft LOGIN SASL Mechanism August 28, 2004 - - -9. - Full Copyright Statement - - Copyright (C) The Internet Society 2003. All Rights Reserved. - - This document and translations of it may be copied and furnished to - others, and derivative works that comment on or otherwise explain it - or assist in its implmentation may be prepared, copied, published and - distributed, in whole or in part, without restriction of any kind, - provided that the above copyright notice and this paragraph are - included on all such copies and derivative works. However, this - document itself may not be modified in any way, such as by removing - the copyright notice or references to the Internet Society or other - Internet organizations, except as needed for the purpose of - developing Internet standards in which case the procedures for - copyrights defined in the Internet Standards process must be followed, - or as required to translate it into languages other than English. - - The limited permissions granted above are perpetual and will not be - revoked by the Internet Society or its successors or assigns. - - This document and the information contained herein is provided on an - "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET - ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, - INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE - INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED - WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - - - - - - - - - - - - - - - - - - - - - - - - -Expires: March 2, 2004 Murchison [Page 7] - diff --git a/doc/draft-newman-sasl-c-api-xx.txt b/doc/draft-newman-sasl-c-api-xx.txt deleted file mode 100644 index 1ad37dd2..00000000 --- a/doc/draft-newman-sasl-c-api-xx.txt +++ /dev/null @@ -1,1681 +0,0 @@ - - - - - - -Network Working Group C. Newman -Internet Draft: SASL C API Innosoft -Document: draft-newman-sasl-c-api-01.txt A. Melnikov - MessagingDirect - February 2003 - Expires in six months - - - Simple Authentication and Security Layer C API - - -Status of this memo - - This document is an Internet-Draft and is in full conformance with - all provisions of Section 10 of RFC2026 [RFC2026]. - - Internet-Drafts are working documents of the Internet Engineering - Task Force (IETF), its areas, and its working groups. Note that other - groups may also distribute working documents as Internet-Drafts. - - Internet-Drafts are draft documents valid for a maximum of six months - and may be updated, replaced, or obsoleted by other documents at any - time. It is inappropriate to use Internet-Drafts as reference - material or to cite them other than as "work in progress." - - The list of current Internet-Drafts can be accessed at - http://www.ietf.org/ietf/1id-abstracts.txt - - The list of Internet-Draft Shadow Directories can be accessed at - http://www.ietf.org/shadow.html. - -Abstract - - Almost every protocol needs authentication. However, there does not - exist an authentication mechanism suitable for all organizations, nor - is it likely that a small fixed set of authentication mechanisms will - remain suitable. SASL [SASL] provides the on-the-wire framework for - authentication (and a security layer) which separates the design of - authentication mechanisms from the protocols in which they're used. - - The SASL protocol model suggests a software architecture where - application protocols call a generic API to authenticate which in - turn calls a generic plug-in interface for extensible authentication - modules. This memo documents the API used in one implementation of - this architecture in the hope that it will be useful to others. An - associated memo documenting the plug-in interface is forthcoming. - -1. Conventions Used in this Memo - - - -Newman et al. Expires: August 2003 FORMFEED[Page 1] - - - - - -INTERNET DRAFT SASL C API February 2003 - - - The key words "MUST", "MUST NOT", "SHOULD", "SHOULD NOT", and "MAY" - in this document are to be interpreted as defined in "Key words for - use in RFCs to Indicate Requirement Levels" [KEYWORDS]. - - This assumes familiarity the SASL [SASL] specification. - - 1.1. Concepts - - The following concepts are necessary to understand this - specification. - -realm - A realm is a name (usually a domain-style name) associated with a - set of users on a server. One realm may span multiple servers. - Alternatively, a single server may have multiple realms. Thus - there may be multiple users with the username "chris" on the same - server, each in a different realm. Some authentication mechanisms - have a special field for the realm (e.g., DIGEST-MD5). For other - mechanisms, a realm can be specified by the client by using the - syntax "username@realm" in the username field. - -service - A service is a basic function provided by one or more protocols. - The GSSAPI service name [GSSAPI] registry is available at: - - - - This registry is used by SASL and the SASL API. The service name - may be used for service-specific passwords for advanced users, or - advanced authentication mechanisms may restrict the services a - given server may offer. - - -virtual domain - When a single server has multiple realms and there is a DNS server - entry for each realm pointing to the same server IP address, then - those realms are "virtual domains". Virtual domains are extremely - popular with web hosting services and are becoming more popular - with POP mail services. The key to providing virtual domain sup- - port is that the client informs the server of the domain it - believes it is speaking to either through a special protocol ele- - ment or by using a username of the form "user@realm". - - -2. Overview of the SASL C API - - The SASL API is initialized once at process startup. The - sasl_server_init() and sasl_client_init() functions provide basic - - - -Newman et al. Expires: August 2003 FORMFEED[Page 2] - - - - - -INTERNET DRAFT SASL C API February 2003 - - - initialization. - - When a network connection occurs where SASL will be used, a connec- - tion-specific context is created for authentication with - sasl_client_new() or sasl_server_new(). The API implementation must - support multi-threaded servers and clients by creating the connection - context in a thread-safe fashion permitting multiple contexts in a - given process. At this point, the caller may adjust security policy - for the context, and the set of mechanisms which are enabled is - determined by requirements from the configuration or by the caller. - - The server end of the API may request a list of enabled authentica- - tion mechanisms either in general or for a specific user. The client - may either select a single mechanism or request a list from the - server (if the SASL profile for the protocol in question supports - that) and pass the list to the API for automated mechanism selection - by configured policy. - - The SASL exchange begins with sasl_client_start() which determines if - one of the desired mechanisms is available on the client and may gen- - erate an initial client response. The client then sends the appro- - priate protocol message to initiate the SASL exchange that the server - passes to sasl_server_start(). - - The SASL exchange continues with calls to sasl_client_step() and - sasl_server_step(), until the server indicates completion or the - client cancels the exchange. - - The server queries the user name and user realm resulting from the - exchange with the sasl_getprop() routine. - - A connection context is released with sasl_dispose() and process ter- - mination is indicated with sasl_done(). - - There are a number of utility functions and customization functions - available in the API for additional services. - - Note, that all functions described in this documen can be implemented - as macroses, so an application using this API MUST NOT assume that - they are functions. - - An application or library trying to use SASL API described in this - document must include "sasl.h" include file. - -3. Basic SASL API Routines - - This section describes the types and functions likely to be used by - every caller of the SASL API. - - - -Newman et al. Expires: August 2003 FORMFEED[Page 3] - - - - - -INTERNET DRAFT SASL C API February 2003 - - - 3.1. Basic SASL API Data Structures - - The following datastructures are basic to the SASL API. - - 3.1.1. sasl_callback_t - - The sasl_callback_t structure is used for the caller of the SASL API - to provide services to both the core SASL API and SASL plug-ins via - callbacks. The most important callback is the "getopt" callback (see - section 3.3.3) which is used to retrieve security policy option set- - tings from the caller's preferences. - - typedef struct sasl_callback { - unsigned long id; - int (*proc)(); - void *context; - } sasl_callback_t; - - id is the label for the callback (XXX IANA registry needed), proc is - a function pointer whose exact type is determined by the id, and con- - text is a context variable which will be passed to the callback (usu- - ally as the first argument). The last callback in the list of call- - backs is indicated with an id of SASL_CB_LIST_END. - - If proc is NULL, this means that the application doesn't want to - specify a corresponding callback, but would provide the necessary - data via interaction. See also section 3.1.4. - - 3.1.2. sasl_secret_t - - The sasl_secret_t structure is used to hold text or binary passwords - for the client API. - - typedef struct sasl_secret { - unsigned long len; - unsigned char data[1]; - } sasl_secret_t; - - The len field holds the length of the password, while the data field - holds the actual data. The structure is variable sized: enough space - must be reserved after the data field to hold the desired password. - An additional that binary passwords are permitted to contain '\0' - characters. - - 3.1.3. sasl_conn_t - - The sasl_conn_t data type is an opaque data type which reflects the - SASL context for a single server connection. Only one SASL API call - - - -Newman et al. Expires: August 2003 FORMFEED[Page 4] - - - - - -INTERNET DRAFT SASL C API February 2003 - - - using a given sasl_conn_t as an argument may be active at a time. - However, each sasl_conn_t is independent and thus the SASL API may be - used in a true multi-processor multi-threaded environment. - - 3.1.4. sasl_interact_t - - The sasl_interact_t structure is used by sasl_client_start and - sasl_client_step to request certain information from the application, - when the application did not provide corresponding callbacks. For - example, an application may choose to present a single dialog to the - user in order to collect all required information interactively. - - typedef struct sasl_interact { - unsigned long id; - const char *challenge; - const char *prompt; - const char *defresult; - const void *result; - unsigned len; - } sasl_interact_t; - - The id field holds the value of the callback ID. The prompt field - contains a string that should be presented to the user. If non-NULL, - challenge is a NUL-terminated string that will allow the user to pre- - sent a specific credential when prompted. This is different from the - prompt in that the prompt is more like a label for a text box (for - example "Response:" while challenge is a string that tells the user - what specifically is required by the response (for example, an OTP - challenge string). The defresult field contains a default value, if - any. Upon return from sasl_client_* the "result" field points to the - defresult. The client must present the information in the challenge - and the prompt to the user and store the result and its length in the - result and the len fields respectively. - - For example, SASL_CB_PASS interaction may contain the following - information: - id - SASL_CB_PASS - challenge - NULL - prompt - "Password:" - defresult - NULL (no default). - - 3.2. Basic SASL API Client Routines - - This section discusses the functions likely to be used by every - client caller of the SASL API. - - 3.2.1. sasl_client_init function - - - - -Newman et al. Expires: August 2003 FORMFEED[Page 5] - - - - - -INTERNET DRAFT SASL C API February 2003 - - -Arguments: - sasl_callback_t *callbacks - -Results: - SASL_OK -- Success - SASL_NOMEM -- Not enough memory - SASL_BADVERS -- Mechanism version mismatch - SASL_BADPARAM -- Error in config file - - This function initializes the client routines for the SASL API. - - The callbacks argument is the default list of callbacks (see sec- - tion 3.1.1 for definition of sasl_callback_t structure) and SHOULD - include the sasl_getopt_t callback (see section 3.3.3). The call- - backs may be NULL. On success, SASL_OK is returned, and on fail- - ure a SASL C API error code such as the ones listed above is - returned. This function may be called a second time to change the - default callbacks used for new connections, but the first call - must be made in a single-threaded environment. The data refer- - enced by the sasl_callback_t structure must persist until - sasl_done() is called. - - 3.2.2. sasl_client_new function - -Arguments: - const char *service, - const char *server_name, - const char *iplocalport, - const char *ipremoteport, - const sasl_callback_t *prompt_supp, - unsigned int flags, - sasl_conn_t **pconn - -Results: - SASL_OK -- Success - SASL_NOTINIT -- SASL API not initialized - SASL_NOMECH -- No mechanisms available - SASL_NOMEM -- Not enough memory - - This function creates a client connection context variable. As - long as each thread uses its own connection context, the SASL C - API is thread-safe. - - The service argument is an IANA registered GSSAPI service element - as defined in section 1.1. It MUST NOT be NULL. - - The server_name is the host name or IP address of the server to - which the client is connecting. NULL may be used for server_name, - - - -Newman et al. Expires: August 2003 FORMFEED[Page 6] - - - - - -INTERNET DRAFT SASL C API February 2003 - - - but may result in advanced mechanisms such as Kerberos being - unavailable. - - The iplocalport is the string with the client IPv4/IPv6 address, - followed by ":" and than by port number. An IPv6 address must be - enclosed in "[" and "]". NULL may be used for iplocalport, but may - result in mechanisms requiring IP address being unavailable. - - The ipremoteport is the string with the server IPv4/IPv6 address, - followed by ":" and than by port number. An IPv6 address must be - enclosed in "[" and "]". NULL may be used for ipremoteport, but - may result in mechanisms requiring IP address being unavailable. - - User input to the SASL C API may be provided in two ways: either - by supplying callbacks (prompt_supp) to this function, or by using - an interaction model with the sasl_client_start/sasl_client_step - functions. Callbacks are more convenient to obtain information - programmatically, such as pulling authentication information - directly from a configuration file. Interactions are more conve- - nient if one wants to get all the data in parallel, for example by - displaying a single dialog box instead of a separate popup for - authentication name, authorization, password, etc. - - The prompt_supp is a list of supported user prompting callbacks - discussed in the section 3.1.1. The prompt_supp argument MAY be - NULL, which means that interactions (i.e. prompt_need parameter to - sasl_client_start (see 3.2.3) and sasl_client_step (see 3.2.4)) - are used instead of callbacks. If prompt_supp is NULL, the - prompt_need argument to sasl_client_start (see 3.2.3) and - sasl_client_step (see 3.2.4) MUST NOT be NULL. - - The flags argument represents client-supported security flags. - The only values currently supported are SASL_SECURITY_LAYER to - indicate the client supports the SASL security layer, or 0 to - indicate it doesn't. - - The pconn argument is set to point to the newly created connection - context. The sasl_conn_t type is opaque to the calling applica- - tion. - - 3.2.3. sasl_client_start function - - - - - - - - - - -Newman et al. Expires: August 2003 FORMFEED[Page 7] - - - - - -INTERNET DRAFT SASL C API February 2003 - - -Arguments: - sasl_conn_t *conn, - const char *mechlist, - sasl_interact_t **prompt_need, - const char **clientout, - unsigned int *clientoutlen, - const char **mech - -Results: - SASL_NOTINIT -- SASL API not initialized - SASL_BADPARAM -- conn or mechlist is NULL - SASL_NOMECH -- No matching mechanisms available - SASL_NOMEM -- Not enough memory - SASL_INTERACT -- User interaction needed to continue - (see prompt_need description below) - SASL_OK -- Success - - This selects an authentication mechanism to use and optionally - generates an initial client response. - - The conn argument is the connection context from sasl_client_new. - - The mechlist argument is a '\0' terminated string containing one - or more SASL mechanism names. All characters in the string that - are not permitted in a SASL mechanism name [SASL] are ignored - except for the purposes of delimiting mechanism names (this per- - mits passing direct results from many protocol capability lists - unparsed). Unknown mechanism names are ignored (although - SASL_NOMECH is returned if no known mechanisms are found). Mecha- - nisms are tried in an implementation-dependent order. Implementa- - tions SHOULD try to use the most secure mechanism possible, within - the constraints specified by the application (e.g. SSF value). - - For applications which support interactions, the prompt_need argu- - ment should initially point to a NULL pointer. If the selected - mechanism needs information from the user (for example, username - or password), then prompt_need will be set to point to an array of - sasl_interact_t structures (terminated by an entry with id equal - to SASL_CB_LIST_END), and sasl_client_start will return - SASL_INTERACT. After that the client must fill in the requested - information and call this function again with the same parameters. - - Applications that do not support interactions MUST pass NULL for - prompt_need. - - The clientout and clientoutlen parameters are set to the initial - client response, if any. If a protocol's SASL profile uses base64 - encoding, this represents the data prior to the encoding (see - - - -Newman et al. Expires: August 2003 FORMFEED[Page 8] - - - - - -INTERNET DRAFT SASL C API February 2003 - - - sasl_encode64). If a protocol's SASL profile doesn't include an - optional initial client response, then these may be NULL and 0 - respectively. The memory used by clientout is interally managed by - the SASL API and may be overwritten on the next call to - sasl_client_step or a call to sasl_dispose. - - The mech argument is set to point to a '\0' terminated string - specifying the mechanism actually selected using all uppercase - letters. It may be NULL if the client does not care which mecha- - nism was selected from mechlist. - - If sasl_client_start is called a second time using the same con- - nection context, it will discard any cached information (e.g., the - username and password) and restart the exchange from the begin- - ning. <> - - 3.2.4. sasl_client_step function - -Arguments: - sasl_conn_t *conn, - const char *serverin, - unsigned int serverinlen, - sasl_interact_t **prompt_need, - const char **clientout, - unsigned int *clientoutlen - -Results: - SASL_NOTINIT -- SASL API not initialized - SASL_NOMECH -- sasl_client_start not called - SASL_BADPROT -- server protocol incorrect/cancelled - SASL_BADSERV -- server failed mutual auth - SASL_INTERACT -- user interaction needed - SASL_OK -- success - - This routine performs one step in an authentication sequence. - - The conn argument must be a connection context created by - sasl_client_new and used in a previous call to sasl_client_start. - - The serverin and serverinlen parameters hold the SASL octet string - received from the server. Note that for those SASL profiles which - base64 encode the exchange, this is the result after the removal - of the base64 encoding (see the sasl_decode64 routine below). The - serverin MUST have a terminating NUL character not counted by - serverinlen - - The prompt_need argument is the same as for sasl_client_start. - - - - -Newman et al. Expires: August 2003 FORMFEED[Page 9] - - - - - -INTERNET DRAFT SASL C API February 2003 - - - The clientout and clientoutlen parameters hold the SASL octet - string to encode (if necessary) and send to the server. - - 3.3. Basic SASL API Callback Routines - - This section describes the basic callback functions needed for a - simple client implementation. See the definition of sasl_call- - back_t in section 3.1.1 for a description of the basic callback - structure. - - 3.3.1. sasl_getsimple_t - -Arguments: - void *context, - int id, - const char **result, - unsigned *len - -Results: - SASL_OK -- success - SASL_FAIL -- error - - This callback is used by the SASL API to request a simple constant - string from the application. This is used with id SASL_CB_USER - for the username, SASL_CB_AUTHNAME for the authentication name (if - different), and SASL_CB_LANGUAGE for a comma separated list of RFC - 1766 language tags. - - The context is the context variable from the sasl_callback_t - structure, the id is the id from the sasl_callback_t structure, - and the callback is expected to set the result to a constant - string and the len to the length of that string. The result and - len parameters are never NULL. - - 3.3.2. sasl_getsecret_t - -Arguments: - sasl_conn_t *conn, - void *context, - int id, - sasl_secret_t **psecret - -Results: - SASL_OK -- success - SASL_FAIL -- error - - This callback is expected to create, prompt or locate a secret and - set it in the connection context with sasl_setprop. The conn - - - -Newman et al. Expires: August 2003 FORMFEED[Page 10] - - - - - -INTERNET DRAFT SASL C API February 2003 - - - argument is the connection context, the context and id parameters - are from the sasl_callback_t structure. The id SASL_CB_PASS is - used to request a clear text password. - - 3.3.3. sasl_getopt_t - -Arguments: - void *context, - const char *plugin_name, - const char *option, - const char **result, - unsigned int *len - -Results: - SASL_OK -- success - SASL_FAIL -- error - - This callback is used by the SASL API to read options from the - application. This allows a SASL configuration to be encapsulated - in the caller's configuration system. Configuration items may be - mechanism-specific and are arbitrary strings. If the application - does not provide a sasl_getopt_t callback, then the API MAY obtain - configuration information from other sources, for example from a - config file. - - The context is the context variable from the sasl_callback_t - structure, the plugin_name is the name of plugin (or NULL), the - option is the option name, and the callback is expected to set the - result to a string valid till next call to sasl_getopt_t in the - same thread and the len to the length of that string. The result - and len parameters are never NULL. If the name of plugin is NULL, - a general SASL option is requested, otherwise a plugin specific - version. - - 3.4. Basic SASL C API Utility Routines - - This section describes utility functions provided as part of the - SASL API which may be used both by clients and servers. - - 3.4.1. sasl_decode64 function - - - - - - - - - - - -Newman et al. Expires: August 2003 FORMFEED[Page 11] - - - - - -INTERNET DRAFT SASL C API February 2003 - - -Arguments: - const char *in, - unsigned int inlen, - char *out, - unsigned int outmax, - unsigned int *outlen - -Results: - SASL_BUFOVER -- output buffer too small - SASL_BADPROT -- invalid base64 string - SASL_OK -- successful decode - - This utility routine converts a base64 string of length inlen - pointed by in into an octet string. It is useful for SASL profiles - which use base64 such as the IMAP [IMAP4] and POP [POP-AUTH] pro- - files. The output is copied to the buffer specified by the out - parameter. It is NUL terminated and the length of the output is - placed in the outlen parameter if outlen is non-NULL. The lenght - doesn't include the terminating NUL character. - - When the size of the output buffer, as specified by outmax, is too - small, the function returns SASL_BUFOVER error code and the - required length is stored in the outlen parameter if it is not - NULL. - - The function may also return SASL_BADPROT error code when it - encounters an invalid base64 character. - - 3.4.2. sasl_encode64 function - -Arguments: - const char *in, - unsigned int inlen, - char *out, - unsigned int outmax, - unsigned int *outlen - -Results: - SASL_BUFOVER -- output buffer too small - SASL_OK -- successful decode - - This utility routine converts an octet string of length inlen - pointed by in into a base64 string. It is useful for SASL profiles - which use base64 such as the IMAP [IMAP4] and POP [POP-AUTH] pro- - files. - - The output is copied to the buffer specified by the out parameter. - It is NUL terminated and the length of the output is placed in the - - - -Newman et al. Expires: August 2003 FORMFEED[Page 12] - - - - - -INTERNET DRAFT SASL C API February 2003 - - - outlen parameter if outlen is non-NULL. The lenght doesn't include - the terminating NUL character. - - When the size of the output buffer, as specified by outmax, is too - small, the function returns SASL_BUFOVER error code and the - required length is stored in the outlen parameter if it is not - NULL. - - 3.4.3. sasl_errstring function - -Arguments: - int saslerr, - const char *langlist, - const char **outlang - -Results: - const char * - - This converts a SASL error number into a constant string. The - second argument MAY be NULL for the default language, or a comma- - separated list of RFC 1766 language tags. The final parameter is - set to the RFC 1766 language tag of the string returned which will - be "i-default" if no matching language is found. The strings are - UTF-8. This requires no context so it may be used for the result - of an sasl_*_init or sasl_*_new result code. - - 3.4.4. sasl_errdetail function - -Arguments: - sasl_conn_t *conn - -Results: - const char * - - This converts the last SASL error code that occured on a connec- - tion to UTF8 string. It uses the SASL_CB_LANGUAGE callback (see - section 3.3.1) to determine the language to use. It may return - more detailed information than sasl_errstring does. - - 3.4.5. sasl_seterror function - - - - - - - - - - - -Newman et al. Expires: August 2003 FORMFEED[Page 13] - - - - - -INTERNET DRAFT SASL C API February 2003 - - -Arguments: - sasl_conn_t *conn - unsigned flags, - const char *fmt, - ... - -Results: - none - - This function sets sets the error string which will be returned by - sasl_errdetail. It uses syslog()-style formatting (i.e. printf- - style with %m as the string form of an errno error). - - Messages should be sensitive to the current language setting. If - there is no SASL_CB_LANGUAGE callback for the connection, text - MUST be in US-ASCII. Otherwise UTF-8 is used and use of RFC 2482 - for mixed-language text is encouraged. - - <> - - This function may be used by server callbacks. - - If conn is NULL, the function does nothing. - - 3.4.6. sasl_erasebuffer function - -Arguments: - char *buf, - unsigned len - -Results: - none - - This function fills the buffer buf of the lenght len with '\0' - characters. The function may be used to clear from memory sensi- - tive informations, like passwords. - - 3.5. Basic SASL C API Server Routines - - This section describes the basic routines for a server implementa- - tion of a SASL profile. - - 3.5.1. sasl_server_init function - - - - - - -Newman et al. Expires: August 2003 FORMFEED[Page 14] - - - - - -INTERNET DRAFT SASL C API February 2003 - - -Arguments: - const sasl_callback_t *callbacks, - const char *appname - -Results: - SASL_BADPARAM -- error in config file - SASL_NOMEM -- out of memory - SASL_BADVERS -- Plug-in version mismatch - SASL_OK -- success - - This function initializes the server routines for the SASL C API. - - The callbacks argument is the default list of callbacks (see sec- - tion 3.1.1 for definition of sasl_callback_t structure) and SHOULD - include the sasl_getopt_t callback (see section 3.3.3). The call- - backs may be NULL. The appname argument is the name of the calling - application and may be used by server plug-ins for logging. On - success, SASL_OK is returned, and on failure a SASL C API error - code is returned. This function may be called a second time to - change the default callbacks, but the first call must be made in a - single-threaded environment. The data referenced by the - sasl_callback_t structure must persist until sasl_done() is - called. - - appname specifies the application name. SASL API may use it, for - example, for logging or to read an application specific configura- - tion. A library must pass NULL as appname. appname can be also be - set with sasl_setprop function, and can be queried with sasl_get- - prop. <> - - 3.5.2. sasl_server_new function - - - - - - - - - - - - - - - - - - - - -Newman et al. Expires: August 2003 FORMFEED[Page 15] - - - - - -INTERNET DRAFT SASL C API February 2003 - - -Arguments: - const char *service, - const char *serverFQDN, - const char *user_realm, - const char *iplocalport, - const char *ipremoteport, - const sasl_callback_t *callbacks, - unsigned int flags, - sasl_conn_t **pconn - -Results: - SASL_OK -- success - SASL_NOTINIT -- SASL API not initialized - SASL_BADPARAM -- Invalid parameter supplied - SASL_NOMECH -- No mechanisms available - SASL_NOMEM -- Not enough memory - - This function creates a server connection context variable. As - long as each thread uses its own connection context, the SASL C - API is thread-safe. - - The service argument is an IANA registered GSSAPI service element - as defined in section 1.1. It MUST NOT be NULL. - - The serverFQDN is the fully qualified name of the server. It MUST - NOT be NULL. - - The user_realm specifies the default realm. A realm defines a set - of users on the system for systems which support multiple user - communities ("realms"). If user_realm is NULL, the value of - serverFQDN is used as the default realm. - - The iplocalport is the string with the server IPv4/IPv6 address, - followed by ":" and than by port number. An IPv6 address must be - enclosed in "[" and "]". NULL may be used for iplocalport, but may - result in mechanisms requiring IP address being unavailable. - - The ipremoteport is the string with the client IPv4/IPv6 address, - followed by ":" and than by port number. An IPv6 address must be - enclosed in "[" and "]". NULL may be used for ipremoteport, but - may result in mechanisms requiring IP address being unavailable. - - The callbacks argument is a set of server callbacks which may - include a connection-specific sasl_getopt_t and/or an authoriza- - tion routine. - - The flags argument represents server-supported security flags. The - only values currently supported are SASL_SECURITY_LAYER to - - - -Newman et al. Expires: August 2003 FORMFEED[Page 16] - - - - - -INTERNET DRAFT SASL C API February 2003 - - - indicate the server supports the SASL security layer, or 0 to - indicate it doesn't. - - The pconn argument is set to point to the newly created connection - context. - - 3.5.3. sasl_server_start function - -Arguments: - sasl_conn_t *conn, - const char *mech, - const char *clientin, - insigned int clientinlen, - const char **serverout, - unsigned int *serveroutlen - -Results: - SASL_CONTINUE -- Another authentication step required - SASL_OK -- Authentication Complete - SASL_NOTINIT -- SASL API not initialized - SASL_BADPARAM -- Invalid parameter supplied - SASL_BADPROT -- Client protocol error - SASL_NOMECH -- Mechanism not supported - SASL_NOVERIFY -- User exists, but no verifier exists for - the mechanism - SASL_TRANS -- A password transition is needed to use mechanism - - This begins an authentication exchange and is called after the - client sends the initial authentication command. The mech argu- - ment is the mechanism name the client is requesting. If the - client includes an optional initial-response, it is passed in the - clientin and clientinlen fields. Otherwise NULL and 0 are passed - for those arguments. The serverout and serveroutlen are filled in - with the server response, if any. If SASL_CONTINUE is returned, - the server will need to wait for another client message and call - sasl_server_step. If SASL_OK is returned, the authentication is - completed successfully, although server out data may be supplied. - - 3.5.4. sasl_server_step function - - - - - - - - - - - - -Newman et al. Expires: August 2003 FORMFEED[Page 17] - - - - - -INTERNET DRAFT SASL C API February 2003 - - -Arguments: - sasl_conn_t *conn, - const char *clientin, - insigned int clientinlen, - const char **serverout, - unsigned int *serveroutlen - -Results: - SASL_CONTINUE -- Another authentication step required - SASL_OK -- Authentication Complete - SASL_NOTINIT -- SASL API not initialized - SASL_NOMECH -- sasl_server_start not called - SASL_BADPARAM -- Invalid parameter supplied - SASL_BADPROT -- Client protocol error - SASL_NOVERIFY -- User exists, but no verifier exists for - the mechanism - SASL_TRANS -- A password transition is needed to use mechanism - - This routine performs one step in an authentication sequence. - - The conn argument must be a connection context created by - sasl_server_new and used in a previous call to sasl_server_start. - - The clientin and clientinlen parameters hold the SASL octet string - received from the client. Note that for those SASL profiles which - base64 encode the exchange, this is the result after the removal - of the base64 encoding (see the sasl_decode64 routine). The cli- - entin MUST have a terminating NUL character not counted by - serverinlen. - - The serverout and serveroutlen parameters hold the SASL octet - string to encode (if necessary) and send to the client. If - SASL_CONTINUE is returned, the server will need to wait for - another client message and call sasl_server_step. If SASL_OK is - returned, the authentication is completed successfully, although - server out data may be supplied. - - 3.6. Common SASL API Routines - - This section describes the routines that are common to both - clients and servers. - - 3.6.1. sasl_listmech function - - - - - - - - -Newman et al. Expires: August 2003 FORMFEED[Page 18] - - - - - -INTERNET DRAFT SASL C API February 2003 - - -Arguments: - sasl_conn_t *conn, - const char *user, - const char *prefix, - const char *sep, - const char *suffix, - char **result, - unsigned int *plen, - unsigned *pcount - -Results: - SASL_OK -- Success - SASL_NOMEM -- Not enough memory - SASL_NOMECH -- No enabled mechanisms - - This returns a list of enabled SASL mechanisms in a NUL-terminated - string. The list is constructed by placing the prefix string at - the beginning, placing the sep string between any pair of mecha- - nisms and placing the suffix string at the end. - - When calling this function plen and pcount MAY be NULL. - - This function returns the list of client side SASL mechanisms, if - the conn was created by sasl_client_new and the list of server - side mechanisms, if the conn was created by sasl_server_new. The - list returned by this function must persist till a next call to - sasl_free_listmech or sasl_listmech. - - 3.6.2. sasl_free_listmech function - -Arguments: - sasl_conn_t *conn, - char **result - -Results: - none - - This disposes of the result string returned by sasl_listmech. - - 3.6.3. sasl_setprop function - - - - - - - - - - - -Newman et al. Expires: August 2003 FORMFEED[Page 19] - - - - - -INTERNET DRAFT SASL C API February 2003 - - -Arguments: - sasl_conn_t *conn, - int propnum, - const void *value - -Results: - SASL_OK -- property set - SASL_BADPARAM -- invalid propnum or value - SASL_NOMEM -- not enough memory to perform operation - - This sets a property in a connection context. Commonly used prop- - erties with their descriptions are listed below: - - SASL_SSF_EXTERNAL - - Security layer strength factor (SSF) -- an unsigned integer usable - by the caller to specify approximate security layer strength - desired. It roughly corresponds to the effective key length for - encryption, e.g. - 0 = no protection - 1 = integrity protection only >1 = key lenght of the cipher - - SASL_SSF_EXTERNAL property denotes SSF of the external security - layer (e.g. provided by TLS). The value parameter points to - sasl_ssf_t, that is described as follows: - - typedef unsigned sasl_ssf_t; - - - - SASL_SEC_PROPS - - The value parameter for SASL_SEC_PROPS points to sasl_secu- - rity_properties_t structure defined below. A particular implemen- - tation may extend it with additional fields. - - typedef struct sasl_security_properties - { - sasl_ssf_t min_ssf; - sasl_ssf_t max_ssf; - - unsigned maxbufsize; - - /* bitfield for attacks to protect against */ - unsigned security_flags; - } sasl_security_properties_t; - - The min_ssf and the max_ssf define the minimal and the maximal - - - -Newman et al. Expires: August 2003 FORMFEED[Page 20] - - - - - -INTERNET DRAFT SASL C API February 2003 - - - acceptable SSF. - - The maxbufsize specifies the biggest buffer size that the - client/server is able to decode. 0 means that security layer is - not supported. - - The security_flags is a bitmask of the various security flags - described below: - - SASL_SEC_NOPLAINTEXT -- don't permit mechanisms susceptible to simple - passive attack (e.g., PLAIN, LOGIN) - SASL_SEC_NOACTIVE -- protection from active (non-dictionary) attacks - during authentication exchange. - Authenticates server. - SASL_SEC_NODICTIONARY -- don't permit mechanisms susceptible to passive - dictionary attack - SASL_SEC_FORWARD_SECRECY -- require forward secrecy between sessions - (breaking one won't help break next) - SASL_SEC_NOANONYMOUS -- don't permit mechanisms that allow anonymous login - SASL_SEC_PASS_CREDENTIALS -- require mechanisms which pass client - credentials, and allow mechanisms which can pass - credentials to do so - SASL_SEC_MUTUAL_AUTH -- require mechanisms which provide mutual - authentication - - SASL_AUTH_EXTERNAL - - The value parameter for SASL_AUTH_EXTERNAL property points to the - external authentication ID as provided by external authentication - method, e.g. TLS, PPP or IPSec. - - 3.6.4. sasl_getprop function - -Arguments: - sasl_conn_t *conn, - int propnum, - const void **pvalue - -Results: - SASL_OK -- Success - SASL_NOTDONE -- Authentication exchange must complete prior to - retrieving this attribute - SASL_BADPARAM -- bad property number - - This requests a pointer to a constant property available through - the SASL API. The most common use by servers is to get the - SASL_USERNAME property which returns the authorization identity - (user to login as) from the SASL mechanism as a UTF-8 string in - - - -Newman et al. Expires: August 2003 FORMFEED[Page 21] - - - - - -INTERNET DRAFT SASL C API February 2003 - - - the pvalue parameter. Additional properties are listed in section - 6. - - 3.6.5. sasl_dispose function - -Arguments: - sasl_conn_t **pconn - -Results: - none - - This function disposes of the connection state created with - sasl_client_new or sasl_server_new, and sets the pointer to NULL. - If the pconn is already NULL the function does nothing. - - 3.6.6. sasl_done function - -Arguments: - none - -Results: - none - - A SASL application that is finished with the SASL API must call - this function. This function frees any memory allocated by the - SASL library or any other library state. After this call most of - the SASL API function will again return the SASL_NOTINIT error - code. - - There must be a call to sasl_done for every successful call to - sasl_server_init or sasl_client_init made. Only the final - sasl_done does the actual cleanup; the preceding calls simply - decrement an internal reference count. - - Connection states MUST be disposed of with sasl_dispose before - calling this function. - -4. SASL Security Layer Routines - - This section describes the routines need to support a security - layer. - - 4.1. sasl_encode function - - - - - - - - -Newman et al. Expires: August 2003 FORMFEED[Page 22] - - - - - -INTERNET DRAFT SASL C API February 2003 - - -Arguments: - sasl_conn_t *conn, - const char *input, - unsigned int inputlen, - const char **output, - unsigned int *outputlen - -Results: - SASL_OK -- Success (returns input if no layer negotiated) - SASL_NOTDONE -- Security layer negotiation not finished - SASL_BADPARAM -- inputlen is greater than the SASL_MAXOUTBUF property - - This function encodes a block of data for transmission using secu- - rity layer (if any). The output and outputlen are filled in with - the encoded data and its length respectively. If there is no secu- - rity layer the input buffer is returned in the output. Otherwise, - the output is only valid until a next call to sasl_encode or - sasl_dispose. - - 4.1. sasl_decode function - -Arguments: - sasl_conn_t *conn, - const char *input, - unsigned int inputlen, - const char **output, - unsigned int *outputlen - -Results: - SASL_OK -- Success (returns input if no layer negotiated) - SASL_NOTDONE -- Security layer negotiation not finished - SASL_BADMAC -- Bad message integrity check - - This function decodes a block of data received using security - layer (if any). The output and outputlen are filled in with the - decoded data and its length respectively. If there is no security - layer the input buffer is returned in the output. Otherwise, the - output is only valid until a next call to sasl_decode or sasl_dis- - pose. - -5. Advanced SASL API Routines - - This section describes the less frequently used functions avail- - able in the SASL API. - - 5.1. Additional Initialization Routines - - 5.1.1. sasl_set_mutex function - - - -Newman et al. Expires: August 2003 FORMFEED[Page 23] - - - - - -INTERNET DRAFT SASL C API February 2003 - - -Arguments: - sasl_mutex_alloc_t *mutex_alloc, - sasl_mutex_lock_t *mutex_lock, - sasl_mutex_unlock_t *mutex_unlock, - sasl_mutex_free_t *mutex_free - -Results: - None - - The sasl_set_mutex call sets the callbacks which the SASL API and - plug-ins will use whenever exclusive access to a process shared - resource is needed. A single-threaded client or server need not - call this. The types are designed to be compatible with the LDAP - API [LDAP-API]: - - typedef void *sasl_mutex_alloc_t(void); - - On success, this returns a pointer to an allocated and initialized - mutex structure. On failure, it returns NULL. - - typedef int sasl_mutex_lock_t(void *mutex); - - This will block the current thread until it is possible to get an - exclusive lock on a mutex allocated by the mutex_alloc callback. - On success it returns 0, on failure due to deadlock or bad parame- - ter, it returns -1. - - typedef int sasl_mutex_unlock_t(void *mutex); - - This releases a lock on a mutex allocated by the mutex_alloc call- - back. On success it returns 0, on failure due to an already - unlocked mutex, or bad parameter, it returns -1. - - typedef void sasl_mutex_free_t(void *mutex); - - This disposes of a mutex allocated by mutex_alloc. - - 5.1.2. sasl_set_alloc function - - - - - - - - - - - - - -Newman et al. Expires: August 2003 FORMFEED[Page 24] - - - - - -INTERNET DRAFT SASL C API February 2003 - - -Arguments: - sasl_malloc_t *malloc, - sasl_calloc_t *calloc, - sasl_realloc_t *realloc, - sasl_free_t *free - -Results: - None - - This sets the memory allocation functions which the SASL API will - use. The SASL API will use its own routines (usually the standard - C library) if these are not set. - - typedef void *sasl_malloc_t(unsigned long mem_size); - - This allocates memory mem_size bytes of memory. The memory is not - initialized to any particular value. It returns NULL on a fail- - ure, or when mem_size is 0. - - typedef void *sasl_calloc_t(unsigned long elem_size, - unsigned long num_elem); - - This allocates elem_size * num_elem bytes of memory. The memory - is initialized to 0. It returns NULL on a failure or when either - elem_size and/or num_elem is 0. - - typedef void *sasl_realloc_t(void *mem_ptr, unsigned long - new_size); - - This changes the size of a memory block previously allocated by - malloc or calloc, and returns a pointer to the new location (which - may be different from mem_ptr). If mem_ptr is NULL, it is identi- - cal to the malloc function. - - It returns NULL on a failure or when new_size is 0. On failure the - original block is unchanged. When new_size is 0 the function works - as the free function. - - typedef void sasl_free_t(void *mem_ptr); - - This releases the memory in mem_ptr that was allocated by the mal- - loc or the calloc or resized by the realloc. If mem_ptr is NULL, - the function does nothing and returns immediately. The contents of - the memory may be altered by this call. - -6. Additional Properties - - <> - - - -Newman et al. Expires: August 2003 FORMFEED[Page 25] - - - - - -INTERNET DRAFT SASL C API February 2003 - - - SASL_SSF -- security layer security strength factor, - if 0, call to sasl_encode, sasl_decode unnecessary - SASL_MAXOUTBUF -- security layer max output buf unsigned - SASL_DEFUSERREALM -- default realm passed to sasl_server_new or set with - sasl_setprop - SASL_GETOPTCTX -- context for getopt callback - SASL_CALLBACK -- current callback function list - SASL_IPLOCALPORT -- iplocalport string passed to sasl_server_new/ - sasl_client_new - SASL_IPREMOTEPORT -- ipremoteport string passed to sasl_server_new/ - sasl_client_new - SASL_SERVICE -- service passed to sasl_*_new - SASL_SERVERFQDN -- serverFQDN passed to sasl_*_new - SASL_AUTHSOURCE -- name of the active plugin, if any - SASL_MECHNAME -- active SASL mechanism name, if any - SASL_AUTHUSER -- authentication/admin user (authorization id?) - -7. References - - [IMAP4] Crispin, M., "Internet Message Access Protocol - Version - 4rev1", RFC 2060, University of Washington, December 1996. - - [KEYWORDS] Bradner, "Key words for use in RFCs to Indicate - Requirement Levels", RFC 2119, Harvard University, March 1997. - - [POP3] Myers, J., Rose, M., "Post Office Protocol - Version 3", - RFC 1939, Carnegie Mellon, Dover Beach Consulting, Inc., May 1996. - - [POP-AUTH] Myers, "POP3 AUTHentication command", RFC 1734, - Carnegie Mellon, December 1994. - - [SASL] Myers, "Simple Authentication and Security Layer (SASL)", - RFC 2222, Netscape Communications, October 1997. - - [GSSAPI] - -8. Acknowledgements - - The editor would like to thank Rob Siemborski and Ken Murchison - for providing useful feedback and suggestions. - -9. Author's and Editor's Addresses - - - Author: - - Chris Newman - Innosoft International, Inc. - - - -Newman et al. Expires: August 2003 FORMFEED[Page 26] - - - - - -INTERNET DRAFT SASL C API February 2003 - - - 1050 Lakes Drive - West Covina, CA 91790 USA - - Email: chris.newman@innosoft.com - - - Editor: - - Alexey Melnikov - ACI WorldWide/MessagingDirect - 59 Clarendon Road - Watford, Hertfordshire, WD17 1FQ, UK - - Email: mel@messagingdirect.com - - -10. Full Copyright Statement - - Copyright (C) The Internet Society (2003). All Rights Reserved. - - This document and translations of it may be copied and furnished to - others, and derivative works that comment on or otherwise explain it - or assist in its implementation may be prepared, copied, published - and distributed, in whole or in part, without restriction of any - kind, provided that the above copyright notice and this paragraph are - included on all such copies and derivative works. However, this doc- - ument itself may not be modified in any way, such as by removing the - copyright notice or references to the Internet Society or other - Internet organizations, except as needed for the purpose of develop- - ing Internet standards in which case the procedures for copyrights - defined in the Internet Standards process must be followed, or as - required to translate it into languages other than English. - - The limited permissions granted above are perpetual and will not be - revoked by the Internet Society or its successors or assigns. - - This document and the information contained herein is provided on an - "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING - TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING - BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION - HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MER- - CHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - -Acknowledgement - - Funding for the RFC Editor function is currently provided by the - Internet Society. - - - - -Newman et al. Expires: August 2003 FORMFEED[Page 27] - - - - - -INTERNET DRAFT SASL C API February 2003 - - -A. Appendix A -- Design Goals - - The design goals of the SASL C API are as follows: - - -o To be simple and practical to use. - -o To provide related utility services in addition to core SASL func- - tionality. - -o To be reasonably extensible. - -o To be suitable for use in a multi-threaded server or client. - -o To avoid dependancies on a specific memory allocation system, thread - package or network model. - -o To be an independent service rather than a new layer. - - -B. SASL API Index - -<> - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Newman et al. Expires: August 2003 FORMFEED[Page 28] - - - diff --git a/doc/draft-newman-sasl-passdss-xx.txt b/doc/draft-newman-sasl-passdss-xx.txt deleted file mode 100644 index 4aa7cb81..00000000 --- a/doc/draft-newman-sasl-passdss-xx.txt +++ /dev/null @@ -1,1122 +0,0 @@ - - - - - - -Network Working Group C. Newman -Internet Draft: PASSDSS-3DES-1 SASL Mechanism Innosoft -Document: draft-newman-sasl-passdss-01.txt March 1998 - Expires in six months - - - DSS Secured Password Authentication Mechanism - - -Status of this memo - - This document is an Internet-Draft. Internet-Drafts are working - documents of the Internet Engineering Task Force (IETF), its areas, - and its working groups. Note that other groups may also distribute - working documents as Internet-Drafts. - - Internet-Drafts are draft documents valid for a maximum of six - months and may be updated, replaced, or obsoleted by other - documents at any time. It is inappropriate to use Internet-Drafts - as reference material or to cite them other than as "work in - progress." - - To view the entire list of current Internet-Drafts, please check - the "1id-abstracts.txt" listing contained in the Internet-Drafts - Shadow Directories on ftp.is.co.za (Africa), ftp.nordu.net - (Europe), munnari.oz.au (Pacific Rim), ds.internic.net (US East - Coast), or ftp.isi.edu (US West Coast). - - -Abstract - - Some system administrators are faced with a choice between - deploying a new authentication infrastructure or sending - unencrypted passwords in the clear over the Internet. Deploying a - new authentication infrastructure often involves modifying - operating system services or keeping parallel authentication - databases up to date and is thus unacceptable to many - administrators. - - Solutions which encrypt the entire session are often crippled with - weak keys (due to government restrictions) which are unsuitable for - passwords. In addition, such solutions often reduce performance of - the entire session to an unacceptable level. This specification - defines a SASL [SASL] mechanism which is compatible with existing - password-based authentication databases and does not require a - security layer for the remainder of the session. - - [NOTE: Public discussion of this mechanism may take place on the - - - -Newman [Page 1] - -Internet Draft PASSDSS-3DES-1 SASL Mechanism March 1998 - - - ietf-sasl@imc.org mailing list with a subscription address of - ietf-sasl-request@imc.org. Private comments may be sent to the - author]. - -1. How to Read This Document - - This document is intended primarily for a programmer. If - successful, it should be possible for a competent programmer to - write a client implementation using this specification, the SASL - [SASL] specification, an understanding of how to generate random - numbers [RANDOM], a description or implementation of the DES and - SHA1 [SHA1] algorithms and a multi-precision integer math library. - A cryptographic library or a copy of "Applied Cryptography" - [SCHNEIER] or similar reference is helpful for any implementation - and necessary for server DSS key generation. - - The key words "MUST", "MUST NOT", "SHOULD", "SHOULD NOT", and "MAY" - in this document are to be interpreted as defined in "Key words for - use in RFCs to Indicate Requirement Levels" [KEYWORDS]. - -1.1. Data Types Used in this Document - - A list of data types used in this document follows. Note that the - majority of this section is copied from the secure shell - specification [SSH-ARCH]. - - octet A basic 8-bit unit of data. - - uint32 A 32-bit unsigned integer. Stored as four octets in - network byte order (also known as big endian or most - significant byte [MSB] first). For example, the decimal - value 699921578 (hexadecimal 29b7f4aa) is represented with - the hexadecimal octet sequence 29 b7 f4 aa. - - string A string is a length-prefixed octet string. The length is - represented as a uint32 with the data immediately - following. A length of 0 indicates an empty string. The - string MAY contain NUL or 8-bit octets. When used to - represent textual strings, the characters are interpreted - in UTF-8 [UTF-8]. Other character encoding schemes MUST - NOT be used. - - mpint Represents multiple precision integers in two's complement - format, stored as a string, most significant octet first. - Negative numbers have one in the most significant bit of - the first octet of the string data. If the most significant - bit would be set for a positive number, the number MUST be - preceded by a zero byte. Unnecessary leading zero or 255 - - - -Newman [Page 2] - -Internet Draft PASSDSS-3DES-1 SASL Mechanism March 1998 - - - bytes MUST NOT be included. The value zero MUST be stored - as a string with zero bytes of data. - - By convention, a number that is used in modular - computations in the field of integers mod n SHOULD be - represented in the range 0 <= x < n. - - Examples: - - value (hex) representation (hex) - ----------------------------------------------------------- - 0 00 00 00 00 - 9a378f9b2e332a7 00 00 00 08 09 a3 78 f9 b2 e3 32 a7 - 80 00 00 00 02 00 80 - -1234 00 00 00 02 ed cc - -deadbeef 00 00 00 05 ff 21 52 41 11 - -1.2. Glossary - - This section includes some acronyms used in this document. - - DES The U.S. Government Data Encryption Standard is a symmetric - encryption algorithm introduced in 1975 which uses a 56 bit - key. The algorithm is documented in [SCHNEIER]. - - DSA The U.S. Government Digital Signature Algorithm standard. A - public key signature algorithm available for unrestricted use - without a license. - - DSS The U.S. Government Digital Signature Standard [DSS] which - employs the DSA algorithm. - - HMAC A hash-based message authentication code [HMAC] summarized in - Appendix A.4. Test cases are available in [HMAC-TEST]. - - SHA The Secure Hash Algorithm (version 1) which is part of the DSS - standard. - - triple-DES - Use of the DES algorithm three times in an encrypt-decrypt- - encrypt mode with three independent keys as described in - appendix A.3. - -2. Overview - - This section includes a brief discussion of design goals, intended - use and an overview for this SASL mechanism. An overview of some - of the algorithms used is in Appendix A. - - - -Newman [Page 3] - -Internet Draft PASSDSS-3DES-1 SASL Mechanism March 1998 - - -2.1. Design Goals - - The ideal authentication mechanism would be simple, fast, fully - secure, freely distributable without restrictions and backwards - compatible with deployed back-end authentication databases. - Unfortunately, it is not possible to achieve all these goals so - priorities and tradeoffs are necessary. This mechanism has - compatibility with deployed back-end authentication databases and - protection from passive and active attacks on the underlying - connection as primary design goals. Simplicity and unrestricted - binary distribution are secondary design goals. - - Backwards compatibility is achieved by using plain-text - passphrases. Protection from passive and active attacks is - achieved by using public and symmetric key technology to encrypt - the passphrase and optionally protect the remainder of the session. - Some simplicity is achieved by avoiding complicated public key - certification issues and formats as well as making the SASL session - security layer and certification by the client optional. - Unrestricted binary distribution is hopefully achieved by using - unencumbered algorithms and making the SASL privacy layer optional. - -2.2. Intended Use - - This is intended as a plug-and-play mechanism for services layered - on top of deployed passphrase-based back-end authentication - databases. When no security layer is implemented it can be added - to a SASL-based protocol without modifying or substituting network - read and write APIs. When the optional session privacy protection - is omitted, the author speculates that it may be possible to make a - binary implementation which would be exportable from the United - States. - - For cases where simplicity, speed or unrestricted source code - distribution is more desirable than backwards compatibility or - security, a mechanism such as CRAM-MD5 [CRAM-MD5] or SCRAM [SCRAM] - is preferred. - - The optional SASL integrity and privacy protection is provided as a - simple alternative to full service security layers such as TLS - [TLS] or Secure Shell [SSH-ARCH]. However, there are many - advantages to full service security layers such as compression, - faster symmetric cipher options, and the ability to leverage other - public key infrastructures. An implementation which supports TLS - may have no incentive to support SASL security layers at all. The - complexity verses functionality tradeoff is significant enough that - these mechanisms do not compete. - - - - -Newman [Page 4] - -Internet Draft PASSDSS-3DES-1 SASL Mechanism March 1998 - - -2.3. Mechanism Overview - - The PASSDSS-3DES-1 mechanism uses three components to perform a - secure authentication against a legacy passphrase database. - - In order to protect against active attacks, a DSS public key in a - format compatible with Secure Shell [SSH-TRANS] is used to - authenticate the server to the client. The client is presumed to - have the server's public key or a SHA-1 hash thereof stored locally - in a secure database. If the client is willing to risk exposure to - active attacks, it may skip the public key certification step - altogether or do a one-time initialization of its local database, - perhaps with user interaction. - - In addition to the DSS public key, a Diffie-Hellman key exchange is - used to generate a key for encrypting the passphrase. The - "PASSDSS-3DES-1" variant of this mechanism uses the same fixed - Diffie-Hellman group used by Secure Shell's diffie-hellman-group1- - sha1 key exchange [SSH-TRANS]. If more groups are necessary, they - will be assigned to mechanism variants "PASSDSS-3DES-2" and so - forth. - - Finally, the triple-DES algorithm is used to encrypt the client's - passphrase and send it to the server. - -2.4. Message Format Overview - - This section provides a quick overview of the format of the - messages. The formal definition of the syntax for these messages - is in section 6. A detailed discussion of their implementation on - clients and servers is in sections 3 and 4 respectively. - - First message from client to server: - string azname ; the user name to login as, may be empty if - same as authentication name - string authname ; the authentication name - mpint X ; Diffie-Hellman parameter X - - The challenge from server to client is as follows: - uint32 pklength ; length of SSH-style DSA server public key - string "ssh-dss" ; constant string "ssh-dss" (lower case) - mpint p ; DSA public key parameters - mpint q - mpint g - mpint y - mpint Y ; Diffie-Hellman parameter Y - OCTET ssecmask ; SASL security layers offered - 3 OCTET sbuflen ; maximum server security layer block size - - - -Newman [Page 5] - -Internet Draft PASSDSS-3DES-1 SASL Mechanism March 1998 - - - uint32 siglength ; length of SSH-style dss signature - string "ssh-dss" ; constant string "ssh-dss" (lower case) - mpint r ; DSA signature parameters - mpint s - - The client then sends the following message encrypted with - triple-DES: - OCTET csecmask ; SASL security layer selection - 3 OCTET cbuflen ; maximum client block size - string passphrase ; the user's passphrase - 20 OCTET cli-hmac ; a client HMAC-SHA-1 signature - -3. Client Implementation of PASSDSS-3DES-1 - - This section includes a step-by-step guide for client implementors. - Although section 6 contains the formal definition of the syntax and - is the authoritative reference in case of errors here, this section - should be sufficient to build a correct implementation. - - The SASL mechanism name is "PASSDSS-3DES-1". - - The value of n used for the Diffie-Hellman exchange is as follows - (represented as an unsigned hexadecimal integer): - - FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 - 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD - EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 - E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED - EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381 - FFFFFFFF FFFFFFFF. - - When represented as an "mpint", this would have a prefix of - "0000008100." The value of g is 2. This group was taken from the - ISAKMP/Oakley specification, and was originally generated by - Richard Schroeppel at the University of Arizona. Properties of - this prime are described in [Orm96]. - - The client begins by doing the following: - - (A) Generate the Diffie-Hellman private value "x". This should be - less than (n - 1)/2. The number of bits of entropy to use in "x" - is an important decision, as shorter lengths will be less secure - and longer lengths will noticeably reduce performance. At the time - this was written, 192 bits of entropy [RANDOM] is probably - sufficient. For more information on this topic, see [SHORT-EXP]. - - - - - - -Newman [Page 6] - -Internet Draft PASSDSS-3DES-1 SASL Mechanism March 1998 - - - (B) Compute the Diffie-Hellman public value "X" as follows. If X - has a value of 0, repeat step (A). - x - X = 2 mod n - - The client then sends the following three pieces of information to - the server: - - (1) An authorization identity represented as a string. When the - empty string is used, this defaults to the authentication identity. - This is used by system administrators or proxy servers to login - with a different user identity. - - (2) An authentication identity represented as a string. This is - the identity whose passphrase will be used. - - (3) The "X" result from step (B) represented as an mpint. - - The server responds by sending a message containing the following - information: - - (4) An "ssh-dss" public key compatible with Secure Shell, including - the 32-bit length prefix in network byte order, the Secure Shell - string "ssh-dss" and mpints for "p", "q", "g" and "y" (see Appendix - A.1). - - (5) The mpint "Y" as defined for the Diffie-Hellman key exchange - (see Appendix A.2). - - (6) A single octet bit mask representing the security layers - available in the same format used by the KERBEROS_V4 mechanism - [SASL]. Bit 0 (value 1) indicates it is permissible to have no - security layer. Bit 1 (value 2) indicates integrity protection is - permissible. Bit 2 (value 4) indicates privacy protection for the - rest of the session is available. The remaining bits are reserved - for future use. - - (7) A three octet unsigned integer in network byte order - representing the maximum cipher-text buffer size the server is able - to receive. If this is less than 32, it indicates that a SASL - security layer is not supported. - - (8) A DSA signature, including a 32-bit length, the Secure Shell - string "ssh-dss" and mpints for "r" and "s". - - The client then does the following: - - (C) Verify that "Y" is between 1 and n - 1 inclusive. If "Y" is - - - -Newman [Page 7] - -Internet Draft PASSDSS-3DES-1 SASL Mechanism March 1998 - - - outside this range, the client MUST cancel the authentication. - - (D) Verify that the public key from step (4) belongs to the server. - This can be done either with a database of SSH public keys or with - a database of SHA1 hashes of such public keys. If the client does - not have a matching entry for the server or does not have a public - key database, it MAY skip this step although it SHOULD alert the - user that the connection is susceptible to active attacks if it - does so. It MAY also record the public key (or SHA1 hash thereof) - in its database with permission from the user. - - (E) Compute the Diffie-Hellman key K as follows. It may be - necessary to mask timing attacks [TIMING]. - x - K = Y mod n - - (F) Create a buffer containing data from steps (1) through (7) in - order immediately followed by K represented as an mpint. - - (G) Compute the SHA1 hash of the buffer from (F). This produces a - 20 octet result. - - (H) If the public key from step (4) was not certified, this step - MAY be skipped. Otherwise, verify that the DSS signature is a - signature of (G). This computation is done as defined in appendix - A.1 where the output of step (G) represents the message "m" (note - that this results in SHA1 being applied twice). - - (I) Compute the following 20-octet values. K represents the output - of step (E) in mpint format. H represents the output of step (G). - The || symbol represents string concatenation. "A" represents a - single octet containing the US-ASCII value of capital letter A. - cs-encryption-iv = SHA1( K || "A" || H ) - sc-encryption-iv = SHA1( K || "B" || H ) - cs-encryption-key-1 = SHA1( K || "C" || H ) - cs-encryption-key-2 = SHA1( K || cs-encryption-key-1 ) - cs-encryption-key = cs-encryption-key-1 || cs-encryption-key-2 - sc-encryption-key-1 = SHA1( K || "D" || H ) - sc-encryption-key-2 = SHA1( K || sc-encryption-key-1 ) - sc-encryption-key = sc-encryption-key-1 || sc-encryption-key-2 - cs-integrity-key = SHA1( K || "E" || H ) - sc-integrity-key = SHA1( K || "F" || H ) - - (J) Create a buffer beginning with a bit mask for the selected - security layer (it MUST be one offered in 6) followed by three - octets representing the maximum cipher-text buffer size (at least - 32) the client can accept in network byte order. This is followed - by a string containing the passphrase. Note that integrity - - - -Newman [Page 8] - -Internet Draft PASSDSS-3DES-1 SASL Mechanism March 1998 - - - protection is pointless unless the public key was certified in - step (D) and the signature was verified in step (H). - - (K) Create a buffer containing items (1) through (7) immediately - followed by the first four octets of (J). - - (L) Compute HMAC-SHA-1 with (K) as the data and the cs-integrity- - key from step (I) as the key. This produces a 20 octet result. A - summary of the HMAC-SHA-1 algorithm [HMAC] is in appendix A.4. - - (M) Create a buffer containing (J) followed by (L) followed by an - arbitrary number of zero octets as necessary to reach the block - size of DES and conceal the passphrase length from an eavesdropper. - - (N) Apply the triple-DES algorithm to (M) with the first 8 octets - of cs-encryption-iv from step (I) as the initialization vector and - the first 24 octets of cs-encryption-key as the key. If optional - privacy protection is negotiated on, the triple-DES state is not - reset. - - The client then sends a message to the server containing the - following: - - (9) The output of step (N). - - If a SASL security layer is negotiated on, the following steps are - used when sending a message: - - (O) Create a buffer containing a uint32 client packet number - (starting from 0) immediately followed by the cs-integrity-key from - step (I). - - (P) Compute HMAC-SHA-1 with (O) as the key and the data to transmit - as the data. - - (Q) Create a buffer containing the data to transmit followed by the - 20-octet output of (P). If privacy was negotiated on, this is - followed by zero to seven padding octets followed by one more octet - indicating the number of padding octets. The total size MUST be a - multiple of the DES block size. - - (R) The result of step (Q) is encrypted with triple-DES if privacy - was negotiated and is sent prefixed by a uint32 length, as required - by SASL. - - If a SASL security layer was negotiated on, the following steps are - taken when receiving a message: - - - - -Newman [Page 9] - -Internet Draft PASSDSS-3DES-1 SASL Mechanism March 1998 - - - (S) If privacy was negotiated on, the message is decrypted using - triple-DES with the first 24 octets of sc-encryption-key as the - key. The value of the last octet plus one indicates the number of - octets to ignore at the end of the output. The sc-encryption-iv is - used to initialize triple-DES state the first time this is done. - - (T) Create a buffer containing a uint32 server packet number - (starting from 0) immediately followed by the sc-integrity-key. - - (U) Compute HMAC-SHA-1 with (T) as the key over the portion of the - data excluding the 20 octet signature and any encryption padding. - If this is the same as the 20 octet signature, then the data is not - corrupted. - -4. Server Implementation of PASSDSS-3DES-1 - - The section includes a step-by-step guide for server implementors. - It is intended to be read in conjunction with section 3. - - The server MUST have a persistent DSS-SSH public key. Mechanisms - for generating such keys are described in [SCHNEIER] and [DSS]. - - IMPORTANT NOTE: The server MUST be able to process any message from - the client, including messages of any size, messages with invalid - content and messages with NULs in the middle of strings. When - input is illegal, the server MUST gracefully reject authentication - or in extreme cases gracefully terminate the connection. - Particular care to avoid buffer overruns is important if the user - name or passphrase strings are copied. - - The server performs the following computations prior to or during - the connection by the client: - - (a) Select a random number k less than (p - 1)/2. It is important - to generate a good random number [RANDOM]. - - (b) Compute signature component "r" as follows: - k - r = (g mod p) mod q - - (c) Optionally pre-compute the group inverse of k, mod q and the - value xr. - - (d) Select a random Diffie-Hellman private key y less than (n - - 1)/2. Follow the same guidance as in (A) above. - - - - - - -Newman [Page 10] - -Internet Draft PASSDSS-3DES-1 SASL Mechanism March 1998 - - - (e) Compute the Diffie-Hellman public value Y as follows. If Y has - a value of 0, repeat step (d) above. - y - Y = 2 mod n - - (f) Verify that the value X from the client is between 1 and (n - - 1). If it isn't, fail the authentication. - - (g) Compute the Diffie-Hellman shared key K as follows. It may be - necessary to mask timing attacks [TIMING]. - y - K = X mod n - - (h) Create a buffer containing items (1) through (7) above followed - by K represented as an mpint. - - (i) Compute the SHA-1 hash of the buffer from (h). This produces a - 20 octet result. - - (j) Generate a DSS signature of (i). The signature is made up of - "r" from step (b) and the result following computation (partially - completed in step c): - -1 - s = (k (SHA1(h) + xr)) mod q - - (k) Create a buffer containing items (4) through (8) and send it to - the client. - - (l) Perform the computations as described in step (I) where K is - the result of step (g) in mpint format and H is the result of step - (i). - - (m) Decrypt message (9) from the client using triple-DES with cs- - encryption-iv as the initialization vector and the first 24 octets - of cs-encryption-key as the key. - - (n) Verify the passphrase from the output of step (m) against the - authentication database. Fail the authentication if verification - fails. - - (o) Verify that the selected security layer is permitted and the - cipher text buffer size is at least 32. If not, fail the - authentication. - - (p) Create a buffer containing steps (1) through (7) followed by - the first four octets of the result from (m). - - (q) Compute the HMAC-SHA-1 of (p) with cs-integrity-key as the key. - - - -Newman [Page 11] - -Internet Draft PASSDSS-3DES-1 SASL Mechanism March 1998 - - - This produces a 20-octet result. - - (r) Compare the output of (q) with the 20 octet signature after the - passphrase in the output of (m). If they don't match, fail the - authentication. - - If a SASL security layer is negotiated on, sending and receiving - procedures are similar to steps (O)-(U), with client and server - roles exchanged (and thus sc-* values and cs-* value exchanged). - Note that triple-DES state from step (m) is not reset. - -5. Example - - The following is an example of the PASSDSS-3DES-1 mechanism using - the IMAP [IMAP4] profile of SASL. Note that base64 encoding and - the lack of an initial client response with the first command are - characteristics of the IMAP profile of SASL and not characteristics - of SASL or this mechanism. - - In this example, "C:" represents lines sent from the client to the - server and "S:" represents lines sent from the server to the - client. The wrapped lines are for editorial clarity -- there are - no actual newlines in the middle of the messages. - - C: a001 AUTHENTICATE PASSDSS-3DES-1 - S: + - C: AAAAAAAAAAVjaHJpcwAAAIEAhuVbMxdLxrAQVyUWbAp+X09h6QmZ2Jebz - H7YhtcbQyLbB9AGi1eIdojZYtAuVeE+PYkKUANLHI9XzWSFliIGMeUvBc - bflHr+s9tZ5/5YZh9blb33km3tUYVKyB5XP530bDn+lY1lAv6tXHKZPrx - b0zPhc+JGgpWGlmT5k9vx2Wk= - S: + AAAA8gAAAAdzc2gtZHNzAAAAQQDPVlO6nFefrq6fA/dQKIoNj75Jjpp - kVv3DkyILABCox2dMql0bnO48rHFuo167y6oukT/ocKupIw6bgKmdofgd - AAAAFQDRpB6FrxemUGRuLjY/oiH/Qef14QAAAEEAkVr9rOlB58k5XoqmP - NYTrVGZKWbCPcYtaL92ANxgWyjyRo49+m0+fHPNhNibQoLddEZF8lHPKW - gb7z7qz0QMdgAAAEARcIEiMz5jTZo8COf2njL3BTWRND5NGAgZY7s1YOm - 2BfjVyf1/MkOiQMiXeonrsfMc0sWQGgpRYRtJWpe56cc2AAAAgQDoV5Uk - bcy3Gjf16MZwPLlJlvmjpSNv2dSSApoddd4+BgZr01zyt7hzb0yRruaN5 - fG43DbJLkk7mtL1Hw8aYXBMQQzrPpHtx+anpCDoN2jlersCGFY2cnjxTf - HqY139ohA8vVXYpapeXxKXR4//Ib/ApTGmwlOeIikKDrBmEGX/JgEAAAA - AAAA8AAAAB3NzaC1kc3MAAAAVAI7j3HG8HyjCOxaGFOUTwZqe0xSHAAAA - FHSqU41vPHTCRTqmxNFwXqazPlJH - C: Obp6vQ83q1O/OnQDifZB1rWOci9LaSck8VxNB4UAFhRI56BAs4XPLqOWI - CoB3LYZ - S: a001 OK Authentication Completed - - The following private values were used in this example. These - values are all represented as an mpint in hexadecimal (msb first). - - - - -Newman [Page 12] - -Internet Draft PASSDSS-3DES-1 SASL Mechanism March 1998 - - - The client private Diffie-Hellman "x" value: - - 00000018 666E35B4 3BF4BF2B 40E31359 7A5D3AD0 61FD4F6F 736A6114 - - The server private Diffie-Hellman "y" value: - - 00000018 587BDFD6 800D101C 8E82E233 3B5A07AA DB87B8F1 68DC194D - - The Diffie-Hellman shared secret: - - 00000080 3B46D3A8 D2163930 1C33D9FE EAFA528D F4B881CF DF906A03 - 33249A88 42547FF6 49FDC149 1A5084B1 B425A105 CE571283 AC61D896 - AF8F7AF7 F95643F3 00A91E57 BCB8CFD7 77A25CBD 35F59A9E 59E98BEA - EA866339 7F0F9AA0 2F0F335C 8C6AAFF7 76BDB668 DF4D51AF 5B4FB807 - 81A70901 F478FB86 BF42055C BAF46094 EC72E98A - - The DSA private key value (the public key is in the exchange): - - 00000014 252BCBFA 5634D706 6ED43128 972E181E 66BF9C30 - - The SHA-1 hash value used to compute the keys: - - 26 75 97 06 EB FE E3 69 C9 03 7D 49 64 19 D5 D2 97 66 E8 CE - -6. Formal Syntax of PASSDSS-3DES-1 Messages - - This is the formal syntactic definition of the client and server - messages. This uses ABNF [ABNF] notation including the core rules. - The first three rules define the formal exchange. The later rules - define the elements of the exchange. - - client-msg-1 = [azname] authname diffie-hellman-X - - server-msg-1 = dss-public-key diffie-hellman-Y - ssecmask sbuflen dss-signature - - client-msg-2 = client-blob - - - authname = string - ;; interpreted as UTF-8 [UTF-8] - - azname = string - ;; interpreted as UTF-8 [UTF-8] - - cbuflen = 3OCTET - ;; Big endian binary unsigned integer - ;; max length of client read buffer - - - -Newman [Page 13] - -Internet Draft PASSDSS-3DES-1 SASL Mechanism March 1998 - - - cli-hmac = 20OCTET - - client-blob = 8*OCTET - ;; encrypted version of client-encrypted - - client-encrypted = csecmask cbuflen passphrase cli-hmac *NUL - ;; MUST be multiple of DES block size - - csecmask = OCTET - ;; client selected protection layer - - diffie-hellman-X = mpint - - diffie-hellman-Y = mpint - - dss-g = mpint - - dss-p = mpint - - dss-public-key = length NUL NUL NUL %x07 "ssh-dss" - dss-p dss-q dss-g dss-y - ;; length is total length of remainder - ;; as defined in [SSH-TRANS] - - dss-q = mpint - - dss-r = mpint - - dss-signature = length NUL NUL NUL %x07 "ssh-dss" - dss-r dss-s - ;; length is total length of remainder - - dss-s = mpint - - dss-y = mpint - - length = 4OCTET - ;; binary number, big endian format (MSB first) - - mpint = length *OCTET - ;; length specifies number of octets - ;; see section 1 for detailed mpint definition - - passphrase = string - ;; At least 64 octets MUST be supported - - - - - - -Newman [Page 14] - -Internet Draft PASSDSS-3DES-1 SASL Mechanism March 1998 - - - sbuflen = 3OCTET - ;; Big endian binary unsigned integer - ;; max length of server read buffer - - ssecmask = OCTET - ;; server protection layer mask - - string = length *OCTET - ;; the length determines the number of octets - ;; OCTETs are interpreted as UTF-8 - - NUL = %x00 ;; US-ASCII NUL character - -7. Security Considerations - - Security considerations are discussed throughout this memo. - - This mechanism supplies the server with the plain-text passphrase, - so the server gains the ability to masquerade as the user to any - other services which share the same passphrase. - - If the public key certification step is skipped, then an active - attacker can gain the client's passphrase and thus the ability to - masquerade as the user to any other services which share the same - passphrase. Negotiating a security layer will fail to provide - protection from an active attacker in this case. - - If no security layer is negotiated, the rest of the protocol - session is subject to active and passive attacks. - - If an integrity-only layer is negotiated, the rest of the protocol - is subject to passive eavesdropping. - - The quality of this mechanism depends on the quality of the random - number generator used. See [RANDOM] for more information. - -8. Multinational Considerations - - As remote access is a crucial service, users are encouraged to - restrict user names and passphrases to the US-ASCII character set. - However, if characters outside the US-ASCII character set are used - in user names and passphrases, then they are interpreted according - to UTF-8 [UTF-8] and it is a protocol error to include any octet - sequences not legal for UTF-8. Servers are encouraged to enforce - this restriction to discourage clients from using non-interoperable - local character sets in this context. - - - - - -Newman [Page 15] - -Internet Draft PASSDSS-3DES-1 SASL Mechanism March 1998 - - -9. Intellectual Property Issues and Acknowledgments - - David Kravitz holds U.S. Patent #5,231,668 on the DSA algorithm. - NIST has made this patent available world-wide on a royalty-free - basis. - - Diffie-Hellman was first published in 1976 [DIFFIE-HELLMAN]. U.S. - Patent #4,200,770 granted April 1980 has expired. Canada Patent - #1,121,480 was granted April 6, 1982 and may still apply at this - time. - - DES is covered under U.S. Patent #3,962,539 granted June 1978, - which has expired. - - The majority of the constructions in this specification were copied - from the Secure Shell specifications [SSH-ARCH, SSH-TRANS]. - Additional information is paraphrased from "Applied Cryptography" - [SCHNEIER]. - -10. References - - [ABNF] Crocker, Overell, "Augmented BNF for Syntax Specifications: - ABNF", RFC 2234, Internet Mail Consortium, Demon Internet Ltd, - November 1997. - - [CRAM-MD5] Klensin, Catoe, Krumviede, "IMAP/POP AUTHorize Extension - for Simple Challenge/Response", RFC 2195, MCI, September 1997. - - [DIFFIE-HELLMAN] Diffie, W., Hellman, M.E., "Privacy and - Authentication: An introduction to Cryptography," Proceedings of - the IEEE, v. 67, n. 3, March 1979, pp. 397-427. - - [DSS] National Institute of Standards and Technology, "Digital - Signature Standard," NIST FIPS PUB 186, U.S. Department of - Commerce, May 1994. - - [HMAC] Krawczyk, Bellare, Canetti, "HMAC: Keyed-Hashing for Message - Authentication", RFC 2104, IBM, UCSD, February 1997. - - [HMAC-TEST] Cheng, Glenn, "Test Cases for HMAC-MD5 and HMAC-SHA-1", - RFC 2202, IBM, NIST, September 1997. - - [IMAP4] Crispin, M., "Internet Message Access Protocol - Version - 4rev1", RFC 2060, University of Washington, December 1996. - - [KEYWORDS] Bradner, "Key words for use in RFCs to Indicate - Requirement Levels", RFC 2119, Harvard University, March 1997. - - - - -Newman [Page 16] - -Internet Draft PASSDSS-3DES-1 SASL Mechanism March 1998 - - - [Orm96] Orman, H., "The Oakley Key Determination Protocol", version - 1, TR97-92, Department of Computer Science Technical Report, - University of Arizona. - - [RANDOM] Eastlake, Crocker, Schiller, "Randomness Recommendations - for Security", RFC 1750, DEC, Cybercash, MIT, December 1994. - - [SASL] Myers, "Simple Authentication and Security Layer (SASL)", - RFC 2222, Netscape Communications, October 1997. - - [SCHNEIER] Schneier, B., "Applied Cryptography: Protocols, - Algorithms and Source Code in C," John Wiley and Sons, Inc., 1996. - - [SCRAM] Newman, "Salted Challenge Response Authentication Mechanism - (SCRAM)", work in progress, January 1998. - - [SHA1] NIST FIPS PUB 180-1, "Secure Hash Standard," National - Institute of Standards and Technology, U.S. Department of Commerce, - April 1995. - - [SHORT-EXP] van Oorschot, P., Wiener, M., "On Diffie-Hellman Key - Agreement with Short Exponents", Advances in Cryptography -- - EUROCRYPT Springer-Verlag, ISBN 3-540-61186-X, pp. 332-343. - - [SSH-ARCH] Ylonen, Kivinen, Saarinen, "SSH Protocol Architecture", - Work in progress, SSH, October 1997. - - [SSH-TRANS] Ylonen, Kivinen, Saarinen, "SSH Transport Layer - Protocol", Work in progress, SSH, October 1997. - - [TIMING] Kocher, P., "Timing Attacks on Implementations of Diffie- - Hellman, RSA, DSS and Other Systems", Advances in Cryptography -- - CRYPTO '96 Proceedings, Lecture Notes in Computer Science, Vol - 1109, Springer-Verlag, ISBN 3-540-61512-1, pp. 104-113. - - [TLS] Dierks, Allen, "The TLS Protocol Version 1.0", Work in - progress. - - [UTF8] Yergeau, "UTF-8, a transformation format of ISO 10646", - RFC 2279, Alis Technologies, January 1998. - - - - - - - - - - - -Newman [Page 17] - -Internet Draft PASSDSS-3DES-1 SASL Mechanism March 1998 - - -11. Author's Address - - Chris Newman - Innosoft International, Inc. - 1050 Lakes Drive - West Covina, CA 91790 USA - - Email: chris.newman@innosoft.com - -Appendix A. Algorithm Overview - - This section provides a quick overview of the algorithms used. For - a full understanding, the reader is encouraged to read "Applied - Cryptography" [SCHNEIER]. The follow descriptions are paraphrased - from that source. - - Note that an overview of the DES algorithm is not included as - publicly available implementations and descriptions are very - common. - -Appendix A.1. DSA Algorithm - - The DSA algorithm is a public key algorithm which can be used to - sign messages such that the source can be verified using a public - key. The algorithm has the following parameters: - - p is a prime number L bits long. Implementations MUST support L - between 512 and 1024 bits. - - q is a 160-bit prime factor of (p - 1). - - (p - 1)/q - g = h mod p where h is any number less than p - 1 such - - (p - 1)/q - that h is greater than 1. - - x is a number less than q and represents the private key. - - x - y = g mod p and represents the public key. - - To sign a message m, the client generates a random number k less - than q and computes: - - k - r = (g mod p) mod q - - - - -Newman [Page 18] - -Internet Draft PASSDSS-3DES-1 SASL Mechanism March 1998 - - - -1 - s = (k (SHA1(m) + xr)) mod q - - The signature is represented as r and s, and is verified as - follows: - - -1 - w = s mod q - - u1 = (SHA1(m) * w) mod q - - u2 = (rw) mod q - - u1 u2 - v = ((g * y ) mod p) mod q - - If v = r then the signature is verified. - -Appendix A.2. Diffie-Hellman Algorithm - - The Diffie-Hellman algorithm is a key-exchange algorithm. It - allows two ends of a communications channel to establish a shared - secret which a passive eavesdropper can not easily determine. This - key can then be used in a symmetric algorithm such as triple-DES. - The two ends have a prior agreement on two numbers: - - n a large prime number - - g a primitive mod n. - - The client chooses a random large integer x and computes: - - x - X = g mod n - - and sends X to the server. The server chooses a random large - integer y and computes: - - y - Y = g mod n - - y - K = X mod n - - The server sends Y to the client. The client computes: - - x - K = Y mod n - - - -Newman [Page 19] - -Internet Draft PASSDSS-3DES-1 SASL Mechanism March 1998 - - - At this point, the client and server share the same secret K. - -Appendix A.3. Triple-DES Algorithm in EDE/outer-CBC Mode - - The DES algorithm uses an 8 octet (64 bit) key of which 56 bits are - significant. The triple-DES EDE algorithm uses a 24 octet (192 - bit) key of which roughly 112 bits are significant see [SCHNEIER] - for more details. The "EDE" refers to encrypt-decrypt-encrypt, and - the "CBC" refers to cipher-block-chaining where each cipher block - affects future cipher blocks. If E() is the DES encryption - function, D() is the DES decryption function, C is a cipher text - block and P is a plain-text block, then triple-DES EDE in CBC mode - with outer chaining is: - - C = E (D (E (P XOR C ))) - i K3 K2 K1 i i-1 - - NOTE: C is the initialization vector - 0 - - and the decryption function is: - - P = C XOR D (E (D (C ))) - i i-1 K3 K2 K1 i - - K1 is the first 8 octets of the triple-DES key, K2 is the second 8 - octets and K3 is the final 8 octets. - -Appendix A.4. HMAC-SHA-1 Keyed hash function - - HMAC-SHA-1 uses the SHA-1 hash function to create a keyed hash - function suitable for use as an integrity protection function. A - more complete description is in [HMAC]. A brief summary of the - algorithm follows: - - (A) If the key is longer than 64 octets, it is run through the - SHA-1 function to produce a 20 octet key. - - (B) The key is exclusive-ored with a 64 octet buffer filled with - the octet value 0x36. - - (C) SHA-1 is computed over (B) followed by the input text. - - (D) The key is exclusive-ored with a 64 octet buffer filled with - the octet value 0x5C. - - (E) SHA-1 is computed over (D) followed by the output of (C). - - - - -Newman [Page 20] diff --git a/doc/rfc1321.txt b/doc/rfc1321.txt deleted file mode 100644 index 68af27d2..00000000 --- a/doc/rfc1321.txt +++ /dev/null @@ -1,1179 +0,0 @@ - - - - - - -Network Working Group R. Rivest -Request for Comments: 1321 MIT Laboratory for Computer Science - and RSA Data Security, Inc. - April 1992 - - - The MD5 Message-Digest Algorithm - -Status of this Memo - - This memo provides information for the Internet community. It does - not specify an Internet standard. Distribution of this memo is - unlimited. - -Acknowlegements - - We would like to thank Don Coppersmith, Burt Kaliski, Ralph Merkle, - David Chaum, and Noam Nisan for numerous helpful comments and - suggestions. - -Table of Contents - - 1. Executive Summary 1 - 2. Terminology and Notation 2 - 3. MD5 Algorithm Description 3 - 4. Summary 6 - 5. Differences Between MD4 and MD5 6 - References 7 - APPENDIX A - Reference Implementation 7 - Security Considerations 21 - Author's Address 21 - -1. Executive Summary - - This document describes the MD5 message-digest algorithm. The - algorithm takes as input a message of arbitrary length and produces - as output a 128-bit "fingerprint" or "message digest" of the input. - It is conjectured that it is computationally infeasible to produce - two messages having the same message digest, or to produce any - message having a given prespecified target message digest. The MD5 - algorithm is intended for digital signature applications, where a - large file must be "compressed" in a secure manner before being - encrypted with a private (secret) key under a public-key cryptosystem - such as RSA. - - - - - - - -Rivest [Page 1] - -RFC 1321 MD5 Message-Digest Algorithm April 1992 - - - The MD5 algorithm is designed to be quite fast on 32-bit machines. In - addition, the MD5 algorithm does not require any large substitution - tables; the algorithm can be coded quite compactly. - - The MD5 algorithm is an extension of the MD4 message-digest algorithm - 1,2]. MD5 is slightly slower than MD4, but is more "conservative" in - design. MD5 was designed because it was felt that MD4 was perhaps - being adopted for use more quickly than justified by the existing - critical review; because MD4 was designed to be exceptionally fast, - it is "at the edge" in terms of risking successful cryptanalytic - attack. MD5 backs off a bit, giving up a little in speed for a much - greater likelihood of ultimate security. It incorporates some - suggestions made by various reviewers, and contains additional - optimizations. The MD5 algorithm is being placed in the public domain - for review and possible adoption as a standard. - - For OSI-based applications, MD5's object identifier is - - md5 OBJECT IDENTIFIER ::= - iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2) 5} - - In the X.509 type AlgorithmIdentifier [3], the parameters for MD5 - should have type NULL. - -2. Terminology and Notation - - In this document a "word" is a 32-bit quantity and a "byte" is an - eight-bit quantity. A sequence of bits can be interpreted in a - natural manner as a sequence of bytes, where each consecutive group - of eight bits is interpreted as a byte with the high-order (most - significant) bit of each byte listed first. Similarly, a sequence of - bytes can be interpreted as a sequence of 32-bit words, where each - consecutive group of four bytes is interpreted as a word with the - low-order (least significant) byte given first. - - Let x_i denote "x sub i". If the subscript is an expression, we - surround it in braces, as in x_{i+1}. Similarly, we use ^ for - superscripts (exponentiation), so that x^i denotes x to the i-th - power. - - Let the symbol "+" denote addition of words (i.e., modulo-2^32 - addition). Let X <<< s denote the 32-bit value obtained by circularly - shifting (rotating) X left by s bit positions. Let not(X) denote the - bit-wise complement of X, and let X v Y denote the bit-wise OR of X - and Y. Let X xor Y denote the bit-wise XOR of X and Y, and let XY - denote the bit-wise AND of X and Y. - - - - - -Rivest [Page 2] - -RFC 1321 MD5 Message-Digest Algorithm April 1992 - - -3. MD5 Algorithm Description - - We begin by supposing that we have a b-bit message as input, and that - we wish to find its message digest. Here b is an arbitrary - nonnegative integer; b may be zero, it need not be a multiple of - eight, and it may be arbitrarily large. We imagine the bits of the - message written down as follows: - - m_0 m_1 ... m_{b-1} - - The following five steps are performed to compute the message digest - of the message. - -3.1 Step 1. Append Padding Bits - - The message is "padded" (extended) so that its length (in bits) is - congruent to 448, modulo 512. That is, the message is extended so - that it is just 64 bits shy of being a multiple of 512 bits long. - Padding is always performed, even if the length of the message is - already congruent to 448, modulo 512. - - Padding is performed as follows: a single "1" bit is appended to the - message, and then "0" bits are appended so that the length in bits of - the padded message becomes congruent to 448, modulo 512. In all, at - least one bit and at most 512 bits are appended. - -3.2 Step 2. Append Length - - A 64-bit representation of b (the length of the message before the - padding bits were added) is appended to the result of the previous - step. In the unlikely event that b is greater than 2^64, then only - the low-order 64 bits of b are used. (These bits are appended as two - 32-bit words and appended low-order word first in accordance with the - previous conventions.) - - At this point the resulting message (after padding with bits and with - b) has a length that is an exact multiple of 512 bits. Equivalently, - this message has a length that is an exact multiple of 16 (32-bit) - words. Let M[0 ... N-1] denote the words of the resulting message, - where N is a multiple of 16. - -3.3 Step 3. Initialize MD Buffer - - A four-word buffer (A,B,C,D) is used to compute the message digest. - Here each of A, B, C, D is a 32-bit register. These registers are - initialized to the following values in hexadecimal, low-order bytes - first): - - - - -Rivest [Page 3] - -RFC 1321 MD5 Message-Digest Algorithm April 1992 - - - word A: 01 23 45 67 - word B: 89 ab cd ef - word C: fe dc ba 98 - word D: 76 54 32 10 - -3.4 Step 4. Process Message in 16-Word Blocks - - We first define four auxiliary functions that each take as input - three 32-bit words and produce as output one 32-bit word. - - F(X,Y,Z) = XY v not(X) Z - G(X,Y,Z) = XZ v Y not(Z) - H(X,Y,Z) = X xor Y xor Z - I(X,Y,Z) = Y xor (X v not(Z)) - - In each bit position F acts as a conditional: if X then Y else Z. - The function F could have been defined using + instead of v since XY - and not(X)Z will never have 1's in the same bit position.) It is - interesting to note that if the bits of X, Y, and Z are independent - and unbiased, the each bit of F(X,Y,Z) will be independent and - unbiased. - - The functions G, H, and I are similar to the function F, in that they - act in "bitwise parallel" to produce their output from the bits of X, - Y, and Z, in such a manner that if the corresponding bits of X, Y, - and Z are independent and unbiased, then each bit of G(X,Y,Z), - H(X,Y,Z), and I(X,Y,Z) will be independent and unbiased. Note that - the function H is the bit-wise "xor" or "parity" function of its - inputs. - - This step uses a 64-element table T[1 ... 64] constructed from the - sine function. Let T[i] denote the i-th element of the table, which - is equal to the integer part of 4294967296 times abs(sin(i)), where i - is in radians. The elements of the table are given in the appendix. - - Do the following: - - /* Process each 16-word block. */ - For i = 0 to N/16-1 do - - /* Copy block i into X. */ - For j = 0 to 15 do - Set X[j] to M[i*16+j]. - end /* of loop on j */ - - /* Save A as AA, B as BB, C as CC, and D as DD. */ - AA = A - BB = B - - - -Rivest [Page 4] - -RFC 1321 MD5 Message-Digest Algorithm April 1992 - - - CC = C - DD = D - - /* Round 1. */ - /* Let [abcd k s i] denote the operation - a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ - /* Do the following 16 operations. */ - [ABCD 0 7 1] [DABC 1 12 2] [CDAB 2 17 3] [BCDA 3 22 4] - [ABCD 4 7 5] [DABC 5 12 6] [CDAB 6 17 7] [BCDA 7 22 8] - [ABCD 8 7 9] [DABC 9 12 10] [CDAB 10 17 11] [BCDA 11 22 12] - [ABCD 12 7 13] [DABC 13 12 14] [CDAB 14 17 15] [BCDA 15 22 16] - - /* Round 2. */ - /* Let [abcd k s i] denote the operation - a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ - /* Do the following 16 operations. */ - [ABCD 1 5 17] [DABC 6 9 18] [CDAB 11 14 19] [BCDA 0 20 20] - [ABCD 5 5 21] [DABC 10 9 22] [CDAB 15 14 23] [BCDA 4 20 24] - [ABCD 9 5 25] [DABC 14 9 26] [CDAB 3 14 27] [BCDA 8 20 28] - [ABCD 13 5 29] [DABC 2 9 30] [CDAB 7 14 31] [BCDA 12 20 32] - - /* Round 3. */ - /* Let [abcd k s t] denote the operation - a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ - /* Do the following 16 operations. */ - [ABCD 5 4 33] [DABC 8 11 34] [CDAB 11 16 35] [BCDA 14 23 36] - [ABCD 1 4 37] [DABC 4 11 38] [CDAB 7 16 39] [BCDA 10 23 40] - [ABCD 13 4 41] [DABC 0 11 42] [CDAB 3 16 43] [BCDA 6 23 44] - [ABCD 9 4 45] [DABC 12 11 46] [CDAB 15 16 47] [BCDA 2 23 48] - - /* Round 4. */ - /* Let [abcd k s t] denote the operation - a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ - /* Do the following 16 operations. */ - [ABCD 0 6 49] [DABC 7 10 50] [CDAB 14 15 51] [BCDA 5 21 52] - [ABCD 12 6 53] [DABC 3 10 54] [CDAB 10 15 55] [BCDA 1 21 56] - [ABCD 8 6 57] [DABC 15 10 58] [CDAB 6 15 59] [BCDA 13 21 60] - [ABCD 4 6 61] [DABC 11 10 62] [CDAB 2 15 63] [BCDA 9 21 64] - - /* Then perform the following additions. (That is increment each - of the four registers by the value it had before this block - was started.) */ - A = A + AA - B = B + BB - C = C + CC - D = D + DD - - end /* of loop on i */ - - - -Rivest [Page 5] - -RFC 1321 MD5 Message-Digest Algorithm April 1992 - - -3.5 Step 5. Output - - The message digest produced as output is A, B, C, D. That is, we - begin with the low-order byte of A, and end with the high-order byte - of D. - - This completes the description of MD5. A reference implementation in - C is given in the appendix. - -4. Summary - - The MD5 message-digest algorithm is simple to implement, and provides - a "fingerprint" or message digest of a message of arbitrary length. - It is conjectured that the difficulty of coming up with two messages - having the same message digest is on the order of 2^64 operations, - and that the difficulty of coming up with any message having a given - message digest is on the order of 2^128 operations. The MD5 algorithm - has been carefully scrutinized for weaknesses. It is, however, a - relatively new algorithm and further security analysis is of course - justified, as is the case with any new proposal of this sort. - -5. Differences Between MD4 and MD5 - - The following are the differences between MD4 and MD5: - - 1. A fourth round has been added. - - 2. Each step now has a unique additive constant. - - 3. The function g in round 2 was changed from (XY v XZ v YZ) to - (XZ v Y not(Z)) to make g less symmetric. - - 4. Each step now adds in the result of the previous step. This - promotes a faster "avalanche effect". - - 5. The order in which input words are accessed in rounds 2 and - 3 is changed, to make these patterns less like each other. - - 6. The shift amounts in each round have been approximately - optimized, to yield a faster "avalanche effect." The shifts in - different rounds are distinct. - - - - - - - - - - -Rivest [Page 6] - -RFC 1321 MD5 Message-Digest Algorithm April 1992 - - -References - - [1] Rivest, R., "The MD4 Message Digest Algorithm", RFC 1320, MIT and - RSA Data Security, Inc., April 1992. - - [2] Rivest, R., "The MD4 message digest algorithm", in A.J. Menezes - and S.A. Vanstone, editors, Advances in Cryptology - CRYPTO '90 - Proceedings, pages 303-311, Springer-Verlag, 1991. - - [3] CCITT Recommendation X.509 (1988), "The Directory - - Authentication Framework." - -APPENDIX A - Reference Implementation - - This appendix contains the following files taken from RSAREF: A - Cryptographic Toolkit for Privacy-Enhanced Mail: - - global.h -- global header file - - md5.h -- header file for MD5 - - md5c.c -- source code for MD5 - - For more information on RSAREF, send email to . - - The appendix also includes the following file: - - mddriver.c -- test driver for MD2, MD4 and MD5 - - The driver compiles for MD5 by default but can compile for MD2 or MD4 - if the symbol MD is defined on the C compiler command line as 2 or 4. - - The implementation is portable and should work on many different - plaforms. However, it is not difficult to optimize the implementation - on particular platforms, an exercise left to the reader. For example, - on "little-endian" platforms where the lowest-addressed byte in a 32- - bit word is the least significant and there are no alignment - restrictions, the call to Decode in MD5Transform can be replaced with - a typecast. - -A.1 global.h - -/* GLOBAL.H - RSAREF types and constants - */ - -/* PROTOTYPES should be set to one if and only if the compiler supports - function argument prototyping. -The following makes PROTOTYPES default to 0 if it has not already - - - -Rivest [Page 7] - -RFC 1321 MD5 Message-Digest Algorithm April 1992 - - - been defined with C compiler flags. - */ -#ifndef PROTOTYPES -#define PROTOTYPES 0 -#endif - -/* POINTER defines a generic pointer type */ -typedef unsigned char *POINTER; - -/* UINT2 defines a two byte word */ -typedef unsigned short int UINT2; - -/* UINT4 defines a four byte word */ -typedef unsigned long int UINT4; - -/* PROTO_LIST is defined depending on how PROTOTYPES is defined above. -If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it - returns an empty list. - */ -#if PROTOTYPES -#define PROTO_LIST(list) list -#else -#define PROTO_LIST(list) () -#endif - -A.2 md5.h - -/* MD5.H - header file for MD5C.C - */ - -/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All -rights reserved. - -License to copy and use this software is granted provided that it -is identified as the "RSA Data Security, Inc. MD5 Message-Digest -Algorithm" in all material mentioning or referencing this software -or this function. - -License is also granted to make and use derivative works provided -that such works are identified as "derived from the RSA Data -Security, Inc. MD5 Message-Digest Algorithm" in all material -mentioning or referencing the derived work. - -RSA Data Security, Inc. makes no representations concerning either -the merchantability of this software or the suitability of this -software for any particular purpose. It is provided "as is" -without express or implied warranty of any kind. - - - - -Rivest [Page 8] - -RFC 1321 MD5 Message-Digest Algorithm April 1992 - - -These notices must be retained in any copies of any part of this -documentation and/or software. - */ - -/* MD5 context. */ -typedef struct { - UINT4 state[4]; /* state (ABCD) */ - UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ - unsigned char buffer[64]; /* input buffer */ -} MD5_CTX; - -void MD5Init PROTO_LIST ((MD5_CTX *)); -void MD5Update PROTO_LIST - ((MD5_CTX *, unsigned char *, unsigned int)); -void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *)); - -A.3 md5c.c - -/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm - */ - -/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All -rights reserved. - -License to copy and use this software is granted provided that it -is identified as the "RSA Data Security, Inc. MD5 Message-Digest -Algorithm" in all material mentioning or referencing this software -or this function. - -License is also granted to make and use derivative works provided -that such works are identified as "derived from the RSA Data -Security, Inc. MD5 Message-Digest Algorithm" in all material -mentioning or referencing the derived work. - -RSA Data Security, Inc. makes no representations concerning either -the merchantability of this software or the suitability of this -software for any particular purpose. It is provided "as is" -without express or implied warranty of any kind. - -These notices must be retained in any copies of any part of this -documentation and/or software. - */ - -#include "global.h" -#include "md5.h" - -/* Constants for MD5Transform routine. - */ - - - -Rivest [Page 9] - -RFC 1321 MD5 Message-Digest Algorithm April 1992 - - -#define S11 7 -#define S12 12 -#define S13 17 -#define S14 22 -#define S21 5 -#define S22 9 -#define S23 14 -#define S24 20 -#define S31 4 -#define S32 11 -#define S33 16 -#define S34 23 -#define S41 6 -#define S42 10 -#define S43 15 -#define S44 21 - -static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64])); -static void Encode PROTO_LIST - ((unsigned char *, UINT4 *, unsigned int)); -static void Decode PROTO_LIST - ((UINT4 *, unsigned char *, unsigned int)); -static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int)); -static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int)); - -static unsigned char PADDING[64] = { - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/* F, G, H and I are basic MD5 functions. - */ -#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) -#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) -#define H(x, y, z) ((x) ^ (y) ^ (z)) -#define I(x, y, z) ((y) ^ ((x) | (~z))) - -/* ROTATE_LEFT rotates x left n bits. - */ -#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) - -/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. -Rotation is separate from addition to prevent recomputation. - */ -#define FF(a, b, c, d, x, s, ac) { \ - (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ - (a) = ROTATE_LEFT ((a), (s)); \ - - - -Rivest [Page 10] - -RFC 1321 MD5 Message-Digest Algorithm April 1992 - - - (a) += (b); \ - } -#define GG(a, b, c, d, x, s, ac) { \ - (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ - (a) = ROTATE_LEFT ((a), (s)); \ - (a) += (b); \ - } -#define HH(a, b, c, d, x, s, ac) { \ - (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ - (a) = ROTATE_LEFT ((a), (s)); \ - (a) += (b); \ - } -#define II(a, b, c, d, x, s, ac) { \ - (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ - (a) = ROTATE_LEFT ((a), (s)); \ - (a) += (b); \ - } - -/* MD5 initialization. Begins an MD5 operation, writing a new context. - */ -void MD5Init (context) -MD5_CTX *context; /* context */ -{ - context->count[0] = context->count[1] = 0; - /* Load magic initialization constants. -*/ - context->state[0] = 0x67452301; - context->state[1] = 0xefcdab89; - context->state[2] = 0x98badcfe; - context->state[3] = 0x10325476; -} - -/* MD5 block update operation. Continues an MD5 message-digest - operation, processing another message block, and updating the - context. - */ -void MD5Update (context, input, inputLen) -MD5_CTX *context; /* context */ -unsigned char *input; /* input block */ -unsigned int inputLen; /* length of input block */ -{ - unsigned int i, index, partLen; - - /* Compute number of bytes mod 64 */ - index = (unsigned int)((context->count[0] >> 3) & 0x3F); - - /* Update number of bits */ - if ((context->count[0] += ((UINT4)inputLen << 3)) - - - -Rivest [Page 11] - -RFC 1321 MD5 Message-Digest Algorithm April 1992 - - - < ((UINT4)inputLen << 3)) - context->count[1]++; - context->count[1] += ((UINT4)inputLen >> 29); - - partLen = 64 - index; - - /* Transform as many times as possible. -*/ - if (inputLen >= partLen) { - MD5_memcpy - ((POINTER)&context->buffer[index], (POINTER)input, partLen); - MD5Transform (context->state, context->buffer); - - for (i = partLen; i + 63 < inputLen; i += 64) - MD5Transform (context->state, &input[i]); - - index = 0; - } - else - i = 0; - - /* Buffer remaining input */ - MD5_memcpy - ((POINTER)&context->buffer[index], (POINTER)&input[i], - inputLen-i); -} - -/* MD5 finalization. Ends an MD5 message-digest operation, writing the - the message digest and zeroizing the context. - */ -void MD5Final (digest, context) -unsigned char digest[16]; /* message digest */ -MD5_CTX *context; /* context */ -{ - unsigned char bits[8]; - unsigned int index, padLen; - - /* Save number of bits */ - Encode (bits, context->count, 8); - - /* Pad out to 56 mod 64. -*/ - index = (unsigned int)((context->count[0] >> 3) & 0x3f); - padLen = (index < 56) ? (56 - index) : (120 - index); - MD5Update (context, PADDING, padLen); - - /* Append length (before padding) */ - MD5Update (context, bits, 8); - - - -Rivest [Page 12] - -RFC 1321 MD5 Message-Digest Algorithm April 1992 - - - /* Store state in digest */ - Encode (digest, context->state, 16); - - /* Zeroize sensitive information. -*/ - MD5_memset ((POINTER)context, 0, sizeof (*context)); -} - -/* MD5 basic transformation. Transforms state based on block. - */ -static void MD5Transform (state, block) -UINT4 state[4]; -unsigned char block[64]; -{ - UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; - - Decode (x, block, 64); - - /* Round 1 */ - FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ - FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ - FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ - FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ - FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ - FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ - FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ - FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ - FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ - FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ - FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ - FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ - FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ - FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ - FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ - FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ - - /* Round 2 */ - GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ - GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ - GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ - GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ - GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ - GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ - GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ - GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ - GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ - GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ - GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ - - - -Rivest [Page 13] - -RFC 1321 MD5 Message-Digest Algorithm April 1992 - - - GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ - GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ - GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ - GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ - GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ - - /* Round 3 */ - HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ - HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ - HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ - HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ - HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ - HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ - HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ - HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ - HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ - HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ - HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ - HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ - HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ - HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ - HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ - HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ - - /* Round 4 */ - II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ - II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ - II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ - II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ - II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ - II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ - II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ - II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ - II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ - II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ - II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ - II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ - II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ - II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ - II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ - II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ - - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; - - /* Zeroize sensitive information. - - - -Rivest [Page 14] - -RFC 1321 MD5 Message-Digest Algorithm April 1992 - - -*/ - MD5_memset ((POINTER)x, 0, sizeof (x)); -} - -/* Encodes input (UINT4) into output (unsigned char). Assumes len is - a multiple of 4. - */ -static void Encode (output, input, len) -unsigned char *output; -UINT4 *input; -unsigned int len; -{ - unsigned int i, j; - - for (i = 0, j = 0; j < len; i++, j += 4) { - output[j] = (unsigned char)(input[i] & 0xff); - output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); - output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); - output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); - } -} - -/* Decodes input (unsigned char) into output (UINT4). Assumes len is - a multiple of 4. - */ -static void Decode (output, input, len) -UINT4 *output; -unsigned char *input; -unsigned int len; -{ - unsigned int i, j; - - for (i = 0, j = 0; j < len; i++, j += 4) - output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | - (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24); -} - -/* Note: Replace "for loop" with standard memcpy if possible. - */ - -static void MD5_memcpy (output, input, len) -POINTER output; -POINTER input; -unsigned int len; -{ - unsigned int i; - - for (i = 0; i < len; i++) - - - -Rivest [Page 15] - -RFC 1321 MD5 Message-Digest Algorithm April 1992 - - - output[i] = input[i]; -} - -/* Note: Replace "for loop" with standard memset if possible. - */ -static void MD5_memset (output, value, len) -POINTER output; -int value; -unsigned int len; -{ - unsigned int i; - - for (i = 0; i < len; i++) - ((char *)output)[i] = (char)value; -} - -A.4 mddriver.c - -/* MDDRIVER.C - test driver for MD2, MD4 and MD5 - */ - -/* Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All -rights reserved. - -RSA Data Security, Inc. makes no representations concerning either -the merchantability of this software or the suitability of this -software for any particular purpose. It is provided "as is" -without express or implied warranty of any kind. - -These notices must be retained in any copies of any part of this -documentation and/or software. - */ - -/* The following makes MD default to MD5 if it has not already been - defined with C compiler flags. - */ -#ifndef MD -#define MD MD5 -#endif - -#include -#include -#include -#include "global.h" -#if MD == 2 -#include "md2.h" -#endif -#if MD == 4 - - - -Rivest [Page 16] - -RFC 1321 MD5 Message-Digest Algorithm April 1992 - - -#include "md4.h" -#endif -#if MD == 5 -#include "md5.h" -#endif - -/* Length of test block, number of test blocks. - */ -#define TEST_BLOCK_LEN 1000 -#define TEST_BLOCK_COUNT 1000 - -static void MDString PROTO_LIST ((char *)); -static void MDTimeTrial PROTO_LIST ((void)); -static void MDTestSuite PROTO_LIST ((void)); -static void MDFile PROTO_LIST ((char *)); -static void MDFilter PROTO_LIST ((void)); -static void MDPrint PROTO_LIST ((unsigned char [16])); - -#if MD == 2 -#define MD_CTX MD2_CTX -#define MDInit MD2Init -#define MDUpdate MD2Update -#define MDFinal MD2Final -#endif -#if MD == 4 -#define MD_CTX MD4_CTX -#define MDInit MD4Init -#define MDUpdate MD4Update -#define MDFinal MD4Final -#endif -#if MD == 5 -#define MD_CTX MD5_CTX -#define MDInit MD5Init -#define MDUpdate MD5Update -#define MDFinal MD5Final -#endif - -/* Main driver. - -Arguments (may be any combination): - -sstring - digests string - -t - runs time trial - -x - runs test script - filename - digests file - (none) - digests standard input - */ -int main (argc, argv) -int argc; - - - -Rivest [Page 17] - -RFC 1321 MD5 Message-Digest Algorithm April 1992 - - -char *argv[]; -{ - int i; - - if (argc > 1) - for (i = 1; i < argc; i++) - if (argv[i][0] == '-' && argv[i][1] == 's') - MDString (argv[i] + 2); - else if (strcmp (argv[i], "-t") == 0) - MDTimeTrial (); - else if (strcmp (argv[i], "-x") == 0) - MDTestSuite (); - else - MDFile (argv[i]); - else - MDFilter (); - - return (0); -} - -/* Digests a string and prints the result. - */ -static void MDString (string) -char *string; -{ - MD_CTX context; - unsigned char digest[16]; - unsigned int len = strlen (string); - - MDInit (&context); - MDUpdate (&context, string, len); - MDFinal (digest, &context); - - printf ("MD%d (\"%s\") = ", MD, string); - MDPrint (digest); - printf ("\n"); -} - -/* Measures the time to digest TEST_BLOCK_COUNT TEST_BLOCK_LEN-byte - blocks. - */ -static void MDTimeTrial () -{ - MD_CTX context; - time_t endTime, startTime; - unsigned char block[TEST_BLOCK_LEN], digest[16]; - unsigned int i; - - - - -Rivest [Page 18] - -RFC 1321 MD5 Message-Digest Algorithm April 1992 - - - printf - ("MD%d time trial. Digesting %d %d-byte blocks ...", MD, - TEST_BLOCK_LEN, TEST_BLOCK_COUNT); - - /* Initialize block */ - for (i = 0; i < TEST_BLOCK_LEN; i++) - block[i] = (unsigned char)(i & 0xff); - - /* Start timer */ - time (&startTime); - - /* Digest blocks */ - MDInit (&context); - for (i = 0; i < TEST_BLOCK_COUNT; i++) - MDUpdate (&context, block, TEST_BLOCK_LEN); - MDFinal (digest, &context); - - /* Stop timer */ - time (&endTime); - - printf (" done\n"); - printf ("Digest = "); - MDPrint (digest); - printf ("\nTime = %ld seconds\n", (long)(endTime-startTime)); - printf - ("Speed = %ld bytes/second\n", - (long)TEST_BLOCK_LEN * (long)TEST_BLOCK_COUNT/(endTime-startTime)); -} - -/* Digests a reference suite of strings and prints the results. - */ -static void MDTestSuite () -{ - printf ("MD%d test suite:\n", MD); - - MDString (""); - MDString ("a"); - MDString ("abc"); - MDString ("message digest"); - MDString ("abcdefghijklmnopqrstuvwxyz"); - MDString - ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"); - MDString - ("1234567890123456789012345678901234567890\ -1234567890123456789012345678901234567890"); -} - -/* Digests a file and prints the result. - - - -Rivest [Page 19] - -RFC 1321 MD5 Message-Digest Algorithm April 1992 - - - */ -static void MDFile (filename) -char *filename; -{ - FILE *file; - MD_CTX context; - int len; - unsigned char buffer[1024], digest[16]; - - if ((file = fopen (filename, "rb")) == NULL) - printf ("%s can't be opened\n", filename); - - else { - MDInit (&context); - while (len = fread (buffer, 1, 1024, file)) - MDUpdate (&context, buffer, len); - MDFinal (digest, &context); - - fclose (file); - - printf ("MD%d (%s) = ", MD, filename); - MDPrint (digest); - printf ("\n"); - } -} - -/* Digests the standard input and prints the result. - */ -static void MDFilter () -{ - MD_CTX context; - int len; - unsigned char buffer[16], digest[16]; - - MDInit (&context); - while (len = fread (buffer, 1, 16, stdin)) - MDUpdate (&context, buffer, len); - MDFinal (digest, &context); - - MDPrint (digest); - printf ("\n"); -} - -/* Prints a message digest in hexadecimal. - */ -static void MDPrint (digest) -unsigned char digest[16]; -{ - - - -Rivest [Page 20] - -RFC 1321 MD5 Message-Digest Algorithm April 1992 - - - unsigned int i; - - for (i = 0; i < 16; i++) - printf ("%02x", digest[i]); -} - -A.5 Test suite - - The MD5 test suite (driver option "-x") should print the following - results: - -MD5 test suite: -MD5 ("") = d41d8cd98f00b204e9800998ecf8427e -MD5 ("a") = 0cc175b9c0f1b6a831c399e269772661 -MD5 ("abc") = 900150983cd24fb0d6963f7d28e17f72 -MD5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0 -MD5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b -MD5 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = -d174ab98d277d9f5a5611c2c9f419d9f -MD5 ("123456789012345678901234567890123456789012345678901234567890123456 -78901234567890") = 57edf4a22be3c955ac49da2e2107b67a - -Security Considerations - - The level of security discussed in this memo is considered to be - sufficient for implementing very high security hybrid digital- - signature schemes based on MD5 and a public-key cryptosystem. - -Author's Address - - Ronald L. Rivest - Massachusetts Institute of Technology - Laboratory for Computer Science - NE43-324 - 545 Technology Square - Cambridge, MA 02139-1986 - - Phone: (617) 253-5880 - EMail: rivest@theory.lcs.mit.edu - - - - - - - - - - - - -Rivest [Page 21] - \ No newline at end of file diff --git a/doc/rfc1939.txt b/doc/rfc1939.txt deleted file mode 100644 index b11350e9..00000000 --- a/doc/rfc1939.txt +++ /dev/null @@ -1,1291 +0,0 @@ - - - - - - -Network Working Group J. Myers -Request for Comments: 1939 Carnegie Mellon -STD: 53 M. Rose -Obsoletes: 1725 Dover Beach Consulting, Inc. -Category: Standards Track May 1996 - - - Post Office Protocol - Version 3 - -Status of this Memo - - This document specifies an Internet standards track protocol for the - Internet community, and requests discussion and suggestions for - improvements. Please refer to the current edition of the "Internet - Official Protocol Standards" (STD 1) for the standardization state - and status of this protocol. Distribution of this memo is unlimited. - -Table of Contents - - 1. Introduction ................................................ 2 - 2. A Short Digression .......................................... 2 - 3. Basic Operation ............................................. 3 - 4. The AUTHORIZATION State ..................................... 4 - QUIT Command ................................................ 5 - 5. The TRANSACTION State ....................................... 5 - STAT Command ................................................ 6 - LIST Command ................................................ 6 - RETR Command ................................................ 8 - DELE Command ................................................ 8 - NOOP Command ................................................ 9 - RSET Command ................................................ 9 - 6. The UPDATE State ............................................ 10 - QUIT Command ................................................ 10 - 7. Optional POP3 Commands ...................................... 11 - TOP Command ................................................. 11 - UIDL Command ................................................ 12 - USER Command ................................................ 13 - PASS Command ................................................ 14 - APOP Command ................................................ 15 - 8. Scaling and Operational Considerations ...................... 16 - 9. POP3 Command Summary ........................................ 18 - 10. Example POP3 Session ....................................... 19 - 11. Message Format ............................................. 19 - 12. References ................................................. 20 - 13. Security Considerations .................................... 20 - 14. Acknowledgements ........................................... 20 - 15. Authors' Addresses ......................................... 21 - Appendix A. Differences from RFC 1725 .......................... 22 - - - -Myers & Rose Standards Track [Page 1] - -RFC 1939 POP3 May 1996 - - - Appendix B. Command Index ...................................... 23 - -1. Introduction - - On certain types of smaller nodes in the Internet it is often - impractical to maintain a message transport system (MTS). For - example, a workstation may not have sufficient resources (cycles, - disk space) in order to permit a SMTP server [RFC821] and associated - local mail delivery system to be kept resident and continuously - running. Similarly, it may be expensive (or impossible) to keep a - personal computer interconnected to an IP-style network for long - amounts of time (the node is lacking the resource known as - "connectivity"). - - Despite this, it is often very useful to be able to manage mail on - these smaller nodes, and they often support a user agent (UA) to aid - the tasks of mail handling. To solve this problem, a node which can - support an MTS entity offers a maildrop service to these less endowed - nodes. The Post Office Protocol - Version 3 (POP3) is intended to - permit a workstation to dynamically access a maildrop on a server - host in a useful fashion. Usually, this means that the POP3 protocol - is used to allow a workstation to retrieve mail that the server is - holding for it. - - POP3 is not intended to provide extensive manipulation operations of - mail on the server; normally, mail is downloaded and then deleted. A - more advanced (and complex) protocol, IMAP4, is discussed in - [RFC1730]. - - For the remainder of this memo, the term "client host" refers to a - host making use of the POP3 service, while the term "server host" - refers to a host which offers the POP3 service. - -2. A Short Digression - - This memo does not specify how a client host enters mail into the - transport system, although a method consistent with the philosophy of - this memo is presented here: - - When the user agent on a client host wishes to enter a message - into the transport system, it establishes an SMTP connection to - its relay host and sends all mail to it. This relay host could - be, but need not be, the POP3 server host for the client host. Of - course, the relay host must accept mail for delivery to arbitrary - recipient addresses, that functionality is not required of all - SMTP servers. - - - - - -Myers & Rose Standards Track [Page 2] - -RFC 1939 POP3 May 1996 - - -3. Basic Operation - - Initially, the server host starts the POP3 service by listening on - TCP port 110. When a client host wishes to make use of the service, - it establishes a TCP connection with the server host. When the - connection is established, the POP3 server sends a greeting. The - client and POP3 server then exchange commands and responses - (respectively) until the connection is closed or aborted. - - Commands in the POP3 consist of a case-insensitive keyword, possibly - followed by one or more arguments. All commands are terminated by a - CRLF pair. Keywords and arguments consist of printable ASCII - characters. Keywords and arguments are each separated by a single - SPACE character. Keywords are three or four characters long. Each - argument may be up to 40 characters long. - - Responses in the POP3 consist of a status indicator and a keyword - possibly followed by additional information. All responses are - terminated by a CRLF pair. Responses may be up to 512 characters - long, including the terminating CRLF. There are currently two status - indicators: positive ("+OK") and negative ("-ERR"). Servers MUST - send the "+OK" and "-ERR" in upper case. - - Responses to certain commands are multi-line. In these cases, which - are clearly indicated below, after sending the first line of the - response and a CRLF, any additional lines are sent, each terminated - by a CRLF pair. When all lines of the response have been sent, a - final line is sent, consisting of a termination octet (decimal code - 046, ".") and a CRLF pair. If any line of the multi-line response - begins with the termination octet, the line is "byte-stuffed" by - pre-pending the termination octet to that line of the response. - Hence a multi-line response is terminated with the five octets - "CRLF.CRLF". When examining a multi-line response, the client checks - to see if the line begins with the termination octet. If so and if - octets other than CRLF follow, the first octet of the line (the - termination octet) is stripped away. If so and if CRLF immediately - follows the termination character, then the response from the POP - server is ended and the line containing ".CRLF" is not considered - part of the multi-line response. - - A POP3 session progresses through a number of states during its - lifetime. Once the TCP connection has been opened and the POP3 - server has sent the greeting, the session enters the AUTHORIZATION - state. In this state, the client must identify itself to the POP3 - server. Once the client has successfully done this, the server - acquires resources associated with the client's maildrop, and the - session enters the TRANSACTION state. In this state, the client - requests actions on the part of the POP3 server. When the client has - - - -Myers & Rose Standards Track [Page 3] - -RFC 1939 POP3 May 1996 - - - issued the QUIT command, the session enters the UPDATE state. In - this state, the POP3 server releases any resources acquired during - the TRANSACTION state and says goodbye. The TCP connection is then - closed. - - A server MUST respond to an unrecognized, unimplemented, or - syntactically invalid command by responding with a negative status - indicator. A server MUST respond to a command issued when the - session is in an incorrect state by responding with a negative status - indicator. There is no general method for a client to distinguish - between a server which does not implement an optional command and a - server which is unwilling or unable to process the command. - - A POP3 server MAY have an inactivity autologout timer. Such a timer - MUST be of at least 10 minutes' duration. The receipt of any command - from the client during that interval should suffice to reset the - autologout timer. When the timer expires, the session does NOT enter - the UPDATE state--the server should close the TCP connection without - removing any messages or sending any response to the client. - -4. The AUTHORIZATION State - - Once the TCP connection has been opened by a POP3 client, the POP3 - server issues a one line greeting. This can be any positive - response. An example might be: - - S: +OK POP3 server ready - - The POP3 session is now in the AUTHORIZATION state. The client must - now identify and authenticate itself to the POP3 server. Two - possible mechanisms for doing this are described in this document, - the USER and PASS command combination and the APOP command. Both - mechanisms are described later in this document. Additional - authentication mechanisms are described in [RFC1734]. While there is - no single authentication mechanism that is required of all POP3 - servers, a POP3 server must of course support at least one - authentication mechanism. - - Once the POP3 server has determined through the use of any - authentication command that the client should be given access to the - appropriate maildrop, the POP3 server then acquires an exclusive- - access lock on the maildrop, as necessary to prevent messages from - being modified or removed before the session enters the UPDATE state. - If the lock is successfully acquired, the POP3 server responds with a - positive status indicator. The POP3 session now enters the - TRANSACTION state, with no messages marked as deleted. If the - maildrop cannot be opened for some reason (for example, a lock can - not be acquired, the client is denied access to the appropriate - - - -Myers & Rose Standards Track [Page 4] - -RFC 1939 POP3 May 1996 - - - maildrop, or the maildrop cannot be parsed), the POP3 server responds - with a negative status indicator. (If a lock was acquired but the - POP3 server intends to respond with a negative status indicator, the - POP3 server must release the lock prior to rejecting the command.) - After returning a negative status indicator, the server may close the - connection. If the server does not close the connection, the client - may either issue a new authentication command and start again, or the - client may issue the QUIT command. - - After the POP3 server has opened the maildrop, it assigns a message- - number to each message, and notes the size of each message in octets. - The first message in the maildrop is assigned a message-number of - "1", the second is assigned "2", and so on, so that the nth message - in a maildrop is assigned a message-number of "n". In POP3 commands - and responses, all message-numbers and message sizes are expressed in - base-10 (i.e., decimal). - - Here is the summary for the QUIT command when used in the - AUTHORIZATION state: - - QUIT - - Arguments: none - - Restrictions: none - - Possible Responses: - +OK - - Examples: - C: QUIT - S: +OK dewey POP3 server signing off - -5. The TRANSACTION State - - Once the client has successfully identified itself to the POP3 server - and the POP3 server has locked and opened the appropriate maildrop, - the POP3 session is now in the TRANSACTION state. The client may now - issue any of the following POP3 commands repeatedly. After each - command, the POP3 server issues a response. Eventually, the client - issues the QUIT command and the POP3 session enters the UPDATE state. - - - - - - - - - - -Myers & Rose Standards Track [Page 5] - -RFC 1939 POP3 May 1996 - - - Here are the POP3 commands valid in the TRANSACTION state: - - STAT - - Arguments: none - - Restrictions: - may only be given in the TRANSACTION state - - Discussion: - The POP3 server issues a positive response with a line - containing information for the maildrop. This line is - called a "drop listing" for that maildrop. - - In order to simplify parsing, all POP3 servers are - required to use a certain format for drop listings. The - positive response consists of "+OK" followed by a single - space, the number of messages in the maildrop, a single - space, and the size of the maildrop in octets. This memo - makes no requirement on what follows the maildrop size. - Minimal implementations should just end that line of the - response with a CRLF pair. More advanced implementations - may include other information. - - NOTE: This memo STRONGLY discourages implementations - from supplying additional information in the drop - listing. Other, optional, facilities are discussed - later on which permit the client to parse the messages - in the maildrop. - - Note that messages marked as deleted are not counted in - either total. - - Possible Responses: - +OK nn mm - - Examples: - C: STAT - S: +OK 2 320 - - - LIST [msg] - - Arguments: - a message-number (optional), which, if present, may NOT - refer to a message marked as deleted - - - - - -Myers & Rose Standards Track [Page 6] - -RFC 1939 POP3 May 1996 - - - Restrictions: - may only be given in the TRANSACTION state - - Discussion: - If an argument was given and the POP3 server issues a - positive response with a line containing information for - that message. This line is called a "scan listing" for - that message. - - If no argument was given and the POP3 server issues a - positive response, then the response given is multi-line. - After the initial +OK, for each message in the maildrop, - the POP3 server responds with a line containing - information for that message. This line is also called a - "scan listing" for that message. If there are no - messages in the maildrop, then the POP3 server responds - with no scan listings--it issues a positive response - followed by a line containing a termination octet and a - CRLF pair. - - In order to simplify parsing, all POP3 servers are - required to use a certain format for scan listings. A - scan listing consists of the message-number of the - message, followed by a single space and the exact size of - the message in octets. Methods for calculating the exact - size of the message are described in the "Message Format" - section below. This memo makes no requirement on what - follows the message size in the scan listing. Minimal - implementations should just end that line of the response - with a CRLF pair. More advanced implementations may - include other information, as parsed from the message. - - NOTE: This memo STRONGLY discourages implementations - from supplying additional information in the scan - listing. Other, optional, facilities are discussed - later on which permit the client to parse the messages - in the maildrop. - - Note that messages marked as deleted are not listed. - - Possible Responses: - +OK scan listing follows - -ERR no such message - - Examples: - C: LIST - S: +OK 2 messages (320 octets) - S: 1 120 - - - -Myers & Rose Standards Track [Page 7] - -RFC 1939 POP3 May 1996 - - - S: 2 200 - S: . - ... - C: LIST 2 - S: +OK 2 200 - ... - C: LIST 3 - S: -ERR no such message, only 2 messages in maildrop - - - RETR msg - - Arguments: - a message-number (required) which may NOT refer to a - message marked as deleted - - Restrictions: - may only be given in the TRANSACTION state - - Discussion: - If the POP3 server issues a positive response, then the - response given is multi-line. After the initial +OK, the - POP3 server sends the message corresponding to the given - message-number, being careful to byte-stuff the termination - character (as with all multi-line responses). - - Possible Responses: - +OK message follows - -ERR no such message - - Examples: - C: RETR 1 - S: +OK 120 octets - S: - S: . - - - DELE msg - - Arguments: - a message-number (required) which may NOT refer to a - message marked as deleted - - Restrictions: - may only be given in the TRANSACTION state - - - - - - -Myers & Rose Standards Track [Page 8] - -RFC 1939 POP3 May 1996 - - - Discussion: - The POP3 server marks the message as deleted. Any future - reference to the message-number associated with the message - in a POP3 command generates an error. The POP3 server does - not actually delete the message until the POP3 session - enters the UPDATE state. - - Possible Responses: - +OK message deleted - -ERR no such message - - Examples: - C: DELE 1 - S: +OK message 1 deleted - ... - C: DELE 2 - S: -ERR message 2 already deleted - - - NOOP - - Arguments: none - - Restrictions: - may only be given in the TRANSACTION state - - Discussion: - The POP3 server does nothing, it merely replies with a - positive response. - - Possible Responses: - +OK - - Examples: - C: NOOP - S: +OK - - - RSET - - Arguments: none - - Restrictions: - may only be given in the TRANSACTION state - - Discussion: - If any messages have been marked as deleted by the POP3 - server, they are unmarked. The POP3 server then replies - - - -Myers & Rose Standards Track [Page 9] - -RFC 1939 POP3 May 1996 - - - with a positive response. - - Possible Responses: - +OK - - Examples: - C: RSET - S: +OK maildrop has 2 messages (320 octets) - -6. The UPDATE State - - When the client issues the QUIT command from the TRANSACTION state, - the POP3 session enters the UPDATE state. (Note that if the client - issues the QUIT command from the AUTHORIZATION state, the POP3 - session terminates but does NOT enter the UPDATE state.) - - If a session terminates for some reason other than a client-issued - QUIT command, the POP3 session does NOT enter the UPDATE state and - MUST not remove any messages from the maildrop. - - QUIT - - Arguments: none - - Restrictions: none - - Discussion: - The POP3 server removes all messages marked as deleted - from the maildrop and replies as to the status of this - operation. If there is an error, such as a resource - shortage, encountered while removing messages, the - maildrop may result in having some or none of the messages - marked as deleted be removed. In no case may the server - remove any messages not marked as deleted. - - Whether the removal was successful or not, the server - then releases any exclusive-access lock on the maildrop - and closes the TCP connection. - - Possible Responses: - +OK - -ERR some deleted messages not removed - - Examples: - C: QUIT - S: +OK dewey POP3 server signing off (maildrop empty) - ... - C: QUIT - - - -Myers & Rose Standards Track [Page 10] - -RFC 1939 POP3 May 1996 - - - S: +OK dewey POP3 server signing off (2 messages left) - ... - -7. Optional POP3 Commands - - The POP3 commands discussed above must be supported by all minimal - implementations of POP3 servers. - - The optional POP3 commands described below permit a POP3 client - greater freedom in message handling, while preserving a simple POP3 - server implementation. - - NOTE: This memo STRONGLY encourages implementations to support - these commands in lieu of developing augmented drop and scan - listings. In short, the philosophy of this memo is to put - intelligence in the part of the POP3 client and not the POP3 - server. - - TOP msg n - - Arguments: - a message-number (required) which may NOT refer to to a - message marked as deleted, and a non-negative number - of lines (required) - - Restrictions: - may only be given in the TRANSACTION state - - Discussion: - If the POP3 server issues a positive response, then the - response given is multi-line. After the initial +OK, the - POP3 server sends the headers of the message, the blank - line separating the headers from the body, and then the - number of lines of the indicated message's body, being - careful to byte-stuff the termination character (as with - all multi-line responses). - - Note that if the number of lines requested by the POP3 - client is greater than than the number of lines in the - body, then the POP3 server sends the entire message. - - Possible Responses: - +OK top of message follows - -ERR no such message - - Examples: - C: TOP 1 10 - S: +OK - - - -Myers & Rose Standards Track [Page 11] - -RFC 1939 POP3 May 1996 - - - S: - S: . - ... - C: TOP 100 3 - S: -ERR no such message - - - UIDL [msg] - - Arguments: - a message-number (optional), which, if present, may NOT - refer to a message marked as deleted - - Restrictions: - may only be given in the TRANSACTION state. - - Discussion: - If an argument was given and the POP3 server issues a positive - response with a line containing information for that message. - This line is called a "unique-id listing" for that message. - - If no argument was given and the POP3 server issues a positive - response, then the response given is multi-line. After the - initial +OK, for each message in the maildrop, the POP3 server - responds with a line containing information for that message. - This line is called a "unique-id listing" for that message. - - In order to simplify parsing, all POP3 servers are required to - use a certain format for unique-id listings. A unique-id - listing consists of the message-number of the message, - followed by a single space and the unique-id of the message. - No information follows the unique-id in the unique-id listing. - - The unique-id of a message is an arbitrary server-determined - string, consisting of one to 70 characters in the range 0x21 - to 0x7E, which uniquely identifies a message within a - maildrop and which persists across sessions. This - persistence is required even if a session ends without - entering the UPDATE state. The server should never reuse an - unique-id in a given maildrop, for as long as the entity - using the unique-id exists. - - Note that messages marked as deleted are not listed. - - While it is generally preferable for server implementations - to store arbitrarily assigned unique-ids in the maildrop, - - - -Myers & Rose Standards Track [Page 12] - -RFC 1939 POP3 May 1996 - - - this specification is intended to permit unique-ids to be - calculated as a hash of the message. Clients should be able - to handle a situation where two identical copies of a - message in a maildrop have the same unique-id. - - Possible Responses: - +OK unique-id listing follows - -ERR no such message - - Examples: - C: UIDL - S: +OK - S: 1 whqtswO00WBw418f9t5JxYwZ - S: 2 QhdPYR:00WBw1Ph7x7 - S: . - ... - C: UIDL 2 - S: +OK 2 QhdPYR:00WBw1Ph7x7 - ... - C: UIDL 3 - S: -ERR no such message, only 2 messages in maildrop - - - USER name - - Arguments: - a string identifying a mailbox (required), which is of - significance ONLY to the server - - Restrictions: - may only be given in the AUTHORIZATION state after the POP3 - greeting or after an unsuccessful USER or PASS command - - Discussion: - To authenticate using the USER and PASS command - combination, the client must first issue the USER - command. If the POP3 server responds with a positive - status indicator ("+OK"), then the client may issue - either the PASS command to complete the authentication, - or the QUIT command to terminate the POP3 session. If - the POP3 server responds with a negative status indicator - ("-ERR") to the USER command, then the client may either - issue a new authentication command or may issue the QUIT - command. - - The server may return a positive response even though no - such mailbox exists. The server may return a negative - response if mailbox exists, but does not permit plaintext - - - -Myers & Rose Standards Track [Page 13] - -RFC 1939 POP3 May 1996 - - - password authentication. - - Possible Responses: - +OK name is a valid mailbox - -ERR never heard of mailbox name - - Examples: - C: USER frated - S: -ERR sorry, no mailbox for frated here - ... - C: USER mrose - S: +OK mrose is a real hoopy frood - - - PASS string - - Arguments: - a server/mailbox-specific password (required) - - Restrictions: - may only be given in the AUTHORIZATION state immediately - after a successful USER command - - Discussion: - When the client issues the PASS command, the POP3 server - uses the argument pair from the USER and PASS commands to - determine if the client should be given access to the - appropriate maildrop. - - Since the PASS command has exactly one argument, a POP3 - server may treat spaces in the argument as part of the - password, instead of as argument separators. - - Possible Responses: - +OK maildrop locked and ready - -ERR invalid password - -ERR unable to lock maildrop - - Examples: - C: USER mrose - S: +OK mrose is a real hoopy frood - C: PASS secret - S: -ERR maildrop already locked - ... - C: USER mrose - S: +OK mrose is a real hoopy frood - C: PASS secret - S: +OK mrose's maildrop has 2 messages (320 octets) - - - -Myers & Rose Standards Track [Page 14] - -RFC 1939 POP3 May 1996 - - - APOP name digest - - Arguments: - a string identifying a mailbox and a MD5 digest string - (both required) - - Restrictions: - may only be given in the AUTHORIZATION state after the POP3 - greeting or after an unsuccessful USER or PASS command - - Discussion: - Normally, each POP3 session starts with a USER/PASS - exchange. This results in a server/user-id specific - password being sent in the clear on the network. For - intermittent use of POP3, this may not introduce a sizable - risk. However, many POP3 client implementations connect to - the POP3 server on a regular basis -- to check for new - mail. Further the interval of session initiation may be on - the order of five minutes. Hence, the risk of password - capture is greatly enhanced. - - An alternate method of authentication is required which - provides for both origin authentication and replay - protection, but which does not involve sending a password - in the clear over the network. The APOP command provides - this functionality. - - A POP3 server which implements the APOP command will - include a timestamp in its banner greeting. The syntax of - the timestamp corresponds to the `msg-id' in [RFC822], and - MUST be different each time the POP3 server issues a banner - greeting. For example, on a UNIX implementation in which a - separate UNIX process is used for each instance of a POP3 - server, the syntax of the timestamp might be: - - - - where `process-ID' is the decimal value of the process's - PID, clock is the decimal value of the system clock, and - hostname is the fully-qualified domain-name corresponding - to the host where the POP3 server is running. - - The POP3 client makes note of this timestamp, and then - issues the APOP command. The `name' parameter has - identical semantics to the `name' parameter of the USER - command. The `digest' parameter is calculated by applying - the MD5 algorithm [RFC1321] to a string consisting of the - timestamp (including angle-brackets) followed by a shared - - - -Myers & Rose Standards Track [Page 15] - -RFC 1939 POP3 May 1996 - - - secret. This shared secret is a string known only to the - POP3 client and server. Great care should be taken to - prevent unauthorized disclosure of the secret, as knowledge - of the secret will allow any entity to successfully - masquerade as the named user. The `digest' parameter - itself is a 16-octet value which is sent in hexadecimal - format, using lower-case ASCII characters. - - When the POP3 server receives the APOP command, it verifies - the digest provided. If the digest is correct, the POP3 - server issues a positive response, and the POP3 session - enters the TRANSACTION state. Otherwise, a negative - response is issued and the POP3 session remains in the - AUTHORIZATION state. - - Note that as the length of the shared secret increases, so - does the difficulty of deriving it. As such, shared - secrets should be long strings (considerably longer than - the 8-character example shown below). - - Possible Responses: - +OK maildrop locked and ready - -ERR permission denied - - Examples: - S: +OK POP3 server ready <1896.697170952@dbc.mtview.ca.us> - C: APOP mrose c4c9334bac560ecc979e58001b3e22fb - S: +OK maildrop has 1 message (369 octets) - - In this example, the shared secret is the string `tan- - staaf'. Hence, the MD5 algorithm is applied to the string - - <1896.697170952@dbc.mtview.ca.us>tanstaaf - - which produces a digest value of - - c4c9334bac560ecc979e58001b3e22fb - -8. Scaling and Operational Considerations - - Since some of the optional features described above were added to the - POP3 protocol, experience has accumulated in using them in large- - scale commercial post office operations where most of the users are - unrelated to each other. In these situations and others, users and - vendors of POP3 clients have discovered that the combination of using - the UIDL command and not issuing the DELE command can provide a weak - version of the "maildrop as semi-permanent repository" functionality - normally associated with IMAP. Of course the other capabilities of - - - -Myers & Rose Standards Track [Page 16] - -RFC 1939 POP3 May 1996 - - - IMAP, such as polling an existing connection for newly arrived - messages and supporting multiple folders on the server, are not - present in POP3. - - When these facilities are used in this way by casual users, there has - been a tendency for already-read messages to accumulate on the server - without bound. This is clearly an undesirable behavior pattern from - the standpoint of the server operator. This situation is aggravated - by the fact that the limited capabilities of the POP3 do not permit - efficient handling of maildrops which have hundreds or thousands of - messages. - - Consequently, it is recommended that operators of large-scale multi- - user servers, especially ones in which the user's only access to the - maildrop is via POP3, consider such options as: - - * Imposing a per-user maildrop storage quota or the like. - - A disadvantage to this option is that accumulation of messages may - result in the user's inability to receive new ones into the - maildrop. Sites which choose this option should be sure to inform - users of impending or current exhaustion of quota, perhaps by - inserting an appropriate message into the user's maildrop. - - * Enforce a site policy regarding mail retention on the server. - - Sites are free to establish local policy regarding the storage and - retention of messages on the server, both read and unread. For - example, a site might delete unread messages from the server after - 60 days and delete read messages after 7 days. Such message - deletions are outside the scope of the POP3 protocol and are not - considered a protocol violation. - - Server operators enforcing message deletion policies should take - care to make all users aware of the policies in force. - - Clients must not assume that a site policy will automate message - deletions, and should continue to explicitly delete messages using - the DELE command when appropriate. - - It should be noted that enforcing site message deletion policies - may be confusing to the user community, since their POP3 client - may contain configuration options to leave mail on the server - which will not in fact be supported by the server. - - One special case of a site policy is that messages may only be - downloaded once from the server, and are deleted after this has - been accomplished. This could be implemented in POP3 server - - - -Myers & Rose Standards Track [Page 17] - -RFC 1939 POP3 May 1996 - - - software by the following mechanism: "following a POP3 login by a - client which was ended by a QUIT, delete all messages downloaded - during the session with the RETR command". It is important not to - delete messages in the event of abnormal connection termination - (ie, if no QUIT was received from the client) because the client - may not have successfully received or stored the messages. - Servers implementing a download-and-delete policy may also wish to - disable or limit the optional TOP command, since it could be used - as an alternate mechanism to download entire messages. - -9. POP3 Command Summary - - Minimal POP3 Commands: - - USER name valid in the AUTHORIZATION state - PASS string - QUIT - - STAT valid in the TRANSACTION state - LIST [msg] - RETR msg - DELE msg - NOOP - RSET - QUIT - - Optional POP3 Commands: - - APOP name digest valid in the AUTHORIZATION state - - TOP msg n valid in the TRANSACTION state - UIDL [msg] - - POP3 Replies: - - +OK - -ERR - - Note that with the exception of the STAT, LIST, and UIDL commands, - the reply given by the POP3 server to any command is significant - only to "+OK" and "-ERR". Any text occurring after this reply - may be ignored by the client. - - - - - - - - - -Myers & Rose Standards Track [Page 18] - -RFC 1939 POP3 May 1996 - - -10. Example POP3 Session - - S: - C: - S: +OK POP3 server ready <1896.697170952@dbc.mtview.ca.us> - C: APOP mrose c4c9334bac560ecc979e58001b3e22fb - S: +OK mrose's maildrop has 2 messages (320 octets) - C: STAT - S: +OK 2 320 - C: LIST - S: +OK 2 messages (320 octets) - S: 1 120 - S: 2 200 - S: . - C: RETR 1 - S: +OK 120 octets - S: - S: . - C: DELE 1 - S: +OK message 1 deleted - C: RETR 2 - S: +OK 200 octets - S: - S: . - C: DELE 2 - S: +OK message 2 deleted - C: QUIT - S: +OK dewey POP3 server signing off (maildrop empty) - C: - S: - -11. Message Format - - All messages transmitted during a POP3 session are assumed to conform - to the standard for the format of Internet text messages [RFC822]. - - It is important to note that the octet count for a message on the - server host may differ from the octet count assigned to that message - due to local conventions for designating end-of-line. Usually, - during the AUTHORIZATION state of the POP3 session, the POP3 server - can calculate the size of each message in octets when it opens the - maildrop. For example, if the POP3 server host internally represents - end-of-line as a single character, then the POP3 server simply counts - each occurrence of this character in a message as two octets. Note - that lines in the message which start with the termination octet need - not (and must not) be counted twice, since the POP3 client will - remove all byte-stuffed termination characters when it receives a - multi-line response. - - - -Myers & Rose Standards Track [Page 19] - -RFC 1939 POP3 May 1996 - - -12. References - - [RFC821] Postel, J., "Simple Mail Transfer Protocol", STD 10, RFC - 821, USC/Information Sciences Institute, August 1982. - - [RFC822] Crocker, D., "Standard for the Format of ARPA-Internet Text - Messages", STD 11, RFC 822, University of Delaware, August 1982. - - [RFC1321] Rivest, R., "The MD5 Message-Digest Algorithm", RFC 1321, - MIT Laboratory for Computer Science, April 1992. - - [RFC1730] Crispin, M., "Internet Message Access Protocol - Version - 4", RFC 1730, University of Washington, December 1994. - - [RFC1734] Myers, J., "POP3 AUTHentication command", RFC 1734, - Carnegie Mellon, December 1994. - -13. Security Considerations - - It is conjectured that use of the APOP command provides origin - identification and replay protection for a POP3 session. - Accordingly, a POP3 server which implements both the PASS and APOP - commands should not allow both methods of access for a given user; - that is, for a given mailbox name, either the USER/PASS command - sequence or the APOP command is allowed, but not both. - - Further, note that as the length of the shared secret increases, so - does the difficulty of deriving it. - - Servers that answer -ERR to the USER command are giving potential - attackers clues about which names are valid. - - Use of the PASS command sends passwords in the clear over the - network. - - Use of the RETR and TOP commands sends mail in the clear over the - network. - - Otherwise, security issues are not discussed in this memo. - -14. Acknowledgements - - The POP family has a long and checkered history. Although primarily - a minor revision to RFC 1460, POP3 is based on the ideas presented in - RFCs 918, 937, and 1081. - - In addition, Alfred Grimstad, Keith McCloghrie, and Neil Ostroff - provided significant comments on the APOP command. - - - -Myers & Rose Standards Track [Page 20] - -RFC 1939 POP3 May 1996 - - -15. Authors' Addresses - - John G. Myers - Carnegie-Mellon University - 5000 Forbes Ave - Pittsburgh, PA 15213 - - EMail: jgm+@cmu.edu - - - Marshall T. Rose - Dover Beach Consulting, Inc. - 420 Whisman Court - Mountain View, CA 94043-2186 - - EMail: mrose@dbc.mtview.ca.us - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Myers & Rose Standards Track [Page 21] - -RFC 1939 POP3 May 1996 - - -Appendix A. Differences from RFC 1725 - - This memo is a revision to RFC 1725, a Draft Standard. It makes the - following changes from that document: - - - clarifies that command keywords are case insensitive. - - - specifies that servers must send "+OK" and "-ERR" in - upper case. - - - specifies that the initial greeting is a positive response, - instead of any string which should be a positive response. - - - clarifies behavior for unimplemented commands. - - - makes the USER and PASS commands optional. - - - clarified the set of possible responses to the USER command. - - - reverses the order of the examples in the USER and PASS - commands, to reduce confusion. - - - clarifies that the PASS command may only be given immediately - after a successful USER command. - - - clarified the persistence requirements of UIDs and added some - implementation notes. - - - specifies a UID length limitation of one to 70 octets. - - - specifies a status indicator length limitation - of 512 octets, including the CRLF. - - - clarifies that LIST with no arguments on an empty mailbox - returns success. - - - adds a reference from the LIST command to the Message Format - section - - - clarifies the behavior of QUIT upon failure - - - clarifies the security section to not imply the use of the - USER command with the APOP command. - - - adds references to RFCs 1730 and 1734 - - - clarifies the method by which a UA may enter mail into the - transport system. - - - -Myers & Rose Standards Track [Page 22] - -RFC 1939 POP3 May 1996 - - - - clarifies that the second argument to the TOP command is a - number of lines. - - - changes the suggestion in the Security Considerations section - for a server to not accept both PASS and APOP for a given user - from a "must" to a "should". - - - adds a section on scaling and operational considerations - -Appendix B. Command Index - - APOP ....................................................... 15 - DELE ....................................................... 8 - LIST ....................................................... 6 - NOOP ....................................................... 9 - PASS ....................................................... 14 - QUIT ....................................................... 5 - QUIT ....................................................... 10 - RETR ....................................................... 8 - RSET ....................................................... 9 - STAT ....................................................... 6 - TOP ........................................................ 11 - UIDL ....................................................... 12 - USER ....................................................... 13 - - - - - - - - - - - - - - - - - - - - - - - - - - - -Myers & Rose Standards Track [Page 23] - diff --git a/doc/rfc2104.txt b/doc/rfc2104.txt deleted file mode 100644 index 1fb8fe11..00000000 --- a/doc/rfc2104.txt +++ /dev/null @@ -1,619 +0,0 @@ - - - - - - -Network Working Group H. Krawczyk -Request for Comments: 2104 IBM -Category: Informational M. Bellare - UCSD - R. Canetti - IBM - February 1997 - - - HMAC: Keyed-Hashing for Message Authentication - -Status of This Memo - - This memo provides information for the Internet community. This memo - does not specify an Internet standard of any kind. Distribution of - this memo is unlimited. - -Abstract - - This document describes HMAC, a mechanism for message authentication - using cryptographic hash functions. HMAC can be used with any - iterative cryptographic hash function, e.g., MD5, SHA-1, in - combination with a secret shared key. The cryptographic strength of - HMAC depends on the properties of the underlying hash function. - -1. Introduction - - Providing a way to check the integrity of information transmitted - over or stored in an unreliable medium is a prime necessity in the - world of open computing and communications. Mechanisms that provide - such integrity check based on a secret key are usually called - "message authentication codes" (MAC). Typically, message - authentication codes are used between two parties that share a secret - key in order to validate information transmitted between these - parties. In this document we present such a MAC mechanism based on - cryptographic hash functions. This mechanism, called HMAC, is based - on work by the authors [BCK1] where the construction is presented and - cryptographically analyzed. We refer to that work for the details on - the rationale and security analysis of HMAC, and its comparison to - other keyed-hash methods. - - - - - - - - - - - -Krawczyk, et. al. Informational [Page 1] - -RFC 2104 HMAC February 1997 - - - HMAC can be used in combination with any iterated cryptographic hash - function. MD5 and SHA-1 are examples of such hash functions. HMAC - also uses a secret key for calculation and verification of the - message authentication values. The main goals behind this - construction are - - * To use, without modifications, available hash functions. - In particular, hash functions that perform well in software, - and for which code is freely and widely available. - - * To preserve the original performance of the hash function without - incurring a significant degradation. - - * To use and handle keys in a simple way. - - * To have a well understood cryptographic analysis of the strength of - the authentication mechanism based on reasonable assumptions on the - underlying hash function. - - * To allow for easy replaceability of the underlying hash function in - case that faster or more secure hash functions are found or - required. - - This document specifies HMAC using a generic cryptographic hash - function (denoted by H). Specific instantiations of HMAC need to - define a particular hash function. Current candidates for such hash - functions include SHA-1 [SHA], MD5 [MD5], RIPEMD-128/160 [RIPEMD]. - These different realizations of HMAC will be denoted by HMAC-SHA1, - HMAC-MD5, HMAC-RIPEMD, etc. - - Note: To the date of writing of this document MD5 and SHA-1 are the - most widely used cryptographic hash functions. MD5 has been recently - shown to be vulnerable to collision search attacks [Dobb]. This - attack and other currently known weaknesses of MD5 do not compromise - the use of MD5 within HMAC as specified in this document (see - [Dobb]); however, SHA-1 appears to be a cryptographically stronger - function. To this date, MD5 can be considered for use in HMAC for - applications where the superior performance of MD5 is critical. In - any case, implementers and users need to be aware of possible - cryptanalytic developments regarding any of these cryptographic hash - functions, and the eventual need to replace the underlying hash - function. (See section 6 for more information on the security of - HMAC.) - - - - - - - - -Krawczyk, et. al. Informational [Page 2] - -RFC 2104 HMAC February 1997 - - -2. Definition of HMAC - - The definition of HMAC requires a cryptographic hash function, which - we denote by H, and a secret key K. We assume H to be a cryptographic - hash function where data is hashed by iterating a basic compression - function on blocks of data. We denote by B the byte-length of such - blocks (B=64 for all the above mentioned examples of hash functions), - and by L the byte-length of hash outputs (L=16 for MD5, L=20 for - SHA-1). The authentication key K can be of any length up to B, the - block length of the hash function. Applications that use keys longer - than B bytes will first hash the key using H and then use the - resultant L byte string as the actual key to HMAC. In any case the - minimal recommended length for K is L bytes (as the hash output - length). See section 3 for more information on keys. - - We define two fixed and different strings ipad and opad as follows - (the 'i' and 'o' are mnemonics for inner and outer): - - ipad = the byte 0x36 repeated B times - opad = the byte 0x5C repeated B times. - - To compute HMAC over the data `text' we perform - - H(K XOR opad, H(K XOR ipad, text)) - - Namely, - - (1) append zeros to the end of K to create a B byte string - (e.g., if K is of length 20 bytes and B=64, then K will be - appended with 44 zero bytes 0x00) - (2) XOR (bitwise exclusive-OR) the B byte string computed in step - (1) with ipad - (3) append the stream of data 'text' to the B byte string resulting - from step (2) - (4) apply H to the stream generated in step (3) - (5) XOR (bitwise exclusive-OR) the B byte string computed in - step (1) with opad - (6) append the H result from step (4) to the B byte string - resulting from step (5) - (7) apply H to the stream generated in step (6) and output - the result - - For illustration purposes, sample code based on MD5 is provided as an - appendix. - - - - - - - -Krawczyk, et. al. Informational [Page 3] - -RFC 2104 HMAC February 1997 - - -3. Keys - - The key for HMAC can be of any length (keys longer than B bytes are - first hashed using H). However, less than L bytes is strongly - discouraged as it would decrease the security strength of the - function. Keys longer than L bytes are acceptable but the extra - length would not significantly increase the function strength. (A - longer key may be advisable if the randomness of the key is - considered weak.) - - Keys need to be chosen at random (or using a cryptographically strong - pseudo-random generator seeded with a random seed), and periodically - refreshed. (Current attacks do not indicate a specific recommended - frequency for key changes as these attacks are practically - infeasible. However, periodic key refreshment is a fundamental - security practice that helps against potential weaknesses of the - function and keys, and limits the damage of an exposed key.) - -4. Implementation Note - - HMAC is defined in such a way that the underlying hash function H can - be used with no modification to its code. In particular, it uses the - function H with the pre-defined initial value IV (a fixed value - specified by each iterative hash function to initialize its - compression function). However, if desired, a performance - improvement can be achieved at the cost of (possibly) modifying the - code of H to support variable IVs. - - The idea is that the intermediate results of the compression function - on the B-byte blocks (K XOR ipad) and (K XOR opad) can be precomputed - only once at the time of generation of the key K, or before its first - use. These intermediate results are stored and then used to - initialize the IV of H each time that a message needs to be - authenticated. This method saves, for each authenticated message, - the application of the compression function of H on two B-byte blocks - (i.e., on (K XOR ipad) and (K XOR opad)). Such a savings may be - significant when authenticating short streams of data. We stress - that the stored intermediate values need to be treated and protected - the same as secret keys. - - Choosing to implement HMAC in the above way is a decision of the - local implementation and has no effect on inter-operability. - - - - - - - - - -Krawczyk, et. al. Informational [Page 4] - -RFC 2104 HMAC February 1997 - - -5. Truncated output - - A well-known practice with message authentication codes is to - truncate the output of the MAC and output only part of the bits - (e.g., [MM, ANSI]). Preneel and van Oorschot [PV] show some - analytical advantages of truncating the output of hash-based MAC - functions. The results in this area are not absolute as for the - overall security advantages of truncation. It has advantages (less - information on the hash result available to an attacker) and - disadvantages (less bits to predict for the attacker). Applications - of HMAC can choose to truncate the output of HMAC by outputting the t - leftmost bits of the HMAC computation for some parameter t (namely, - the computation is carried in the normal way as defined in section 2 - above but the end result is truncated to t bits). We recommend that - the output length t be not less than half the length of the hash - output (to match the birthday attack bound) and not less than 80 bits - (a suitable lower bound on the number of bits that need to be - predicted by an attacker). We propose denoting a realization of HMAC - that uses a hash function H with t bits of output as HMAC-H-t. For - example, HMAC-SHA1-80 denotes HMAC computed using the SHA-1 function - and with the output truncated to 80 bits. (If the parameter t is not - specified, e.g. HMAC-MD5, then it is assumed that all the bits of the - hash are output.) - -6. Security - - The security of the message authentication mechanism presented here - depends on cryptographic properties of the hash function H: the - resistance to collision finding (limited to the case where the - initial value is secret and random, and where the output of the - function is not explicitly available to the attacker), and the - message authentication property of the compression function of H when - applied to single blocks (in HMAC these blocks are partially unknown - to an attacker as they contain the result of the inner H computation - and, in particular, cannot be fully chosen by the attacker). - - These properties, and actually stronger ones, are commonly assumed - for hash functions of the kind used with HMAC. In particular, a hash - function for which the above properties do not hold would become - unsuitable for most (probably, all) cryptographic applications, - including alternative message authentication schemes based on such - functions. (For a complete analysis and rationale of the HMAC - function the reader is referred to [BCK1].) - - - - - - - - -Krawczyk, et. al. Informational [Page 5] - -RFC 2104 HMAC February 1997 - - - Given the limited confidence gained so far as for the cryptographic - strength of candidate hash functions, it is important to observe the - following two properties of the HMAC construction and its secure use - for message authentication: - - 1. The construction is independent of the details of the particular - hash function H in use and then the latter can be replaced by any - other secure (iterative) cryptographic hash function. - - 2. Message authentication, as opposed to encryption, has a - "transient" effect. A published breaking of a message authentication - scheme would lead to the replacement of that scheme, but would have - no adversarial effect on information authenticated in the past. This - is in sharp contrast with encryption, where information encrypted - today may suffer from exposure in the future if, and when, the - encryption algorithm is broken. - - The strongest attack known against HMAC is based on the frequency of - collisions for the hash function H ("birthday attack") [PV,BCK2], and - is totally impractical for minimally reasonable hash functions. - - As an example, if we consider a hash function like MD5 where the - output length equals L=16 bytes (128 bits) the attacker needs to - acquire the correct message authentication tags computed (with the - _same_ secret key K!) on about 2**64 known plaintexts. This would - require the processing of at least 2**64 blocks under H, an - impossible task in any realistic scenario (for a block length of 64 - bytes this would take 250,000 years in a continuous 1Gbps link, and - without changing the secret key K during all this time). This attack - could become realistic only if serious flaws in the collision - behavior of the function H are discovered (e.g. collisions found - after 2**30 messages). Such a discovery would determine the immediate - replacement of the function H (the effects of such failure would be - far more severe for the traditional uses of H in the context of - digital signatures, public key certificates, etc.). - - Note: this attack needs to be strongly contrasted with regular - collision attacks on cryptographic hash functions where no secret key - is involved and where 2**64 off-line parallelizable (!) operations - suffice to find collisions. The latter attack is approaching - feasibility [VW] while the birthday attack on HMAC is totally - impractical. (In the above examples, if one uses a hash function - with, say, 160 bit of output then 2**64 should be replaced by 2**80.) - - - - - - - - -Krawczyk, et. al. Informational [Page 6] - -RFC 2104 HMAC February 1997 - - - A correct implementation of the above construction, the choice of - random (or cryptographically pseudorandom) keys, a secure key - exchange mechanism, frequent key refreshments, and good secrecy - protection of keys are all essential ingredients for the security of - the integrity verification mechanism provided by HMAC. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Krawczyk, et. al. Informational [Page 7] - -RFC 2104 HMAC February 1997 - - -Appendix -- Sample Code - - For the sake of illustration we provide the following sample code for - the implementation of HMAC-MD5 as well as some corresponding test - vectors (the code is based on MD5 code as described in [MD5]). - -/* -** Function: hmac_md5 -*/ - -void -hmac_md5(text, text_len, key, key_len, digest) -unsigned char* text; /* pointer to data stream */ -int text_len; /* length of data stream */ -unsigned char* key; /* pointer to authentication key */ -int key_len; /* length of authentication key */ -caddr_t digest; /* caller digest to be filled in */ - -{ - MD5_CTX context; - unsigned char k_ipad[65]; /* inner padding - - * key XORd with ipad - */ - unsigned char k_opad[65]; /* outer padding - - * key XORd with opad - */ - unsigned char tk[16]; - int i; - /* if key is longer than 64 bytes reset it to key=MD5(key) */ - if (key_len > 64) { - - MD5_CTX tctx; - - MD5Init(&tctx); - MD5Update(&tctx, key, key_len); - MD5Final(tk, &tctx); - - key = tk; - key_len = 16; - } - - /* - * the HMAC_MD5 transform looks like: - * - * MD5(K XOR opad, MD5(K XOR ipad, text)) - * - * where K is an n byte key - * ipad is the byte 0x36 repeated 64 times - - - -Krawczyk, et. al. Informational [Page 8] - -RFC 2104 HMAC February 1997 - - - * opad is the byte 0x5c repeated 64 times - * and text is the data being protected - */ - - /* start out by storing key in pads */ - bzero( k_ipad, sizeof k_ipad); - bzero( k_opad, sizeof k_opad); - bcopy( key, k_ipad, key_len); - bcopy( key, k_opad, key_len); - - /* XOR key with ipad and opad values */ - for (i=0; i<64; i++) { - k_ipad[i] ^= 0x36; - k_opad[i] ^= 0x5c; - } - /* - * perform inner MD5 - */ - MD5Init(&context); /* init context for 1st - * pass */ - MD5Update(&context, k_ipad, 64) /* start with inner pad */ - MD5Update(&context, text, text_len); /* then text of datagram */ - MD5Final(digest, &context); /* finish up 1st pass */ - /* - * perform outer MD5 - */ - MD5Init(&context); /* init context for 2nd - * pass */ - MD5Update(&context, k_opad, 64); /* start with outer pad */ - MD5Update(&context, digest, 16); /* then results of 1st - * hash */ - MD5Final(digest, &context); /* finish up 2nd pass */ -} - -Test Vectors (Trailing '\0' of a character string not included in test): - - key = 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b - key_len = 16 bytes - data = "Hi There" - data_len = 8 bytes - digest = 0x9294727a3638bb1c13f48ef8158bfc9d - - key = "Jefe" - data = "what do ya want for nothing?" - data_len = 28 bytes - digest = 0x750c783e6ab0b503eaa86e310a5db738 - - key = 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - - - -Krawczyk, et. al. Informational [Page 9] - -RFC 2104 HMAC February 1997 - - - key_len 16 bytes - data = 0xDDDDDDDDDDDDDDDDDDDD... - ..DDDDDDDDDDDDDDDDDDDD... - ..DDDDDDDDDDDDDDDDDDDD... - ..DDDDDDDDDDDDDDDDDDDD... - ..DDDDDDDDDDDDDDDDDDDD - data_len = 50 bytes - digest = 0x56be34521d144c88dbb8c733f0e8b3f6 - -Acknowledgments - - Pau-Chen Cheng, Jeff Kraemer, and Michael Oehler, have provided - useful comments on early drafts, and ran the first interoperability - tests of this specification. Jeff and Pau-Chen kindly provided the - sample code and test vectors that appear in the appendix. Burt - Kaliski, Bart Preneel, Matt Robshaw, Adi Shamir, and Paul van - Oorschot have provided useful comments and suggestions during the - investigation of the HMAC construction. - -References - - [ANSI] ANSI X9.9, "American National Standard for Financial - Institution Message Authentication (Wholesale)," American - Bankers Association, 1981. Revised 1986. - - [Atk] Atkinson, R., "IP Authentication Header", RFC 1826, August - 1995. - - [BCK1] M. Bellare, R. Canetti, and H. Krawczyk, - "Keyed Hash Functions and Message Authentication", - Proceedings of Crypto'96, LNCS 1109, pp. 1-15. - (http://www.research.ibm.com/security/keyed-md5.html) - - [BCK2] M. Bellare, R. Canetti, and H. Krawczyk, - "Pseudorandom Functions Revisited: The Cascade Construction", - Proceedings of FOCS'96. - - [Dobb] H. Dobbertin, "The Status of MD5 After a Recent Attack", - RSA Labs' CryptoBytes, Vol. 2 No. 2, Summer 1996. - http://www.rsa.com/rsalabs/pubs/cryptobytes.html - - [PV] B. Preneel and P. van Oorschot, "Building fast MACs from hash - functions", Advances in Cryptology -- CRYPTO'95 Proceedings, - Lecture Notes in Computer Science, Springer-Verlag Vol.963, - 1995, pp. 1-14. - - [MD5] Rivest, R., "The MD5 Message-Digest Algorithm", - RFC 1321, April 1992. - - - -Krawczyk, et. al. Informational [Page 10] - -RFC 2104 HMAC February 1997 - - - [MM] Meyer, S. and Matyas, S.M., Cryptography, New York Wiley, - 1982. - - [RIPEMD] H. Dobbertin, A. Bosselaers, and B. Preneel, "RIPEMD-160: A - strengthened version of RIPEMD", Fast Software Encryption, - LNCS Vol 1039, pp. 71-82. - ftp://ftp.esat.kuleuven.ac.be/pub/COSIC/bosselae/ripemd/. - - [SHA] NIST, FIPS PUB 180-1: Secure Hash Standard, April 1995. - - [Tsu] G. Tsudik, "Message authentication with one-way hash - functions", In Proceedings of Infocom'92, May 1992. - (Also in "Access Control and Policy Enforcement in - Internetworks", Ph.D. Dissertation, Computer Science - Department, University of Southern California, April 1991.) - - [VW] P. van Oorschot and M. Wiener, "Parallel Collision - Search with Applications to Hash Functions and Discrete - Logarithms", Proceedings of the 2nd ACM Conf. Computer and - Communications Security, Fairfax, VA, November 1994. - -Authors' Addresses - - Hugo Krawczyk - IBM T.J. Watson Research Center - P.O.Box 704 - Yorktown Heights, NY 10598 - - EMail: hugo@watson.ibm.com - - Mihir Bellare - Dept of Computer Science and Engineering - Mail Code 0114 - University of California at San Diego - 9500 Gilman Drive - La Jolla, CA 92093 - - EMail: mihir@cs.ucsd.edu - - Ran Canetti - IBM T.J. Watson Research Center - P.O.Box 704 - Yorktown Heights, NY 10598 - - EMail: canetti@watson.ibm.com - - - - - - -Krawczyk, et. al. Informational [Page 11] - diff --git a/doc/rfc2195.txt b/doc/rfc2195.txt deleted file mode 100644 index 4a2725bf..00000000 --- a/doc/rfc2195.txt +++ /dev/null @@ -1,283 +0,0 @@ - - - - - - -Network Working Group J. Klensin -Request for Comments: 2195 R. Catoe -Category: Standards Track P. Krumviede -Obsoletes: 2095 MCI - September 1997 - - - IMAP/POP AUTHorize Extension for Simple Challenge/Response - -Status of this Memo - - This document specifies an Internet standards track protocol for the - Internet community, and requests discussion and suggestions for - improvements. Please refer to the current edition of the "Internet - Official Protocol Standards" (STD 1) for the standardization state - and status of this protocol. Distribution of this memo is unlimited. - -Abstract - - While IMAP4 supports a number of strong authentication mechanisms as - described in RFC 1731, it lacks any mechanism that neither passes - cleartext, reusable passwords across the network nor requires either - a significant security infrastructure or that the mail server update - a mail-system-wide user authentication file on each mail access. - This specification provides a simple challenge-response - authentication protocol that is suitable for use with IMAP4. Since - it utilizes Keyed-MD5 digests and does not require that the secret be - stored in the clear on the server, it may also constitute an - improvement on APOP for POP3 use as specified in RFC 1734. - -1. Introduction - - Existing Proposed Standards specify an AUTHENTICATE mechanism for the - IMAP4 protocol [IMAP, IMAP-AUTH] and a parallel AUTH mechanism for - the POP3 protocol [POP3-AUTH]. The AUTHENTICATE mechanism is - intended to be extensible; the four methods specified in [IMAP-AUTH] - are all fairly powerful and require some security infrastructure to - support. The base POP3 specification [POP3] also contains a - lightweight challenge-response mechanism called APOP. APOP is - associated with most of the risks associated with such protocols: in - particular, it requires that both the client and server machines have - access to the shared secret in cleartext form. CRAM offers a method - for avoiding such cleartext storage while retaining the algorithmic - simplicity of APOP in using only MD5, though in a "keyed" method. - - - - - - - -Klensin, Catoe & Krumviede Standards Track [Page 1] - -RFC 2195 IMAP/POP AUTHorize Extension September 1997 - - - At present, IMAP [IMAP] lacks any facility corresponding to APOP. - The only alternative to the strong mechanisms identified in [IMAP- - AUTH] is a presumably cleartext username and password, supported - through the LOGIN command in [IMAP]. This document describes a - simple challenge-response mechanism, similar to APOP and PPP CHAP - [PPP], that can be used with IMAP (and, in principle, with POP3). - - This mechanism also has the advantage over some possible alternatives - of not requiring that the server maintain information about email - "logins" on a per-login basis. While mechanisms that do require such - per-login history records may offer enhanced security, protocols such - as IMAP, which may have several connections between a given client - and server open more or less simultaneous, may make their - implementation particularly challenging. - -2. Challenge-Response Authentication Mechanism (CRAM) - - The authentication type associated with CRAM is "CRAM-MD5". - - The data encoded in the first ready response contains an - presumptively arbitrary string of random digits, a timestamp, and the - fully-qualified primary host name of the server. The syntax of the - unencoded form must correspond to that of an RFC 822 'msg-id' - [RFC822] as described in [POP3]. - - The client makes note of the data and then responds with a string - consisting of the user name, a space, and a 'digest'. The latter is - computed by applying the keyed MD5 algorithm from [KEYED-MD5] where - the key is a shared secret and the digested text is the timestamp - (including angle-brackets). - - This shared secret is a string known only to the client and server. - The `digest' parameter itself is a 16-octet value which is sent in - hexadecimal format, using lower-case ASCII characters. - - When the server receives this client response, it verifies the digest - provided. If the digest is correct, the server should consider the - client authenticated and respond appropriately. - - Keyed MD5 is chosen for this application because of the greater - security imparted to authentication of short messages. In addition, - the use of the techniques described in [KEYED-MD5] for precomputation - of intermediate results make it possible to avoid explicit cleartext - storage of the shared secret on the server system by instead storing - the intermediate results which are known as "contexts". - - - - - - -Klensin, Catoe & Krumviede Standards Track [Page 2] - -RFC 2195 IMAP/POP AUTHorize Extension September 1997 - - - CRAM does not support a protection mechanism. - - Example: - - The examples in this document show the use of the CRAM mechanism with - the IMAP4 AUTHENTICATE command [IMAP-AUTH]. The base64 encoding of - the challenges and responses is part of the IMAP4 AUTHENTICATE - command, not part of the CRAM specification itself. - - S: * OK IMAP4 Server - C: A0001 AUTHENTICATE CRAM-MD5 - S: + PDE4OTYuNjk3MTcwOTUyQHBvc3RvZmZpY2UucmVzdG9uLm1jaS5uZXQ+ - C: dGltIGI5MTNhNjAyYzdlZGE3YTQ5NWI0ZTZlNzMzNGQzODkw - S: A0001 OK CRAM authentication successful - - In this example, the shared secret is the string - 'tanstaaftanstaaf'. Hence, the Keyed MD5 digest is produced by - calculating - - MD5((tanstaaftanstaaf XOR opad), - MD5((tanstaaftanstaaf XOR ipad), - <1896.697170952@postoffice.reston.mci.net>)) - - where ipad and opad are as defined in the keyed-MD5 Work in - Progress [KEYED-MD5] and the string shown in the challenge is the - base64 encoding of <1896.697170952@postoffice.reston.mci.net>. The - shared secret is null-padded to a length of 64 bytes. If the - shared secret is longer than 64 bytes, the MD5 digest of the - shared secret is used as a 16 byte input to the keyed MD5 - calculation. - - This produces a digest value (in hexadecimal) of - - b913a602c7eda7a495b4e6e7334d3890 - - The user name is then prepended to it, forming - - tim b913a602c7eda7a495b4e6e7334d3890 - - Which is then base64 encoded to meet the requirements of the IMAP4 - AUTHENTICATE command (or the similar POP3 AUTH command), yielding - - dGltIGI5MTNhNjAyYzdlZGE3YTQ5NWI0ZTZlNzMzNGQzODkw - - - - - - - - -Klensin, Catoe & Krumviede Standards Track [Page 3] - -RFC 2195 IMAP/POP AUTHorize Extension September 1997 - - -3. References - - [CHAP] Lloyd, B., and W. Simpson, "PPP Authentication Protocols", - RFC 1334, October 1992. - - [IMAP] Crispin, M., "Internet Message Access Protocol - Version - 4rev1", RFC 2060, University of Washington, December 1996. - - [IMAP-AUTH] Myers, J., "IMAP4 Authentication Mechanisms", - RFC 1731, Carnegie Mellon, December 1994. - - [KEYED-MD5] Krawczyk, Bellare, Canetti, "HMAC: Keyed-Hashing for - Message Authentication", RFC 2104, February 1997. - - [MD5] Rivest, R., "The MD5 Message Digest Algorithm", - RFC 1321, MIT Laboratory for Computer Science, April 1992. - - [POP3] Myers, J., and M. Rose, "Post Office Protocol - Version 3", - STD 53, RFC 1939, Carnegie Mellon, May 1996. - - [POP3-AUTH] Myers, J., "POP3 AUTHentication command", RFC 1734, - Carnegie Mellon, December, 1994. - -4. Security Considerations - - It is conjectured that use of the CRAM authentication mechanism - provides origin identification and replay protection for a session. - Accordingly, a server that implements both a cleartext password - command and this authentication type should not allow both methods of - access for a given user. - - While the saving, on the server, of "contexts" (see section 2) is - marginally better than saving the shared secrets in cleartext as is - required by CHAP [CHAP] and APOP [POP3], it is not sufficient to - protect the secrets if the server itself is compromised. - Consequently, servers that store the secrets or contexts must both be - protected to a level appropriate to the potential information value - in user mailboxes and identities. - - As the length of the shared secret increases, so does the difficulty - of deriving it. - - While there are now suggestions in the literature that the use of MD5 - and keyed MD5 in authentication procedures probably has a limited - effective lifetime, the technique is now widely deployed and widely - understood. It is believed that this general understanding may - assist with the rapid replacement, by CRAM-MD5, of the current uses - of permanent cleartext passwords in IMAP. This document has been - - - -Klensin, Catoe & Krumviede Standards Track [Page 4] - -RFC 2195 IMAP/POP AUTHorize Extension September 1997 - - - deliberately written to permit easy upgrading to use SHA (or whatever - alternatives emerge) when they are considered to be widely available - and adequately safe. - - Even with the use of CRAM, users are still vulnerable to active - attacks. An example of an increasingly common active attack is 'TCP - Session Hijacking' as described in CERT Advisory CA-95:01 [CERT95]. - - See section 1 above for additional discussion. - -5. Acknowledgements - - This memo borrows ideas and some text liberally from [POP3] and - [RFC-1731] and thanks are due the authors of those documents. Ran - Atkinson made a number of valuable technical and editorial - contributions to the document. - -6. Authors' Addresses - - John C. Klensin - MCI Telecommunications - 800 Boylston St, 7th floor - Boston, MA 02199 - USA - - EMail: klensin@mci.net - Phone: +1 617 960 1011 - - Randy Catoe - MCI Telecommunications - 2100 Reston Parkway - Reston, VA 22091 - USA - - EMail: randy@mci.net - Phone: +1 703 715 7366 - - Paul Krumviede - MCI Telecommunications - 2100 Reston Parkway - Reston, VA 22091 - USA - - EMail: paul@mci.net - Phone: +1 703 715 7251 - - - - - - -Klensin, Catoe & Krumviede Standards Track [Page 5] - diff --git a/doc/rfc2222.txt b/doc/rfc2222.txt deleted file mode 100644 index 2b0a2abc..00000000 --- a/doc/rfc2222.txt +++ /dev/null @@ -1,899 +0,0 @@ - - - - - - -Network Working Group J. Myers -Request for Comments: 2222 Netscape Communications -Category: Standards Track October 1997 - - - Simple Authentication and Security Layer (SASL) - -Status of this Memo - - This document specifies an Internet standards track protocol for the - Internet community, and requests discussion and suggestions for - improvements. Please refer to the current edition of the "Internet - Official Protocol Standards" (STD 1) for the standardization state - and status of this protocol. Distribution of this memo is unlimited. - -Copyright Notice - - Copyright (C) The Internet Society (1997). All Rights Reserved. - -Table of Contents - - 1. Abstract .............................................. 2 - 2. Organization of this Document ......................... 2 - 2.1. How to Read This Document ............................. 2 - 2.2. Conventions Used in this Document ..................... 2 - 2.3. Examples .............................................. 3 - 3. Introduction and Overview ............................. 3 - 4. Profiling requirements ................................ 4 - 5. Specific issues ....................................... 5 - 5.1. Client sends data first ............................... 5 - 5.2. Server returns success with additional data ........... 5 - 5.3. Multiple authentications .............................. 5 - 6. Registration procedures ............................... 6 - 6.1. Comments on SASL mechanism registrations .............. 6 - 6.2. Location of Registered SASL Mechanism List ............ 6 - 6.3. Change Control ........................................ 7 - 6.4. Registration Template ................................. 7 - 7. Mechanism definitions ................................. 8 - 7.1. Kerberos version 4 mechanism .......................... 8 - 7.2. GSSAPI mechanism ...................................... 9 - 7.2.1 Client side of authentication protocol exchange ....... 9 - 7.2.2 Server side of authentication protocol exchange ....... 10 - 7.2.3 Security layer ........................................ 11 - 7.3. S/Key mechanism ....................................... 11 - 7.4. External mechanism .................................... 12 - 8. References ............................................ 13 - 9. Security Considerations ............................... 13 - 10. Author's Address ...................................... 14 - - - -Myers Standards Track [Page 1] - -RFC 2222 SASL October 1997 - - - Appendix A. Relation of SASL to Transport Security .......... 15 - Full Copyright Statement .................................... 16 - -1. Abstract - - This document describes a method for adding authentication support to - connection-based protocols. To use this specification, a protocol - includes a command for identifying and authenticating a user to a - server and for optionally negotiating protection of subsequent - protocol interactions. If its use is negotiated, a security layer is - inserted between the protocol and the connection. This document - describes how a protocol specifies such a command, defines several - mechanisms for use by the command, and defines the protocol used for - carrying a negotiated security layer over the connection. - -2. Organization of this Document - -2.1. How to Read This Document - - This document is written to serve two different audiences, protocol - designers using this specification to support authentication in their - protocol, and implementors of clients or servers for those protocols - using this specification. - - The sections "Introduction and Overview", "Profiling requirements", - and "Security Considerations" cover issues that protocol designers - need to understand and address in profiling this specification for - use in a specific protocol. - - Implementors of a protocol using this specification need the - protocol-specific profiling information in addition to the - information in this document. - -2.2. Conventions Used in this Document - - In examples, "C:" and "S:" indicate lines sent by the client and - server respectively. - - The key words "MUST", "MUST NOT", "SHOULD", "SHOULD NOT", and "MAY" - in this document are to be interpreted as defined in "Key words for - use in RFCs to Indicate Requirement Levels" [RFC 2119]. - - - - - - - - - - -Myers Standards Track [Page 2] - -RFC 2222 SASL October 1997 - - -2.3. Examples - - Examples in this document are for the IMAP profile [RFC 2060] of this - specification. The base64 encoding of challenges and responses, as - well as the "+ " preceding the responses are part of the IMAP4 - profile, not part of the SASL specification itself. - -3. Introduction and Overview - - The Simple Authentication and Security Layer (SASL) is a method for - adding authentication support to connection-based protocols. To use - this specification, a protocol includes a command for identifying and - authenticating a user to a server and for optionally negotiating a - security layer for subsequent protocol interactions. - - The command has a required argument identifying a SASL mechanism. - SASL mechanisms are named by strings, from 1 to 20 characters in - length, consisting of upper-case letters, digits, hyphens, and/or - underscores. SASL mechanism names must be registered with the IANA. - Procedures for registering new SASL mechanisms are given in the - section "Registration procedures" - - If a server supports the requested mechanism, it initiates an - authentication protocol exchange. This consists of a series of - server challenges and client responses that are specific to the - requested mechanism. The challenges and responses are defined by the - mechanisms as binary tokens of arbitrary length. The protocol's - profile then specifies how these binary tokens are then encoded for - transfer over the connection. - - After receiving the authentication command or any client response, a - server may issue a challenge, indicate failure, or indicate - completion. The protocol's profile specifies how the server - indicates which of the above it is doing. - - After receiving a challenge, a client may issue a response or abort - the exchange. The protocol's profile specifies how the client - indicates which of the above it is doing. - - During the authentication protocol exchange, the mechanism performs - authentication, transmits an authorization identity (frequently known - as a userid) from the client to server, and negotiates the use of a - mechanism-specific security layer. If the use of a security layer is - agreed upon, then the mechanism must also define or negotiate the - maximum cipher-text buffer size that each side is able to receive. - - - - - - -Myers Standards Track [Page 3] - -RFC 2222 SASL October 1997 - - - The transmitted authorization identity may be different than the - identity in the client's authentication credentials. This permits - agents such as proxy servers to authenticate using their own - credentials, yet request the access privileges of the identity for - which they are proxying. With any mechanism, transmitting an - authorization identity of the empty string directs the server to - derive an authorization identity from the client's authentication - credentials. - - If use of a security layer is negotiated, it is applied to all - subsequent data sent over the connection. The security layer takes - effect immediately following the last response of the authentication - exchange for data sent by the client and the completion indication - for data sent by the server. Once the security layer is in effect, - the protocol stream is processed by the security layer into buffers - of cipher-text. Each buffer is transferred over the connection as a - stream of octets prepended with a four octet field in network byte - order that represents the length of the following buffer. The length - of the cipher-text buffer must be no larger than the maximum size - that was defined or negotiated by the other side. - -4. Profiling requirements - - In order to use this specification, a protocol definition must supply - the following information: - - 1. A service name, to be selected from the IANA registry of "service" - elements for the GSSAPI host-based service name form [RFC 2078]. - - 2. A definition of the command to initiate the authentication - protocol exchange. This command must have as a parameter the - mechanism name being selected by the client. - - The command SHOULD have an optional parameter giving an initial - response. This optional parameter allows the client to avoid a - round trip when using a mechanism which is defined to have the - client send data first. When this initial response is sent by the - client and the selected mechanism is defined to have the server - start with an initial challenge, the command fails. See section - 5.1 of this document for further information. - - 3. A definition of the method by which the authentication protocol - exchange is carried out, including how the challenges and - responses are encoded, how the server indicates completion or - failure of the exchange, how the client aborts an exchange, and - how the exchange method interacts with any line length limits in - the protocol. - - - - -Myers Standards Track [Page 4] - -RFC 2222 SASL October 1997 - - - 4. Identification of the octet where any negotiated security layer - starts to take effect, in both directions. - - 5. A specification of how the authorization identity passed from the - client to the server is to be interpreted. - -5. Specific issues - -5.1. Client sends data first - - Some mechanisms specify that the first data sent in the - authentication protocol exchange is from the client to the server. - - If a protocol's profile permits the command which initiates an - authentication protocol exchange to contain an initial client - response, this parameter SHOULD be used with such mechanisms. - - If the initial client response parameter is not given, or if a - protocol's profile does not permit the command which initiates an - authentication protocol exchange to contain an initial client - response, then the server issues a challenge with no data. The - client's response to this challenge is then used as the initial - client response. (The server then proceeds to send the next - challenge, indicates completion, or indicates failure.) - -5.2. Server returns success with additional data - - Some mechanisms may specify that server challenge data be sent to the - client along with an indication of successful completion of the - exchange. This data would, for example, authenticate the server to - the client. - - If a protocol's profile does not permit this server challenge to be - returned with a success indication, then the server issues the server - challenge without an indication of successful completion. The client - then responds with no data. After receiving this empty response, the - server then indicates successful completion. - -5.3. Multiple authentications - - Unless otherwise stated by the protocol's profile, only one - successful SASL negotiation may occur in a protocol session. In this - case, once an authentication protocol exchange has successfully - completed, further attempts to initiate an authentication protocol - exchange fail. - - - - - - -Myers Standards Track [Page 5] - -RFC 2222 SASL October 1997 - - - In the case that a profile explicitly permits multiple successful - SASL negotiations to occur, then in no case may multiple security - layers be simultaneously in effect. If a security layer is in effect - and a subsequent SASL negotiation selects no security layer, the - original security layer remains in effect. If a security layer is in - effect and a subsequent SASL negotiation selects a second security - layer, then the second security layer replaces the first. - -6. Registration procedures - - Registration of a SASL mechanism is done by filling in the template - in section 6.4 and sending it in to iana@isi.edu. IANA has the right - to reject obviously bogus registrations, but will perform no review - of clams made in the registration form. - - There is no naming convention for SASL mechanisms; any name that - conforms to the syntax of a SASL mechanism name can be registered. - - While the registration procedures do not require it, authors of SASL - mechanisms are encouraged to seek community review and comment - whenever that is feasible. Authors may seek community review by - posting a specification of their proposed mechanism as an internet- - draft. SASL mechanisms intended for widespread use should be - standardized through the normal IETF process, when appropriate. - -6.1. Comments on SASL mechanism registrations - - Comments on registered SASL mechanisms should first be sent to the - "owner" of the mechanism. Submitters of comments may, after a - reasonable attempt to contact the owner, request IANA to attach their - comment to the SASL mechanism registration itself. If IANA approves - of this the comment will be made accessible in conjunction with the - SASL mechanism registration itself. - -6.2. Location of Registered SASL Mechanism List - - SASL mechanism registrations will be posted in the anonymous FTP - directory "ftp://ftp.isi.edu/in-notes/iana/assignments/sasl- - mechanisms/" and all registered SASL mechanisms will be listed in the - periodically issued "Assigned Numbers" RFC [currently STD 2, RFC - 1700]. The SASL mechanism description and other supporting material - may also be published as an Informational RFC by sending it to "rfc- - editor@isi.edu" (please follow the instructions to RFC authors [RFC - 2223]). - - - - - - - -Myers Standards Track [Page 6] - -RFC 2222 SASL October 1997 - - -6.3. Change Control - - Once a SASL mechanism registration has been published by IANA, the - author may request a change to its definition. The change request - follows the same procedure as the registration request. - - The owner of a SASL mechanism may pass responsibility for the SASL - mechanism to another person or agency by informing IANA; this can be - done without discussion or review. - - The IESG may reassign responsibility for a SASL mechanism. The most - common case of this will be to enable changes to be made to - mechanisms where the author of the registration has died, moved out - of contact or is otherwise unable to make changes that are important - to the community. - - SASL mechanism registrations may not be deleted; mechanisms which are - no longer believed appropriate for use can be declared OBSOLETE by a - change to their "intended use" field; such SASL mechanisms will be - clearly marked in the lists published by IANA. - - The IESG is considered to be the owner of all SASL mechanisms which - are on the IETF standards track. - -6.4. Registration Template - - To: iana@iana.org - Subject: Registration of SASL mechanism X - - SASL mechanism name: - - Security considerations: - - Published specification (optional, recommended): - - Person & email address to contact for further information: - - Intended usage: - - (One of COMMON, LIMITED USE or OBSOLETE) - - Author/Change controller: - - (Any other information that the author deems interesting may be - added below this line.) - - - - - - -Myers Standards Track [Page 7] - -RFC 2222 SASL October 1997 - - -7. Mechanism definitions - - The following mechanisms are hereby defined. - -7.1. Kerberos version 4 mechanism - - The mechanism name associated with Kerberos version 4 is - "KERBEROS_V4". - - The first challenge consists of a random 32-bit number in network - byte order. The client responds with a Kerberos ticket and an - authenticator for the principal "service.hostname@realm", where - "service" is the service name specified in the protocol's profile, - "hostname" is the first component of the host name of the server with - all letters in lower case, and where "realm" is the Kerberos realm of - the server. The encrypted checksum field included within the - Kerberos authenticator contains the server provided challenge in - network byte order. - - Upon decrypting and verifying the ticket and authenticator, the - server verifies that the contained checksum field equals the original - server provided random 32-bit number. Should the verification be - successful, the server must add one to the checksum and construct 8 - octets of data, with the first four octets containing the incremented - checksum in network byte order, the fifth octet containing a bit-mask - specifying the security layers supported by the server, and the sixth - through eighth octets containing, in network byte order, the maximum - cipher-text buffer size the server is able to receive. The server - must encrypt using DES ECB mode the 8 octets of data in the session - key and issue that encrypted data in a second challenge. The client - considers the server authenticated if the first four octets of the - un-encrypted data is equal to one plus the checksum it previously - sent. - - The client must construct data with the first four octets containing - the original server-issued checksum in network byte order, the fifth - octet containing the bit-mask specifying the selected security layer, - the sixth through eighth octets containing in network byte order the - maximum cipher-text buffer size the client is able to receive, and - the following octets containing the authorization identity. The - client must then append from one to eight zero-valued octets so that - the length of the data is a multiple of eight octets. The client must - then encrypt using DES PCBC mode the data with the session key and - respond with the encrypted data. The server decrypts the data and - verifies the contained checksum. The server must verify that the - principal identified in the Kerberos ticket is authorized to connect - as that authorization identity. After this verification, the - authentication process is complete. - - - -Myers Standards Track [Page 8] - -RFC 2222 SASL October 1997 - - - The security layers and their corresponding bit-masks are as follows: - - 1 No security layer - 2 Integrity (krb_mk_safe) protection - 4 Privacy (krb_mk_priv) protection - - Other bit-masks may be defined in the future; bits which are not - understood must be negotiated off. - - EXAMPLE: The following are two Kerberos version 4 login scenarios to - the IMAP4 protocol (note that the line breaks in the sample - authenticators are for editorial clarity and are not in real - authenticators) - - S: * OK IMAP4 Server - C: A001 AUTHENTICATE KERBEROS_V4 - S: + AmFYig== - C: BAcAQU5EUkVXLkNNVS5FRFUAOCAsho84kLN3/IJmrMG+25a4DT - +nZImJjnTNHJUtxAA+o0KPKfHEcAFs9a3CL5Oebe/ydHJUwYFd - WwuQ1MWiy6IesKvjL5rL9WjXUb9MwT9bpObYLGOKi1Qh - S: + or//EoAADZI= - C: DiAF5A4gA+oOIALuBkAAmw== - S: A001 OK Kerberos V4 authentication successful - - - S: * OK IMAP4 Server - C: A001 AUTHENTICATE KERBEROS_V4 - S: + gcfgCA== - C: BAcAQU5EUkVXLkNNVS5FRFUAOCAsho84kLN3/IJmrMG+25a4DT - +nZImJjnTNHJUtxAA+o0KPKfHEcAFs9a3CL5Oebe/ydHJUwYFd - WwuQ1MWiy6IesKvjL5rL9WjXUb9MwT9bpObYLGOKi1Qh - S: A001 NO Kerberos V4 authentication failed - -7.2. GSSAPI mechanism - - The mechanism name associated with all mechanisms employing the - GSSAPI [RFC 2078] is "GSSAPI". - -7.2.1 Client side of authentication protocol exchange - - The client calls GSS_Init_sec_context, passing in 0 for - input_context_handle (initially) and a targ_name equal to output_name - from GSS_Import_Name called with input_name_type of - GSS_C_NT_HOSTBASED_SERVICE and input_name_string of - "service@hostname" where "service" is the service name specified in - the protocol's profile, and "hostname" is the fully qualified host - name of the server. The client then responds with the resulting - output_token. If GSS_Init_sec_context returns GSS_S_CONTINUE_NEEDED, - - - -Myers Standards Track [Page 9] - -RFC 2222 SASL October 1997 - - - then the client should expect the server to issue a token in a - subsequent challenge. The client must pass the token to another call - to GSS_Init_sec_context, repeating the actions in this paragraph. - - When GSS_Init_sec_context returns GSS_S_COMPLETE, the client takes - the following actions: If the last call to GSS_Init_sec_context - returned an output_token, then the client responds with the - output_token, otherwise the client responds with no data. The client - should then expect the server to issue a token in a subsequent - challenge. The client passes this token to GSS_Unwrap and interprets - the first octet of resulting cleartext as a bit-mask specifying the - security layers supported by the server and the second through fourth - octets as the maximum size output_message to send to the server. The - client then constructs data, with the first octet containing the - bit-mask specifying the selected security layer, the second through - fourth octets containing in network byte order the maximum size - output_message the client is able to receive, and the remaining - octets containing the authorization identity. The client passes the - data to GSS_Wrap with conf_flag set to FALSE, and responds with the - generated output_message. The client can then consider the server - authenticated. - -7.2.2 Server side of authentication protocol exchange - - The server passes the initial client response to - GSS_Accept_sec_context as input_token, setting input_context_handle - to 0 (initially). If GSS_Accept_sec_context returns - GSS_S_CONTINUE_NEEDED, the server returns the generated output_token - to the client in challenge and passes the resulting response to - another call to GSS_Accept_sec_context, repeating the actions in this - paragraph. - - When GSS_Accept_sec_context returns GSS_S_COMPLETE, the client takes - the following actions: If the last call to GSS_Accept_sec_context - returned an output_token, the server returns it to the client in a - challenge and expects a reply from the client with no data. Whether - or not an output_token was returned (and after receipt of any - response from the client to such an output_token), the server then - constructs 4 octets of data, with the first octet containing a bit- - mask specifying the security layers supported by the server and the - second through fourth octets containing in network byte order the - maximum size output_token the server is able to receive. The server - must then pass the plaintext to GSS_Wrap with conf_flag set to FALSE - and issue the generated output_message to the client in a challenge. - The server must then pass the resulting response to GSS_Unwrap and - interpret the first octet of resulting cleartext as the bit-mask for - the selected security layer, the second through fourth octets as the - maximum size output_message to send to the client, and the remaining - - - -Myers Standards Track [Page 10] - -RFC 2222 SASL October 1997 - - - octets as the authorization identity. The server must verify that - the src_name is authorized to authenticate as the authorization - identity. After these verifications, the authentication process is - complete. - -7.2.3 Security layer - - The security layers and their corresponding bit-masks are as follows: - - 1 No security layer - 2 Integrity protection. - Sender calls GSS_Wrap with conf_flag set to FALSE - 4 Privacy protection. - Sender calls GSS_Wrap with conf_flag set to TRUE - - Other bit-masks may be defined in the future; bits which are not - understood must be negotiated off. - -7.3. S/Key mechanism - - The mechanism name associated with S/Key [RFC 1760] using the MD4 - digest algorithm is "SKEY". - - The client sends an initial response with the authorization identity. - - The server then issues a challenge which contains the decimal - sequence number followed by a single space and the seed string for - the indicated authorization identity. The client responds with the - one-time-password, as either a 64-bit value in network byte order or - encoded in the "six English words" format. - - The server must verify the one-time-password. After this - verification, the authentication process is complete. - - S/Key authentication does not provide for any security layers. - - EXAMPLE: The following are two S/Key login scenarios in the IMAP4 - protocol. - - S: * OK IMAP4 Server - C: A001 AUTHENTICATE SKEY - S: + - C: bW9yZ2Fu - S: + OTUgUWE1ODMwOA== - C: Rk9VUiBNQU5OIFNPT04gRklSIFZBUlkgTUFTSA== - S: A001 OK S/Key authentication successful - - - - - -Myers Standards Track [Page 11] - -RFC 2222 SASL October 1997 - - - S: * OK IMAP4 Server - C: A001 AUTHENTICATE SKEY - S: + - C: c21pdGg= - S: + OTUgUWE1ODMwOA== - C: BsAY3g4gBNo= - S: A001 NO S/Key authentication failed - - The following is an S/Key login scenario in an IMAP4-like protocol - which has an optional "initial response" argument to the AUTHENTICATE - command. - - S: * OK IMAP4-Like Server - C: A001 AUTHENTICATE SKEY bW9yZ2Fu - S: + OTUgUWE1ODMwOA== - C: Rk9VUiBNQU5OIFNPT04gRklSIFZBUlkgTUFTSA== - S: A001 OK S/Key authentication successful - -7.4. External mechanism - - The mechanism name associated with external authentication is - "EXTERNAL". - - The client sends an initial response with the authorization identity. - - The server uses information, external to SASL, to determine whether - the client is authorized to authenticate as the authorization - identity. If the client is so authorized, the server indicates - successful completion of the authentication exchange; otherwise the - server indicates failure. - - The system providing this external information may be, for example, - IPsec or TLS. - - If the client sends the empty string as the authorization identity - (thus requesting the authorization identity be derived from the - client's authentication credentials), the authorization identity is - to be derived from authentication credentials which exist in the - system which is providing the external authentication. - - - - - - - - - - - - -Myers Standards Track [Page 12] - -RFC 2222 SASL October 1997 - - -8. References - - [RFC 2060] Crispin, M., "Internet Message Access Protocol - Version - 4rev1", RFC 2060, December 1996. - - [RFC 2078] Linn, J., "Generic Security Service Application Program - Interface, Version 2", RFC 2078, January 1997. - - [RFC 2119] Bradner, S., "Key words for use in RFCs to Indicate - Requirement Levels", RFC 2119, March 1997. - - [RFC 2223] Postel, J., and J. Reynolds, "Instructions to RFC - Authors", RFC 2223, October 1997. - - [RFC 1760] Haller, N., "The S/Key One-Time Password System", RFC - 1760, February 1995. - - [RFC 1700] Reynolds, J., and J. Postel, "Assigned Numbers", STD 2, - RFC 1700, October 1994. - -9. Security Considerations - - Security issues are discussed throughout this memo. - - The mechanisms that support integrity protection are designed such - that the negotiation of the security layer and authorization identity - is integrity protected. When the client selects a security layer - with at least integrity protection, this protects against an active - attacker hijacking the connection and modifying the authentication - exchange to negotiate a plaintext connection. - - When a server or client supports multiple authentication mechanisms, - each of which has a different security strength, it is possible for - an active attacker to cause a party to use the least secure mechanism - supported. To protect against this sort of attack, a client or - server which supports mechanisms of different strengths should have a - configurable minimum strength that it will use. It is not sufficient - for this minimum strength check to only be on the server, since an - active attacker can change which mechanisms the client sees as being - supported, causing the client to send authentication credentials for - its weakest supported mechanism. - - - - - - - - - - -Myers Standards Track [Page 13] - -RFC 2222 SASL October 1997 - - - The client's selection of a SASL mechanism is done in the clear and - may be modified by an active attacker. It is important for any new - SASL mechanisms to be designed such that an active attacker cannot - obtain an authentication with weaker security properties by modifying - the SASL mechanism name and/or the challenges and responses. - - Any protocol interactions prior to authentication are performed in - the clear and may be modified by an active attacker. In the case - where a client selects integrity protection, it is important that any - security-sensitive protocol negotiations be performed after - authentication is complete. Protocols should be designed such that - negotiations performed prior to authentication should be either - ignored or revalidated once authentication is complete. - -10. Author's Address - - John G. Myers - Netscape Communications - 501 E. Middlefield Road - Mail Stop MV-029 - Mountain View, CA 94043-4042 - - EMail: jgmyers@netscape.com - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Myers Standards Track [Page 14] - -RFC 2222 SASL October 1997 - - -Appendix A. Relation of SASL to Transport Security - - Questions have been raised about the relationship between SASL and - various services (such as IPsec and TLS) which provide a secured - connection. - - Two of the key features of SASL are: - - 1. The separation of the authorization identity from the identity in - the client's credentials. This permits agents such as proxy - servers to authenticate using their own credentials, yet request - the access privileges of the identity for which they are proxying. - - 2. Upon successful completion of an authentication exchange, the - server knows the authorization identity the client wishes to use. - This allows servers to move to a "user is authenticated" state in - the protocol. - - These features are extremely important to some application protocols, - yet Transport Security services do not always provide them. To - define SASL mechanisms based on these services would be a very messy - task, as the framing of these services would be redundant with the - framing of SASL and some method of providing these important SASL - features would have to be devised. - - Sometimes it is desired to enable within an existing connection the - use of a security service which does not fit the SASL model. (TLS is - an example of such a service.) This can be done by adding a command, - for example "STARTTLS", to the protocol. Such a command is outside - the scope of SASL, and should be different from the command which - starts a SASL authentication protocol exchange. - - In certain situations, it is reasonable to use SASL underneath one of - these Transport Security services. The transport service would - secure the connection, either service would authenticate the client, - and SASL would negotiate the authorization identity. The SASL - negotiation would be what moves the protocol from "unauthenticated" - to "authenticated" state. The "EXTERNAL" SASL mechanism is - explicitly intended to handle the case where the transport service - secures the connection and authenticates the client and SASL - negotiates the authorization identity. - - When using SASL underneath a sufficiently strong Transport Security - service, a SASL security layer would most likely be redundant. The - client and server would thus probably want to negotiate off the use - of a SASL security layer. - - - - - -Myers Standards Track [Page 15] - -RFC 2222 SASL October 1997 - - -Full Copyright Statement - - Copyright (C) The Internet Society (1997). All Rights Reserved. - - This document and translations of it may be copied and furnished to - others, and derivative works that comment on or otherwise explain it - or assist in its implmentation may be prepared, copied, published - andand distributed, in whole or in part, without restriction of any - kind, provided that the above copyright notice and this paragraph are - included on all such copies and derivative works. However, this - document itself may not be modified in any way, such as by removing - the copyright notice or references to the Internet Society or other - Internet organizations, except as needed for the purpose of - developing Internet standards in which case the procedures for - copyrights defined in the Internet Standards process must be - followed, or as required to translate it into languages other than - English. - - The limited permissions granted above are perpetual and will not be - revoked by the Internet Society or its successors or assigns. - - This document and the information contained herein is provided on an - "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING - TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING - BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION - HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - - - - - - - - - - - - - - - - - - - - - - - - -Myers Standards Track [Page 16] - diff --git a/doc/rfc2243.txt b/doc/rfc2243.txt deleted file mode 100644 index 0ad5a637..00000000 --- a/doc/rfc2243.txt +++ /dev/null @@ -1,563 +0,0 @@ - - - - - - -Network Working Group C. Metz -Request for Comments: 2243 The Inner Net -Category: Standards Track November 1997 - - - - - OTP Extended Responses - - -Status of this Memo - - This document specifies an Internet standards track protocol for the - Internet community, and requests discussion and suggestions for - improvements. Please refer to the current edition of the "Internet - Official Protocol Standards" (STD 1) for the standardization state - and status of this protocol. Distribution of this memo is unlimited. - -Copyright Notice - - Copyright (C) The Internet Society (1997). All Rights Reserved. - -Abstract - - This document provides a specification for a type of response to an - OTP [RFC 1938] challenge that carries explicit indication of the - response's encoding. Codings for the two mandatory OTP data formats - using this new type of response are presented. - - This document also provides a specification for a response that - allows an OTP generator to request that a server re-initialize a - sequence and change parameters such as the secret pass phrase. - -1. Conventions, Terms, and Notation - - This document specifies the data formats and software behaviors - needed to use OTP extended responses. The data formats are described - three ways: using an ad-hoc UNIX manual page style syntax, using - augmented BNF described in sections two and three of RFC 822, and by - examples. Should there be any conflict between these descriptions, - the augmented BNF takes precedence. The software behaviors are - described in words, and specific behavior compliance requirements are - itemized using the requirements terminology (specifically, the words - MUST, SHOULD, and MAY) defined in RFC 2119. - - - - - - - -Metz Standards Track [Page 1] - -RFC 2243 OTP Extended Responses November 1997 - - -2. Extended Challenges and Extended Responses - - This document builds on the protocol and terminology specified in RFC - 1938 and assumes that you have already read this document and - understand its contents. - - An extended challenge is a single line of printable text terminated - by either a new line sequence appropriate for the context of its use - (e.g., ASCII CR followed by ASCII LF) or a whitespace character. It - contains a standard OTP challenge, a whitespace character, and a list - that generators use to determine which extended responses are - supported by a server. - - An extended response is a single line of printable text terminated by - a new line sequence appropriate for the context of its use. It - contains two or more tokens that are separated with a single colon - (':') character. The first token contains a type specifier that - indicates the format of the rest of the response. The tokens that - follow are argument data for the OTP extended response. At least one - token of data MUST be present. - -2.1. Syntax - - In UNIX manual page like syntax, the general form of an extended - challenge could be described as: - - ext[,[, ...]] - - And the general form of an extended response could be described as: - - :[:[:...]] - - In augmented BNF syntax, the syntax of the general form of an - extended challenge and an extended response is: - - extended-challenge = otp-challenge 1*LWSP-char capability-list - (NL / *LWSP-char) - otp-challenge = - capability-list = "ext" *("," extension-set-id) - extension-set-id = * - extended-response = type 1*(":" argument) NL - type = token - argument = token - token = 1* - NL = - - - - - -Metz Standards Track [Page 2] - -RFC 2243 OTP Extended Responses November 1997 - - - An example of an extended challenge indicating support for OTP - extended responses and for a mythical response set "foo" is: - - otp-md5 123 mi1234 ext,foo - - An example of an extended response using a mythical type named "foo" - is: - - foo:some data:some more data:12345 - -2.2. Requirements - - A server compliant with this specification: - - 1. MUST be able to receive and parse the general form of an - extended response - 2. MUST be able to receive, parse, and correctly process all - extended responses specified in this document - 3. MUST process the type field in a case-insensitive manner - 4. MUST reject any authentication attempt using an extended - response if it does not support that type of response - 5. SHOULD provide an appropriate indication to the generator - if the response was rejected because of (4) - 6. MUST limit the length of the input reasonably - 7. MUST accept otherwise arbitrary amounts of whitespace - wherever a response allows it - 8. MUST be able to receive and correctly process standard OTP - responses - - A generator compliant with this specification: - - 1. MUST be able to generate standard OTP responses - 2. MUST use standard responses unless an extended challenge - has been received for the particular server AND seed - 3. MUST generate the type field in lower case - 4. MUST NOT send a response type for which the server has not - indicated support through an extended challenge - - Extension set identifiers and extension type identifiers named with - the prefix "x-" are reserved for private use among mutually - consenting implementations. Implementations that do not recognise a - particular "x-" extension MUST ignore that extension. This means that - all "x-" extensions are likely to be non-interoperable with other - extensions. Careful consideration should be given to the possibility - of a server interacting with with a generator implementation which, - although it recognizes a given "x-" extension, uses it for a - different purpose. All of the remaining extension namespace is - reserved to IANA, which will only officially assign the extension - - - -Metz Standards Track [Page 3] - -RFC 2243 OTP Extended Responses November 1997 - - - into this namespace after the IESG approves of such an assignment. - During the lifetime of the OTP WG, it is recommended that the IESG - consult with the OTP WG prior to approving such an assignment. - -3. The "hex" and "word" Responses - - There exists a very rare case in which a standard OTP response could - be a valid coding in both the hexadecimal and six-word formats. An - example of this is the response "ABE ACE ADA ADD BAD A." The - solution to this problem mandated by the OTP specification is that - compliant servers MUST attempt to parse and verify a standard - response in both hexadecimal and six-word formats and must consider - the authentication successful if either succeeds. - - This problem can be solved easily using extended responses. The "hex" - response and the "word" response are two response types that encode - an OTP in an extended response that explicitly describes the - encoding. These responses start with a type label of "hex" for a - hexadecimal OTP and "word" for a six-word coded OTP. These responses - contain one argument field that contains a standard OTP response - coded in the indicated format. - -3.1. Syntax - - In UNIX manual page like syntax, the format of these responses could - be described as: - - hex: - word: - - In augmented BNF syntax and with the definitions already provided, - the syntax of these responses is: - - hex-response = "hex:" hex-64bit NL - hex-64bit = 16(hex-char *LWSP-char) - hex-char = ("A" / "B" / "C" / "D" / "E" / "F" / - "a" / "b" / "c" / "d" / "e" / "f" / - "0" / "1" / "2" / "3" / "4" / "5" / - "6" / "7" / "8" / "9") - - word-response = "word:" word-64bit NL - word-64bit = 6(otp-word 1*LWSP-char) - otp-word = - - - - - - - -Metz Standards Track [Page 4] - -RFC 2243 OTP Extended Responses November 1997 - - - Examples of these responses are: - - hex:8720 33d4 6202 9172 - word:VAST SAUL TAKE SODA SUCH BOLT - -3.2. Requirements - - A server compliant with this specification: - - 1. MUST process all arguments in a case-insensitive manner - - A generator compliant with this specification: - - 1. SHOULD generate otp-word tokens in upper case with single - spaces separating them - 2. SHOULD generate hexadecimal numbers using only lower case - for letters - -4. The "init-hex" and "init-word" Responses - - The OTP specification requires that implementations provide a means - for a client to re-initialize or change its OTP information with a - server but does not require any specific protocol for doing it. - Implementations that support the OTP extended responses described in - this document MUST support the response with the "init-hex" and - "init-word" type specifiers, which provide a standard way for a - client to re-initialize its OTP information with a server. This - response is intended to be used only by automated clients. Because of - this, the recommended form of this response uses the hexadecimal - encoding for binary data. It is possible for a user to type an "init- - hex" or "init-word" response. - -4.1. Syntax - - In UNIX manual page like syntax, the format of these responses could - be described as: - - init-hex::: - init-word::: - - In augmented BNF syntax and with the definitions already provided, - the syntax of the "init-hex" response is: - - init-hex-response = "init-hex:" current-OTP ":" new-params ":" - new-OTP NL - - current-OTP = hex-64bit - new-OTP = hex-64bit - - - -Metz Standards Track [Page 5] - -RFC 2243 OTP Extended Responses November 1997 - - - new-params = algorithm SPACE sequence-number SPACE seed - algorithm = "md4" / "md5" / "sha1" - sequence-number = 4*3DIGIT - seed = 16*1(ALPHA / DIGIT) - - In augmented BNF syntax and with the definitions already provided, - the syntax of the "init-word" response is: - - init-word-response = "init-word:" current-OTP ":" new-params ":" - new-OTP NL - - current-OTP = word-64bit - new-OTP = word-64bit - - new-params = algorithm SPACE sequence-number SPACE seed - algorithm = "md4" / "md5" / "sha1" - sequence-number = 4*3DIGIT - seed = 16*1(ALPHA / DIGIT) - - Note that all appropriate fields for the "init-hex" response MUST be - hexadecimally coded and that all appropriate fields for the "init- - word" response MUST be six-word coded. - - Examples of these responses are: - - init-hex:f6bd 6b33 89b8 7203:md5 499 ke6118:23d1 b253 5ae0 2b7e - init-hex:c9b2 12bb 6425 5a0f:md5 499 ke0986:fd17 cef1 b4df 093e - - init-word:MOOD SOFT POP COMB BOLO LIFE:md5 499 ke1235: - ARTY WEAR TAD RUG HALO GIVE - init-word:END KERN BALM NICK EROS WAVY:md5 499 ke1235: - BABY FAIN OILY NIL TIDY DADE - - (Note that all of these responses are one line. Due to their length, - they had to be split into multiple lines in order to be included - here. These responses MUST NOT span more than one line in actual use) - -4.2. Description of Fields - - The current-OTP field contains the (RFC 1938) response to the OTP - challenge. The new-params field contains the parameters for the - client's new requested challenge and the new-OTP field contains a - response to that challenge. If the re-initialization is successful, a - server MUST store the new OTP in its database as the last successful - OTP received and the sequence number in the next challenge presented - by the server MUST be one less than the sequence number specified in - the new-params field. - - - - -Metz Standards Track [Page 6] - -RFC 2243 OTP Extended Responses November 1997 - - - The new-params field is hashed as a string the same way that a seed - or secret pass phrase would be. All other field values are hashed in - their uncoded binary forms, in network byte order and without any - padding. - -4.3. Requirements - - A server compliant with this specification: - - 1. SHOULD NOT allow a user to use the same value for their - seed and secret pass phrase. - 2. MUST disable all OTP access to any principal whose - sequence number would be less than one - 3. MUST decrement the sequence number if a reinitialization - response includes a valid current-OTP, but the server is - unable to successfully process the new-params or new-OTP for - any reason. - - A generator compliant with this specification: - - 1. SHOULD NOT allow a user to use the same value for their - seed and secret pass phrase - 2. MUST take specific steps to prevent infinite loops of - re-initialization attempts in case of failure - 3. SHOULD provide the user with some indication that the - re-initialization is taking place - 4. SHOULD NOT do a re-initialization without the user's - permission, either for that specific instance or as a - configuration option - 5. SHOULD NOT retry a failed re-initialization without a user's - permission - 6. SHOULD warn the user if the sequence number falls below ten - 7. MUST refuse to generate OTPs with a sequence number below one - -5. Security Considerations - - All of the security considerations for the OTP system also apply to - the OTP system with extended responses. - - These extended responses, like OTP itself, do not protect the user - against active attacks. The IPsec Authentication Header (RFC-1826) - (or another technique with at least as much strength as IPsec AH) - SHOULD be used to protect against such attacks. - - The consequences of a successful active attack on the re- - initialization response may be more severe than simply hijacking a - single session. An attacker could substitute his own response for - - - - -Metz Standards Track [Page 7] - -RFC 2243 OTP Extended Responses November 1997 - - - that of a legitimate user. The attacker may then be able to use the - OTP system to authenticate himself as the user at will (at least - until detected). - - Failure to implement server requirement 3 in section 4.3 opens an - implementation to an attack based on replay of the current-OTP part - of the response. - -6. Acknowledgments - - Like RFC 1938, the protocol described in this document was created by - contributors in the IETF OTP working group. Specific contributions - were made by Neil Haller, who provided input on the overall design - requirements of a re-initialization protocol, Denis Pinkas, who - suggested several modifications to the originally proposed re- - initialization protocol, and Phil Servita, who opened the debate with - the first real protocol proposal and provided lots of specific input - on the design of this and earlier protocols. The extensions to the - OTP challenge were suggested by Chris Newman and John Valdes. - - Randall Atkinson and Ted T'so also contributed their views to - discussions about details of the protocol extensions in this - document. - -References - - [RFC 822] Crocker, D., "Standard for the Format of ARPA Internet - Text Messages," RFC 822, August 1982. - - [RFC 1825] Atkinson, R., "Security Architecture for the Internet - Protocol," RFC 1825, August 1995. - - [RFC 1938] Haller, N. and C. Metz, "A One-Time Password System," - RFC 1938, May 1996. - - [RFC 2119] Bradner, S., "Key words for use in RFCs to - Indicate Requirement Level," RFC 2119, - March 1997. - -Author's Address - - Craig Metz - The Inner Net - Box 10314-1936 - Blacksburg, VA 24062-0314 - (DSN) 354-8590 - cmetz@inner.net - - - - -Metz Standards Track [Page 8] - -RFC 2243 OTP Extended Responses November 1997 - - -Appendix: Reference Responses - - The following responses were generated by a development version of - the One-Time Passwords in Everything (OPIE) implementation of this - specification. - - All of these are responses to the challenge: - - otp-md5 499 ke1234 ext - - Note that the re-initialization responses use the same secret pass - phrase for new and current and a new seed of "ke1235". Also, these - responses have been split for formatting purposes into multiple - lines; they MUST NOT be multiple lines in actual use. - - The secret pass phrase for these responses is: - - This is a test. - - The OTP standard hexadecimal response is: - - 5bf0 75d9 959d 036f - - The OTP standard six-word response is: - - BOND FOGY DRAB NE RISE MART - - The OTP extended "hex" response is: - - hex:5Bf0 75d9 959d 036f - - The OTP extended "word" response is: - - word:BOND FOGY DRAB NE RISE MART - - The OTP extended "init-hex" response is: - - init-hex:5bf0 75d9 959d 036f:md5 499 ke1235:3712 dcb4 aa53 16c1 - - The OTP extended "init-word" response is: - - init-word:BOND FOGY DRAB NE RISE MART:md5 499 ke1235: RED HERD - NOW BEAN PA BURG - - - - - - - - -Metz Standards Track [Page 9] - -RFC 2243 OTP Extended Responses November 1997 - - -Full Copyright Statement - - Copyright (C) The Internet Society (1997). All Rights Reserved. - - This document and translations of it may be copied and furnished to - others, and derivative works that comment on or otherwise explain it - or assist in its implementation may be prepared, copied, published - and distributed, in whole or in part, without restriction of any - kind, provided that the above copyright notice and this paragraph are - included on all such copies and derivative works. However, this - document itself may not be modified in any way, such as by removing - the copyright notice or references to the Internet Society or other - Internet organizations, except as needed for the purpose of - developing Internet standards in which case the procedures for - copyrights defined in the Internet Standards process must be - followed, or as required to translate it into languages other than - English. - - The limited permissions granted above are perpetual and will not be - revoked by the Internet Society or its successors or assigns. - - This document and the information contained herein is provided on an - "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING - TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING - BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION - HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - - - - - - - - - - - - - - - - - - - - - - - - -Metz Standards Track [Page 10] - diff --git a/doc/rfc2245.txt b/doc/rfc2245.txt deleted file mode 100644 index 1025a906..00000000 --- a/doc/rfc2245.txt +++ /dev/null @@ -1,283 +0,0 @@ - - - - - - -Network Working Group C. Newman -Request for Comments: 2245 Innosoft -Category: Standards Track November 1997 - - - Anonymous SASL Mechanism - -Status of this Memo - - This document specifies an Internet standards track protocol for the - Internet community, and requests discussion and suggestions for - improvements. Please refer to the current edition of the "Internet - Official Protocol Standards" (STD 1) for the standardization state - and status of this protocol. Distribution of this memo is unlimited. - -Copyright Notice - - Copyright (C) The Internet Society (1997). All Rights Reserved. - -Abstract - - It is common practice on the Internet to permit anonymous access to - various services. Traditionally, this has been done with a plain - text password mechanism using "anonymous" as the user name and - optional trace information, such as an email address, as the - password. As plaintext login commands are not permitted in new IETF - protocols, a new way to provide anonymous login is needed within the - context of the SASL [SASL] framework. - -1. Conventions Used in this Document - - The key words "MUST", "MUST NOT", "SHOULD", "SHOULD NOT", and "MAY" - in this document are to be interpreted as defined in "Key words for - use in RFCs to Indicate Requirement Levels" [KEYWORDS]. - -2. Anonymous SASL mechanism - - The mechanism name associated with anonymous access is "ANONYMOUS". - The mechanism consists of a single message from the client to the - server. The client sends optional trace information in the form of a - human readable string. The trace information should take one of - three forms: an Internet email address, an opaque string which does - not contain the '@' character and can be interpreted by the system - administrator of the client's domain, or nothing. For privacy - reasons, an Internet email address should only be used with - permission from the user. - - - - - -Newman Standards Track [Page 1] - -RFC 2245 Anonymous SASL Mechanism November 1997 - - - A server which permits anonymous access will announce support for the - ANONYMOUS mechanism, and allow anyone to log in using that mechanism, - usually with restricted access. - - The formal grammar for the client message using Augmented BNF [ABNF] - follows. - - message = [email / token] - - TCHAR = %x20-3F / %x41-7E - ;; any printable US-ASCII character except '@' - - email = addr-spec - ;; as defined in [IMAIL], except with no free - ;; insertion of linear-white-space, and the - ;; local-part MUST either be entirely enclosed in - ;; quotes or entirely unquoted - - token = 1*255TCHAR - -3. Example - - - Here is a sample anonymous login between an IMAP client and server. - In this example, "C:" and "S:" indicate lines sent by the client and - server respectively. If such lines are wrapped without a new "C:" or - "S:" label, then the wrapping is for editorial clarity and is not - part of the command. - - Note that this example uses the IMAP profile [IMAP4] of SASL. The - base64 encoding of challenges and responses, as well as the "+ " - preceding the responses are part of the IMAP4 profile, not part of - SASL itself. Newer profiles of SASL will include the client message - with the AUTHENTICATE command itself so the extra round trip below - (the server response with an empty "+ ") can be eliminated. - - In this example, the user's opaque identification token is "sirhc". - - S: * OK IMAP4 server ready - C: A001 CAPABILITY - S: * CAPABILITY IMAP4 IMAP4rev1 AUTH=CRAM-MD5 AUTH=ANONYMOUS - S: A001 OK done - C: A002 AUTHENTICATE ANONYMOUS - S: + - C: c2lyaGM= - S: A003 OK Welcome, trace information has been logged. - - - - - -Newman Standards Track [Page 2] - -RFC 2245 Anonymous SASL Mechanism November 1997 - - -4. Security Considerations - - The anonymous mechanism grants access to information by anyone. For - this reason it should be disabled by default so the administrator can - make an explicit decision to enable it. - - If the anonymous user has any write privileges, a denial of service - attack is possible by filling up all available space. This can be - prevented by disabling all write access by anonymous users. - - If anonymous users have read and write access to the same area, the - server can be used as a communication mechanism to anonymously - exchange information. Servers which accept anonymous submissions - should implement the common "drop box" model which forbids anonymous - read access to the area where anonymous submissions are accepted. - - If the anonymous user can run many expensive operations (e.g., an - IMAP SEARCH BODY command), this could enable a denial of service - attack. Servers are encouraged to limit the number of anonymous - users and reduce their priority or limit their resource usage. - - If there is no idle timeout for the anonymous user and there is a - limit on the number of anonymous users, a denial of service attack is - enabled. Servers should implement an idle timeout for anonymous - users. - - The trace information is not authenticated so it can be falsified. - This can be used as an attempt to get someone else in trouble for - access to questionable information. Administrators trying to trace - abuse need to realize this information may be falsified. - - A client which uses the user's correct email address as trace - information without explicit permission may violate that user's - privacy. Information about who accesses an anonymous archive on a - sensitive subject (e.g., sexual abuse) has strong privacy needs. - Clients should not send the email address without explicit permission - of the user and should offer the option of supplying no trace token - -- thus only exposing the source IP address and time. Anonymous - proxy servers could enhance this privacy, but would have to consider - the resulting potential denial of service attacks. - - Anonymous connections are susceptible to man in the middle attacks - which view or alter the data transferred. Clients and servers are - encouraged to support external integrity and encryption mechanisms. - - Protocols which fail to require an explicit anonymous login are more - susceptible to break-ins given certain common implementation - techniques. Specifically, Unix servers which offer user login may - - - -Newman Standards Track [Page 3] - -RFC 2245 Anonymous SASL Mechanism November 1997 - - - initially start up as root and switch to the appropriate user id - after an explicit login command. Normally such servers refuse all - data access commands prior to explicit login and may enter a - restricted security environment (e.g., the Unix chroot function) for - anonymous users. If anonymous access is not explicitly requested, - the entire data access machinery is exposed to external security - attacks without the chance for explicit protective measures. - Protocols which offer restricted data access should not allow - anonymous data access without an explicit login step. - -5. References - - [ABNF] Crocker, D. and P. Overell, "Augmented BNF for Syntax - Specifications: ABNF", RFC 2234, November 1997. - - [IMAIL] Crocker, D., "Standard for the Format of Arpa Internet Text - Messages", STD 11, RFC 822, August 1982. - - [IMAP4] Crispin, M., "Internet Message Access Protocol - Version - 4rev1", RFC 2060, December 1996. - - [KEYWORDS] Bradner, S., "Key words for use in RFCs to Indicate - Requirement Levels", RFC 2119, March 1997. - - [SASL] Myers, J., "Simple Authentication and Security Layer (SASL)", - RFC 2222, October 1997. - -6. Author's Address - - Chris Newman - Innosoft International, Inc. - 1050 Lakes Drive - West Covina, CA 91790 USA - - Email: chris.newman@innosoft.com - - - - - - - - - - - - - - - - -Newman Standards Track [Page 4] - -RFC 2245 Anonymous SASL Mechanism November 1997 - - -7. Full Copyright Statement - - Copyright (C) The Internet Society (1997). All Rights Reserved. - - This document and translations of it may be copied and furnished to - others, and derivative works that comment on or otherwise explain it - or assist in its implementation may be prepared, copied, published - and distributed, in whole or in part, without restriction of any - kind, provided that the above copyright notice and this paragraph are - included on all such copies and derivative works. However, this - document itself may not be modified in any way, such as by removing - the copyright notice or references to the Internet Society or other - Internet organizations, except as needed for the purpose of - developing Internet standards in which case the procedures for - copyrights defined in the Internet Standards process must be - followed, or as required to translate it into languages other than - English. - - The limited permissions granted above are perpetual and will not be - revoked by the Internet Society or its successors or assigns. - - This document and the information contained herein is provided on an - "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING - TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING - BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION - HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - - - - - - - - - - - - - - - - - - - - - - - - -Newman Standards Track [Page 5] - diff --git a/doc/rfc2289.txt b/doc/rfc2289.txt deleted file mode 100644 index 8d1d7222..00000000 --- a/doc/rfc2289.txt +++ /dev/null @@ -1,1403 +0,0 @@ - - - - - - -Network Working Group N. Haller -Request for Comments: 2289 Bellcore -Obsoletes: 1938 C. Metz -Category: Standards Track Kaman Sciences Corporation - P. Nesser - Nesser & Nesser Consulting - M. Straw - Bellcore - February 1998 - - - A One-Time Password System - -Status of this Memo - - This document specifies an Internet standards track protocol for the - Internet community, and requests discussion and suggestions for - improvements. Please refer to the current edition of the "Internet - Official Protocol Standards" (STD 1) for the standardization state - and status of this protocol. Distribution of this memo is unlimited. - -Copyright Notice - - Copyright (C) The Internet Society (1998). All Rights Reserved. - -1.0 ABSTRACT - - This document describes a one-time password authentication system - (OTP). The system provides authentication for system access (login) - and other applications requiring authentication that is secure - against passive attacks based on replaying captured reusable - passwords. OTP evolved from the S/KEY (S/KEY is a trademark of - Bellcore) One-Time Password System that was released by Bellcore and - is described in references [3] and [5]. - -2.0 OVERVIEW - - One form of attack on networked computing systems is eavesdropping on - network connections to obtain authentication information such as the - login IDs and passwords of legitimate users. Once this information is - captured, it can be used at a later time to gain access to the - system. One-time password systems are designed to counter this type - of attack, called a "replay attack" [4]. - - The authentication system described in this document uses a secret - pass-phrase to generate a sequence of one-time (single use) - passwords. With this system, the user's secret pass-phrase never - needs to cross the network at any time such as during authentication - - - -Haller Standards Track [Page 1] - -RFC 2289 A One-Time Password System February 1998 - - - or during pass-phrase changes. Thus, it is not vulnerable to replay - attacks. Added security is provided by the property that no secret - information need be stored on any system, including the server being - protected. - - The OTP system protects against external passive attacks against the - authentication subsystem. It does not prevent a network eavesdropper - from gaining access to private information and does not provide - protection against either "social engineering" or active attacks [9]. - -3.0 INTRODUCTION - - There are two entities in the operation of the OTP one-time password - system. The generator must produce the appropriate one-time password - from the user's secret pass-phrase and from information provided in - the challenge from the server. The server must send a challenge that - includes the appropriate generation parameters to the generator, must - verify the one-time password received, must store the last valid - one-time password it received, and must store the corresponding one- - time password sequence number. The server must also facilitate the - changing of the user's secret pass-phrase in a secure manner. - - The OTP system generator passes the user's secret pass-phrase, along - with a seed received from the server as part of the challenge, - through multiple iterations of a secure hash function to produce a - one-time password. After each successful authentication, the number - of secure hash function iterations is reduced by one. Thus, a unique - sequence of passwords is generated. The server verifies the one-time - password received from the generator by computing the secure hash - function once and comparing the result with the previously accepted - one-time password. This technique was first suggested by Leslie - Lamport [1]. - -4.0 REQUIREMENTS TERMINOLOGY - - In this document, the words that are used to define the significance - of each particular requirement are usually capitalized. These words - are: - - - MUST - - This word or the adjective "REQUIRED" means that the item is an - absolute requirement of the specification. - - - - - - - - -Haller Standards Track [Page 2] - -RFC 2289 A One-Time Password System February 1998 - - - - SHOULD - - This word or the adjective "RECOMMENDED" means that there might - exist valid reasons in particular circumstances to ignore this - item, but the full implications should be understood and the case - carefully weighed before taking a different course. - - - MAY - - This word or the adjective "OPTIONAL" means that this item is - truly optional. One vendor might choose to include the item - because a particular marketplace requires it or because it - enhances the product, for example; another vendor may omit the - same item. - -5.0 SECURE HASH FUNCTION - - The security of the OTP system is based on the non-invertability of a - secure hash function. Such a function must be tractable to compute in - the forward direction, but computationally infeasible to invert. - - The interfaces are currently defined for three such hash algorithms, - MD4 [2] and MD5 [6] by Ronald Rivest, and SHA [7] by NIST. All - conforming implementations of both server and generators MUST support - MD5. They SHOULD support SHA and MAY also support MD4. Clearly, the - generator and server must use the same algorithm in order to - interoperate. Other hash algorithms may be specified for use with - this system by publishing the appropriate interfaces. - - The secure hash algorithms listed above have the property that they - accept an input that is arbitrarily long and produce a fixed size - output. The OTP system folds this output to 64 bits using the - algorithms in the Appendix A. 64 bits is also the length of the one- - time passwords. This is believed to be long enough to be secure and - short enough to be entered manually (see below, Form of Output) when - necessary. - -6.0 GENERATION OF ONE-TIME PASSWORDS - - This section describes the generation of the one-time passwords. - This process consists of an initial step in which all inputs are - combined, a computation step where the secure hash function is - applied a specified number of times, and an output function where the - 64 bit one-time password is converted to a human readable form. - - Appendix C contains examples of the outputs given a collection of - inputs. It provides implementors with a means of verification the - use of these algorithms. - - - -Haller Standards Track [Page 3] - -RFC 2289 A One-Time Password System February 1998 - - - Initial Step - - In principle, the user's secret pass-phrase may be of any length. To - reduce the risk from techniques such as exhaustive search or - dictionary attacks, character string pass-phrases MUST contain at - least 10 characters (see Form of Inputs below). All implementations - MUST support a pass-phrases of at least 63 characters. The secret - pass-phrase is frequently, but is not required to be, textual - information provided by a user. - - In this step, the pass phrase is concatenated with a seed that is - transmitted from the server in clear text. This non-secret seed - allows clients to use the same secret pass-phrase on multiple - machines (using different seeds) and to safely recycle their secret - pass-phrases by changing the seed. - - The result of the concatenation is passed through the secure hash - function and then is reduced to 64 bits using one of the function - dependent algorithms shown in Appendix A. - - Computation Step - - A sequence of one-time passwords is produced by applying the secure - hash function multiple times to the output of the initial step - (called S). That is, the first one-time password to be used is - produced by passing S through the secure hash function a number of - times (N) specified by the user. The next one-time password to be - used is generated by passing S though the secure hash function N-1 - times. An eavesdropper who has monitored the transmission of a one- - time password would not be able to generate the next required - password because doing so would mean inverting the hash function. - - Form of Inputs - - The secret pass-phrase is seen only by the OTP generator. To allow - interchangeability of generators, all generators MUST support a - secret pass-phrase of 10 to 63 characters. Implementations MAY - support a longer pass-phrase, but such implementations risk the loss - of interchangeability with implementations supporting only the - minimum. - - The seed MUST consist of purely alphanumeric characters and MUST be - of one to 16 characters in length. The seed is a string of characters - that MUST not contain any blanks and SHOULD consist of strictly - alphanumeric characters from the ISO-646 Invariant Code Set. The - seed MUST be case insensitive and MUST be internally converted to - lower case before it is processed. - - - - -Haller Standards Track [Page 4] - -RFC 2289 A One-Time Password System February 1998 - - - The sequence number and seed together constitute a larger unit of - data called the challenge. The challenge gives the generator the - parameters it needs to calculate the correct one-time password from - the secret pass-phrase. The challenge MUST be in a standard syntax so - that automated generators can recognize the challenge in context and - extract these parameters. The syntax of the challenge is: - - otp- - - The three tokens MUST be separated by a white space (defined as any - number of spaces and/or tabs) and the entire challenge string MUST be - terminated with either a space or a new line. The string "otp-" MUST - be in lower case. The algorithm identifier is case sensitive (the - existing identifiers are all lower case), and the seed is case - insensitive and converted before use to lower case. If additional - algorithms are defined, appropriate identifiers (short, but not - limited to three or four characters) must be defined. The currently - defined algorithm identifiers are: - - md4 MD4 Message Digest - md5 MD5 Message Digest - sha1 NIST Secure Hash Algorithm Revision 1 - - An example of an OTP challenge is: otp-md5 487 dog2 - - Form of Output - - The one-time password generated by the above procedure is 64 bits in - length. Entering a 64 bit number is a difficult and error prone - process. Some generators insert this password into the input stream - and some others make it available for system "cut and paste." Still - other arrangements require the one-time password to be entered - manually. The OTP system is designed to facilitate this manual entry - without impeding automatic methods. The one-time password therefore - MAY be converted to, and all servers MUST be capable of accepting it - as, a sequence of six short (1 to 4 letter) easily typed words that - only use characters from ISO-646 IVCS. Each word is chosen from a - dictionary of 2048 words; at 11 bits per word, all one-time passwords - may be encoded. - - The two extra bits in this encoding are used to store a checksum. - The 64 bits of key are broken down into pairs of bits, then these - pairs are summed together. The two least significant bits of this sum - are encoded in the last two bits of the six word sequence with the - least significant bit of the sum as the last bit encoded. All OTP - generators MUST calculate this checksum and all OTP servers MUST - verify this checksum explicitly as part of the operation of decoding - this representation of the one-time password. - - - -Haller Standards Track [Page 5] - -RFC 2289 A One-Time Password System February 1998 - - - Generators that produce the six-word format MUST present the words in - upper case with single spaces used as separators. All servers MUST - accept six-word format without regard to case and white space used as - a separator. The two lines below represent the same one-time - password. The first is valid as output from a generator and as input - a server, the second is valid only as human input to a server. - - OUST COAT FOAL MUG BEAK TOTE - oust coat foal mug beak tote - - Interoperability requires that all OTP servers and generators use - the same dictionary. The standard dictionary was originally - specified in the "S/KEY One Time Password System" that is described - in RFC 1760 [5]. This dictionary is included in this document as - Appendix D. - - To facilitate the implementation of smaller generators, hexadecimal - output is an acceptable alternative for the presentation of the - one-time password. All implementations of the server software MUST - accept case-insensitive hexadecimal as well as six-word format. The - hexadecimal digits may be separated by white space so servers are - REQUIRED to ignore all white space. If the representation is - partitioned by white space, leading zeros must be retained. - Examples of hexadecimal format are: - - Representation Value - - 3503785b369cda8b 0x3503785b369cda8b - e5cc a1b8 7c13 096b 0xe5cca1b87c13096b - C7 48 90 F4 27 7B A1 CF 0xc74890f4277ba1cf - 47 9 A68 28 4C 9D 0 1BC 0x479a68284c9d01bc - - In addition to accepting six-word and hexadecimal encodings of the - 64 bit one-time password, servers SHOULD accept the alternate - dictionary encoding described in Appendix B. The six words in this - encoding MUST not overlap the set of words in the standard - dictionary. To avoid ambiguity with the hexadecimal representation, - words in the alternate dictionary MUST not be comprised solely of - the letters A-F. Decoding words thus encoded does not require any - knowledge of the alternative dictionary used so the acceptance of - any alternate dictionary implies the acceptance of all alternate - dictionaries. Words in the alternative dictionaries are case - sensitive. Generators and servers MUST preserve the case in the - processing of these words. - - In summary, all conforming servers MUST accept six-word input that - uses the Standard Dictionary (RFC 1760 and Appendix D), MUST accept - hexadecimal encoding, and SHOULD accept six-word input that uses the - - - -Haller Standards Track [Page 6] - -RFC 2289 A One-Time Password System February 1998 - - - Alternative Dictionary technique (Appendix B). As there is a remote - possibility that a hexadecimal encoding of a one-time password will - look like a valid six-word standard dictionary encoding, all - implementations MUST use the following scheme. If a six-word - encoded one-time password is valid, it is accepted. Otherwise, if - the one-time password can be interpreted as hexadecimal, and with - that decoding it is valid, then it is accepted. - -7.0 VERIFICATION OF ONE-TIME PASSWORDS - - An application on the server system that requires OTP authentication - is expected to issue an OTP challenge as described above. Given the - parameters from this challenge and the secret pass-phrase, the - generator can compute (or lookup) the one-time password that is - passed to the server to be verified. - - The server system has a database containing, for each user, the - one-time password from the last successful authentication or the - first OTP of a newly initialized sequence. To authenticate the user, - the server decodes the one-time password received from the generator - into a 64-bit key and then runs this key through the secure hash - function once. If the result of this operation matches the stored - previous OTP, the authentication is successful and the accepted - one-time password is stored for future use. - -8.0 PASS-PHRASE CHANGES - - Because the number of hash function applications executed by the - generator decreases by one each time, at some point the user must - reinitialize the system or be unable to authenticate. - - Although some installations may not permit users to initialize - remotely, implementations MUST provide a means to do so that does - not reveal the user's secret pass-phrase. One way is to provide a - means to reinitialize the sequence through explicit specification - of the first one-time password. - - When the sequence of one-time passwords is reinitialized, - implementations MUST verify that the seed or the pass-phrase is - changed. Installations SHOULD discourage any operation that sends - the secret pass-phrase over a network in clear-text as such practice - defeats the concept of a one-time password. - - Implementations MAY use the following technique for - [re]initialization: - - - - - - -Haller Standards Track [Page 7] - -RFC 2289 A One-Time Password System February 1998 - - - o The user picks a new seed and hash count (default values may - be offered). The user provides these, along with the - corresponding generated one-time password, to the host system. - - o The user MAY also provide the corresponding generated one - time password for count-1 as an error check. - - o The user SHOULD provide the generated one-time password for - the old seed and old hash count to protect an idle terminal - or workstation (this implies that when the count is 1, the - user can login but cannot then change the seed or count). - - In the future a specific protocol may be defined for - reinitialization that will permit smooth and possibly automated - interoperation of all hosts and generators. - -9.0 PROTECTION AGAINST RACE ATTACK - - All conforming server implementations MUST protect against the race - condition described in this section. A defense against this attack - is outlined; implementations MAY use this approach or MAY select an - alternative defense. - - It is possible for an attacker to listen to most of a one-time - password, guess the remainder, and then race the legitimate user to - complete the authentication. Multiple guesses against the last word - of the six-word format are likely to succeed. - - One possible defense is to prevent a user from starting multiple - simultaneous authentication sessions. This means that once the - legitimate user has initiated authentication, an attacker would be - blocked until the first authentication process has completed. In - this approach, a timeout is necessary to thwart a denial of service - attack. - -10.0 SECURITY CONSIDERATIONS - - This entire document discusses an authentication system that - improves security by limiting the danger of eavesdropping/replay - attacks that have been used against simple password systems [4]. - - The use of the OTP system only provides protections against passive - eavesdropping/replay attacks. It does not provide for the privacy - of transmitted data, and it does not provide protection against - active attacks such as session hijacking that are known to be - present in the current Internet [9]. The use of IP Security - (IPsec), see [10], [11], and [12] is recommended to protect against - TCP session hijacking. - - - -Haller Standards Track [Page 8] - -RFC 2289 A One-Time Password System February 1998 - - - The success of the OTP system to protect host systems is dependent - on the non-invertability of the secure hash functions used. To our - knowledge, none of the hash algorithms have been broken, but it is - generally believed [6] that MD4 is not as strong as MD5. If a - server supports multiple hash algorithms, it is only as secure as - the weakest algorithm. - -11.0 ACKNOWLEDGMENTS - - The idea behind OTP authentication was first proposed by Leslie - Lamport [1]. Bellcore's S/KEY system, from which OTP is derived, was - proposed by Phil Karn, who also wrote most of the Bellcore reference - implementation. - -12.0 REFERENCES - - [1] Leslie Lamport, "Password Authentication with Insecure - Communication", Communications of the ACM 24.11 (November - 1981), 770-772 - - [2] Rivest, R., "The MD4 Message-Digest Algorithm", RFC 1320, - April 1992. - - [3] Neil Haller, "The S/KEY One-Time Password System", Proceedings - of the ISOC Symposium on Network and Distributed System - Security, February 1994, San Diego, CA - - [4] Haller, N., and R. Atkinson, "On Internet Authentication", - RFC 1704, October 1994. - - [5] Haller, N., "The S/KEY One-Time Password System", - RFC 1760, February 1995. - - [6] Rivest, R., "The MD5 Message-Digest Algorithm", RFC 1321, - April 1992. - - [7] National Institute of Standards and Technology (NIST), - "Announcing the Secure Hash Standard", FIPS 180-1, U.S. - Department of Commerce, April 1995. - - [8] International Standard - Information Processing -- ISO 7-bit - coded character set for information interchange (Invariant Code - Set), ISO-646, International Standards Organization, Geneva, - Switzerland, 1983 - - - - - - - -Haller Standards Track [Page 9] - -RFC 2289 A One-Time Password System February 1998 - - - [9] Computer Emergency Response Team (CERT), "IP Spoofing and - Hijacked Terminal Connections", CA-95:01, January 1995. - Available via anonymous ftp from info.cert.org in - /pub/cert_advisories. - - [10] Atkinson, R., "Security Architecture for the Internet Protocol", - RFC 1825, August 1995. - - [11] Atkinson, R., "IP Authentication Header", RFC 1826, August - 1995. - - [12] Atkinson, R., "IP Encapsulating Security Payload (ESP)", RFC - 1827, August 1995. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Haller Standards Track [Page 10] - -RFC 2289 A One-Time Password System February 1998 - - -13.0 AUTHORS' ADDRESSES - - Neil Haller - Bellcore - MCC 1C-265B - 445 South Street - Morristown, NJ, 07960-6438, USA - - Phone: +1 201 829-4478 - Fax: +1 201 829-2504 - EMail: nmh@bellcore.com - - - Craig Metz - Kaman Sciences Corporation - For NRL Code 5544 - 4555 Overlook Avenue, S.W. - Washington, DC, 20375-5337, USA - - Phone: +1 202 404-7122 - Fax: +1 202 404-7942 - EMail: cmetz@cs.nrl.navy.mil - - - Philip J. Nesser II - Nesser & Nesser Consulting - 13501 100th Ave NE - Suite 5202 - Kirkland, WA 98034, USA - - Phone: +1 206 481 4303 - EMail: pjnesser@martigny.ai.mit.edu - - - Mike Straw - Bellcore - RRC 1A-225 - 445 Hoes Lane - Piscataway, NJ 08854-4182 - - Phone: +1 908 699-5212 - EMail: mess@bellcore.com - - - - - - - - - -Haller Standards Track [Page 11] - -RFC 2289 A One-Time Password System February 1998 - - -Appendix A - Interfaces to Secure Hash Algorithms - - Original interoperability tests provided valuable insights into the - subtle problems which occur when converting protocol specifications - into running code. In particular, the manipulation of bit ordered - data is dependent on the architecture of the hardware, specifically - the way in which a computer stores multi-byte data. The method is - typically called big or little "endian." A big endian machine stores - data with the most significant byte first, while a little endian - machine stores the least significant byte first. Thus, on a big - endian machine data is stored left to right, while little endian - machines store data right to left. - - For example, the four byte value 0x11AABBCC is stored in a big endian - machine as the following series of four bytes, "0x11", "0xAA", - "0xBB", and "0xCC", while on a little endian machine the value would - be stored as "0xCC", "0xBB", "0xAA", and "0x11". - - For historical reasons, and to promote interoperability with existing - implementations, it was decided that ALL hashes incorporated into the - OTP protocol MUST store the output of their hash function in LITTLE - ENDIAN format BEFORE the bit folding to 64 bits occurs. This is done - in the implementations of MD4 and MD5 (see references [2] and [6]), - while it must be explicitly done for the implementation of SHA1 (see - reference [7]). - - Any future hash functions implemented into the OTP protocol SHOULD - provide a similar reference fragment of code to allow independent - implementations to operate successfully. - - - MD4 Message Digest (see reference [2]) - - MD4_CTX md; - unsigned char result[16]; - - strcpy(buf, seed); /* seed must be in lower case */ - strcat(buf, passwd); - MD4Init(&md); - MD4Update(&md, (unsigned char *)buf, strlen(buf)); - MD4Final(result, &md); - - /* Fold the 128 bit result to 64 bits */ - for (i = 0; i < 8; i++) - result[i] ^= result[i+8]; - - - - - - -Haller Standards Track [Page 12] - -RFC 2289 A One-Time Password System February 1998 - - -MD5 Message Digest (see reference [6]) - - MD5_CTX md; - unsigned char result[16]; - strcpy(buf, seed); /* seed must be in lower case */ - strcat(buf, passwd); - MD5Init(&md); - MD5Update(&md, (unsigned char *)buf, strlen(buf)); - MD5Final(result, &md); - - /* Fold the 128 bit result to 64 bits */ - for (i = 0; i < 8; i++) - result[i] ^= result[i+8]; - - -SHA Secure Hash Algorithm (see reference [7]) - - SHA_INFO sha; - unsigned char result[16]; - strcpy(buf, seed); /* seed must be in lower case */ - strcat(buf, passwd); - sha_init(&sha); - sha_update(&sha, (unsigned char *)buf, strlen(buf)); - sha_final(&sha); /* NOTE: no result buffer */ - - /* Fold the 160 bit result to 64 bits */ - sha.digest[0] ^= sha.digest[2]; - sha.digest[1] ^= sha.digest[3]; - sha.digest[0] ^= sha.digest[4]; - - /* - * copy the resulting 64 bits to the result buffer in little endian - * fashion (analogous to the way MD4Final() and MD5Final() do). - */ - for (i = 0, j = 0; j < 8; i++, j += 4) - { - result[j] = (unsigned char)(sha.digest[i] & 0xff); - result[j+1] = (unsigned char)((sha.digest[i] >> 8) & 0xff); - result[j+2] = (unsigned char)((sha.digest[i] >> 16) & 0xff); - result[j+3] = (unsigned char)((sha.digest[i] >> 24) & 0xff); - } - - - - - - - - - - -Haller Standards Track [Page 13] - -RFC 2289 A One-Time Password System February 1998 - - -Appendix B - Alternative Dictionary Algorithm - - The purpose of alternative dictionary encoding of the OTP one-time - password is to allow the use of language specific or friendly words. - As case translation is not always well defined, the alternative - dictionary encoding is case sensitive. Servers SHOULD accept this - encoding in addition to the standard 6-word and hexadecimal - encodings. - - - GENERATOR ENCODING USING AN ALTERNATE DICTIONARY - - The standard 6-word encoding uses the placement of a word in the - dictionary to represent an 11-bit number. The 64-bit one-time - password can then be represented by six words. - - An alternative dictionary of 2048 words may be created such that - each word W and position of the word in the dictionary N obey the - relationship: - - alg( W ) % 2048 == N - where - alg is the hash algorithm used (e.g. MD4, MD5, SHA1). - - In addition, no words in the standard dictionary may be chosen. - - The generator expands the 64-bit one-time password to 66 bits by - computing parity as with the standard 6-word encoding. The six 11- - bit numbers are then converted to words using the dictionary that - was created such that the above relationship holds. - - SERVER DECODING OF ALTERNATE DICTIONARY ONE-TIME PASSWORDS - - The server accepting alternative dictionary encoding converts each - word to an 11-bit number using the above encoding. These numbers - are then used in the same way as the decoded standard dictionary - words to form the 66-bit one-time password. - - The server does not need to have access to the alternate dictionary - that was used to create the one-time password it is authenticating. - This is because the decoding from word to 11-bit number does not - make any use of the dictionary. As a result of the independence of - the dictionary, a server accepting one alternate dictionary accept - all alternate dictionaries. - - - - - - - -Haller Standards Track [Page 14] - -RFC 2289 A One-Time Password System February 1998 - - -Appendix C - OTP Verification Examples - - This appendix provides a series of inputs and correct outputs for all - three of the defined OTP cryptographic hashes, specifically MD4, MD5, - and SHA1. This document is intended to be used by developers for - interoperability checks when creating generators or servers. Output - is provided in both hexadecimal notation and the six word encoding - documented in Appendix D. - - GENERAL CHECKS - - Note that the output given for these checks is not intended to be - taken literally, but describes the type of action that should be - taken. - - Pass Phrase Length - - Input: - Pass Phrase: Too_short - Seed: iamvalid - Count: 99 - Hash: ANY - Output: - ERROR: Pass Phrase too short - - Input: - Pass Phrase: - 1234567890123456789012345678901234567890123456789012345678901234 - Seed: iamvalid - Count: 99 - Hash: ANY - Output: - WARNING: Pass Phrase longer than the recommended maximum length of -63 - -Seed Values - - Input: - Pass Phrase: A_Valid_Pass_Phrase - Seed: Length_Okay - Count: 99 - Hash: ANY - Output: - ERROR: Seed must be purely alphanumeric - - Input: - Pass Phrase: A_Valid_Pass_Phrase - Seed: LengthOfSeventeen - - - -Haller Standards Track [Page 15] - -RFC 2289 A One-Time Password System February 1998 - - - Count: 99 - Hash: ANY - - Output: - ERROR: Seed must be between 1 and 16 characters in length - - Input: - Pass Phrase: A_Valid_Pass_Phrase - Seed: A Seed - Count: 99 - Hash: ANY - Output: - ERROR: Seed must not contain any spaces - -Parity Calculations - - Input: - Pass Phrase: A_Valid_Pass_Phrase - Seed: AValidSeed - Count: 99 - Hash: MD5 - Output: - Hex: 85c43ee03857765b - Six Word(CORRECT): FOWL KID MASH DEAD DUAL OAF - Six Word(INCORRECT PARITY): FOWL KID MASH DEAD DUAL NUT - Six Word(INCORRECT PARITY): FOWL KID MASH DEAD DUAL O - Six Word(INCORRECT PARITY): FOWL KID MASH DEAD DUAL OAK - - - - - - - - - - - - - - - - - - - - - - - - -Haller Standards Track [Page 16] - -RFC 2289 A One-Time Password System February 1998 - - -MD4 ENCODINGS - -Pass Phrase Seed Cnt Hex Six Word Format -======================================================================== -This is a test. TeSt 0 D185 4218 EBBB 0B51 - ROME MUG FRED SCAN LIVE LACE -This is a test. TeSt 1 6347 3EF0 1CD0 B444 - CARD SAD MINI RYE COL KIN -This is a test. TeSt 99 C5E6 1277 6E6C 237A - NOTE OUT IBIS SINK NAVE MODE -AbCdEfGhIjK alpha1 0 5007 6F47 EB1A DE4E - AWAY SEN ROOK SALT LICE MAP -AbCdEfGhIjK alpha1 1 65D2 0D19 49B5 F7AB - CHEW GRIM WU HANG BUCK SAID -AbCdEfGhIjK alpha1 99 D150 C82C CE6F 62D1 - ROIL FREE COG HUNK WAIT COCA -OTP's are good correct 0 849C 79D4 F6F5 5388 - FOOL STEM DONE TOOL BECK NILE -OTP's are good correct 1 8C09 92FB 2508 47B1 - GIST AMOS MOOT AIDS FOOD SEEM -OTP's are good correct 99 3F3B F4B4 145F D74B - TAG SLOW NOV MIN WOOL KENO - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Haller Standards Track [Page 17] - -RFC 2289 A One-Time Password System February 1998 - - -MD5 ENCODINGS - -Pass Phrase Seed Cnt Hex Six Word Format -======================================================================== -This is a test. TeSt 0 9E87 6134 D904 99DD - INCH SEA ANNE LONG AHEM TOUR -This is a test. TeSt 1 7965 E054 36F5 029F - EASE OIL FUM CURE AWRY AVIS -This is a test. TeSt 99 50FE 1962 C496 5880 - BAIL TUFT BITS GANG CHEF THY -AbCdEfGhIjK alpha1 0 8706 6DD9 644B F206 - FULL PEW DOWN ONCE MORT ARC -AbCdEfGhIjK alpha1 1 7CD3 4C10 40AD D14B - FACT HOOF AT FIST SITE KENT -AbCdEfGhIjK alpha1 99 5AA3 7A81 F212 146C - BODE HOP JAKE STOW JUT RAP -OTP's are good correct 0 F205 7539 43DE 4CF9 - ULAN NEW ARMY FUSE SUIT EYED -OTP's are good correct 1 DDCD AC95 6F23 4937 - SKIM CULT LOB SLAM POE HOWL -OTP's are good correct 99 B203 E28F A525 BE47 - LONG IVY JULY AJAR BOND LEE - - -SHA1 ENCODINGS - -Pass Phrase Seed Cnt Hex Six Word Format -======================================================================== -This is a test. TeSt 0 BB9E 6AE1 979D 8FF4 - MILT VARY MAST OK SEES WENT -This is a test. TeSt 1 63D9 3663 9734 385B - CART OTTO HIVE ODE VAT NUT -This is a test. TeSt 99 87FE C776 8B73 CCF9 - GAFF WAIT SKID GIG SKY EYED -AbCdEfGhIjK alpha1 0 AD85 F658 EBE3 83C9 - LEST OR HEEL SCOT ROB SUIT -AbCdEfGhIjK alpha1 1 D07C E229 B5CF 119B - RITE TAKE GELD COST TUNE RECK -AbCdEfGhIjK alpha1 99 27BC 7103 5AAF 3DC6 - MAY STAR TIN LYON VEDA STAN -OTP's are good correct 0 D51F 3E99 BF8E 6F0B - RUST WELT KICK FELL TAIL FRAU -OTP's are good correct 1 82AE B52D 9437 74E4 - FLIT DOSE ALSO MEW DRUM DEFY -OTP's are good correct 99 4F29 6A74 FE15 67EC - AURA ALOE HURL WING BERG WAIT - - - - - -Haller Standards Track [Page 18] - -RFC 2289 A One-Time Password System February 1998 - - -Appendix D - Dictionary for Converting Between 6-Word and Binary Formats - - This dictionary is from the module put.c in the original Bellcore - reference distribution. - -{ "A", "ABE", "ACE", "ACT", "AD", "ADA", "ADD", -"AGO", "AID", "AIM", "AIR", "ALL", "ALP", "AM", "AMY", -"AN", "ANA", "AND", "ANN", "ANT", "ANY", "APE", "APS", -"APT", "ARC", "ARE", "ARK", "ARM", "ART", "AS", "ASH", -"ASK", "AT", "ATE", "AUG", "AUK", "AVE", "AWE", "AWK", -"AWL", "AWN", "AX", "AYE", "BAD", "BAG", "BAH", "BAM", -"BAN", "BAR", "BAT", "BAY", "BE", "BED", "BEE", "BEG", -"BEN", "BET", "BEY", "BIB", "BID", "BIG", "BIN", "BIT", -"BOB", "BOG", "BON", "BOO", "BOP", "BOW", "BOY", "BUB", -"BUD", "BUG", "BUM", "BUN", "BUS", "BUT", "BUY", "BY", -"BYE", "CAB", "CAL", "CAM", "CAN", "CAP", "CAR", "CAT", -"CAW", "COD", "COG", "COL", "CON", "COO", "COP", "COT", -"COW", "COY", "CRY", "CUB", "CUE", "CUP", "CUR", "CUT", -"DAB", "DAD", "DAM", "DAN", "DAR", "DAY", "DEE", "DEL", -"DEN", "DES", "DEW", "DID", "DIE", "DIG", "DIN", "DIP", -"DO", "DOE", "DOG", "DON", "DOT", "DOW", "DRY", "DUB", -"DUD", "DUE", "DUG", "DUN", "EAR", "EAT", "ED", "EEL", -"EGG", "EGO", "ELI", "ELK", "ELM", "ELY", "EM", "END", -"EST", "ETC", "EVA", "EVE", "EWE", "EYE", "FAD", "FAN", -"FAR", "FAT", "FAY", "FED", "FEE", "FEW", "FIB", "FIG", -"FIN", "FIR", "FIT", "FLO", "FLY", "FOE", "FOG", "FOR", -"FRY", "FUM", "FUN", "FUR", "GAB", "GAD", "GAG", "GAL", -"GAM", "GAP", "GAS", "GAY", "GEE", "GEL", "GEM", "GET", -"GIG", "GIL", "GIN", "GO", "GOT", "GUM", "GUN", "GUS", -"GUT", "GUY", "GYM", "GYP", "HA", "HAD", "HAL", "HAM", -"HAN", "HAP", "HAS", "HAT", "HAW", "HAY", "HE", "HEM", -"HEN", "HER", "HEW", "HEY", "HI", "HID", "HIM", "HIP", -"HIS", "HIT", "HO", "HOB", "HOC", "HOE", "HOG", "HOP", -"HOT", "HOW", "HUB", "HUE", "HUG", "HUH", "HUM", "HUT", -"I", "ICY", "IDA", "IF", "IKE", "ILL", "INK", "INN", -"IO", "ION", "IQ", "IRA", "IRE", "IRK", "IS", "IT", -"ITS", "IVY", "JAB", "JAG", "JAM", "JAN", "JAR", "JAW", -"JAY", "JET", "JIG", "JIM", "JO", "JOB", "JOE", "JOG", -"JOT", "JOY", "JUG", "JUT", "KAY", "KEG", "KEN", "KEY", -"KID", "KIM", "KIN", "KIT", "LA", "LAB", "LAC", "LAD", -"LAG", "LAM", "LAP", "LAW", "LAY", "LEA", "LED", "LEE", -"LEG", "LEN", "LEO", "LET", "LEW", "LID", "LIE", "LIN", -"LIP", "LIT", "LO", "LOB", "LOG", "LOP", "LOS", "LOT", -"LOU", "LOW", "LOY", "LUG", "LYE", "MA", "MAC", "MAD", -"MAE", "MAN", "MAO", "MAP", "MAT", "MAW", "MAY", "ME", -"MEG", "MEL", "MEN", "MET", "MEW", "MID", "MIN", "MIT", -"MOB", "MOD", "MOE", "MOO", "MOP", "MOS", "MOT", "MOW", -"MUD", "MUG", "MUM", "MY", "NAB", "NAG", "NAN", "NAP", - - - -Haller Standards Track [Page 19] - -RFC 2289 A One-Time Password System February 1998 - - -"NAT", "NAY", "NE", "NED", "NEE", "NET", "NEW", "NIB", -"NIL", "NIP", "NIT", "NO", "NOB", "NOD", "NON", "NOR", -"NOT", "NOV", "NOW", "NU", "NUN", "NUT", "O", "OAF", -"OAK", "OAR", "OAT", "ODD", "ODE", "OF", "OFF", "OFT", -"OH", "OIL", "OK", "OLD", "ON", "ONE", "OR", "ORB", -"ORE", "ORR", "OS", "OTT", "OUR", "OUT", "OVA", "OW", -"OWE", "OWL", "OWN", "OX", "PA", "PAD", "PAL", "PAM", -"PAN", "PAP", "PAR", "PAT", "PAW", "PAY", "PEA", "PEG", -"PEN", "PEP", "PER", "PET", "PEW", "PHI", "PI", "PIE", -"PIN", "PIT", "PLY", "PO", "POD", "POE", "POP", "POT", -"POW", "PRO", "PRY", "PUB", "PUG", "PUN", "PUP", "PUT", -"QUO", "RAG", "RAM", "RAN", "RAP", "RAT", "RAW", "RAY", -"REB", "RED", "REP", "RET", "RIB", "RID", "RIG", "RIM", -"RIO", "RIP", "ROB", "ROD", "ROE", "RON", "ROT", "ROW", -"ROY", "RUB", "RUE", "RUG", "RUM", "RUN", "RYE", "SAC", -"SAD", "SAG", "SAL", "SAM", "SAN", "SAP", "SAT", "SAW", -"SAY", "SEA", "SEC", "SEE", "SEN", "SET", "SEW", "SHE", -"SHY", "SIN", "SIP", "SIR", "SIS", "SIT", "SKI", "SKY", -"SLY", "SO", "SOB", "SOD", "SON", "SOP", "SOW", "SOY", -"SPA", "SPY", "SUB", "SUD", "SUE", "SUM", "SUN", "SUP", -"TAB", "TAD", "TAG", "TAN", "TAP", "TAR", "TEA", "TED", -"TEE", "TEN", "THE", "THY", "TIC", "TIE", "TIM", "TIN", -"TIP", "TO", "TOE", "TOG", "TOM", "TON", "TOO", "TOP", -"TOW", "TOY", "TRY", "TUB", "TUG", "TUM", "TUN", "TWO", -"UN", "UP", "US", "USE", "VAN", "VAT", "VET", "VIE", -"WAD", "WAG", "WAR", "WAS", "WAY", "WE", "WEB", "WED", -"WEE", "WET", "WHO", "WHY", "WIN", "WIT", "WOK", "WON", -"WOO", "WOW", "WRY", "WU", "YAM", "YAP", "YAW", "YE", -"YEA", "YES", "YET", "YOU", "ABED", "ABEL", "ABET", "ABLE", -"ABUT", "ACHE", "ACID", "ACME", "ACRE", "ACTA", "ACTS", "ADAM", -"ADDS", "ADEN", "AFAR", "AFRO", "AGEE", "AHEM", "AHOY", "AIDA", -"AIDE", "AIDS", "AIRY", "AJAR", "AKIN", "ALAN", "ALEC", "ALGA", -"ALIA", "ALLY", "ALMA", "ALOE", "ALSO", "ALTO", "ALUM", "ALVA", -"AMEN", "AMES", "AMID", "AMMO", "AMOK", "AMOS", "AMRA", "ANDY", -"ANEW", "ANNA", "ANNE", "ANTE", "ANTI", "AQUA", "ARAB", "ARCH", -"AREA", "ARGO", "ARID", "ARMY", "ARTS", "ARTY", "ASIA", "ASKS", -"ATOM", "AUNT", "AURA", "AUTO", "AVER", "AVID", "AVIS", "AVON", -"AVOW", "AWAY", "AWRY", "BABE", "BABY", "BACH", "BACK", "BADE", -"BAIL", "BAIT", "BAKE", "BALD", "BALE", "BALI", "BALK", "BALL", -"BALM", "BAND", "BANE", "BANG", "BANK", "BARB", "BARD", "BARE", -"BARK", "BARN", "BARR", "BASE", "BASH", "BASK", "BASS", "BATE", -"BATH", "BAWD", "BAWL", "BEAD", "BEAK", "BEAM", "BEAN", "BEAR", -"BEAT", "BEAU", "BECK", "BEEF", "BEEN", "BEER", "BEET", "BELA", -"BELL", "BELT", "BEND", "BENT", "BERG", "BERN", "BERT", "BESS", -"BEST", "BETA", "BETH", "BHOY", "BIAS", "BIDE", "BIEN", "BILE", -"BILK", "BILL", "BIND", "BING", "BIRD", "BITE", "BITS", "BLAB", -"BLAT", "BLED", "BLEW", "BLOB", "BLOC", "BLOT", "BLOW", "BLUE", -"BLUM", "BLUR", "BOAR", "BOAT", "BOCA", "BOCK", "BODE", "BODY", - - - -Haller Standards Track [Page 20] - -RFC 2289 A One-Time Password System February 1998 - - -"BOGY", "BOHR", "BOIL", "BOLD", "BOLO", "BOLT", "BOMB", "BONA", -"BOND", "BONE", "BONG", "BONN", "BONY", "BOOK", "BOOM", "BOON", -"BOOT", "BORE", "BORG", "BORN", "BOSE", "BOSS", "BOTH", "BOUT", -"BOWL", "BOYD", "BRAD", "BRAE", "BRAG", "BRAN", "BRAY", "BRED", -"BREW", "BRIG", "BRIM", "BROW", "BUCK", "BUDD", "BUFF", "BULB", -"BULK", "BULL", "BUNK", "BUNT", "BUOY", "BURG", "BURL", "BURN", -"BURR", "BURT", "BURY", "BUSH", "BUSS", "BUST", "BUSY", "BYTE", -"CADY", "CAFE", "CAGE", "CAIN", "CAKE", "CALF", "CALL", "CALM", -"CAME", "CANE", "CANT", "CARD", "CARE", "CARL", "CARR", "CART", -"CASE", "CASH", "CASK", "CAST", "CAVE", "CEIL", "CELL", "CENT", -"CERN", "CHAD", "CHAR", "CHAT", "CHAW", "CHEF", "CHEN", "CHEW", -"CHIC", "CHIN", "CHOU", "CHOW", "CHUB", "CHUG", "CHUM", "CITE", -"CITY", "CLAD", "CLAM", "CLAN", "CLAW", "CLAY", "CLOD", "CLOG", -"CLOT", "CLUB", "CLUE", "COAL", "COAT", "COCA", "COCK", "COCO", -"CODA", "CODE", "CODY", "COED", "COIL", "COIN", "COKE", "COLA", -"COLD", "COLT", "COMA", "COMB", "COME", "COOK", "COOL", "COON", -"COOT", "CORD", "CORE", "CORK", "CORN", "COST", "COVE", "COWL", -"CRAB", "CRAG", "CRAM", "CRAY", "CREW", "CRIB", "CROW", "CRUD", -"CUBA", "CUBE", "CUFF", "CULL", "CULT", "CUNY", "CURB", "CURD", -"CURE", "CURL", "CURT", "CUTS", "DADE", "DALE", "DAME", "DANA", -"DANE", "DANG", "DANK", "DARE", "DARK", "DARN", "DART", "DASH", -"DATA", "DATE", "DAVE", "DAVY", "DAWN", "DAYS", "DEAD", "DEAF", -"DEAL", "DEAN", "DEAR", "DEBT", "DECK", "DEED", "DEEM", "DEER", -"DEFT", "DEFY", "DELL", "DENT", "DENY", "DESK", "DIAL", "DICE", -"DIED", "DIET", "DIME", "DINE", "DING", "DINT", "DIRE", "DIRT", -"DISC", "DISH", "DISK", "DIVE", "DOCK", "DOES", "DOLE", "DOLL", -"DOLT", "DOME", "DONE", "DOOM", "DOOR", "DORA", "DOSE", "DOTE", -"DOUG", "DOUR", "DOVE", "DOWN", "DRAB", "DRAG", "DRAM", "DRAW", -"DREW", "DRUB", "DRUG", "DRUM", "DUAL", "DUCK", "DUCT", "DUEL", -"DUET", "DUKE", "DULL", "DUMB", "DUNE", "DUNK", "DUSK", "DUST", -"DUTY", "EACH", "EARL", "EARN", "EASE", "EAST", "EASY", "EBEN", -"ECHO", "EDDY", "EDEN", "EDGE", "EDGY", "EDIT", "EDNA", "EGAN", -"ELAN", "ELBA", "ELLA", "ELSE", "EMIL", "EMIT", "EMMA", "ENDS", -"ERIC", "EROS", "EVEN", "EVER", "EVIL", "EYED", "FACE", "FACT", -"FADE", "FAIL", "FAIN", "FAIR", "FAKE", "FALL", "FAME", "FANG", -"FARM", "FAST", "FATE", "FAWN", "FEAR", "FEAT", "FEED", "FEEL", -"FEET", "FELL", "FELT", "FEND", "FERN", "FEST", "FEUD", "FIEF", -"FIGS", "FILE", "FILL", "FILM", "FIND", "FINE", "FINK", "FIRE", -"FIRM", "FISH", "FISK", "FIST", "FITS", "FIVE", "FLAG", "FLAK", -"FLAM", "FLAT", "FLAW", "FLEA", "FLED", "FLEW", "FLIT", "FLOC", -"FLOG", "FLOW", "FLUB", "FLUE", "FOAL", "FOAM", "FOGY", "FOIL", -"FOLD", "FOLK", "FOND", "FONT", "FOOD", "FOOL", "FOOT", "FORD", -"FORE", "FORK", "FORM", "FORT", "FOSS", "FOUL", "FOUR", "FOWL", -"FRAU", "FRAY", "FRED", "FREE", "FRET", "FREY", "FROG", "FROM", -"FUEL", "FULL", "FUME", "FUND", "FUNK", "FURY", "FUSE", "FUSS", -"GAFF", "GAGE", "GAIL", "GAIN", "GAIT", "GALA", "GALE", "GALL", -"GALT", "GAME", "GANG", "GARB", "GARY", "GASH", "GATE", "GAUL", -"GAUR", "GAVE", "GAWK", "GEAR", "GELD", "GENE", "GENT", "GERM", - - - -Haller Standards Track [Page 21] - -RFC 2289 A One-Time Password System February 1998 - - -"GETS", "GIBE", "GIFT", "GILD", "GILL", "GILT", "GINA", "GIRD", -"GIRL", "GIST", "GIVE", "GLAD", "GLEE", "GLEN", "GLIB", "GLOB", -"GLOM", "GLOW", "GLUE", "GLUM", "GLUT", "GOAD", "GOAL", "GOAT", -"GOER", "GOES", "GOLD", "GOLF", "GONE", "GONG", "GOOD", "GOOF", -"GORE", "GORY", "GOSH", "GOUT", "GOWN", "GRAB", "GRAD", "GRAY", -"GREG", "GREW", "GREY", "GRID", "GRIM", "GRIN", "GRIT", "GROW", -"GRUB", "GULF", "GULL", "GUNK", "GURU", "GUSH", "GUST", "GWEN", -"GWYN", "HAAG", "HAAS", "HACK", "HAIL", "HAIR", "HALE", "HALF", -"HALL", "HALO", "HALT", "HAND", "HANG", "HANK", "HANS", "HARD", -"HARK", "HARM", "HART", "HASH", "HAST", "HATE", "HATH", "HAUL", -"HAVE", "HAWK", "HAYS", "HEAD", "HEAL", "HEAR", "HEAT", "HEBE", -"HECK", "HEED", "HEEL", "HEFT", "HELD", "HELL", "HELM", "HERB", -"HERD", "HERE", "HERO", "HERS", "HESS", "HEWN", "HICK", "HIDE", -"HIGH", "HIKE", "HILL", "HILT", "HIND", "HINT", "HIRE", "HISS", -"HIVE", "HOBO", "HOCK", "HOFF", "HOLD", "HOLE", "HOLM", "HOLT", -"HOME", "HONE", "HONK", "HOOD", "HOOF", "HOOK", "HOOT", "HORN", -"HOSE", "HOST", "HOUR", "HOVE", "HOWE", "HOWL", "HOYT", "HUCK", -"HUED", "HUFF", "HUGE", "HUGH", "HUGO", "HULK", "HULL", "HUNK", -"HUNT", "HURD", "HURL", "HURT", "HUSH", "HYDE", "HYMN", "IBIS", -"ICON", "IDEA", "IDLE", "IFFY", "INCA", "INCH", "INTO", "IONS", -"IOTA", "IOWA", "IRIS", "IRMA", "IRON", "ISLE", "ITCH", "ITEM", -"IVAN", "JACK", "JADE", "JAIL", "JAKE", "JANE", "JAVA", "JEAN", -"JEFF", "JERK", "JESS", "JEST", "JIBE", "JILL", "JILT", "JIVE", -"JOAN", "JOBS", "JOCK", "JOEL", "JOEY", "JOHN", "JOIN", "JOKE", -"JOLT", "JOVE", "JUDD", "JUDE", "JUDO", "JUDY", "JUJU", "JUKE", -"JULY", "JUNE", "JUNK", "JUNO", "JURY", "JUST", "JUTE", "KAHN", -"KALE", "KANE", "KANT", "KARL", "KATE", "KEEL", "KEEN", "KENO", -"KENT", "KERN", "KERR", "KEYS", "KICK", "KILL", "KIND", "KING", -"KIRK", "KISS", "KITE", "KLAN", "KNEE", "KNEW", "KNIT", "KNOB", -"KNOT", "KNOW", "KOCH", "KONG", "KUDO", "KURD", "KURT", "KYLE", -"LACE", "LACK", "LACY", "LADY", "LAID", "LAIN", "LAIR", "LAKE", -"LAMB", "LAME", "LAND", "LANE", "LANG", "LARD", "LARK", "LASS", -"LAST", "LATE", "LAUD", "LAVA", "LAWN", "LAWS", "LAYS", "LEAD", -"LEAF", "LEAK", "LEAN", "LEAR", "LEEK", "LEER", "LEFT", "LEND", -"LENS", "LENT", "LEON", "LESK", "LESS", "LEST", "LETS", "LIAR", -"LICE", "LICK", "LIED", "LIEN", "LIES", "LIEU", "LIFE", "LIFT", -"LIKE", "LILA", "LILT", "LILY", "LIMA", "LIMB", "LIME", "LIND", -"LINE", "LINK", "LINT", "LION", "LISA", "LIST", "LIVE", "LOAD", -"LOAF", "LOAM", "LOAN", "LOCK", "LOFT", "LOGE", "LOIS", "LOLA", -"LONE", "LONG", "LOOK", "LOON", "LOOT", "LORD", "LORE", "LOSE", -"LOSS", "LOST", "LOUD", "LOVE", "LOWE", "LUCK", "LUCY", "LUGE", -"LUKE", "LULU", "LUND", "LUNG", "LURA", "LURE", "LURK", "LUSH", -"LUST", "LYLE", "LYNN", "LYON", "LYRA", "MACE", "MADE", "MAGI", -"MAID", "MAIL", "MAIN", "MAKE", "MALE", "MALI", "MALL", "MALT", -"MANA", "MANN", "MANY", "MARC", "MARE", "MARK", "MARS", "MART", -"MARY", "MASH", "MASK", "MASS", "MAST", "MATE", "MATH", "MAUL", -"MAYO", "MEAD", "MEAL", "MEAN", "MEAT", "MEEK", "MEET", "MELD", -"MELT", "MEMO", "MEND", "MENU", "MERT", "MESH", "MESS", "MICE", - - - -Haller Standards Track [Page 22] - -RFC 2289 A One-Time Password System February 1998 - - -"MIKE", "MILD", "MILE", "MILK", "MILL", "MILT", "MIMI", "MIND", -"MINE", "MINI", "MINK", "MINT", "MIRE", "MISS", "MIST", "MITE", -"MITT", "MOAN", "MOAT", "MOCK", "MODE", "MOLD", "MOLE", "MOLL", -"MOLT", "MONA", "MONK", "MONT", "MOOD", "MOON", "MOOR", "MOOT", -"MORE", "MORN", "MORT", "MOSS", "MOST", "MOTH", "MOVE", "MUCH", -"MUCK", "MUDD", "MUFF", "MULE", "MULL", "MURK", "MUSH", "MUST", -"MUTE", "MUTT", "MYRA", "MYTH", "NAGY", "NAIL", "NAIR", "NAME", -"NARY", "NASH", "NAVE", "NAVY", "NEAL", "NEAR", "NEAT", "NECK", -"NEED", "NEIL", "NELL", "NEON", "NERO", "NESS", "NEST", "NEWS", -"NEWT", "NIBS", "NICE", "NICK", "NILE", "NINA", "NINE", "NOAH", -"NODE", "NOEL", "NOLL", "NONE", "NOOK", "NOON", "NORM", "NOSE", -"NOTE", "NOUN", "NOVA", "NUDE", "NULL", "NUMB", "OATH", "OBEY", -"OBOE", "ODIN", "OHIO", "OILY", "OINT", "OKAY", "OLAF", "OLDY", -"OLGA", "OLIN", "OMAN", "OMEN", "OMIT", "ONCE", "ONES", "ONLY", -"ONTO", "ONUS", "ORAL", "ORGY", "OSLO", "OTIS", "OTTO", "OUCH", -"OUST", "OUTS", "OVAL", "OVEN", "OVER", "OWLY", "OWNS", "QUAD", -"QUIT", "QUOD", "RACE", "RACK", "RACY", "RAFT", "RAGE", "RAID", -"RAIL", "RAIN", "RAKE", "RANK", "RANT", "RARE", "RASH", "RATE", -"RAVE", "RAYS", "READ", "REAL", "REAM", "REAR", "RECK", "REED", -"REEF", "REEK", "REEL", "REID", "REIN", "RENA", "REND", "RENT", -"REST", "RICE", "RICH", "RICK", "RIDE", "RIFT", "RILL", "RIME", -"RING", "RINK", "RISE", "RISK", "RITE", "ROAD", "ROAM", "ROAR", -"ROBE", "ROCK", "RODE", "ROIL", "ROLL", "ROME", "ROOD", "ROOF", -"ROOK", "ROOM", "ROOT", "ROSA", "ROSE", "ROSS", "ROSY", "ROTH", -"ROUT", "ROVE", "ROWE", "ROWS", "RUBE", "RUBY", "RUDE", "RUDY", -"RUIN", "RULE", "RUNG", "RUNS", "RUNT", "RUSE", "RUSH", "RUSK", -"RUSS", "RUST", "RUTH", "SACK", "SAFE", "SAGE", "SAID", "SAIL", -"SALE", "SALK", "SALT", "SAME", "SAND", "SANE", "SANG", "SANK", -"SARA", "SAUL", "SAVE", "SAYS", "SCAN", "SCAR", "SCAT", "SCOT", -"SEAL", "SEAM", "SEAR", "SEAT", "SEED", "SEEK", "SEEM", "SEEN", -"SEES", "SELF", "SELL", "SEND", "SENT", "SETS", "SEWN", "SHAG", -"SHAM", "SHAW", "SHAY", "SHED", "SHIM", "SHIN", "SHOD", "SHOE", -"SHOT", "SHOW", "SHUN", "SHUT", "SICK", "SIDE", "SIFT", "SIGH", -"SIGN", "SILK", "SILL", "SILO", "SILT", "SINE", "SING", "SINK", -"SIRE", "SITE", "SITS", "SITU", "SKAT", "SKEW", "SKID", "SKIM", -"SKIN", "SKIT", "SLAB", "SLAM", "SLAT", "SLAY", "SLED", "SLEW", -"SLID", "SLIM", "SLIT", "SLOB", "SLOG", "SLOT", "SLOW", "SLUG", -"SLUM", "SLUR", "SMOG", "SMUG", "SNAG", "SNOB", "SNOW", "SNUB", -"SNUG", "SOAK", "SOAR", "SOCK", "SODA", "SOFA", "SOFT", "SOIL", -"SOLD", "SOME", "SONG", "SOON", "SOOT", "SORE", "SORT", "SOUL", -"SOUR", "SOWN", "STAB", "STAG", "STAN", "STAR", "STAY", "STEM", -"STEW", "STIR", "STOW", "STUB", "STUN", "SUCH", "SUDS", "SUIT", -"SULK", "SUMS", "SUNG", "SUNK", "SURE", "SURF", "SWAB", "SWAG", -"SWAM", "SWAN", "SWAT", "SWAY", "SWIM", "SWUM", "TACK", "TACT", -"TAIL", "TAKE", "TALE", "TALK", "TALL", "TANK", "TASK", "TATE", -"TAUT", "TEAL", "TEAM", "TEAR", "TECH", "TEEM", "TEEN", "TEET", -"TELL", "TEND", "TENT", "TERM", "TERN", "TESS", "TEST", "THAN", -"THAT", "THEE", "THEM", "THEN", "THEY", "THIN", "THIS", "THUD", - - - -Haller Standards Track [Page 23] - -RFC 2289 A One-Time Password System February 1998 - - -"THUG", "TICK", "TIDE", "TIDY", "TIED", "TIER", "TILE", "TILL", -"TILT", "TIME", "TINA", "TINE", "TINT", "TINY", "TIRE", "TOAD", -"TOGO", "TOIL", "TOLD", "TOLL", "TONE", "TONG", "TONY", "TOOK", -"TOOL", "TOOT", "TORE", "TORN", "TOTE", "TOUR", "TOUT", "TOWN", -"TRAG", "TRAM", "TRAY", "TREE", "TREK", "TRIG", "TRIM", "TRIO", -"TROD", "TROT", "TROY", "TRUE", "TUBA", "TUBE", "TUCK", "TUFT", -"TUNA", "TUNE", "TUNG", "TURF", "TURN", "TUSK", "TWIG", "TWIN", -"TWIT", "ULAN", "UNIT", "URGE", "USED", "USER", "USES", "UTAH", -"VAIL", "VAIN", "VALE", "VARY", "VASE", "VAST", "VEAL", "VEDA", -"VEIL", "VEIN", "VEND", "VENT", "VERB", "VERY", "VETO", "VICE", -"VIEW", "VINE", "VISE", "VOID", "VOLT", "VOTE", "WACK", "WADE", -"WAGE", "WAIL", "WAIT", "WAKE", "WALE", "WALK", "WALL", "WALT", -"WAND", "WANE", "WANG", "WANT", "WARD", "WARM", "WARN", "WART", -"WASH", "WAST", "WATS", "WATT", "WAVE", "WAVY", "WAYS", "WEAK", -"WEAL", "WEAN", "WEAR", "WEED", "WEEK", "WEIR", "WELD", "WELL", -"WELT", "WENT", "WERE", "WERT", "WEST", "WHAM", "WHAT", "WHEE", -"WHEN", "WHET", "WHOA", "WHOM", "WICK", "WIFE", "WILD", "WILL", -"WIND", "WINE", "WING", "WINK", "WINO", "WIRE", "WISE", "WISH", -"WITH", "WOLF", "WONT", "WOOD", "WOOL", "WORD", "WORE", "WORK", -"WORM", "WORN", "WOVE", "WRIT", "WYNN", "YALE", "YANG", "YANK", -"YARD", "YARN", "YAWL", "YAWN", "YEAH", "YEAR", "YELL", "YOGA", -"YOKE" }; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Haller Standards Track [Page 24] - -RFC 2289 A One-Time Password System February 1998 - - -Full Copyright Statement - - Copyright (C) The Internet Society (1998). All Rights Reserved. - - This document and translations of it may be copied and furnished to - others, and derivative works that comment on or otherwise explain it - or assist in its implementation may be prepared, copied, published - and distributed, in whole or in part, without restriction of any - kind, provided that the above copyright notice and this paragraph are - included on all such copies and derivative works. However, this - document itself may not be modified in any way, such as by removing - the copyright notice or references to the Internet Society or other - Internet organizations, except as needed for the purpose of - developing Internet standards in which case the procedures for - copyrights defined in the Internet Standards process must be - followed, or as required to translate it into languages other than - English. - - The limited permissions granted above are perpetual and will not be - revoked by the Internet Society or its successors or assigns. - - This document and the information contained herein is provided on an - "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING - TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING - BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION - HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - - - - - - - - - - - - - - - - - - - - - - - - -Haller Standards Track [Page 25] - diff --git a/doc/rfc2444.txt b/doc/rfc2444.txt deleted file mode 100644 index 80a65a2a..00000000 --- a/doc/rfc2444.txt +++ /dev/null @@ -1,395 +0,0 @@ - - - - - - -Network Working Group C. Newman -Request for Comments: 2444 Innosoft -Updates: 2222 October 1998 -Category: Standards Track - - - The One-Time-Password SASL Mechanism - -Status of this Memo - - This document specifies an Internet standards track protocol for the - Internet community, and requests discussion and suggestions for - improvements. Please refer to the current edition of the "Internet - Official Protocol Standards" (STD 1) for the standardization state - and status of this protocol. Distribution of this memo is unlimited. - -Copyright Notice - - Copyright (C) The Internet Society (1998). All Rights Reserved. - -Abstract - - OTP [OTP] provides a useful authentication mechanism for situations - where there is limited client or server trust. Currently, OTP is - added to protocols in an ad-hoc fashion with heuristic parsing. This - specification defines an OTP SASL [SASL] mechanism so it can be - easily and formally integrated into many application protocols. - -1. How to Read This Document - - The key words "MUST", "MUST NOT", "REQUIRED", "SHOULD", "SHOULD NOT", - "RECOMMENDED" and "MAY" in this document are to be interpreted as - defined in "Key words for use in RFCs to Indicate Requirement Levels" - [KEYWORDS]. - - This memo assumes the reader is familiar with OTP [OTP], OTP extended - responses [OTP-EXT] and SASL [SASL]. - -2. Intended Use - - The OTP SASL mechanism replaces the SKEY SASL mechanism [SASL]. OTP - is a good choice for usage scenarios where the client is untrusted - (e.g., a kiosk client), as a one-time password will only give the - client a single opportunity to act on behalf of the user. OTP is - also a good choice for situations where interactive logins are - permitted to the server, as a compromised OTP authentication database - is only subject to dictionary attacks, unlike authentication - databases for other simple mechanisms such as CRAM-MD5 [CRAM-MD5]. - - - -Newman Standards Track [Page 1] - -RFC 2444 OTP SASL Mechanism October 1998 - - - It is important to note that each use of the OTP mechanism causes the - authentication database entry for a user to be updated. - - This SASL mechanism provides a formal way to integrate OTP into - SASL-enabled protocols including IMAP [IMAP4], ACAP [ACAP], POP3 - [POP-AUTH] and LDAPv3 [LDAPv3]. - -3. Profiling OTP for SASL - - OTP [OTP] and OTP extended responses [OTP-EXT] offer a number of - options. However, for authentication to succeed, the client and - server need compatible option sets. This specification defines a - single SASL mechanism: OTP. The following rules apply to this - mechanism: - - o The extended response syntax MUST be used. - - o Servers MUST support the following four OTP extended responses: - "hex", "word", "init-hex" and "init-word". Servers MUST support - the "word" and "init-word" responses for the standard dictionary - and SHOULD support alternate dictionaries. Servers MUST NOT - require use of any additional OTP extensions or options. - - o Clients SHOULD support display of the OTP challenge to the user - and entry of an OTP in multi-word format. Clients MAY also - support direct entry of the pass phrase and compute the "hex" or - "word" response. - - o Clients MUST indicate when authentication fails due to the - sequence number getting too low and SHOULD offer the user the - option to reset the sequence using the "init-hex" or "init-word" - response. - - Support for the MD5 algorithm is REQUIRED, and support for the SHA1 - algorithm is RECOMMENDED. - -4. OTP Authentication Mechanism - - The mechanism does not provide any security layer. - - The client begins by sending a message to the server containing the - following two pieces of information. - - (1) An authorization identity. When the empty string is used, this - defaults to the authentication identity. This is used by system - administrators or proxy servers to login with a different user - identity. This field may be up to 255 octets and is terminated by a - NUL (0) octet. US-ASCII printable characters are preferred, although - - - -Newman Standards Track [Page 2] - -RFC 2444 OTP SASL Mechanism October 1998 - - - UTF-8 [UTF-8] printable characters are permitted to support - international names. Use of character sets other than US-ASCII and - UTF-8 is forbidden. - - (2) An authentication identity. The identity whose pass phrase will - be used. This field may be up to 255 octets. US-ASCII printable - characters are preferred, although UTF-8 [UTF-8] printable characters - are permitted to support international names. Use of character sets - other than US-ASCII and UTF-8 is forbidden. - - The server responds by sending a message containing the OTP challenge - as described in OTP [OTP] and OTP extended responses [OTP-EXT]. - - If a client sees an unknown hash algorithm name it will not be able - to process a pass phrase input by the user. In this situation the - client MAY prompt for the six-word format, issue the cancel sequence - as specified by the SASL profile for the protocol in use and try a - different SASL mechanism, or close the connection and refuse to - authenticate. As a result of this behavior, a server is restricted - to one OTP hash algorithm per user. - - On success, the client generates an extended response in the "hex", - "word", "init-hex" or "init-word" format. The client is not required - to terminate the response with a space or a newline and SHOULD NOT - include unnecessary whitespace. - - Servers MUST tolerate input of arbitrary length, but MAY fail the - authentication if the length of client input exceeds reasonable size. - -5. Examples - - In these example, "C:" represents lines sent from the client to the - server and "S:" represents lines sent from the server to the client. - The user name is "tim" and no authorization identity is provided. - The "" below represents an ASCII NUL octet. - - The following is an example of the OTP mechanism using the ACAP - [ACAP] profile of SASL. The pass phrase used in this example is: - This is a test. - - C: a001 AUTHENTICATE "OTP" {4} - C: tim - S: + "otp-md5 499 ke1234 ext" - C: "hex:5bf075d9959d036f" - S: a001 OK "AUTHENTICATE completed" - - - - - - -Newman Standards Track [Page 3] - -RFC 2444 OTP SASL Mechanism October 1998 - - - Here is the same example using the six-words response: - - C: a001 AUTHENTICATE "OTP" {4} - C: tim - S: + "otp-md5 499 ke1234 ext" - C: "word:BOND FOGY DRAB NE RISE MART" - S: a001 OK "AUTHENTICATE completed" - - Here is the same example using the OTP-SHA1 mechanism: - - C: a001 AUTHENTICATE "OTP" {4} - C: tim - S: + "otp-sha1 499 ke1234 ext" - C: "hex:c90fc02cc488df5e" - S: a001 OK "AUTHENTICATE completed" - - Here is the same example with the init-hex extended response - - C: a001 AUTHENTICATE "OTP" {4} - C: tim - S: + "otp-md5 499 ke1234 ext" - C: "init-hex:5bf075d9959d036f:md5 499 ke1235:3712dcb4aa5316c1" - S: a001 OK "OTP sequence reset, authentication complete" - - The following is an example of the OTP mechanism using the IMAP - [IMAP4] profile of SASL. The pass phrase used in this example is: - this is a test - - C: a001 AUTHENTICATE OTP - S: + - C: AHRpbQ== - S: + b3RwLW1kNSAxMjMga2UxMjM0IGV4dA== - C: aGV4OjExZDRjMTQ3ZTIyN2MxZjE= - S: a001 OK AUTHENTICATE completed - - Note that the lack of an initial client response and the base64 - encoding are characteristics of the IMAP profile of SASL. The server - challenge is "otp-md5 123 ke1234 ext" and the client response is - "hex:11d4c147e227c1f1". - -6. Security Considerations - - This specification introduces no security considerations beyond those - those described in SASL [SASL], OTP [OTP] and OTP extended responses - [OTP-EXT]. A brief summary of these considerations follows: - - This mechanism does not provide session privacy, server - authentication or protection from active attacks. - - - -Newman Standards Track [Page 4] - -RFC 2444 OTP SASL Mechanism October 1998 - - - This mechanism is subject to passive dictionary attacks. The - severity of this attack can be reduced by choosing pass phrases well. - - The server authentication database necessary for use with OTP need - not be plaintext-equivalent. - - Server implementations MUST protect against the race attack [OTP]. - -7. Multinational Considerations - - As remote access is a crucial service, users are encouraged to - restrict user names and pass phrases to the US-ASCII character set. - However, if characters outside the US-ASCII chracter set are used in - user names and pass phrases, then they are interpreted according to - UTF-8 [UTF-8]. - - Server support for alternate dictionaries is strongly RECOMMENDED to - permit use of the six-word format with non-English words. - -8. IANA Considerations - - Here is the registration template for the OTP SASL mechanism: - - SASL mechanism name: OTP - Security Considerations: See section 6 of this memo - Published specification: this memo - Person & email address to contact for futher information: - see author's address section below - Intended usage: COMMON - Author/Change controller: see author's address section below - - This memo also amends the SKEY SASL mechanism registration [SASL] by - changing its intended usage to OBSOLETE. - -9. References - - [ACAP] Newman, C. and J. Myers, "ACAP -- Application - Configuration Access Protocol", RFC 2244, November 1997. - - [CRAM-MD5] Klensin, J., Catoe, R. and P. Krumviede, "IMAP/POP - AUTHorize Extension for Simple Challenge/Response", RFC - 2195, September 1997. - - [IMAP4] Crispin, M., "Internet Message Access Protocol - Version - 4rev1", RFC 2060, December 1996. - - [KEYWORDS] Bradner, S., "Key words for use in RFCs to Indicate - Requirement Levels", BCP 14, RFC 2119, March 1997. - - - -Newman Standards Track [Page 5] - -RFC 2444 OTP SASL Mechanism October 1998 - - - [LDAPv3] Wahl, M., Howes, T. and S. Kille, "Lightweight Directory - Access Protocol (v3)", RFC 2251, December 1997. - - [MD5] Rivest, R., "The MD5 Message Digest Algorithm", RFC 1321, - April 1992. - - [OTP] Haller, N., Metz, C., Nesser, P. and M. Straw, "A One-Time - Password System", RFC 2289, February 1998. - - [OTP-EXT] Metz, C., "OTP Extended Responses", RFC 2243, November - 1997. - - [POP-AUTH] Myers, J., "POP3 AUTHentication command", RFC 1734, - December 1994. - - [SASL] Myers, J., "Simple Authentication and Security Layer - (SASL)", RFC 2222, October 1997. - - [UTF-8] Yergeau, F., "UTF-8, a transformation format of ISO - 10646", RFC 2279, January 1998. - -10. Author's Address - - Chris Newman - Innosoft International, Inc. - 1050 Lakes Drive - West Covina, CA 91790 USA - - EMail: chris.newman@innosoft.com - - - - - - - - - - - - - - - - - - - - - - -Newman Standards Track [Page 6] - -RFC 2444 OTP SASL Mechanism October 1998 - - -11. Full Copyright Statement - - Copyright (C) The Internet Society (1998). All Rights Reserved. - - This document and translations of it may be copied and furnished to - others, and derivative works that comment on or otherwise explain it - or assist in its implementation may be prepared, copied, published - and distributed, in whole or in part, without restriction of any - kind, provided that the above copyright notice and this paragraph are - included on all such copies and derivative works. However, this - document itself may not be modified in any way, such as by removing - the copyright notice or references to the Internet Society or other - Internet organizations, except as needed for the purpose of - developing Internet standards in which case the procedures for - copyrights defined in the Internet Standards process must be - followed, or as required to translate it into languages other than - English. - - The limited permissions granted above are perpetual and will not be - revoked by the Internet Society or its successors or assigns. - - This document and the information contained herein is provided on an - "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING - TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING - BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION - HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - - - - - - - - - - - - - - - - - - - - - - - - -Newman Standards Track [Page 7] - diff --git a/doc/rfc2595.txt b/doc/rfc2595.txt deleted file mode 100644 index 3b2b4c5d..00000000 --- a/doc/rfc2595.txt +++ /dev/null @@ -1,843 +0,0 @@ - - - - - - -Network Working Group C. Newman -Request for Comments: 2595 Innosoft -Category: Standards Track June 1999 - - - Using TLS with IMAP, POP3 and ACAP - - -Status of this Memo - - This document specifies an Internet standards track protocol for the - Internet community, and requests discussion and suggestions for - improvements. Please refer to the current edition of the "Internet - Official Protocol Standards" (STD 1) for the standardization state - and status of this protocol. Distribution of this memo is unlimited. - -Copyright Notice - - Copyright (C) The Internet Society (1999). All Rights Reserved. - -1. Motivation - - The TLS protocol (formerly known as SSL) provides a way to secure an - application protocol from tampering and eavesdropping. The option of - using such security is desirable for IMAP, POP and ACAP due to common - connection eavesdropping and hijacking attacks [AUTH]. Although - advanced SASL authentication mechanisms can provide a lightweight - version of this service, TLS is complimentary to simple - authentication-only SASL mechanisms or deployed clear-text password - login commands. - - Many sites have a high investment in authentication infrastructure - (e.g., a large database of a one-way-function applied to user - passwords), so a privacy layer which is not tightly bound to user - authentication can protect against network eavesdropping attacks - without requiring a new authentication infrastructure and/or forcing - all users to change their password. Recognizing that such sites will - desire simple password authentication in combination with TLS - encryption, this specification defines the PLAIN SASL mechanism for - use with protocols which lack a simple password authentication - command such as ACAP and SMTP. (Note there is a separate RFC for the - STARTTLS command in SMTP [SMTPTLS].) - - There is a strong desire in the IETF to eliminate the transmission of - clear-text passwords over unencrypted channels. While SASL can be - used for this purpose, TLS provides an additional tool with different - deployability characteristics. A server supporting both TLS with - - - - -Newman Standards Track [Page 1] - -RFC 2595 Using TLS with IMAP, POP3 and ACAP June 1999 - - - simple passwords and a challenge/response SASL mechanism is likely to - interoperate with a wide variety of clients without resorting to - unencrypted clear-text passwords. - - The STARTTLS command rectifies a number of the problems with using a - separate port for a "secure" protocol variant. Some of these are - mentioned in section 7. - -1.1. Conventions Used in this Document - - The key words "REQUIRED", "MUST", "MUST NOT", "SHOULD", "SHOULD NOT", - "MAY", and "OPTIONAL" in this document are to be interpreted as - described in "Key words for use in RFCs to Indicate Requirement - Levels" [KEYWORDS]. - - Terms related to authentication are defined in "On Internet - Authentication" [AUTH]. - - Formal syntax is defined using ABNF [ABNF]. - - In examples, "C:" and "S:" indicate lines sent by the client and - server respectively. - -2. Basic Interoperability and Security Requirements - - The following requirements apply to all implementations of the - STARTTLS extension for IMAP, POP3 and ACAP. - -2.1. Cipher Suite Requirements - - Implementation of the TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA [TLS] cipher - suite is REQUIRED. This is important as it assures that any two - compliant implementations can be configured to interoperate. - - All other cipher suites are OPTIONAL. - -2.2. Privacy Operational Mode Security Requirements - - Both clients and servers SHOULD have a privacy operational mode which - refuses authentication unless successful activation of an encryption - layer (such as that provided by TLS) occurs prior to or at the time - of authentication and which will terminate the connection if that - encryption layer is deactivated. Implementations are encouraged to - have flexibility with respect to the minimal encryption strength or - cipher suites permitted. A minimalist approach to this - recommendation would be an operational mode where the - TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA cipher suite is mandatory prior to - permitting authentication. - - - -Newman Standards Track [Page 2] - -RFC 2595 Using TLS with IMAP, POP3 and ACAP June 1999 - - - Clients MAY have an operational mode which uses encryption only when - it is advertised by the server, but authentication continues - regardless. For backwards compatibility, servers SHOULD have an - operational mode where only the authentication mechanisms required by - the relevant base protocol specification are needed to successfully - authenticate. - -2.3. Clear-Text Password Requirements - - Clients and servers which implement STARTTLS MUST be configurable to - refuse all clear-text login commands or mechanisms (including both - standards-track and nonstandard mechanisms) unless an encryption - layer of adequate strength is active. Servers which allow - unencrypted clear-text logins SHOULD be configurable to refuse - clear-text logins both for the entire server, and on a per-user - basis. - -2.4. Server Identity Check - - During the TLS negotiation, the client MUST check its understanding - of the server hostname against the server's identity as presented in - the server Certificate message, in order to prevent man-in-the-middle - attacks. Matching is performed according to these rules: - - - The client MUST use the server hostname it used to open the - connection as the value to compare against the server name as - expressed in the server certificate. The client MUST NOT use any - form of the server hostname derived from an insecure remote source - (e.g., insecure DNS lookup). CNAME canonicalization is not done. - - - If a subjectAltName extension of type dNSName is present in the - certificate, it SHOULD be used as the source of the server's - identity. - - - Matching is case-insensitive. - - - A "*" wildcard character MAY be used as the left-most name - component in the certificate. For example, *.example.com would - match a.example.com, foo.example.com, etc. but would not match - example.com. - - - If the certificate contains multiple names (e.g. more than one - dNSName field), then a match with any one of the fields is - considered acceptable. - - If the match fails, the client SHOULD either ask for explicit user - confirmation, or terminate the connection and indicate the server's - identity is suspect. - - - -Newman Standards Track [Page 3] - -RFC 2595 Using TLS with IMAP, POP3 and ACAP June 1999 - - -2.5. TLS Security Policy Check - - Both the client and server MUST check the result of the STARTTLS - command and subsequent TLS negotiation to see whether acceptable - authentication or privacy was achieved. Ignoring this step - completely invalidates using TLS for security. The decision about - whether acceptable authentication or privacy was achieved is made - locally, is implementation-dependent, and is beyond the scope of this - document. - -3. IMAP STARTTLS extension - - When the TLS extension is present in IMAP, "STARTTLS" is listed as a - capability in response to the CAPABILITY command. This extension - adds a single command, "STARTTLS" to the IMAP protocol which is used - to begin a TLS negotiation. - -3.1. STARTTLS Command - - Arguments: none - - Responses: no specific responses for this command - - Result: OK - begin TLS negotiation - BAD - command unknown or arguments invalid - - A TLS negotiation begins immediately after the CRLF at the end of - the tagged OK response from the server. Once a client issues a - STARTTLS command, it MUST NOT issue further commands until a - server response is seen and the TLS negotiation is complete. - - The STARTTLS command is only valid in non-authenticated state. - The server remains in non-authenticated state, even if client - credentials are supplied during the TLS negotiation. The SASL - [SASL] EXTERNAL mechanism MAY be used to authenticate once TLS - client credentials are successfully exchanged, but servers - supporting the STARTTLS command are not required to support the - EXTERNAL mechanism. - - Once TLS has been started, the client MUST discard cached - information about server capabilities and SHOULD re-issue the - CAPABILITY command. This is necessary to protect against - man-in-the-middle attacks which alter the capabilities list prior - to STARTTLS. The server MAY advertise different capabilities - after STARTTLS. - - The formal syntax for IMAP is amended as follows: - - - - -Newman Standards Track [Page 4] - -RFC 2595 Using TLS with IMAP, POP3 and ACAP June 1999 - - - command_any =/ "STARTTLS" - - Example: C: a001 CAPABILITY - S: * CAPABILITY IMAP4rev1 STARTTLS LOGINDISABLED - S: a001 OK CAPABILITY completed - C: a002 STARTTLS - S: a002 OK Begin TLS negotiation now - - C: a003 CAPABILITY - S: * CAPABILITY IMAP4rev1 AUTH=EXTERNAL - S: a003 OK CAPABILITY completed - C: a004 LOGIN joe password - S: a004 OK LOGIN completed - -3.2. IMAP LOGINDISABLED capability - - The current IMAP protocol specification (RFC 2060) requires the - implementation of the LOGIN command which uses clear-text passwords. - Many sites may choose to disable this command unless encryption is - active for security reasons. An IMAP server MAY advertise that the - LOGIN command is disabled by including the LOGINDISABLED capability - in the capability response. Such a server will respond with a tagged - "NO" response to any attempt to use the LOGIN command. - - An IMAP server which implements STARTTLS MUST implement support for - the LOGINDISABLED capability on unencrypted connections. - - An IMAP client which complies with this specification MUST NOT issue - the LOGIN command if this capability is present. - - This capability is useful to prevent clients compliant with this - specification from sending an unencrypted password in an environment - subject to passive attacks. It has no impact on an environment - subject to active attacks as a man-in-the-middle attacker can remove - this capability. Therefore this does not relieve clients of the need - to follow the privacy mode recommendation in section 2.2. - - Servers advertising this capability will fail to interoperate with - many existing compliant IMAP clients and will be unable to prevent - those clients from disclosing the user's password. - -4. POP3 STARTTLS extension - - The POP3 STARTTLS extension adds the STLS command to POP3 servers. - If this is implemented, the POP3 extension mechanism [POP3EXT] MUST - also be implemented to avoid the need for client probing of multiple - commands. The capability name "STLS" indicates this command is - present and permitted in the current state. - - - -Newman Standards Track [Page 5] - -RFC 2595 Using TLS with IMAP, POP3 and ACAP June 1999 - - - STLS - - Arguments: none - - Restrictions: - Only permitted in AUTHORIZATION state. - - Discussion: - A TLS negotiation begins immediately after the CRLF at the - end of the +OK response from the server. A -ERR response - MAY result if a security layer is already active. Once a - client issues a STLS command, it MUST NOT issue further - commands until a server response is seen and the TLS - negotiation is complete. - - The STLS command is only permitted in AUTHORIZATION state - and the server remains in AUTHORIZATION state, even if - client credentials are supplied during the TLS negotiation. - The AUTH command [POP-AUTH] with the EXTERNAL mechanism - [SASL] MAY be used to authenticate once TLS client - credentials are successfully exchanged, but servers - supporting the STLS command are not required to support the - EXTERNAL mechanism. - - Once TLS has been started, the client MUST discard cached - information about server capabilities and SHOULD re-issue - the CAPA command. This is necessary to protect against - man-in-the-middle attacks which alter the capabilities list - prior to STLS. The server MAY advertise different - capabilities after STLS. - - Possible Responses: - +OK -ERR - - Examples: - C: STLS - S: +OK Begin TLS negotiation - - ... - C: STLS - S: -ERR Command not permitted when TLS active - - - - - - - - - - -Newman Standards Track [Page 6] - -RFC 2595 Using TLS with IMAP, POP3 and ACAP June 1999 - - -5. ACAP STARTTLS extension - - When the TLS extension is present in ACAP, "STARTTLS" is listed as a - capability in the ACAP greeting. No arguments to this capability are - defined at this time. This extension adds a single command, - "STARTTLS" to the ACAP protocol which is used to begin a TLS - negotiation. - -5.1. STARTTLS Command - - Arguments: none - - Responses: no specific responses for this command - - Result: OK - begin TLS negotiation - BAD - command unknown or arguments invalid - - A TLS negotiation begins immediately after the CRLF at the end of - the tagged OK response from the server. Once a client issues a - STARTTLS command, it MUST NOT issue further commands until a - server response is seen and the TLS negotiation is complete. - - The STARTTLS command is only valid in non-authenticated state. - The server remains in non-authenticated state, even if client - credentials are supplied during the TLS negotiation. The SASL - [SASL] EXTERNAL mechanism MAY be used to authenticate once TLS - client credentials are successfully exchanged, but servers - supporting the STARTTLS command are not required to support the - EXTERNAL mechanism. - - After the TLS layer is established, the server MUST re-issue an - untagged ACAP greeting. This is necessary to protect against - man-in-the-middle attacks which alter the capabilities list prior - to STARTTLS. The client MUST discard cached capability - information and replace it with the information from the new ACAP - greeting. The server MAY advertise different capabilities after - STARTTLS. - - The formal syntax for ACAP is amended as follows: - - command_any =/ "STARTTLS" - - Example: S: * ACAP (SASL "CRAM-MD5") (STARTTLS) - C: a002 STARTTLS - S: a002 OK "Begin TLS negotiation now" - - S: * ACAP (SASL "CRAM-MD5" "PLAIN" "EXTERNAL") - - - - -Newman Standards Track [Page 7] - -RFC 2595 Using TLS with IMAP, POP3 and ACAP June 1999 - - -6. PLAIN SASL mechanism - - Clear-text passwords are simple, interoperate with almost all - existing operating system authentication databases, and are useful - for a smooth transition to a more secure password-based - authentication mechanism. The drawback is that they are unacceptable - for use over an unencrypted network connection. - - This defines the "PLAIN" SASL mechanism for use with ACAP and other - protocols with no clear-text login command. The PLAIN SASL mechanism - MUST NOT be advertised or used unless a strong encryption layer (such - as the provided by TLS) is active or backwards compatibility dictates - otherwise. - - The mechanism consists of a single message from the client to the - server. The client sends the authorization identity (identity to - login as), followed by a US-ASCII NUL character, followed by the - authentication identity (identity whose password will be used), - followed by a US-ASCII NUL character, followed by the clear-text - password. The client may leave the authorization identity empty to - indicate that it is the same as the authentication identity. - - The server will verify the authentication identity and password with - the system authentication database and verify that the authentication - credentials permit the client to login as the authorization identity. - If both steps succeed, the user is logged in. - - The server MAY also use the password to initialize any new - authentication database, such as one suitable for CRAM-MD5 - [CRAM-MD5]. - - Non-US-ASCII characters are permitted as long as they are represented - in UTF-8 [UTF-8]. Use of non-visible characters or characters which - a user may be unable to enter on some keyboards is discouraged. - - The formal grammar for the client message using Augmented BNF [ABNF] - follows. - - message = [authorize-id] NUL authenticate-id NUL password - authenticate-id = 1*UTF8-SAFE ; MUST accept up to 255 octets - authorize-id = 1*UTF8-SAFE ; MUST accept up to 255 octets - password = 1*UTF8-SAFE ; MUST accept up to 255 octets - NUL = %x00 - UTF8-SAFE = %x01-09 / %x0B-0C / %x0E-7F / UTF8-2 / - UTF8-3 / UTF8-4 / UTF8-5 / UTF8-6 - UTF8-1 = %x80-BF - UTF8-2 = %xC0-DF UTF8-1 - UTF8-3 = %xE0-EF 2UTF8-1 - - - -Newman Standards Track [Page 8] - -RFC 2595 Using TLS with IMAP, POP3 and ACAP June 1999 - - - UTF8-4 = %xF0-F7 3UTF8-1 - UTF8-5 = %xF8-FB 4UTF8-1 - UTF8-6 = %xFC-FD 5UTF8-1 - - Here is an example of how this might be used to initialize a CRAM-MD5 - authentication database for ACAP: - - Example: S: * ACAP (SASL "CRAM-MD5") (STARTTLS) - C: a001 AUTHENTICATE "CRAM-MD5" - S: + "<1896.697170952@postoffice.reston.mci.net>" - C: "tim b913a602c7eda7a495b4e6e7334d3890" - S: a001 NO (TRANSITION-NEEDED) - "Please change your password, or use TLS to login" - C: a002 STARTTLS - S: a002 OK "Begin TLS negotiation now" - - S: * ACAP (SASL "CRAM-MD5" "PLAIN" "EXTERNAL") - C: a003 AUTHENTICATE "PLAIN" {21+} - C: timtanstaaftanstaaf - S: a003 OK CRAM-MD5 password initialized - - Note: In this example, represents a single ASCII NUL octet. - -7. imaps and pop3s ports - - Separate "imaps" and "pop3s" ports were registered for use with SSL. - Use of these ports is discouraged in favor of the STARTTLS or STLS - commands. - - A number of problems have been observed with separate ports for - "secure" variants of protocols. This is an attempt to enumerate some - of those problems. - - - Separate ports lead to a separate URL scheme which intrudes into - the user interface in inappropriate ways. For example, many web - pages use language like "click here if your browser supports SSL." - This is a decision the browser is often more capable of making than - the user. - - - Separate ports imply a model of either "secure" or "not secure." - This can be misleading in a number of ways. First, the "secure" - port may not in fact be acceptably secure as an export-crippled - cipher suite might be in use. This can mislead users into a false - sense of security. Second, the normal port might in fact be - secured by using a SASL mechanism which includes a security layer. - Thus the separate port distinction makes the complex topic of - security policy even more confusing. One common result of this - confusion is that firewall administrators are often misled into - - - -Newman Standards Track [Page 9] - -RFC 2595 Using TLS with IMAP, POP3 and ACAP June 1999 - - - permitting the "secure" port and blocking the standard port. This - could be a poor choice given the common use of SSL with a 40-bit - key encryption layer and plain-text password authentication is less - secure than strong SASL mechanisms such as GSSAPI with Kerberos 5. - - - Use of separate ports for SSL has caused clients to implement only - two security policies: use SSL or don't use SSL. The desirable - security policy "use TLS when available" would be cumbersome with - the separate port model, but is simple with STARTTLS. - - - Port numbers are a limited resource. While they are not yet in - short supply, it is unwise to set a precedent that could double (or - worse) the speed of their consumption. - - -8. IANA Considerations - - This constitutes registration of the "STARTTLS" and "LOGINDISABLED" - IMAP capabilities as required by section 7.2.1 of RFC 2060 [IMAP]. - - The registration for the POP3 "STLS" capability follows: - - CAPA tag: STLS - Arguments: none - Added commands: STLS - Standard commands affected: May enable USER/PASS as a side-effect. - CAPA command SHOULD be re-issued after successful completion. - Announced states/Valid states: AUTHORIZATION state only. - Specification reference: this memo - - The registration for the ACAP "STARTTLS" capability follows: - - Capability name: STARTTLS - Capability keyword: STARTTLS - Capability arguments: none - Published Specification(s): this memo - Person and email address for further information: - see author's address section below - - The registration for the PLAIN SASL mechanism follows: - - SASL mechanism name: PLAIN - Security Considerations: See section 9 of this memo - Published specification: this memo - Person & email address to contact for further information: - see author's address section below - Intended usage: COMMON - Author/Change controller: see author's address section below - - - -Newman Standards Track [Page 10] - -RFC 2595 Using TLS with IMAP, POP3 and ACAP June 1999 - - -9. Security Considerations - - TLS only provides protection for data sent over a network connection. - Messages transferred over IMAP or POP3 are still available to server - administrators and usually subject to eavesdropping, tampering and - forgery when transmitted through SMTP or NNTP. TLS is no substitute - for an end-to-end message security mechanism using MIME security - multiparts [MIME-SEC]. - - A man-in-the-middle attacker can remove STARTTLS from the capability - list or generate a failure response to the STARTTLS command. In - order to detect such an attack, clients SHOULD warn the user when - session privacy is not active and/or be configurable to refuse to - proceed without an acceptable level of security. - - A man-in-the-middle attacker can always cause a down-negotiation to - the weakest authentication mechanism or cipher suite available. For - this reason, implementations SHOULD be configurable to refuse weak - mechanisms or cipher suites. - - Any protocol interactions prior to the TLS handshake are performed in - the clear and can be modified by a man-in-the-middle attacker. For - this reason, clients MUST discard cached information about server - capabilities advertised prior to the start of the TLS handshake. - - Clients are encouraged to clearly indicate when the level of - encryption active is known to be vulnerable to attack using modern - hardware (such as encryption keys with 56 bits of entropy or less). - - The LOGINDISABLED IMAP capability (discussed in section 3.2) only - reduces the potential for passive attacks, it provides no protection - against active attacks. The responsibility remains with the client - to avoid sending a password over a vulnerable channel. - - The PLAIN mechanism relies on the TLS encryption layer for security. - When used without TLS, it is vulnerable to a common network - eavesdropping attack. Therefore PLAIN MUST NOT be advertised or used - unless a suitable TLS encryption layer is active or backwards - compatibility dictates otherwise. - - When the PLAIN mechanism is used, the server gains the ability to - impersonate the user to all services with the same password - regardless of any encryption provided by TLS or other network privacy - mechanisms. While many other authentication mechanisms have similar - weaknesses, stronger SASL mechanisms such as Kerberos address this - issue. Clients are encouraged to have an operational mode where all - mechanisms which are likely to reveal the user's password to the - server are disabled. - - - -Newman Standards Track [Page 11] - -RFC 2595 Using TLS with IMAP, POP3 and ACAP June 1999 - - - The security considerations for TLS apply to STARTTLS and the - security considerations for SASL apply to the PLAIN mechanism. - Additional security requirements are discussed in section 2. - -10. References - - [ABNF] Crocker, D. and P. Overell, "Augmented BNF for Syntax - Specifications: ABNF", RFC 2234, November 1997. - - [ACAP] Newman, C. and J. Myers, "ACAP -- Application - Configuration Access Protocol", RFC 2244, November 1997. - - [AUTH] Haller, N. and R. Atkinson, "On Internet Authentication", - RFC 1704, October 1994. - - [CRAM-MD5] Klensin, J., Catoe, R. and P. Krumviede, "IMAP/POP - AUTHorize Extension for Simple Challenge/Response", RFC - 2195, September 1997. - - [IMAP] Crispin, M., "Internet Message Access Protocol - Version - 4rev1", RFC 2060, December 1996. - - [KEYWORDS] Bradner, S., "Key words for use in RFCs to Indicate - Requirement Levels", BCP 14, RFC 2119, March 1997. - - [MIME-SEC] Galvin, J., Murphy, S., Crocker, S. and N. Freed, - "Security Multiparts for MIME: Multipart/Signed and - Multipart/Encrypted", RFC 1847, October 1995. - - [POP3] Myers, J. and M. Rose, "Post Office Protocol - Version 3", - STD 53, RFC 1939, May 1996. - - [POP3EXT] Gellens, R., Newman, C. and L. Lundblade, "POP3 Extension - Mechanism", RFC 2449, November 1998. - - [POP-AUTH] Myers, J., "POP3 AUTHentication command", RFC 1734, - December 1994. - - [SASL] Myers, J., "Simple Authentication and Security Layer - (SASL)", RFC 2222, October 1997. - - [SMTPTLS] Hoffman, P., "SMTP Service Extension for Secure SMTP over - TLS", RFC 2487, January 1999. - - [TLS] Dierks, T. and C. Allen, "The TLS Protocol Version 1.0", - RFC 2246, January 1999. - - - - - -Newman Standards Track [Page 12] - -RFC 2595 Using TLS with IMAP, POP3 and ACAP June 1999 - - - [UTF-8] Yergeau, F., "UTF-8, a transformation format of ISO - 10646", RFC 2279, January 1998. - - -11. Author's Address - - Chris Newman - Innosoft International, Inc. - 1050 Lakes Drive - West Covina, CA 91790 USA - - EMail: chris.newman@innosoft.com - - -A. Appendix -- Compliance Checklist - - An implementation is not compliant if it fails to satisfy one or more - of the MUST requirements for the protocols it implements. An - implementation that satisfies all the MUST and all the SHOULD - requirements for its protocols is said to be "unconditionally - compliant"; one that satisfies all the MUST requirements but not all - the SHOULD requirements for its protocols is said to be - "conditionally compliant". - - Rules Section - ----- ------- - Mandatory-to-implement Cipher Suite 2.1 - SHOULD have mode where encryption required 2.2 - server SHOULD have mode where TLS not required 2.2 - MUST be configurable to refuse all clear-text login - commands or mechanisms 2.3 - server SHOULD be configurable to refuse clear-text - login commands on entire server and on per-user basis 2.3 - client MUST check server identity 2.4 - client MUST use hostname used to open connection 2.4 - client MUST NOT use hostname from insecure remote lookup 2.4 - client SHOULD support subjectAltName of dNSName type 2.4 - client SHOULD ask for confirmation or terminate on fail 2.4 - MUST check result of STARTTLS for acceptable privacy 2.5 - client MUST NOT issue commands after STARTTLS - until server response and negotiation done 3.1,4,5.1 - client MUST discard cached information 3.1,4,5.1,9 - client SHOULD re-issue CAPABILITY/CAPA command 3.1,4 - IMAP server with STARTTLS MUST implement LOGINDISABLED 3.2 - IMAP client MUST NOT issue LOGIN if LOGINDISABLED 3.2 - POP server MUST implement POP3 extensions 4 - ACAP server MUST re-issue ACAP greeting 5.1 - - - - -Newman Standards Track [Page 13] - -RFC 2595 Using TLS with IMAP, POP3 and ACAP June 1999 - - - client SHOULD warn when session privacy not active and/or - refuse to proceed without acceptable security level 9 - SHOULD be configurable to refuse weak mechanisms or - cipher suites 9 - - The PLAIN mechanism is an optional part of this specification. - However if it is implemented the following rules apply: - - Rules Section - ----- ------- - MUST NOT use PLAIN unless strong encryption active - or backwards compatibility dictates otherwise 6,9 - MUST use UTF-8 encoding for characters in PLAIN 6 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Newman Standards Track [Page 14] - -RFC 2595 Using TLS with IMAP, POP3 and ACAP June 1999 - - -Full Copyright Statement - - Copyright (C) The Internet Society (1999). All Rights Reserved. - - This document and translations of it may be copied and furnished to - others, and derivative works that comment on or otherwise explain it - or assist in its implementation may be prepared, copied, published - and distributed, in whole or in part, without restriction of any - kind, provided that the above copyright notice and this paragraph are - included on all such copies and derivative works. However, this - document itself may not be modified in any way, such as by removing - the copyright notice or references to the Internet Society or other - Internet organizations, except as needed for the purpose of - developing Internet standards in which case the procedures for - copyrights defined in the Internet Standards process must be - followed, or as required to translate it into languages other than - English. - - The limited permissions granted above are perpetual and will not be - revoked by the Internet Society or its successors or assigns. - - This document and the information contained herein is provided on an - "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING - TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING - BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION - HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - -Acknowledgement - - Funding for the RFC Editor function is currently provided by the - Internet Society. - - - - - - - - - - - - - - - - - - - -Newman Standards Track [Page 15] - diff --git a/doc/rfc2831.txt b/doc/rfc2831.txt deleted file mode 100644 index c1a54c49..00000000 --- a/doc/rfc2831.txt +++ /dev/null @@ -1,1515 +0,0 @@ - - - - - - -Network Working Group P. Leach -Request for Comments: 2831 Microsoft -Category: Standards Track C. Newman - Innosoft - May 2000 - - - Using Digest Authentication as a SASL Mechanism - -Status of this Memo - - This document specifies an Internet standards track protocol for the - Internet community, and requests discussion and suggestions for - improvements. Please refer to the current edition of the "Internet - Official Protocol Standards" (STD 1) for the standardization state - and status of this protocol. Distribution of this memo is unlimited. - -Copyright Notice - - Copyright (C) The Internet Society (2000). All Rights Reserved. - -Abstract - - This specification defines how HTTP Digest Authentication [Digest] - can be used as a SASL [RFC 2222] mechanism for any protocol that has - a SASL profile. It is intended both as an improvement over CRAM-MD5 - [RFC 2195] and as a convenient way to support a single authentication - mechanism for web, mail, LDAP, and other protocols. - -Table of Contents - - 1 INTRODUCTION.....................................................2 - 1.1 CONVENTIONS AND NOTATION......................................2 - 1.2 REQUIREMENTS..................................................3 - 2 AUTHENTICATION...................................................3 - 2.1 INITIAL AUTHENTICATION........................................3 - 2.1.1 Step One...................................................3 - 2.1.2 Step Two...................................................6 - 2.1.3 Step Three................................................12 - 2.2 SUBSEQUENT AUTHENTICATION....................................12 - 2.2.1 Step one..................................................13 - 2.2.2 Step Two..................................................13 - 2.3 INTEGRITY PROTECTION.........................................13 - 2.4 CONFIDENTIALITY PROTECTION...................................14 - 3 SECURITY CONSIDERATIONS.........................................15 - 3.1 AUTHENTICATION OF CLIENTS USING DIGEST AUTHENTICATION........15 - 3.2 COMPARISON OF DIGEST WITH PLAINTEXT PASSWORDS................16 - 3.3 REPLAY ATTACKS...............................................16 - - - -Leach & Newman Standards Track [Page 1] - -RFC 2831 Digest SASL Mechanism May 2000 - - - 3.4 ONLINE DICTIONARY ATTACKS....................................16 - 3.5 OFFLINE DICTIONARY ATTACKS...................................16 - 3.6 MAN IN THE MIDDLE............................................17 - 3.7 CHOSEN PLAINTEXT ATTACKS.....................................17 - 3.8 SPOOFING BY COUNTERFEIT SERVERS..............................17 - 3.9 STORING PASSWORDS............................................17 - 3.10 MULTIPLE REALMS.............................................18 - 3.11 SUMMARY.....................................................18 - 4 EXAMPLE.........................................................18 - 5 REFERENCES......................................................20 - 6 AUTHORS' ADDRESSES..............................................21 - 7 ABNF............................................................21 - 7.1 AUGMENTED BNF................................................21 - 7.2 BASIC RULES..................................................23 - 8 SAMPLE CODE.....................................................25 - 9 FULL COPYRIGHT STATEMENT........................................27 - -1 Introduction - - This specification describes the use of HTTP Digest Access - Authentication as a SASL mechanism. The authentication type - associated with the Digest SASL mechanism is "DIGEST-MD5". - - This specification is intended to be upward compatible with the - "md5-sess" algorithm of HTTP/1.1 Digest Access Authentication - specified in [Digest]. The only difference in the "md5-sess" - algorithm is that some directives not needed in a SASL mechanism have - had their values defaulted. - - There is one new feature for use as a SASL mechanism: integrity - protection on application protocol messages after an authentication - exchange. - - Also, compared to CRAM-MD5, DIGEST-MD5 prevents chosen plaintext - attacks, and permits the use of third party authentication servers, - mutual authentication, and optimized reauthentication if a client has - recently authenticated to a server. - -1.1 Conventions and Notation - - This specification uses the same ABNF notation and lexical - conventions as HTTP/1.1 specification; see appendix A. - - Let { a, b, ... } be the concatenation of the octet strings a, b, ... - - Let H(s) be the 16 octet MD5 hash [RFC 1321] of the octet string s. - - - - - -Leach & Newman Standards Track [Page 2] - -RFC 2831 Digest SASL Mechanism May 2000 - - - Let KD(k, s) be H({k, ":", s}), i.e., the 16 octet hash of the string - k, a colon and the string s. - - Let HEX(n) be the representation of the 16 octet MD5 hash n as a - string of 32 hex digits (with alphabetic characters always in lower - case, since MD5 is case sensitive). - - Let HMAC(k, s) be the 16 octet HMAC-MD5 [RFC 2104] of the octet - string s using the octet string k as a key. - - The value of a quoted string constant as an octet string does not - include any terminating null character. - -1.2 Requirements - - The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", - "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this - document are to be interpreted as described in RFC 2119 [RFC 2119]. - - An implementation is not compliant if it fails to satisfy one or more - of the MUST level requirements for the protocols it implements. An - implementation that satisfies all the MUST level and all the SHOULD - level requirements for its protocols is said to be "unconditionally - compliant"; one that satisfies all the MUST level requirements but - not all the SHOULD level requirements for its protocols is said to be - "conditionally compliant." - -2 Authentication - - The following sections describe how to use Digest as a SASL - authentication mechanism. - -2.1 Initial Authentication - - If the client has not recently authenticated to the server, then it - must perform "initial authentication", as defined in this section. If - it has recently authenticated, then a more efficient form is - available, defined in the next section. - -2.1.1 Step One - - The server starts by sending a challenge. The data encoded in the - challenge contains a string formatted according to the rules for a - "digest-challenge" defined as follows: - - - - - - - -Leach & Newman Standards Track [Page 3] - -RFC 2831 Digest SASL Mechanism May 2000 - - - digest-challenge = - 1#( realm | nonce | qop-options | stale | maxbuf | charset - algorithm | cipher-opts | auth-param ) - - realm = "realm" "=" <"> realm-value <"> - realm-value = qdstr-val - nonce = "nonce" "=" <"> nonce-value <"> - nonce-value = qdstr-val - qop-options = "qop" "=" <"> qop-list <"> - qop-list = 1#qop-value - qop-value = "auth" | "auth-int" | "auth-conf" | - token - stale = "stale" "=" "true" - maxbuf = "maxbuf" "=" maxbuf-value - maxbuf-value = 1*DIGIT - charset = "charset" "=" "utf-8" - algorithm = "algorithm" "=" "md5-sess" - cipher-opts = "cipher" "=" <"> 1#cipher-value <"> - cipher-value = "3des" | "des" | "rc4-40" | "rc4" | - "rc4-56" | token - auth-param = token "=" ( token | quoted-string ) - - The meanings of the values of the directives used above are as - follows: - - realm - Mechanistically, a string which can enable users to know which - username and password to use, in case they might have different - ones for different servers. Conceptually, it is the name of a - collection of accounts that might include the user's account. This - string should contain at least the name of the host performing the - authentication and might additionally indicate the collection of - users who might have access. An example might be - "registered_users@gotham.news.example.com". This directive is - optional; if not present, the client SHOULD solicit it from the - user or be able to compute a default; a plausible default might be - the realm supplied by the user when they logged in to the client - system. Multiple realm directives are allowed, in which case the - user or client must choose one as the realm for which to supply to - username and password. - - nonce - A server-specified data string which MUST be different each time a - digest-challenge is sent as part of initial authentication. It is - recommended that this string be base64 or hexadecimal data. Note - that since the string is passed as a quoted string, the - double-quote character is not allowed unless escaped (see section - 7.2). The contents of the nonce are implementation dependent. The - - - -Leach & Newman Standards Track [Page 4] - -RFC 2831 Digest SASL Mechanism May 2000 - - - security of the implementation depends on a good choice. It is - RECOMMENDED that it contain at least 64 bits of entropy. The nonce - is opaque to the client. This directive is required and MUST - appear exactly once; if not present, or if multiple instances are - present, the client should abort the authentication exchange. - - qop-options - A quoted string of one or more tokens indicating the "quality of - protection" values supported by the server. The value "auth" - indicates authentication; the value "auth-int" indicates - authentication with integrity protection; the value "auth-conf" - indicates authentication with integrity protection and encryption. - This directive is optional; if not present it defaults to "auth". - The client MUST ignore unrecognized options; if the client - recognizes no option, it should abort the authentication exchange. - - stale - The "stale" directive is not used in initial authentication. See - the next section for its use in subsequent authentications. This - directive may appear at most once; if multiple instances are - present, the client should abort the authentication exchange. - - maxbuf - A number indicating the size of the largest buffer the server is - able to receive when using "auth-int" or "auth-conf". If this - directive is missing, the default value is 65536. This directive - may appear at most once; if multiple instances are present, the - client should abort the authentication exchange. - - charset - This directive, if present, specifies that the server supports - UTF-8 encoding for the username and password. If not present, the - username and password must be encoded in ISO 8859-1 (of which - US-ASCII is a subset). The directive is needed for backwards - compatibility with HTTP Digest, which only supports ISO 8859-1. - This directive may appear at most once; if multiple instances are - present, the client should abort the authentication exchange. - - algorithm - This directive is required for backwards compatibility with HTTP - Digest., which supports other algorithms. . This directive is - required and MUST appear exactly once; if not present, or if - multiple instances are present, the client should abort the - authentication exchange. - - - - - - - -Leach & Newman Standards Track [Page 5] - -RFC 2831 Digest SASL Mechanism May 2000 - - - cipher-opts - A list of ciphers that the server supports. This directive must be - present exactly once if "auth-conf" is offered in the - "qop-options" directive, in which case the "3des" and "des" modes - are mandatory-to-implement. The client MUST ignore unrecognized - options; if the client recognizes no option, it should abort the - authentication exchange. - - des - the Data Encryption Standard (DES) cipher [FIPS] in cipher - block chaining (CBC) mode with a 56 bit key. - - 3des - the "triple DES" cipher in CBC mode with EDE with the same key - for each E stage (aka "two keys mode") for a total key length - of 112 bits. - - rc4, rc4-40, rc4-56 - the RC4 cipher with a 128 bit, 40 bit, and 56 bit key, - respectively. - - auth-param This construct allows for future extensions; it may appear - more than once. The client MUST ignore any unrecognized - directives. - - For use as a SASL mechanism, note that the following changes are made - to "digest-challenge" from HTTP: the following Digest options (called - "directives" in HTTP terminology) are unused (i.e., MUST NOT be sent, - and MUST be ignored if received): - - opaque - domain - - The size of a digest-challenge MUST be less than 2048 bytes. - -2.1.2 Step Two - - The client makes note of the "digest-challenge" and then responds - with a string formatted and computed according to the rules for a - "digest-response" defined as follows: - - - - - - - - - - - -Leach & Newman Standards Track [Page 6] - -RFC 2831 Digest SASL Mechanism May 2000 - - - digest-response = 1#( username | realm | nonce | cnonce | - nonce-count | qop | digest-uri | response | - maxbuf | charset | cipher | authzid | - auth-param ) - - username = "username" "=" <"> username-value <"> - username-value = qdstr-val - cnonce = "cnonce" "=" <"> cnonce-value <"> - cnonce-value = qdstr-val - nonce-count = "nc" "=" nc-value - nc-value = 8LHEX - qop = "qop" "=" qop-value - digest-uri = "digest-uri" "=" <"> digest-uri-value <"> - digest-uri-value = serv-type "/" host [ "/" serv-name ] - serv-type = 1*ALPHA - host = 1*( ALPHA | DIGIT | "-" | "." ) - serv-name = host - response = "response" "=" response-value - response-value = 32LHEX - LHEX = "0" | "1" | "2" | "3" | - "4" | "5" | "6" | "7" | - "8" | "9" | "a" | "b" | - "c" | "d" | "e" | "f" - cipher = "cipher" "=" cipher-value - authzid = "authzid" "=" <"> authzid-value <"> - authzid-value = qdstr-val - - - username - The user's name in the specified realm, encoded according to the - value of the "charset" directive. This directive is required and - MUST be present exactly once; otherwise, authentication fails. - - realm - The realm containing the user's account. This directive is - required if the server provided any realms in the - "digest-challenge", in which case it may appear exactly once and - its value SHOULD be one of those realms. If the directive is - missing, "realm-value" will set to the empty string when computing - A1 (see below for details). - - nonce - The server-specified data string received in the preceding - digest-challenge. This directive is required and MUST be present - exactly once; otherwise, authentication fails. - - - - - - -Leach & Newman Standards Track [Page 7] - -RFC 2831 Digest SASL Mechanism May 2000 - - - cnonce - A client-specified data string which MUST be different each time a - digest-response is sent as part of initial authentication. The - cnonce-value is an opaque quoted string value provided by the - client and used by both client and server to avoid chosen - plaintext attacks, and to provide mutual authentication. The - security of the implementation depends on a good choice. It is - RECOMMENDED that it contain at least 64 bits of entropy. This - directive is required and MUST be present exactly once; otherwise, - authentication fails. - - nonce-count - The nc-value is the hexadecimal count of the number of requests - (including the current request) that the client has sent with the - nonce value in this request. For example, in the first request - sent in response to a given nonce value, the client sends - "nc=00000001". The purpose of this directive is to allow the - server to detect request replays by maintaining its own copy of - this count - if the same nc-value is seen twice, then the request - is a replay. See the description below of the construction of - the response value. This directive may appear at most once; if - multiple instances are present, the client should abort the - authentication exchange. - - qop - Indicates what "quality of protection" the client accepted. If - present, it may appear exactly once and its value MUST be one of - the alternatives in qop-options. If not present, it defaults to - "auth". These values affect the computation of the response. Note - that this is a single token, not a quoted list of alternatives. - - serv-type - Indicates the type of service, such as "www" for web service, - "ftp" for FTP service, "smtp" for mail delivery service, etc. The - service name as defined in the SASL profile for the protocol see - section 4 of [RFC 2222], registered in the IANA registry of - "service" elements for the GSSAPI host-based service name form - [RFC 2078]. - - host - The DNS host name or IP address for the service requested. The - DNS host name must be the fully-qualified canonical name of the - host. The DNS host name is the preferred form; see notes on server - processing of the digest-uri. - - - - - - - -Leach & Newman Standards Track [Page 8] - -RFC 2831 Digest SASL Mechanism May 2000 - - - serv-name - Indicates the name of the service if it is replicated. The service - is considered to be replicated if the client's service-location - process involves resolution using standard DNS lookup operations, - and if these operations involve DNS records (such as SRV, or MX) - which resolve one DNS name into a set of other DNS names. In this - case, the initial name used by the client is the "serv-name", and - the final name is the "host" component. For example, the incoming - mail service for "example.com" may be replicated through the use - of MX records stored in the DNS, one of which points at an SMTP - server called "mail3.example.com"; it's "serv-name" would be - "example.com", it's "host" would be "mail3.example.com". If the - service is not replicated, or the serv-name is identical to the - host, then the serv-name component MUST be omitted. - - digest-uri - Indicates the principal name of the service with which the client - wishes to connect, formed from the serv-type, host, and serv-name. - For example, the FTP service on "ftp.example.com" would have a - "digest-uri" value of "ftp/ftp.example.com"; the SMTP server from - the example above would have a "digest-uri" value of - "smtp/mail3.example.com/example.com". - - Servers SHOULD check that the supplied value is correct. This will - detect accidental connection to the incorrect server. It is also so - that clients will be trained to provide values that will work with - implementations that use a shared back-end authentication service - that can provide server authentication. - - The serv-type component should match the service being offered. The - host component should match one of the host names of the host on - which the service is running, or it's IP address. Servers SHOULD NOT - normally support the IP address form, because server authentication - by IP address is not very useful; they should only do so if the DNS - is unavailable or unreliable. The serv-name component should match - one of the service's configured service names. - - This directive may appear at most once; if multiple instances are - present, the client should abort the authentication exchange. - - Note: In the HTTP use of Digest authentication, the digest-uri is the - URI (usually a URL) of the resource requested -- hence the name of - the directive. - - response - A string of 32 hex digits computed as defined below, which proves - that the user knows a password. This directive is required and - MUST be present exactly once; otherwise, authentication fails. - - - -Leach & Newman Standards Track [Page 9] - -RFC 2831 Digest SASL Mechanism May 2000 - - - maxbuf - A number indicating the size of the largest buffer the client is - able to receive. If this directive is missing, the default value - is 65536. This directive may appear at most once; if multiple - instances are present, the server should abort the authentication - exchange. - - charset - This directive, if present, specifies that the client has used - UTF-8 encoding for the username and password. If not present, the - username and password must be encoded in ISO 8859-1 (of which - US-ASCII is a subset). The client should send this directive only - if the server has indicated it supports UTF-8. The directive is - needed for backwards compatibility with HTTP Digest, which only - supports ISO 8859-1. - - LHEX - 32 hex digits, where the alphabetic characters MUST be lower case, - because MD5 is not case insensitive. - - cipher - The cipher chosen by the client. This directive MUST appear - exactly once if "auth-conf" is negotiated; if required and not - present, authentication fails. - - authzid - The "authorization ID" as per RFC 2222, encoded in UTF-8. This - directive is optional. If present, and the authenticating user has - sufficient privilege, and the server supports it, then after - authentication the server will use this identity for making all - accesses and access checks. If the client specifies it, and the - server does not support it, then the response-value will be - incorrect, and authentication will fail. - - The size of a digest-response MUST be less than 4096 bytes. - -2.1.2.1 Response-value - - The definition of "response-value" above indicates the encoding for - its value -- 32 lower case hex characters. The following definitions - show how the value is computed. - - Although qop-value and components of digest-uri-value may be - case-insensitive, the case which the client supplies in step two is - preserved for the purpose of computing and verifying the - response-value. - - response-value = - - - -Leach & Newman Standards Track [Page 10] - -RFC 2831 Digest SASL Mechanism May 2000 - - - HEX( KD ( HEX(H(A1)), - { nonce-value, ":" nc-value, ":", - cnonce-value, ":", qop-value, ":", HEX(H(A2)) })) - - If authzid is specified, then A1 is - - - A1 = { H( { username-value, ":", realm-value, ":", passwd } ), - ":", nonce-value, ":", cnonce-value, ":", authzid-value } - - If authzid is not specified, then A1 is - - - A1 = { H( { username-value, ":", realm-value, ":", passwd } ), - ":", nonce-value, ":", cnonce-value } - - where - - passwd = *OCTET - - The "username-value", "realm-value" and "passwd" are encoded - according to the value of the "charset" directive. If "charset=UTF-8" - is present, and all the characters of either "username-value" or - "passwd" are in the ISO 8859-1 character set, then it must be - converted to ISO 8859-1 before being hashed. This is so that - authentication databases that store the hashed username, realm and - password (which is common) can be shared compatibly with HTTP, which - specifies ISO 8859-1. A sample implementation of this conversion is - in section 8. - - If the "qop" directive's value is "auth", then A2 is: - - A2 = { "AUTHENTICATE:", digest-uri-value } - - If the "qop" value is "auth-int" or "auth-conf" then A2 is: - - A2 = { "AUTHENTICATE:", digest-uri-value, - ":00000000000000000000000000000000" } - - Note that "AUTHENTICATE:" must be in upper case, and the second - string constant is a string with a colon followed by 32 zeros. - - These apparently strange values of A2 are for compatibility with - HTTP; they were arrived at by setting "Method" to "AUTHENTICATE" and - the hash of the entity body to zero in the HTTP digest calculation of - A2. - - Also, in the HTTP usage of Digest, several directives in the - - - -Leach & Newman Standards Track [Page 11] - -RFC 2831 Digest SASL Mechanism May 2000 - - - "digest-challenge" sent by the server have to be returned by the - client in the "digest-response". These are: - - opaque - algorithm - - These directives are not needed when Digest is used as a SASL - mechanism (i.e., MUST NOT be sent, and MUST be ignored if received). - -2.1.3 Step Three - - The server receives and validates the "digest-response". The server - checks that the nonce-count is "00000001". If it supports subsequent - authentication (see section 2.2), it saves the value of the nonce and - the nonce-count. It sends a message formatted as follows: - - response-auth = "rspauth" "=" response-value - - where response-value is calculated as above, using the values sent in - step two, except that if qop is "auth", then A2 is - - A2 = { ":", digest-uri-value } - - And if qop is "auth-int" or "auth-conf" then A2 is - - A2 = { ":", digest-uri-value, ":00000000000000000000000000000000" } - - Compared to its use in HTTP, the following Digest directives in the - "digest-response" are unused: - - nextnonce - qop - cnonce - nonce-count - -2.2 Subsequent Authentication - - If the client has previously authenticated to the server, and - remembers the values of username, realm, nonce, nonce-count, cnonce, - and qop that it used in that authentication, and the SASL profile for - a protocol permits an initial client response, then it MAY perform - "subsequent authentication", as defined in this section. - - - - - - - - - -Leach & Newman Standards Track [Page 12] - -RFC 2831 Digest SASL Mechanism May 2000 - - -2.2.1 Step one - - The client uses the values from the previous authentication and sends - an initial response with a string formatted and computed according to - the rules for a "digest-response", as defined above, but with a - nonce-count one greater than used in the last "digest-response". - -2.2.2 Step Two - - The server receives the "digest-response". If the server does not - support subsequent authentication, then it sends a - "digest-challenge", and authentication proceeds as in initial - authentication. If the server has no saved nonce and nonce-count from - a previous authentication, then it sends a "digest-challenge", and - authentication proceeds as in initial authentication. Otherwise, the - server validates the "digest-response", checks that the nonce-count - is one greater than that used in the previous authentication using - that nonce, and saves the new value of nonce-count. - - If the response is invalid, then the server sends a - "digest-challenge", and authentication proceeds as in initial - authentication (and should be configurable to log an authentication - failure in some sort of security audit log, since the failure may be - a symptom of an attack). The nonce-count MUST NOT be incremented in - this case: to do so would allow a denial of service attack by sending - an out-of-order nonce-count. - - If the response is valid, the server MAY choose to deem that - authentication has succeeded. However, if it has been too long since - the previous authentication, or for any other reason, the server MAY - send a new "digest-challenge" with a new value for nonce. The - challenge MAY contain a "stale" directive with value "true", which - says that the client may respond to the challenge using the password - it used in the previous response; otherwise, the client must solicit - the password anew from the user. This permits the server to make sure - that the user has presented their password recently. (The directive - name refers to the previous nonce being stale, not to the last use of - the password.) Except for the handling of "stale", after sending the - "digest-challenge" authentication proceeds as in the case of initial - authentication. - -2.3 Integrity Protection - - If the server offered "qop=auth-int" and the client responded - "qop=auth-int", then subsequent messages, up to but not including the - next subsequent authentication, between the client and the server - - - - - -Leach & Newman Standards Track [Page 13] - -RFC 2831 Digest SASL Mechanism May 2000 - - - MUST be integrity protected. Using as a base session key the value of - H(A1) as defined above the client and server calculate a pair of - message integrity keys as follows. - - The key for integrity protecting messages from client to server is: - - Kic = MD5({H(A1), - "Digest session key to client-to-server signing key magic constant"}) - - The key for integrity protecting messages from server to client is: - - Kis = MD5({H(A1), - "Digest session key to server-to-client signing key magic constant"}) - - where MD5 is as specified in [RFC 1321]. If message integrity is - negotiated, a MAC block for each message is appended to the message. - The MAC block is 16 bytes: the first 10 bytes of the HMAC-MD5 [RFC - 2104] of the message, a 2-byte message type number in network byte - order with value 1, and the 4-byte sequence number in network byte - order. The message type is to allow for future extensions such as - rekeying. - - MAC(Ki, SeqNum, msg) = (HMAC(Ki, {SeqNum, msg})[0..9], 0x0001, - SeqNum) - - where Ki is Kic for messages sent by the client and Kis for those - sent by the server. The sequence number is initialized to zero, and - incremented by one for each message sent. - - Upon receipt, MAC(Ki, SeqNum, msg) is computed and compared with the - received value; the message is discarded if they differ. - -2.4 Confidentiality Protection - - If the server sent a "cipher-opts" directive and the client responded - with a "cipher" directive, then subsequent messages between the - client and the server MUST be confidentiality protected. Using as a - base session key the value of H(A1) as defined above the client and - server calculate a pair of message integrity keys as follows. - - The key for confidentiality protecting messages from client to server - is: - - Kcc = MD5({H(A1)[0..n], - "Digest H(A1) to client-to-server sealing key magic constant"}) - - The key for confidentiality protecting messages from server to client - is: - - - -Leach & Newman Standards Track [Page 14] - -RFC 2831 Digest SASL Mechanism May 2000 - - - Kcs = MD5({H(A1)[0..n], - "Digest H(A1) to server-to-client sealing key magic constant"}) - - where MD5 is as specified in [RFC 1321]. For cipher "rc4-40" n is 5; - for "rc4-56" n is 7; for the rest n is 16. The key for the "rc-*" - ciphers is all 16 bytes of Kcc or Kcs; the key for "des" is the first - 7 bytes; the key for "3des" is the first 14 bytes. The IV for "des" - and "3des" is the last 8 bytes of Kcc or Kcs. - - If message confidentiality is negotiated, each message is encrypted - with the chosen cipher and a MAC block is appended to the message. - - The MAC block is a variable length padding prefix followed by 16 - bytes formatted as follows: the first 10 bytes of the HMAC-MD5 [RFC - 2104] of the message, a 2-byte message type number in network byte - order with value 1, and the 4-byte sequence number in network byte - order. If the blocksize of the chosen cipher is not 1 byte, the - padding prefix is one or more octets each containing the number of - padding bytes, such that total length of the encrypted part of the - message is a multiple of the blocksize. The padding and first 10 - bytes of the MAC block are encrypted along with the message. - - SEAL(Ki, Kc, SeqNum, msg) = - {CIPHER(Kc, {msg, pad, HMAC(Ki, {SeqNum, msg})[0..9])}), 0x0001, - SeqNum} - - where CIPHER is the chosen cipher, Ki and Kc are Kic and Kcc for - messages sent by the client and Kis and Kcs for those sent by the - server. The sequence number is initialized to zero, and incremented - by one for each message sent. - - Upon receipt, the message is decrypted, HMAC(Ki, {SeqNum, msg}) is - computed and compared with the received value; the message is - discarded if they differ. - -3 Security Considerations - -3.1 Authentication of Clients using Digest Authentication - - Digest Authentication does not provide a strong authentication - mechanism, when compared to public key based mechanisms, for example. - However, since it prevents chosen plaintext attacks, it is stronger - than (e.g.) CRAM-MD5, which has been proposed for use with LDAP [10], - POP and IMAP (see RFC 2195 [9]). It is intended to replace the much - weaker and even more dangerous use of plaintext passwords; however, - since it is still a password based mechanism it avoids some of the - potential deployabilty issues with public-key, OTP or similar - mechanisms. - - - -Leach & Newman Standards Track [Page 15] - -RFC 2831 Digest SASL Mechanism May 2000 - - - Digest Authentication offers no confidentiality protection beyond - protecting the actual password. All of the rest of the challenge and - response are available to an eavesdropper, including the user's name - and authentication realm. - -3.2 Comparison of Digest with Plaintext Passwords - - The greatest threat to the type of transactions for which these - protocols are used is network snooping. This kind of transaction - might involve, for example, online access to a mail service whose use - is restricted to paying subscribers. With plaintext password - authentication an eavesdropper can obtain the password of the user. - This not only permits him to access anything in the database, but, - often worse, will permit access to anything else the user protects - with the same password. - -3.3 Replay Attacks - - Replay attacks are defeated if the client or the server chooses a - fresh nonce for each authentication, as this specification requires. - -3.4 Online dictionary attacks - - If the attacker can eavesdrop, then it can test any overheard - nonce/response pairs against a (potentially very large) list of - common words. Such a list is usually much smaller than the total - number of possible passwords. The cost of computing the response for - each password on the list is paid once for each challenge. - - The server can mitigate this attack by not allowing users to select - passwords that are in a dictionary. - -3.5 Offline dictionary attacks - - If the attacker can choose the challenge, then it can precompute the - possible responses to that challenge for a list of common words. Such - a list is usually much smaller than the total number of possible - passwords. The cost of computing the response for each password on - the list is paid just once. - - Offline dictionary attacks are defeated if the client chooses a fresh - nonce for each authentication, as this specification requires. - - - - - - - - - -Leach & Newman Standards Track [Page 16] - -RFC 2831 Digest SASL Mechanism May 2000 - - -3.6 Man in the Middle - - Digest authentication is vulnerable to "man in the middle" (MITM) - attacks. Clearly, a MITM would present all the problems of - eavesdropping. But it also offers some additional opportunities to - the attacker. - - A possible man-in-the-middle attack would be to substitute a weaker - qop scheme for the one(s) sent by the server; the server will not be - able to detect this attack. For this reason, the client should always - use the strongest scheme that it understands from the choices - offered, and should never choose a scheme that does not meet its - minimum requirements. - -3.7 Chosen plaintext attacks - - A chosen plaintext attack is where a MITM or a malicious server can - arbitrarily choose the challenge that the client will use to compute - the response. The ability to choose the challenge is known to make - cryptanalysis much easier [8]. - - However, Digest does not permit the attack to choose the challenge as - long as the client chooses a fresh nonce for each authentication, as - this specification requires. - -3.8 Spoofing by Counterfeit Servers - - If a user can be led to believe that she is connecting to a host - containing information protected by a password she knows, when in - fact she is connecting to a hostile server, then the hostile server - can obtain challenge/response pairs where it was able to partly - choose the challenge. There is no known way that this can be - exploited. - -3.9 Storing passwords - - Digest authentication requires that the authenticating agent (usually - the server) store some data derived from the user's name and password - in a "password file" associated with a given realm. Normally this - might contain pairs consisting of username and H({ username-value, - ":", realm-value, ":", passwd }), which is adequate to compute H(A1) - as described above without directly exposing the user's password. - - The security implications of this are that if this password file is - compromised, then an attacker gains immediate access to documents on - the server using this realm. Unlike, say a standard UNIX password - file, this information need not be decrypted in order to access - documents in the server realm associated with this file. On the other - - - -Leach & Newman Standards Track [Page 17] - -RFC 2831 Digest SASL Mechanism May 2000 - - - hand, decryption, or more likely a brute force attack, would be - necessary to obtain the user's password. This is the reason that the - realm is part of the digested data stored in the password file. It - means that if one Digest authentication password file is compromised, - it does not automatically compromise others with the same username - and password (though it does expose them to brute force attack). - - There are two important security consequences of this. First the - password file must be protected as if it contained plaintext - passwords, because for the purpose of accessing documents in its - realm, it effectively does. - - A second consequence of this is that the realm string should be - unique among all realms that any single user is likely to use. In - particular a realm string should include the name of the host doing - the authentication. - -3.10 Multiple realms - - Use of multiple realms may mean both that compromise of a the - security database for a single realm does not compromise all - security, and that there are more things to protect in order to keep - the whole system secure. - -3.11 Summary - - By modern cryptographic standards Digest Authentication is weak, - compared to (say) public key based mechanisms. But for a large range - of purposes it is valuable as a replacement for plaintext passwords. - Its strength may vary depending on the implementation. - -4 Example - - This example shows the use of the Digest SASL mechanism with the - IMAP4 AUTHENTICATE command [RFC 2060]. - - In this example, "C:" and "S:" represent a line sent by the client or - server respectively including a CRLF at the end. Linebreaks and - indentation within a "C:" or "S:" are editorial and not part of the - protocol. The password in this example was "secret". Note that the - base64 encoding of the challenges and responses is part of the IMAP4 - AUTHENTICATE command, not part of the Digest specification itself. - - S: * OK elwood.innosoft.com PMDF IMAP4rev1 V6.0-9 - C: c CAPABILITY - S: * CAPABILITY IMAP4 IMAP4rev1 ACL LITERAL+ NAMESPACE QUOTA - UIDPLUS AUTH=CRAM-MD5 AUTH=DIGEST-MD5 AUTH=PLAIN - S: c OK Completed - - - -Leach & Newman Standards Track [Page 18] - -RFC 2831 Digest SASL Mechanism May 2000 - - - C: a AUTHENTICATE DIGEST-MD5 - S: + cmVhbG09ImVsd29vZC5pbm5vc29mdC5jb20iLG5vbmNlPSJPQTZNRzl0 - RVFHbTJoaCIscW9wPSJhdXRoIixhbGdvcml0aG09bWQ1LXNlc3MsY2hh - cnNldD11dGYtOA== - C: Y2hhcnNldD11dGYtOCx1c2VybmFtZT0iY2hyaXMiLHJlYWxtPSJlbHdvb2 - QuaW5ub3NvZnQuY29tIixub25jZT0iT0E2TUc5dEVRR20yaGgiLG5jPTAw - MDAwMDAxLGNub25jZT0iT0E2TUhYaDZWcVRyUmsiLGRpZ2VzdC11cmk9Im - ltYXAvZWx3b29kLmlubm9zb2Z0LmNvbSIscmVzcG9uc2U9ZDM4OGRhZDkw - ZDRiYmQ3NjBhMTUyMzIxZjIxNDNhZjcscW9wPWF1dGg= - S: + cnNwYXV0aD1lYTQwZjYwMzM1YzQyN2I1NTI3Yjg0ZGJhYmNkZmZmZA== - C: - S: a OK User logged in - --- - - The base64-decoded version of the SASL exchange is: - - S: realm="elwood.innosoft.com",nonce="OA6MG9tEQGm2hh",qop="auth", - algorithm=md5-sess,charset=utf-8 - C: charset=utf-8,username="chris",realm="elwood.innosoft.com", - nonce="OA6MG9tEQGm2hh",nc=00000001,cnonce="OA6MHXh6VqTrRk", - digest-uri="imap/elwood.innosoft.com", - response=d388dad90d4bbd760a152321f2143af7,qop=auth - S: rspauth=ea40f60335c427b5527b84dbabcdfffd - - The password in this example was "secret". - - This example shows the use of the Digest SASL mechanism with the - ACAP, using the same notational conventions and password as in the - previous example. Note that ACAP does not base64 encode and uses - fewer round trips that IMAP4. - - S: * ACAP (IMPLEMENTATION "Test ACAP server") (SASL "CRAM-MD5" - "DIGEST-MD5" "PLAIN") - C: a AUTHENTICATE "DIGEST-MD5" - S: + {94} - S: realm="elwood.innosoft.com",nonce="OA9BSXrbuRhWay",qop="auth", - algorithm=md5-sess,charset=utf-8 - C: {206} - C: charset=utf-8,username="chris",realm="elwood.innosoft.com", - nonce="OA9BSXrbuRhWay",nc=00000001,cnonce="OA9BSuZWMSpW8m", - digest-uri="acap/elwood.innosoft.com", - response=6084c6db3fede7352c551284490fd0fc,qop=auth - S: a OK (SASL {40} - S: rspauth=2f0b3d7c3c2e486600ef710726aa2eae) "AUTHENTICATE - Completed" - --- - - - - - -Leach & Newman Standards Track [Page 19] - -RFC 2831 Digest SASL Mechanism May 2000 - - - The server uses the values of all the directives, plus knowledge of - the users password (or the hash of the user's name, server's realm - and the user's password) to verify the computations above. If they - check, then the user has authenticated. - -5 References - - [Digest] Franks, J., et al., "HTTP Authentication: Basic and Digest - Access Authentication", RFC 2617, June 1999. - - [ISO-8859] ISO-8859. International Standard--Information Processing-- - 8-bit Single-Byte Coded Graphic Character Sets -- - Part 1: Latin alphabet No. 1, ISO-8859-1:1987. - Part 2: Latin alphabet No. 2, ISO-8859-2, 1987. - Part 3: Latin alphabet No. 3, ISO-8859-3, 1988. - Part 4: Latin alphabet No. 4, ISO-8859-4, 1988. - Part 5: Latin/Cyrillic alphabet, ISO-8859-5, 1988. - Part 6: Latin/Arabic alphabet, ISO-8859-6, 1987. - Part 7: Latin/Greek alphabet, ISO-8859-7, 1987. - Part 8: Latin/Hebrew alphabet, ISO-8859-8, 1988. - Part 9: Latin alphabet No. 5, ISO-8859-9, 1990. - - [RFC 822] Crocker, D., "Standard for The Format of ARPA Internet - Text Messages," STD 11, RFC 822, August 1982. - - [RFC 1321] Rivest, R., "The MD5 Message-Digest Algorithm", RFC 1321, - April 1992. - - [RFC 2047] Moore, K., "MIME (Multipurpose Internet Mail Extensions) - Part Three: Message Header Extensions for Non-ASCII Text", - RFC 2047, November 1996. - - [RFC 2052] Gulbrandsen, A. and P. Vixie, "A DNS RR for specifying the - location of services (DNS SRV)", RFC 2052, October 1996. - - [RFC 2060] Crispin, M., "Internet Message Access Protocol - Version - 4rev1", RFC 2060, December 1996. - - [RFC 2104] Krawczyk, H., Bellare, M. and R. Canetti, "HMAC: Keyed- - Hashing for Message Authentication", RFC 2104, February - 1997. - - [RFC 2195] Klensin, J., Catoe, R. and P. Krumviede, "IMAP/POP - AUTHorize Extension for Simple Challenge/Response", RFC - 2195, September 1997. - - - - - - -Leach & Newman Standards Track [Page 20] - -RFC 2831 Digest SASL Mechanism May 2000 - - - [RFC 2119] Bradner, S., "Key words for use in RFCs to Indicate - Requirement Levels", BCP 14, RFC 2119, March 1997. - - [RFC 2222] Myers, J., "Simple Authentication and Security Layer - (SASL)", RFC 2222, October 1997. - - [USASCII] US-ASCII. Coded Character Set - 7-Bit American Standard - Code for Information Interchange. Standard ANSI X3.4-1986, - ANSI, 1986. - -6 Authors' Addresses - - Paul Leach - Microsoft - 1 Microsoft Way - Redmond, WA 98052 - - EMail: paulle@microsoft.com - - - Chris Newman - Innosoft International, Inc. - 1050 Lakes Drive - West Covina, CA 91790 USA - - EMail: chris.newman@innosoft.com - -7 ABNF - - What follows is the definition of the notation as is used in the - HTTP/1.1 specification (RFC 2616) and the HTTP authentication - specification (RFC 2617); it is reproduced here for ease of - reference. Since it is intended that a single Digest implementation - can support both HTTP and SASL-based protocols, the same notation is - used in both to facilitate comparison and prevention of unwanted - differences. Since it is cut-and-paste from the HTTP specifications, - not all productions may be used in this specification. It is also not - quite legal ABNF; again, the errors were copied from the HTTP - specifications. - -7.1 Augmented BNF - - All of the mechanisms specified in this document are described in - both prose and an augmented Backus-Naur Form (BNF) similar to that - used by RFC 822 [RFC 822]. Implementers will need to be familiar with - the notation in order to understand this specification. - - - - - -Leach & Newman Standards Track [Page 21] - -RFC 2831 Digest SASL Mechanism May 2000 - - - The augmented BNF includes the following constructs: - - name = definition - The name of a rule is simply the name itself (without any - enclosing "<" and ">") and is separated from its definition by the - equal "=" character. White space is only significant in that - indentation of continuation lines is used to indicate a rule - definition that spans more than one line. Certain basic rules are - in uppercase, such as SP, LWS, HT, CRLF, DIGIT, ALPHA, etc. Angle - brackets are used within definitions whenever their presence will - facilitate discerning the use of rule names. - - "literal" - Quotation marks surround literal text. Unless stated otherwise, - the text is case-insensitive. - - rule1 | rule2 - Elements separated by a bar ("|") are alternatives, e.g., "yes | - no" will accept yes or no. - - (rule1 rule2) - Elements enclosed in parentheses are treated as a single element. - Thus, "(elem (foo | bar) elem)" allows the token sequences - "elem foo elem" and "elem bar elem". - - *rule - The character "*" preceding an element indicates repetition. The - full form is "*element" indicating at least and at most - occurrences of element. Default values are 0 and infinity so - that "*(element)" allows any number, including zero; "1*element" - requires at least one; and "1*2element" allows one or two. - - [rule] - Square brackets enclose optional elements; "[foo bar]" is - equivalent to "*1(foo bar)". - - N rule - Specific repetition: "(element)" is equivalent to - "*(element)"; that is, exactly occurrences of (element). - Thus 2DIGIT is a 2-digit number, and 3ALPHA is a string of three - alphabetic characters. - - #rule - A construct "#" is defined, similar to "*", for defining lists of - elements. The full form is "#element" indicating at least - and at most elements, each separated by one or more commas - (",") and OPTIONAL linear white space (LWS). This makes the usual - form of lists very easy; a rule such as - - - -Leach & Newman Standards Track [Page 22] - -RFC 2831 Digest SASL Mechanism May 2000 - - - ( *LWS element *( *LWS "," *LWS element )) - can be shown as - 1#element - Wherever this construct is used, null elements are allowed, but do - not contribute to the count of elements present. That is, - "(element), , (element) " is permitted, but counts as only two - elements. Therefore, where at least one element is required, at - least one non-null element MUST be present. Default values are 0 - and infinity so that "#element" allows any number, including zero; - "1#element" requires at least one; and "1#2element" allows one or - two. - - ; comment - A semi-colon, set off some distance to the right of rule text, - starts a comment that continues to the end of line. This is a - simple way of including useful notes in parallel with the - specifications. - - implied *LWS - The grammar described by this specification is word-based. Except - where noted otherwise, linear white space (LWS) can be included - between any two adjacent words (token or quoted-string), and - between adjacent words and separators, without changing the - interpretation of a field. At least one delimiter (LWS and/or - separators) MUST exist between any two tokens (for the definition - of "token" below), since they would otherwise be interpreted as a - single token. - -7.2 Basic Rules - - The following rules are used throughout this specification to - describe basic parsing constructs. The US-ASCII coded character set - is defined by ANSI X3.4-1986 [USASCII]. - - OCTET = - CHAR = - UPALPHA = - LOALPHA = - ALPHA = UPALPHA | LOALPHA - DIGIT = - CTL = - CR = - LF = - SP = - HT = - <"> = - CRLF = CR LF - - - -Leach & Newman Standards Track [Page 23] - -RFC 2831 Digest SASL Mechanism May 2000 - - - - All linear white space, including folding, has the same semantics as - SP. A recipient MAY replace any linear white space with a single SP - before interpreting the field value or forwarding the message - downstream. - - LWS = [CRLF] 1*( SP | HT ) - - The TEXT rule is only used for descriptive field contents and values - that are not intended to be interpreted by the message parser. Words - of *TEXT MAY contain characters from character sets other than - ISO-8859-1 [ISO 8859] only when encoded according to the rules of RFC - 2047 [RFC 2047]. - - TEXT = - - A CRLF is allowed in the definition of TEXT only as part of a header - field continuation. It is expected that the folding LWS will be - replaced with a single SP before interpretation of the TEXT value. - - Hexadecimal numeric characters are used in several protocol elements. - - HEX = "A" | "B" | "C" | "D" | "E" | "F" - | "a" | "b" | "c" | "d" | "e" | "f" | DIGIT - - Many HTTP/1.1 header field values consist of words separated by LWS - or special characters. These special characters MUST be in a quoted - string to be used within a parameter value. - - token = 1* - separators = "(" | ")" | "<" | ">" | "@" - | "," | ";" | ":" | "\" | <"> - | "/" | "[" | "]" | "?" | "=" - | "{" | "}" | SP | HT - - A string of text is parsed as a single word if it is quoted using - double-quote marks. - - quoted-string = ( <"> qdstr-val <"> ) - qdstr-val = *( qdtext | quoted-pair ) - qdtext = > - - Note that LWS is NOT implicit between the double-quote marks (<">) - surrounding a qdstr-val and the qdstr-val; any LWS will be considered - part of the qdstr-val. This is also the case for quotation marks - surrounding any other construct. - - - - -Leach & Newman Standards Track [Page 24] - -RFC 2831 Digest SASL Mechanism May 2000 - - - The backslash character ("\") MAY be used as a single-character - quoting mechanism only within qdstr-val and comment constructs. - - quoted-pair = "\" CHAR - - The value of this construct is CHAR. Note that an effect of this rule - is that backslash must be quoted. - -8 Sample Code - - The sample implementation in [Digest] also applies to DIGEST-MD5. - - The following code implements the conversion from UTF-8 to 8859-1 if - necessary. - - /* if the string is entirely in the 8859-1 subset of UTF-8, then - * translate to 8859-1 prior to MD5 - */ - void MD5_UTF8_8859_1(MD5_CTX *ctx, const unsigned char *base, - int len) - { - const unsigned char *scan, *end; - unsigned char cbuf; - - end = base + len; - for (scan = base; scan < end; ++scan) { - if (*scan > 0xC3) break; /* abort if outside 8859-1 */ - if (*scan >= 0xC0 && *scan <= 0xC3) { - if (++scan == end || *scan < 0x80 || *scan > 0xBF) - break; - } - } - /* if we found a character outside 8859-1, don't alter string - */ - if (scan < end) { - MD5Update(ctx, base, len); - return; - } - - /* convert to 8859-1 prior to applying hash - */ - do { - for (scan = base; scan < end && *scan < 0xC0; ++scan) - ; - if (scan != base) MD5Update(ctx, base, scan - base); - if (scan + 1 >= end) break; - cbuf = ((scan[0] & 0x3) << 6) | (scan[1] & 0x3f); - MD5Update(ctx, &cbuf, 1); - - - -Leach & Newman Standards Track [Page 25] - -RFC 2831 Digest SASL Mechanism May 2000 - - - base = scan + 2; - } while (base < end); - } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Leach & Newman Standards Track [Page 26] - -RFC 2831 Digest SASL Mechanism May 2000 - - -9 Full Copyright Statement - - Copyright (C) The Internet Society (2000). All Rights Reserved. - - This document and translations of it may be copied and furnished to - others, and derivative works that comment on or otherwise explain it - or assist in its implementation may be prepared, copied, published - and distributed, in whole or in part, without restriction of any - kind, provided that the above copyright notice and this paragraph are - included on all such copies and derivative works. However, this - document itself may not be modified in any way, such as by removing - the copyright notice or references to the Internet Society or other - Internet organizations, except as needed for the purpose of - developing Internet standards in which case the procedures for - copyrights defined in the Internet Standards process must be - followed, or as required to translate it into languages other than - English. - - The limited permissions granted above are perpetual and will not be - revoked by the Internet Society or its successors or assigns. - - This document and the information contained herein is provided on an - "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING - TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING - BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION - HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - -Acknowledgement - - Funding for the RFC Editor function is currently provided by the - Internet Society. - - - - - - - - - - - - - - - - - - - -Leach & Newman Standards Track [Page 27] - diff --git a/doc/rfc2945.txt b/doc/rfc2945.txt deleted file mode 100644 index 983c441c..00000000 --- a/doc/rfc2945.txt +++ /dev/null @@ -1,451 +0,0 @@ - - - - - - -Network Working Group T. Wu -Request for Comments: 2945 Stanford University -Category: Standards Track September 2000 - - - The SRP Authentication and Key Exchange System - -Status of this Memo - - This document specifies an Internet standards track protocol for the - Internet community, and requests discussion and suggestions for - improvements. Please refer to the current edition of the "Internet - Official Protocol Standards" (STD 1) for the standardization state - and status of this protocol. Distribution of this memo is unlimited. - -Copyright Notice - - Copyright (C) The Internet Society (2000). All Rights Reserved. - -Abstract - - This document describes a cryptographically strong network - authentication mechanism known as the Secure Remote Password (SRP) - protocol. This mechanism is suitable for negotiating secure - connections using a user-supplied password, while eliminating the - security problems traditionally associated with reusable passwords. - This system also performs a secure key exchange in the process of - authentication, allowing security layers (privacy and/or integrity - protection) to be enabled during the session. Trusted key servers - and certificate infrastructures are not required, and clients are not - required to store or manage any long-term keys. SRP offers both - security and deployment advantages over existing challenge-response - techniques, making it an ideal drop-in replacement where secure - password authentication is needed. - -1. Introduction - - The lack of a secure authentication mechanism that is also easy to - use has been a long-standing problem with the vast majority of - Internet protocols currently in use. The problem is two-fold: Users - like to use passwords that they can remember, but most password-based - authentication systems offer little protection against even passive - attackers, especially if weak and easily-guessed passwords are used. - - Eavesdropping on a TCP/IP network can be carried out very easily and - very effectively against protocols that transmit passwords in the - clear. Even so-called "challenge-response" techniques like the one - described in [RFC 2095] and [RFC 1760], which are designed to defeat - - - -Wu Standards Track [Page 1] - -RFC 2945 SRP Authentication & Key Exchange System September 2000 - - - simple sniffing attacks, can be compromised by what is known as a - "dictionary attack". This occurs when an attacker captures the - messages exchanged during a legitimate run of the protocol and uses - that information to verify a series of guessed passwords taken from a - precompiled "dictionary" of common passwords. This works because - users often choose simple, easy-to-remember passwords, which - invariably are also easy to guess. - - Many existing mechanisms also require the password database on the - host to be kept secret because the password P or some private hash - h(P) is stored there and would compromise security if revealed. That - approach often degenerates into "security through obscurity" and goes - against the UNIX convention of keeping a "public" password file whose - contents can be revealed without destroying system security. - - SRP meets the strictest requirements laid down in [RFC 1704] for a - non-disclosing authentication protocol. It offers complete - protection against both passive and active attacks, and accomplishes - this efficiently using a single Diffie-Hellman-style round of - computation, making it feasible to use in both interactive and non- - interactive authentication for a wide range of Internet protocols. - Since it retains its security when used with low-entropy passwords, - it can be seamlessly integrated into existing user applications. - -2. Conventions and Terminology - - The protocol described by this document is sometimes referred to as - "SRP-3" for historical purposes. This particular protocol is - described in [SRP] and is believed to have very good logical and - cryptographic resistance to both eavesdropping and active attacks. - - This document does not attempt to describe SRP in the context of any - particular Internet protocol; instead it describes an abstract - protocol that can be easily fitted to a particular application. For - example, the specific format of messages (including padding) is not - specified. Those issues have been left to the protocol implementor - to decide. - - The one implementation issue worth specifying here is the mapping - between strings and integers. Internet protocols are byte-oriented, - while SRP performs algebraic operations on its messages, so it is - logical to define at least one method by which integers can be - converted into a string of bytes and vice versa. - - An n-byte string S can be converted to an integer as follows: - - i = S[n-1] + 256 * S[n-2] + 256^2 * S[n-3] + ... + 256^(n-1) * S[0] - - - - -Wu Standards Track [Page 2] - -RFC 2945 SRP Authentication & Key Exchange System September 2000 - - - where i is the integer and S[x] is the value of the x'th byte of S. - In human terms, the string of bytes is the integer expressed in base - 256, with the most significant digit first. When converting back to - a string, S[0] must be non-zero (padding is considered to be a - separate, independent process). This conversion method is suitable - for file storage, in-memory representation, and network transmission - of large integer values. Unless otherwise specified, this mapping - will be assumed. - - If implementations require padding a string that represents an - integer value, it is recommended that they use zero bytes and add - them to the beginning of the string. The conversion back to integer - automatically discards leading zero bytes, making this padding scheme - less prone to error. - - The SHA hash function, when used in this document, refers to the - SHA-1 message digest algorithm described in [SHA1]. - -3. The SRP-SHA1 mechanism - - This section describes an implementation of the SRP authentication - and key-exchange protocol that employs the SHA hash function to - generate session keys and authentication proofs. - - The host stores user passwords as triplets of the form - - { , , } - - Password entries are generated as follows: - - = random() - x = SHA( | SHA( | ":" | )) - = v = g^x % N - - The | symbol indicates string concatenation, the ^ operator is the - exponentiation operation, and the % operator is the integer remainder - operation. Most implementations perform the exponentiation and - remainder in a single stage to avoid generating unwieldy intermediate - results. Note that the 160-bit output of SHA is implicitly converted - to an integer before it is operated upon. - - Authentication is generally initiated by the client. - - Client Host - -------- ------ - U = --> - <-- s = - - - - -Wu Standards Track [Page 3] - -RFC 2945 SRP Authentication & Key Exchange System September 2000 - - - Upon identifying himself to the host, the client will receive the - salt stored on the host under his username. - - a = random() - A = g^a % N --> - v = - b = random() - <-- B = (v + g^b) % N - - p = - x = SHA(s | SHA(U | ":" | p)) - - S = (B - g^x) ^ (a + u * x) % N S = (A * v^u) ^ b % N - K = SHA_Interleave(S) K = SHA_Interleave(S) - (this function is described - in the next section) - - The client generates a random number, raises g to that power modulo - the field prime, and sends the result to the host. The host does the - same thing and also adds the public verifier before sending it to the - client. Both sides then construct the shared session key based on - the respective formulae. - - The parameter u is a 32-bit unsigned integer which takes its value - from the first 32 bits of the SHA1 hash of B, MSB first. - - The client MUST abort authentication if B % N is zero. - - The host MUST abort the authentication attempt if A % N is zero. The - host MUST send B after receiving A from the client, never before. - - At this point, the client and server should have a common session key - that is secure (i.e. not known to an outside party). To finish - authentication, they must prove to each other that their keys are - identical. - - M = H(H(N) XOR H(g) | H(U) | s | A | B | K) - --> - <-- H(A | M | K) - - The server will calculate M using its own K and compare it against - the client's response. If they do not match, the server MUST abort - and signal an error before it attempts to answer the client's - challenge. Not doing so could compromise the security of the user's - password. - - - - - - -Wu Standards Track [Page 4] - -RFC 2945 SRP Authentication & Key Exchange System September 2000 - - - If the server receives a correct response, it issues its own proof to - the client. The client will compute the expected response using its - own K to verify the authenticity of the server. If the client - responded correctly, the server MUST respond with its hash value. - - The transactions in this protocol description do not necessarily have - a one-to-one correspondence with actual protocol messages. This - description is only intended to illustrate the relationships between - the different parameters and how they are computed. It is possible, - for example, for an implementation of the SRP-SHA1 mechanism to - consolidate some of the flows as follows: - - Client Host - -------- ------ - U, A --> - <-- s, B - H(H(N) XOR H(g) | H(U) | s | A | B | K) - --> - <-- H(A | M | K) - - The values of N and g used in this protocol must be agreed upon by - the two parties in question. They can be set in advance, or the host - can supply them to the client. In the latter case, the host should - send the parameters in the first message along with the salt. For - maximum security, N should be a safe prime (i.e. a number of the form - N = 2q + 1, where q is also prime). Also, g should be a generator - modulo N (see [SRP] for details), which means that for any X where 0 - < X < N, there exists a value x for which g^x % N == X. - -3.1. Interleaved SHA - - The SHA_Interleave function used in SRP-SHA1 is used to generate a - session key that is twice as long as the 160-bit output of SHA1. To - compute this function, remove all leading zero bytes from the input. - If the length of the resulting string is odd, also remove the first - byte. Call the resulting string T. Extract the even-numbered bytes - into a string E and the odd-numbered bytes into a string F, i.e. - - E = T[0] | T[2] | T[4] | ... - F = T[1] | T[3] | T[5] | ... - - Both E and F should be exactly half the length of T. Hash each one - with regular SHA1, i.e. - - G = SHA(E) - H = SHA(F) - - - - - -Wu Standards Track [Page 5] - -RFC 2945 SRP Authentication & Key Exchange System September 2000 - - - Interleave the two hashes back together to form the output, i.e. - - result = G[0] | H[0] | G[1] | H[1] | ... | G[19] | H[19] - - The result will be 40 bytes (320 bits) long. - -3.2. Other Hash Algorithms - - SRP can be used with hash functions other than SHA. If the hash - function produces an output of a different length than SHA (20 - bytes), it may change the length of some of the messages in the - protocol, but the fundamental operation will be unaffected. - - Earlier versions of the SRP mechanism used the MD5 hash function, - described in [RFC 1321]. Keyed hash transforms are also recommended - for use with SRP; one possible construction uses HMAC [RFC 2104], - using K to key the hash in each direction instead of concatenating it - with the other parameters. - - Any hash function used with SRP should produce an output of at least - 16 bytes and have the property that small changes in the input cause - significant nonlinear changes in the output. [SRP] covers these - issues in more depth. - -4. Security Considerations - - This entire memo discusses an authentication and key-exchange system - that protects passwords and exchanges keys across an untrusted - network. This system improves security by eliminating the need to - send cleartext passwords over the network and by enabling encryption - through its secure key-exchange mechanism. - - The private values for a and b correspond roughly to the private - values in a Diffie-Hellman exchange and have similar constraints of - length and entropy. Implementations may choose to increase the - length of the parameter u, as long as both client and server agree, - but it is not recommended that it be shorter than 32 bits. - - SRP has been designed not only to counter the threat of casual - password-sniffing, but also to prevent a determined attacker equipped - with a dictionary of passwords from guessing at passwords using - captured network traffic. The SRP protocol itself also resists - active network attacks, and implementations can use the securely - exchanged keys to protect the session against hijacking and provide - confidentiality. - - - - - - -Wu Standards Track [Page 6] - -RFC 2945 SRP Authentication & Key Exchange System September 2000 - - - SRP also has the added advantage of permitting the host to store - passwords in a form that is not directly useful to an attacker. Even - if the host's password database were publicly revealed, the attacker - would still need an expensive dictionary search to obtain any - passwords. The exponential computation required to validate a guess - in this case is much more time-consuming than the hash currently used - by most UNIX systems. Hosts are still advised, though, to try their - best to keep their password files secure. - -5. References - - [RFC 1321] Rivest, R., "The MD5 Message-Digest Algorithm", RFC 1321, - April 1992. - - [RFC 1704] Haller, N. and R. Atkinson, "On Internet Authentication", - RFC 1704, October 1994. - - [RFC 1760] Haller, N., "The S/Key One-Time Password System", RFC - 1760, Feburary 1995. - - [RFC 2095] Klensin, J., Catoe, R. and P. Krumviede, "IMAP/POP - AUTHorize Extension for Simple Challenge/Response", RFC - 2095, January 1997. - - [RFC 2104] Krawczyk, H., Bellare, M. and R. Canetti, "HMAC: Keyed- - Hashing for Message Authentication", RFC 2104, February - 1997. - - [SHA1] National Institute of Standards and Technology (NIST), - "Announcing the Secure Hash Standard", FIPS 180-1, U.S. - Department of Commerce, April 1995. - - [SRP] T. Wu, "The Secure Remote Password Protocol", In - Proceedings of the 1998 Internet Society Symposium on - Network and Distributed Systems Security, San Diego, CA, - pp. 97-111. - -6. Author's Address - - Thomas Wu - Stanford University - Stanford, CA 94305 - - EMail: tjw@cs.Stanford.EDU - - - - - - - -Wu Standards Track [Page 7] - -RFC 2945 SRP Authentication & Key Exchange System September 2000 - - -7. Full Copyright Statement - - Copyright (C) The Internet Society (2000). All Rights Reserved. - - This document and translations of it may be copied and furnished to - others, and derivative works that comment on or otherwise explain it - or assist in its implementation may be prepared, copied, published - and distributed, in whole or in part, without restriction of any - kind, provided that the above copyright notice and this paragraph are - included on all such copies and derivative works. However, this - document itself may not be modified in any way, such as by removing - the copyright notice or references to the Internet Society or other - Internet organizations, except as needed for the purpose of - developing Internet standards in which case the procedures for - copyrights defined in the Internet Standards process must be - followed, or as required to translate it into languages other than - English. - - The limited permissions granted above are perpetual and will not be - revoked by the Internet Society or its successors or assigns. - - This document and the information contained herein is provided on an - "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING - TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING - BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION - HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - -Acknowledgement - - Funding for the RFC Editor function is currently provided by the - Internet Society. - - - - - - - - - - - - - - - - - - - -Wu Standards Track [Page 8] - diff --git a/doc/rfc3174.txt b/doc/rfc3174.txt deleted file mode 100644 index ebe515d3..00000000 --- a/doc/rfc3174.txt +++ /dev/null @@ -1,1235 +0,0 @@ - - - - - - -Network Working Group D. Eastlake, 3rd -Request for Comments: 3174 Motorola -Category: Informational P. Jones - Cisco Systems - September 2001 - - - US Secure Hash Algorithm 1 (SHA1) - -Status of this Memo - - This memo provides information for the Internet community. It does - not specify an Internet standard of any kind. Distribution of this - memo is unlimited. - -Copyright Notice - - Copyright (C) The Internet Society (2001). All Rights Reserved. - -Abstract - - The purpose of this document is to make the SHA-1 (Secure Hash - Algorithm 1) hash algorithm conveniently available to the Internet - community. The United States of America has adopted the SHA-1 hash - algorithm described herein as a Federal Information Processing - Standard. Most of the text herein was taken by the authors from FIPS - 180-1. Only the C code implementation is "original". - -Acknowledgements - - Most of the text herein was taken from [FIPS 180-1]. Only the C code - implementation is "original" but its style is similar to the - previously published MD4 and MD5 RFCs [RFCs 1320, 1321]. - - The SHA-1 is based on principles similar to those used by Professor - Ronald L. Rivest of MIT when designing the MD4 message digest - algorithm [MD4] and is modeled after that algorithm [RFC 1320]. - - Useful comments from the following, which have been incorporated - herein, are gratefully acknowledged: - - Tony Hansen - Garrett Wollman - - - - - - - - -Eastlake & Jones Informational [Page 1] - -RFC 3174 US Secure Hash Algorithm 1 (SHA1) September 2001 - - -Table of Contents - - 1. Overview of Contents........................................... 2 - 2. Definitions of Bit Strings and Integers........................ 3 - 3. Operations on Words............................................ 3 - 4. Message Padding................................................ 4 - 5. Functions and Constants Used................................... 6 - 6. Computing the Message Digest................................... 6 - 6.1 Method 1...................................................... 6 - 6.2 Method 2...................................................... 7 - 7. C Code......................................................... 8 - 7.1 .h file....................................................... 8 - 7.2 .c file....................................................... 10 - 7.3 Test Driver................................................... 18 - 8. Security Considerations........................................ 20 - References........................................................ 21 - Authors' Addresses................................................ 21 - Full Copyright Statement.......................................... 22 - -1. Overview of Contents - - NOTE: The text below is mostly taken from [FIPS 180-1] and assertions - therein of the security of SHA-1 are made by the US Government, the - author of [FIPS 180-1], and not by the authors of this document. - - This document specifies a Secure Hash Algorithm, SHA-1, for computing - a condensed representation of a message or a data file. When a - message of any length < 2^64 bits is input, the SHA-1 produces a - 160-bit output called a message digest. The message digest can then, - for example, be input to a signature algorithm which generates or - verifies the signature for the message. Signing the message digest - rather than the message often improves the efficiency of the process - because the message digest is usually much smaller in size than the - message. The same hash algorithm must be used by the verifier of a - digital signature as was used by the creator of the digital - signature. Any change to the message in transit will, with very high - probability, result in a different message digest, and the signature - will fail to verify. - - The SHA-1 is called secure because it is computationally infeasible - to find a message which corresponds to a given message digest, or to - find two different messages which produce the same message digest. - Any change to a message in transit will, with very high probability, - result in a different message digest, and the signature will fail to - verify. - - - - - - -Eastlake & Jones Informational [Page 2] - -RFC 3174 US Secure Hash Algorithm 1 (SHA1) September 2001 - - - Section 2 below defines the terminology and functions used as - building blocks to form SHA-1. - -2. Definitions of Bit Strings and Integers - - The following terminology related to bit strings and integers will be - used: - - a. A hex digit is an element of the set {0, 1, ... , 9, A, ... , F}. - A hex digit is the representation of a 4-bit string. Examples: 7 - = 0111, A = 1010. - - b. A word equals a 32-bit string which may be represented as a - sequence of 8 hex digits. To convert a word to 8 hex digits each - 4-bit string is converted to its hex equivalent as described in - (a) above. Example: - - 1010 0001 0000 0011 1111 1110 0010 0011 = A103FE23. - - c. An integer between 0 and 2^32 - 1 inclusive may be represented as - a word. The least significant four bits of the integer are - represented by the right-most hex digit of the word - representation. Example: the integer 291 = 2^8+2^5+2^1+2^0 = - 256+32+2+1 is represented by the hex word, 00000123. - - If z is an integer, 0 <= z < 2^64, then z = (2^32)x + y where 0 <= - x < 2^32 and 0 <= y < 2^32. Since x and y can be represented as - words X and Y, respectively, z can be represented as the pair of - words (X,Y). - - d. block = 512-bit string. A block (e.g., B) may be represented as a - sequence of 16 words. - -3. Operations on Words - - The following logical operators will be applied to words: - - a. Bitwise logical word operations - - X AND Y = bitwise logical "and" of X and Y. - - X OR Y = bitwise logical "inclusive-or" of X and Y. - - X XOR Y = bitwise logical "exclusive-or" of X and Y. - - NOT X = bitwise logical "complement" of X. - - - - - -Eastlake & Jones Informational [Page 3] - -RFC 3174 US Secure Hash Algorithm 1 (SHA1) September 2001 - - - Example: - - 01101100101110011101001001111011 - XOR 01100101110000010110100110110111 - -------------------------------- - = 00001001011110001011101111001100 - - b. The operation X + Y is defined as follows: words X and Y - represent integers x and y, where 0 <= x < 2^32 and 0 <= y < 2^32. - For positive integers n and m, let n mod m be the remainder upon - dividing n by m. Compute - - z = (x + y) mod 2^32. - - Then 0 <= z < 2^32. Convert z to a word, Z, and define Z = X + - Y. - - c. The circular left shift operation S^n(X), where X is a word and n - is an integer with 0 <= n < 32, is defined by - - S^n(X) = (X << n) OR (X >> 32-n). - - In the above, X << n is obtained as follows: discard the left-most - n bits of X and then pad the result with n zeroes on the right - (the result will still be 32 bits). X >> n is obtained by - discarding the right-most n bits of X and then padding the result - with n zeroes on the left. Thus S^n(X) is equivalent to a - circular shift of X by n positions to the left. - -4. Message Padding - - SHA-1 is used to compute a message digest for a message or data file - that is provided as input. The message or data file should be - considered to be a bit string. The length of the message is the - number of bits in the message (the empty message has length 0). If - the number of bits in a message is a multiple of 8, for compactness - we can represent the message in hex. The purpose of message padding - is to make the total length of a padded message a multiple of 512. - SHA-1 sequentially processes blocks of 512 bits when computing the - message digest. The following specifies how this padding shall be - performed. As a summary, a "1" followed by m "0"s followed by a 64- - bit integer are appended to the end of the message to produce a - padded message of length 512 * n. The 64-bit integer is the length - of the original message. The padded message is then processed by the - SHA-1 as n 512-bit blocks. - - - - - - -Eastlake & Jones Informational [Page 4] - -RFC 3174 US Secure Hash Algorithm 1 (SHA1) September 2001 - - - Suppose a message has length l < 2^64. Before it is input to the - SHA-1, the message is padded on the right as follows: - - a. "1" is appended. Example: if the original message is "01010000", - this is padded to "010100001". - - b. "0"s are appended. The number of "0"s will depend on the original - length of the message. The last 64 bits of the last 512-bit block - are reserved - - for the length l of the original message. - - Example: Suppose the original message is the bit string - - 01100001 01100010 01100011 01100100 01100101. - - After step (a) this gives - - 01100001 01100010 01100011 01100100 01100101 1. - - Since l = 40, the number of bits in the above is 41 and 407 "0"s - are appended, making the total now 448. This gives (in hex) - - 61626364 65800000 00000000 00000000 - 00000000 00000000 00000000 00000000 - 00000000 00000000 00000000 00000000 - 00000000 00000000. - - c. Obtain the 2-word representation of l, the number of bits in the - original message. If l < 2^32 then the first word is all zeroes. - Append these two words to the padded message. - - Example: Suppose the original message is as in (b). Then l = 40 - (note that l is computed before any padding). The two-word - representation of 40 is hex 00000000 00000028. Hence the final - padded message is hex - - 61626364 65800000 00000000 00000000 - 00000000 00000000 00000000 00000000 - 00000000 00000000 00000000 00000000 - 00000000 00000000 00000000 00000028. - - The padded message will contain 16 * n words for some n > 0. - The padded message is regarded as a sequence of n blocks M(1) , - M(2), first characters (or bits) of the message. - - - - - - -Eastlake & Jones Informational [Page 5] - -RFC 3174 US Secure Hash Algorithm 1 (SHA1) September 2001 - - -5. Functions and Constants Used - - A sequence of logical functions f(0), f(1),..., f(79) is used in - SHA-1. Each f(t), 0 <= t <= 79, operates on three 32-bit words B, C, - D and produces a 32-bit word as output. f(t;B,C,D) is defined as - follows: for words B, C, D, - - f(t;B,C,D) = (B AND C) OR ((NOT B) AND D) ( 0 <= t <= 19) - - f(t;B,C,D) = B XOR C XOR D (20 <= t <= 39) - - f(t;B,C,D) = (B AND C) OR (B AND D) OR (C AND D) (40 <= t <= 59) - - f(t;B,C,D) = B XOR C XOR D (60 <= t <= 79). - - A sequence of constant words K(0), K(1), ... , K(79) is used in the - SHA-1. In hex these are given by - - K(t) = 5A827999 ( 0 <= t <= 19) - - K(t) = 6ED9EBA1 (20 <= t <= 39) - - K(t) = 8F1BBCDC (40 <= t <= 59) - - K(t) = CA62C1D6 (60 <= t <= 79). - -6. Computing the Message Digest - - The methods given in 6.1 and 6.2 below yield the same message digest. - Although using method 2 saves sixty-four 32-bit words of storage, it - is likely to lengthen execution time due to the increased complexity - of the address computations for the { W[t] } in step (c). There are - other computation methods which give identical results. - -6.1 Method 1 - - The message digest is computed using the message padded as described - in section 4. The computation is described using two buffers, each - consisting of five 32-bit words, and a sequence of eighty 32-bit - words. The words of the first 5-word buffer are labeled A,B,C,D,E. - The words of the second 5-word buffer are labeled H0, H1, H2, H3, H4. - The words of the 80-word sequence are labeled W(0), W(1),..., W(79). - A single word buffer TEMP is also employed. - - To generate the message digest, the 16-word blocks M(1), M(2),..., - M(n) defined in section 4 are processed in order. The processing of - each M(i) involves 80 steps. - - - - -Eastlake & Jones Informational [Page 6] - -RFC 3174 US Secure Hash Algorithm 1 (SHA1) September 2001 - - - Before processing any blocks, the H's are initialized as follows: in - hex, - - H0 = 67452301 - - H1 = EFCDAB89 - - H2 = 98BADCFE - - H3 = 10325476 - - H4 = C3D2E1F0. - - Now M(1), M(2), ... , M(n) are processed. To process M(i), we - proceed as follows: - - a. Divide M(i) into 16 words W(0), W(1), ... , W(15), where W(0) - is the left-most word. - - b. For t = 16 to 79 let - - W(t) = S^1(W(t-3) XOR W(t-8) XOR W(t-14) XOR W(t-16)). - - c. Let A = H0, B = H1, C = H2, D = H3, E = H4. - - d. For t = 0 to 79 do - - TEMP = S^5(A) + f(t;B,C,D) + E + W(t) + K(t); - - E = D; D = C; C = S^30(B); B = A; A = TEMP; - - e. Let H0 = H0 + A, H1 = H1 + B, H2 = H2 + C, H3 = H3 + D, H4 = H4 - + E. - - After processing M(n), the message digest is the 160-bit string - represented by the 5 words - - H0 H1 H2 H3 H4. - -6.2 Method 2 - - The method above assumes that the sequence W(0), ... , W(79) is - implemented as an array of eighty 32-bit words. This is efficient - from the standpoint of minimization of execution time, since the - addresses of W(t-3), ... ,W(t-16) in step (b) are easily computed. - If space is at a premium, an alternative is to regard { W(t) } as a - - - - - -Eastlake & Jones Informational [Page 7] - -RFC 3174 US Secure Hash Algorithm 1 (SHA1) September 2001 - - - circular queue, which may be implemented using an array of sixteen - 32-bit words W[0], ... W[15]. In this case, in hex let - - MASK = 0000000F. Then processing of M(i) is as follows: - - a. Divide M(i) into 16 words W[0], ... , W[15], where W[0] is the - left-most word. - - b. Let A = H0, B = H1, C = H2, D = H3, E = H4. - - c. For t = 0 to 79 do - - s = t AND MASK; - - if (t >= 16) W[s] = S^1(W[(s + 13) AND MASK] XOR W[(s + 8) AND - MASK] XOR W[(s + 2) AND MASK] XOR W[s]); - - TEMP = S^5(A) + f(t;B,C,D) + E + W[s] + K(t); - - E = D; D = C; C = S^30(B); B = A; A = TEMP; - - d. Let H0 = H0 + A, H1 = H1 + B, H2 = H2 + C, H3 = H3 + D, H4 = H4 - + E. - -7. C Code - - Below is a demonstration implementation of SHA-1 in C. Section 7.1 - contains the header file, 7.2 the C code, and 7.3 a test driver. - -7.1 .h file - -/* - * sha1.h - * - * Description: - * This is the header file for code which implements the Secure - * Hashing Algorithm 1 as defined in FIPS PUB 180-1 published - * April 17, 1995. - * - * Many of the variable names in this code, especially the - * single character names, were used because those were the names - * used in the publication. - * - * Please read the file sha1.c for more information. - * - */ - - - - - -Eastlake & Jones Informational [Page 8] - -RFC 3174 US Secure Hash Algorithm 1 (SHA1) September 2001 - - -#ifndef _SHA1_H_ -#define _SHA1_H_ - -#include -/* - * If you do not have the ISO standard stdint.h header file, then you - * must typdef the following: - * name meaning - * uint32_t unsigned 32 bit integer - * uint8_t unsigned 8 bit integer (i.e., unsigned char) - * int_least16_t integer of >= 16 bits - * - */ - -#ifndef _SHA_enum_ -#define _SHA_enum_ -enum -{ - shaSuccess = 0, - shaNull, /* Null pointer parameter */ - shaInputTooLong, /* input data too long */ - shaStateError /* called Input after Result */ -}; -#endif -#define SHA1HashSize 20 - -/* - * This structure will hold context information for the SHA-1 - * hashing operation - */ -typedef struct SHA1Context -{ - uint32_t Intermediate_Hash[SHA1HashSize/4]; /* Message Digest */ - - uint32_t Length_Low; /* Message length in bits */ - uint32_t Length_High; /* Message length in bits */ - - /* Index into message block array */ - int_least16_t Message_Block_Index; - uint8_t Message_Block[64]; /* 512-bit message blocks */ - - int Computed; /* Is the digest computed? */ - int Corrupted; /* Is the message digest corrupted? */ -} SHA1Context; - -/* - * Function Prototypes - */ - - - -Eastlake & Jones Informational [Page 9] - -RFC 3174 US Secure Hash Algorithm 1 (SHA1) September 2001 - - -int SHA1Reset( SHA1Context *); -int SHA1Input( SHA1Context *, - const uint8_t *, - unsigned int); -int SHA1Result( SHA1Context *, - uint8_t Message_Digest[SHA1HashSize]); - -#endif - -7.2 .c file - -/* - * sha1.c - * - * Description: - * This file implements the Secure Hashing Algorithm 1 as - * defined in FIPS PUB 180-1 published April 17, 1995. - * - * The SHA-1, produces a 160-bit message digest for a given - * data stream. It should take about 2**n steps to find a - * message with the same digest as a given message and - * 2**(n/2) to find any two messages with the same digest, - * when n is the digest size in bits. Therefore, this - * algorithm can serve as a means of providing a - * "fingerprint" for a message. - * - * Portability Issues: - * SHA-1 is defined in terms of 32-bit "words". This code - * uses (included via "sha1.h" to define 32 and 8 - * bit unsigned integer types. If your C compiler does not - * support 32 bit unsigned integers, this code is not - * appropriate. - * - * Caveats: - * SHA-1 is designed to work with messages less than 2^64 bits - * long. Although SHA-1 allows a message digest to be generated - * for messages of any number of bits less than 2^64, this - * implementation only works with messages with a length that is - * a multiple of the size of an 8-bit character. - * - */ - - - - - - - - - - -Eastlake & Jones Informational [Page 10] - -RFC 3174 US Secure Hash Algorithm 1 (SHA1) September 2001 - - -#include "sha1.h" - -/* - * Define the SHA1 circular left shift macro - */ -#define SHA1CircularShift(bits,word) \ - (((word) << (bits)) | ((word) >> (32-(bits)))) - -/* Local Function Prototyptes */ -void SHA1PadMessage(SHA1Context *); -void SHA1ProcessMessageBlock(SHA1Context *); - -/* - * SHA1Reset - * - * Description: - * This function will initialize the SHA1Context in preparation - * for computing a new SHA1 message digest. - * - * Parameters: - * context: [in/out] - * The context to reset. - * - * Returns: - * sha Error Code. - * - */ -int SHA1Reset(SHA1Context *context) -{ - if (!context) - { - return shaNull; - } - - context->Length_Low = 0; - context->Length_High = 0; - context->Message_Block_Index = 0; - - context->Intermediate_Hash[0] = 0x67452301; - context->Intermediate_Hash[1] = 0xEFCDAB89; - context->Intermediate_Hash[2] = 0x98BADCFE; - context->Intermediate_Hash[3] = 0x10325476; - context->Intermediate_Hash[4] = 0xC3D2E1F0; - - context->Computed = 0; - context->Corrupted = 0; - - - - - -Eastlake & Jones Informational [Page 11] - -RFC 3174 US Secure Hash Algorithm 1 (SHA1) September 2001 - - - return shaSuccess; -} - -/* - * SHA1Result - * - * Description: - * This function will return the 160-bit message digest into the - * Message_Digest array provided by the caller. - * NOTE: The first octet of hash is stored in the 0th element, - * the last octet of hash in the 19th element. - * - * Parameters: - * context: [in/out] - * The context to use to calculate the SHA-1 hash. - * Message_Digest: [out] - * Where the digest is returned. - * - * Returns: - * sha Error Code. - * - */ -int SHA1Result( SHA1Context *context, - uint8_t Message_Digest[SHA1HashSize]) -{ - int i; - - if (!context || !Message_Digest) - { - return shaNull; - } - - if (context->Corrupted) - { - return context->Corrupted; - } - - if (!context->Computed) - { - SHA1PadMessage(context); - for(i=0; i<64; ++i) - { - /* message may be sensitive, clear it out */ - context->Message_Block[i] = 0; - } - context->Length_Low = 0; /* and clear length */ - context->Length_High = 0; - context->Computed = 1; - - - -Eastlake & Jones Informational [Page 12] - -RFC 3174 US Secure Hash Algorithm 1 (SHA1) September 2001 - - - } - - for(i = 0; i < SHA1HashSize; ++i) - { - Message_Digest[i] = context->Intermediate_Hash[i>>2] - >> 8 * ( 3 - ( i & 0x03 ) ); - } - - return shaSuccess; -} - -/* - * SHA1Input - * - * Description: - * This function accepts an array of octets as the next portion - * of the message. - * - * Parameters: - * context: [in/out] - * The SHA context to update - * message_array: [in] - * An array of characters representing the next portion of - * the message. - * length: [in] - * The length of the message in message_array - * - * Returns: - * sha Error Code. - * - */ -int SHA1Input( SHA1Context *context, - const uint8_t *message_array, - unsigned length) -{ - if (!length) - { - return shaSuccess; - } - - if (!context || !message_array) - { - return shaNull; - } - - if (context->Computed) - { - context->Corrupted = shaStateError; - - - -Eastlake & Jones Informational [Page 13] - -RFC 3174 US Secure Hash Algorithm 1 (SHA1) September 2001 - - - return shaStateError; - } - - if (context->Corrupted) - { - return context->Corrupted; - } - while(length-- && !context->Corrupted) - { - context->Message_Block[context->Message_Block_Index++] = - (*message_array & 0xFF); - - context->Length_Low += 8; - if (context->Length_Low == 0) - { - context->Length_High++; - if (context->Length_High == 0) - { - /* Message is too long */ - context->Corrupted = 1; - } - } - - if (context->Message_Block_Index == 64) - { - SHA1ProcessMessageBlock(context); - } - - message_array++; - } - - return shaSuccess; -} - -/* - * SHA1ProcessMessageBlock - * - * Description: - * This function will process the next 512 bits of the message - * stored in the Message_Block array. - * - * Parameters: - * None. - * - * Returns: - * Nothing. - * - * Comments: - - - -Eastlake & Jones Informational [Page 14] - -RFC 3174 US Secure Hash Algorithm 1 (SHA1) September 2001 - - - * Many of the variable names in this code, especially the - * single character names, were used because those were the - * names used in the publication. - * - * - */ -void SHA1ProcessMessageBlock(SHA1Context *context) -{ - const uint32_t K[] = { /* Constants defined in SHA-1 */ - 0x5A827999, - 0x6ED9EBA1, - 0x8F1BBCDC, - 0xCA62C1D6 - }; - int t; /* Loop counter */ - uint32_t temp; /* Temporary word value */ - uint32_t W[80]; /* Word sequence */ - uint32_t A, B, C, D, E; /* Word buffers */ - - /* - * Initialize the first 16 words in the array W - */ - for(t = 0; t < 16; t++) - { - W[t] = context->Message_Block[t * 4] << 24; - W[t] |= context->Message_Block[t * 4 + 1] << 16; - W[t] |= context->Message_Block[t * 4 + 2] << 8; - W[t] |= context->Message_Block[t * 4 + 3]; - } - - for(t = 16; t < 80; t++) - { - W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); - } - - A = context->Intermediate_Hash[0]; - B = context->Intermediate_Hash[1]; - C = context->Intermediate_Hash[2]; - D = context->Intermediate_Hash[3]; - E = context->Intermediate_Hash[4]; - - for(t = 0; t < 20; t++) - { - temp = SHA1CircularShift(5,A) + - ((B & C) | ((~B) & D)) + E + W[t] + K[0]; - E = D; - D = C; - C = SHA1CircularShift(30,B); - - - -Eastlake & Jones Informational [Page 15] - -RFC 3174 US Secure Hash Algorithm 1 (SHA1) September 2001 - - - B = A; - A = temp; - } - - for(t = 20; t < 40; t++) - { - temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1]; - E = D; - D = C; - C = SHA1CircularShift(30,B); - B = A; - A = temp; - } - - for(t = 40; t < 60; t++) - { - temp = SHA1CircularShift(5,A) + - ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]; - E = D; - D = C; - C = SHA1CircularShift(30,B); - B = A; - A = temp; - } - - for(t = 60; t < 80; t++) - { - temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3]; - E = D; - D = C; - C = SHA1CircularShift(30,B); - B = A; - A = temp; - } - - context->Intermediate_Hash[0] += A; - context->Intermediate_Hash[1] += B; - context->Intermediate_Hash[2] += C; - context->Intermediate_Hash[3] += D; - context->Intermediate_Hash[4] += E; - - context->Message_Block_Index = 0; -} - - -/* - * SHA1PadMessage - * - - - -Eastlake & Jones Informational [Page 16] - -RFC 3174 US Secure Hash Algorithm 1 (SHA1) September 2001 - - - * Description: - * According to the standard, the message must be padded to an even - * 512 bits. The first padding bit must be a '1'. The last 64 - * bits represent the length of the original message. All bits in - * between should be 0. This function will pad the message - * according to those rules by filling the Message_Block array - * accordingly. It will also call the ProcessMessageBlock function - * provided appropriately. When it returns, it can be assumed that - * the message digest has been computed. - * - * Parameters: - * context: [in/out] - * The context to pad - * ProcessMessageBlock: [in] - * The appropriate SHA*ProcessMessageBlock function - * Returns: - * Nothing. - * - */ - -void SHA1PadMessage(SHA1Context *context) -{ - /* - * Check to see if the current message block is too small to hold - * the initial padding bits and length. If so, we will pad the - * block, process it, and then continue padding into a second - * block. - */ - if (context->Message_Block_Index > 55) - { - context->Message_Block[context->Message_Block_Index++] = 0x80; - while(context->Message_Block_Index < 64) - { - context->Message_Block[context->Message_Block_Index++] = 0; - } - - SHA1ProcessMessageBlock(context); - - while(context->Message_Block_Index < 56) - { - context->Message_Block[context->Message_Block_Index++] = 0; - } - } - else - { - context->Message_Block[context->Message_Block_Index++] = 0x80; - while(context->Message_Block_Index < 56) - { - - - -Eastlake & Jones Informational [Page 17] - -RFC 3174 US Secure Hash Algorithm 1 (SHA1) September 2001 - - - context->Message_Block[context->Message_Block_Index++] = 0; - } - } - - /* - * Store the message length as the last 8 octets - */ - context->Message_Block[56] = context->Length_High >> 24; - context->Message_Block[57] = context->Length_High >> 16; - context->Message_Block[58] = context->Length_High >> 8; - context->Message_Block[59] = context->Length_High; - context->Message_Block[60] = context->Length_Low >> 24; - context->Message_Block[61] = context->Length_Low >> 16; - context->Message_Block[62] = context->Length_Low >> 8; - context->Message_Block[63] = context->Length_Low; - - SHA1ProcessMessageBlock(context); -} - -7.3 Test Driver - - The following code is a main program test driver to exercise the code - in sha1.c. - -/* - * sha1test.c - * - * Description: - * This file will exercise the SHA-1 code performing the three - * tests documented in FIPS PUB 180-1 plus one which calls - * SHA1Input with an exact multiple of 512 bits, plus a few - * error test checks. - * - * Portability Issues: - * None. - * - */ - -#include -#include -#include -#include "sha1.h" - -/* - * Define patterns for testing - */ -#define TEST1 "abc" -#define TEST2a "abcdbcdecdefdefgefghfghighijhi" - - - -Eastlake & Jones Informational [Page 18] - -RFC 3174 US Secure Hash Algorithm 1 (SHA1) September 2001 - - -#define TEST2b "jkijkljklmklmnlmnomnopnopq" -#define TEST2 TEST2a TEST2b -#define TEST3 "a" -#define TEST4a "01234567012345670123456701234567" -#define TEST4b "01234567012345670123456701234567" - /* an exact multiple of 512 bits */ -#define TEST4 TEST4a TEST4b -char *testarray[4] = -{ - TEST1, - TEST2, - TEST3, - TEST4 -}; -long int repeatcount[4] = { 1, 1, 1000000, 10 }; -char *resultarray[4] = -{ - "A9 99 3E 36 47 06 81 6A BA 3E 25 71 78 50 C2 6C 9C D0 D8 9D", - "84 98 3E 44 1C 3B D2 6E BA AE 4A A1 F9 51 29 E5 E5 46 70 F1", - "34 AA 97 3C D4 C4 DA A4 F6 1E EB 2B DB AD 27 31 65 34 01 6F", - "DE A3 56 A2 CD DD 90 C7 A7 EC ED C5 EB B5 63 93 4F 46 04 52" -}; - -int main() -{ - SHA1Context sha; - int i, j, err; - uint8_t Message_Digest[20]; - - /* - * Perform SHA-1 tests - */ - for(j = 0; j < 4; ++j) - { - printf( "\nTest %d: %d, '%s'\n", - j+1, - repeatcount[j], - testarray[j]); - - err = SHA1Reset(&sha); - if (err) - { - fprintf(stderr, "SHA1Reset Error %d.\n", err ); - break; /* out of for j loop */ - } - - for(i = 0; i < repeatcount[j]; ++i) - { - - - -Eastlake & Jones Informational [Page 19] - -RFC 3174 US Secure Hash Algorithm 1 (SHA1) September 2001 - - - err = SHA1Input(&sha, - (const unsigned char *) testarray[j], - strlen(testarray[j])); - if (err) - { - fprintf(stderr, "SHA1Input Error %d.\n", err ); - break; /* out of for i loop */ - } - } - - err = SHA1Result(&sha, Message_Digest); - if (err) - { - fprintf(stderr, - "SHA1Result Error %d, could not compute message digest.\n", - err ); - } - else - { - printf("\t"); - for(i = 0; i < 20 ; ++i) - { - printf("%02X ", Message_Digest[i]); - } - printf("\n"); - } - printf("Should match:\n"); - printf("\t%s\n", resultarray[j]); - } - - /* Test some error returns */ - err = SHA1Input(&sha,(const unsigned char *) testarray[1], 1); - printf ("\nError %d. Should be %d.\n", err, shaStateError ); - err = SHA1Reset(0); - printf ("\nError %d. Should be %d.\n", err, shaNull ); - return 0; -} - -8. Security Considerations - - This document is intended to provide convenient open source access by - the Internet community to the United States of America Federal - Information Processing Standard Secure Hash Function SHA-1 [FIPS - 180-1]. No independent assertion of the security of this hash - function by the authors for any particular use is intended. - - - - - - -Eastlake & Jones Informational [Page 20] - -RFC 3174 US Secure Hash Algorithm 1 (SHA1) September 2001 - - -References - - [FIPS 180-1] "Secure Hash Standard", United States of American, - National Institute of Science and Technology, Federal - Information Processing Standard (FIPS) 180-1, April - 1993. - - [MD4] "The MD4 Message Digest Algorithm," Advances in - Cryptology - CRYPTO '90 Proceedings, Springer-Verlag, - 1991, pp. 303-311. - - [RFC 1320] Rivest, R., "The MD4 Message-Digest Algorithm", RFC - 1320, April 1992. - - [RFC 1321] Rivest, R., "The MD5 Message-Digest Algorithm", RFC - 1321, April 1992. - - [RFC 1750] Eastlake, D., Crocker, S. and J. Schiller, "Randomness - Requirements for Security", RFC 1750, December 1994. - -Authors' Addresses - - Donald E. Eastlake, 3rd - Motorola - 155 Beaver Street - Milford, MA 01757 USA - - Phone: +1 508-634-2066 (h) - +1 508-261-5434 (w) - Fax: +1 508-261-4777 - EMail: Donald.Eastlake@motorola.com - - - Paul E. Jones - Cisco Systems, Inc. - 7025 Kit Creek Road - Research Triangle Park, NC 27709 USA - - Phone: +1 919 392 6948 - EMail: paulej@packetizer.com - - - - - - - - - - - -Eastlake & Jones Informational [Page 21] - -RFC 3174 US Secure Hash Algorithm 1 (SHA1) September 2001 - - -Full Copyright Statement - - Copyright (C) The Internet Society (2001). All Rights Reserved. - - This document and translations of it may be copied and furnished to - others, and derivative works that comment on or otherwise explain it - or assist in its implementation may be prepared, copied, published - and distributed, in whole or in part, without restriction of any - kind, provided that the above copyright notice and this paragraph are - included on all such copies and derivative works. However, this - document itself may not be modified in any way, such as by removing - the copyright notice or references to the Internet Society or other - Internet organizations, except as needed for the purpose of - developing Internet standards in which case the procedures for - copyrights defined in the Internet Standards process must be - followed, or as required to translate it into languages other than - English. - - The limited permissions granted above are perpetual and will not be - revoked by the Internet Society or its successors or assigns. - - This document and the information contained herein is provided on an - "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING - TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING - BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION - HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - -Acknowledgement - - Funding for the RFC Editor function is currently provided by the - Internet Society. - - - - - - - - - - - - - - - - - - - -Eastlake & Jones Informational [Page 22] - From 92775076e967ea90d6d425a0d70873f3e735a642 Mon Sep 17 00:00:00 2001 From: Ken Murchison Date: Mon, 7 Nov 2016 11:48:54 -0500 Subject: [PATCH 257/796] mechanisms.html: added G2, GSS-SPNEGO, SCRAM --- doc/mechanisms.html | 86 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 84 insertions(+), 2 deletions(-) diff --git a/doc/mechanisms.html b/doc/mechanisms.html index 4f7d4393..a38ad52c 100644 --- a/doc/mechanisms.html +++ b/doc/mechanisms.html @@ -15,7 +15,7 @@

    SASL Mechanism Properties/Features


    MAX
    SSF SECURITY PROPERTIES -FEATURES +FEATURES @@ -30,6 +30,8 @@

    SASL Mechanism Properties/Features

    SRV FIRST
    SRV LAST
    PROXY
    +
    BIND
    +
    HTTP
    @@ -46,6 +48,8 @@

    SASL Mechanism Properties/Features




    +

    +

    @@ -62,6 +66,8 @@

    SASL Mechanism Properties/Features

    X


    +

    +

    @@ -78,6 +84,8 @@

    SASL Mechanism Properties/Features

    initial auth
    X
    X
    +

    +
    X
    @@ -94,6 +102,26 @@

    SASL Mechanism Properties/Features



    X
    +

    +

    + + + +G2 +
    56
    +
    X
    +
    X
    +

    +

    +
    X
    +

    +
    X
    +
    X
    +

    +
    X
    +
    X
    +
    X
    +

    @@ -104,12 +132,32 @@

    SASL Mechanism Properties/Features



    X
    +
    X
    +
    X
    +
    X
    +

    +

    +
    X
    +

    +

    + + + +GSS-SPNEGO +
    56
    +
    X
    +
    X

    +

    +
    X
    +
    X
    X
    X


    X
    +

    +
    X
    @@ -126,6 +174,8 @@

    SASL Mechanism Properties/Features

    X

    X
    +

    +

    @@ -142,6 +192,8 @@

    SASL Mechanism Properties/Features

    X


    +

    +

    @@ -158,6 +210,8 @@

    SASL Mechanism Properties/Features




    +

    +
    X
    @@ -174,10 +228,12 @@

    SASL Mechanism Properties/Features



    X
    +

    +

    -PASSDSS-3DES-1 +PASSDSS
    112
    X
    X
    @@ -190,6 +246,8 @@

    SASL Mechanism Properties/Features



    X
    +

    +

    @@ -206,6 +264,8 @@

    SASL Mechanism Properties/Features



    X
    +

    +

    + +SCRAM +
    0
    +
    X
    +
    X
    +
    +
    +
    X
    +

    +
    X
    +
    X
    +

    +
    X
    +
    X
    +
    X
    +
    ?
    + + SRP
    128
    @@ -254,6 +332,8 @@

    SASL Mechanism Properties/Features


    X
    X
    +

    +

    @@ -278,6 +358,8 @@

    Understanding this table:

  • SRVFIRST - The server must send first in this mechanism.
  • SRVLAST - This mechanism supports server-send-last configurations.
  • PROXY - This mechanism supports proxy authentication.
  • +
  • BIND - This mechanism supports channel binding.
  • +
  • HTTP - This mechanism has a profile for HTTP.
  • From 41c3e7ab8ceb3e9d69fa004f4ccf7a31030c5bdf Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Mon, 7 Nov 2016 14:27:03 +0100 Subject: [PATCH 258/796] Add OpenSSL 1.1.0 support in saslauthd Author: Tomas Mraz --- plugins/ntlm.c | 6 ++--- plugins/otp.c | 12 ++++----- saslauthd/lak.c | 66 ++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 64 insertions(+), 20 deletions(-) diff --git a/plugins/ntlm.c b/plugins/ntlm.c index b5630d8c..b2d1ed55 100644 --- a/plugins/ntlm.c +++ b/plugins/ntlm.c @@ -424,8 +424,8 @@ static HMAC_CTX *_plug_HMAC_CTX_new(const sasl_utils_t *utils) #if OPENSSL_VERSION_NUMBER >= 0x10100000L return HMAC_CTX_new(); #else - return utils->malloc(sizeof(EVP_MD_CTX)); -#endif + return utils->malloc(sizeof(HMAC_CTX)); +#endif } static void _plug_HMAC_CTX_free(HMAC_CTX *ctx, const sasl_utils_t *utils) @@ -437,7 +437,7 @@ static void _plug_HMAC_CTX_free(HMAC_CTX *ctx, const sasl_utils_t *utils) #else HMAC_cleanup(ctx); utils->free(ctx); -#endif +#endif } static unsigned char *V2(unsigned char *V2, sasl_secret_t *passwd, diff --git a/plugins/otp.c b/plugins/otp.c index 07a58f57..63cf0172 100644 --- a/plugins/otp.c +++ b/plugins/otp.c @@ -104,7 +104,7 @@ static EVP_MD_CTX *_plug_EVP_MD_CTX_new(const sasl_utils_t *utils) return EVP_MD_CTX_new(); #else return utils->malloc(sizeof(EVP_MD_CTX)); -#endif +#endif } static void _plug_EVP_MD_CTX_free(EVP_MD_CTX *ctx, const sasl_utils_t *utils) @@ -115,7 +115,7 @@ static void _plug_EVP_MD_CTX_free(EVP_MD_CTX *ctx, const sasl_utils_t *utils) EVP_MD_CTX_free(ctx); #else utils->free(ctx); -#endif +#endif } /* Convert the binary data into ASCII hex */ @@ -180,13 +180,13 @@ static int generate_otp(const sasl_utils_t *utils, "OTP algorithm %s is not available", alg->evp_name); return SASL_FAIL; } - + if ((mdctx = _plug_EVP_MD_CTX_new(utils)) == NULL) { SETERROR(utils, "cannot allocate MD CTX"); r = SASL_NOMEM; goto done; } - + if ((key = utils->malloc(strlen(seed) + secret_len + 1)) == NULL) { SETERROR(utils, "cannot allocate OTP key"); r = SASL_NOMEM; @@ -201,10 +201,10 @@ static int generate_otp(const sasl_utils_t *utils, while (seq-- > 0) otp_hash(md, (char *) otp, OTP_HASH_SIZE, otp, alg->swab, mdctx); - done: +done: if (key) utils->free(key); if (mdctx) _plug_EVP_MD_CTX_free(mdctx, utils); - + return r; } diff --git a/saslauthd/lak.c b/saslauthd/lak.c index d752f7b7..2a2772a7 100644 --- a/saslauthd/lak.c +++ b/saslauthd/lak.c @@ -61,6 +61,35 @@ #include #include "lak.h" +#if OPENSSL_VERSION_NUMBER < 0x10100000L +static EVP_MD_CTX *EVP_MD_CTX_new(void) +{ + return EVP_MD_CTX_create(); +} +static void EVP_MD_CTX_free(EVP_MD_CTX *ctx) +{ + if (ctx == NULL) + return; + + EVP_MD_CTX_destroy(ctx); +} + +static EVP_ENCODE_CTX *EVP_ENCODE_CTX_new(void) +{ + EVP_ENCODE_CTX *ctx = OPENSSL_malloc(sizeof(*ctx)); + + if (ctx != NULL) { + memset(ctx, 0, sizeof(*ctx)); + } + return ctx; +} +static void EVP_ENCODE_CTX_free(EVP_ENCODE_CTX *ctx) +{ + OPENSSL_free(ctx); + return; +} +#endif + typedef struct lak_auth_method { int method; int (*check) (LAK *lak, const char *user, const char *service, const char *realm, const char *password) ; @@ -1720,20 +1749,28 @@ static int lak_base64_decode( int rc, i, tlen = 0; char *text; - EVP_ENCODE_CTX EVP_ctx; + EVP_ENCODE_CTX *enc_ctx = EVP_ENCODE_CTX_new(); + + if (enc_ctx == NULL) + return LAK_NOMEM; text = (char *)malloc(((strlen(src)+3)/4 * 3) + 1); - if (text == NULL) + if (text == NULL) { + EVP_ENCODE_CTX_free(enc_ctx); return LAK_NOMEM; + } - EVP_DecodeInit(&EVP_ctx); - rc = EVP_DecodeUpdate(&EVP_ctx, (unsigned char *) text, &i, (const unsigned char *)src, strlen(src)); + EVP_DecodeInit(enc_ctx); + rc = EVP_DecodeUpdate(enc_ctx, (unsigned char *) text, &i, (const unsigned char *)src, strlen(src)); if (rc < 0) { + EVP_ENCODE_CTX_free(enc_ctx); free(text); return LAK_FAIL; } tlen += i; - EVP_DecodeFinal(&EVP_ctx, (unsigned char *) text, &i); + EVP_DecodeFinal(enc_ctx, (unsigned char *) text, &i); + + EVP_ENCODE_CTX_free(enc_ctx); *ret = text; if (rlen != NULL) @@ -1749,7 +1786,7 @@ static int lak_check_hashed( { int rc, clen; LAK_HASH_ROCK *hrock = (LAK_HASH_ROCK *) rock; - EVP_MD_CTX mdctx; + EVP_MD_CTX *mdctx; const EVP_MD *md; unsigned char digest[EVP_MAX_MD_SIZE]; char *cred; @@ -1758,17 +1795,24 @@ static int lak_check_hashed( if (!md) return LAK_FAIL; + mdctx = EVP_MD_CTX_new(); + if (!mdctx) + return LAK_NOMEM; + rc = lak_base64_decode(hash, &cred, &clen); - if (rc != LAK_OK) + if (rc != LAK_OK) { + EVP_MD_CTX_free(mdctx); return rc; + } - EVP_DigestInit(&mdctx, md); - EVP_DigestUpdate(&mdctx, passwd, strlen(passwd)); + EVP_DigestInit(mdctx, md); + EVP_DigestUpdate(mdctx, passwd, strlen(passwd)); if (hrock->salted) { - EVP_DigestUpdate(&mdctx, &cred[EVP_MD_size(md)], + EVP_DigestUpdate(mdctx, &cred[EVP_MD_size(md)], clen - EVP_MD_size(md)); } - EVP_DigestFinal(&mdctx, digest, NULL); + EVP_DigestFinal(mdctx, digest, NULL); + EVP_MD_CTX_free(mdctx); rc = memcmp((char *)cred, (char *)digest, EVP_MD_size(md)); free(cred); From a8eb4f7caf8c8537aa2e8b497368a8924ed63485 Mon Sep 17 00:00:00 2001 From: Ken Murchison Date: Mon, 7 Nov 2016 14:03:14 -0500 Subject: [PATCH 259/796] lak.c: replacement OpenSSL functions should be inside #if HAVE_OPENSSL --- saslauthd/lak.c | 44 +++++++++++++++----------------------------- 1 file changed, 15 insertions(+), 29 deletions(-) diff --git a/saslauthd/lak.c b/saslauthd/lak.c index 2a2772a7..53ed5ab9 100644 --- a/saslauthd/lak.c +++ b/saslauthd/lak.c @@ -61,35 +61,6 @@ #include #include "lak.h" -#if OPENSSL_VERSION_NUMBER < 0x10100000L -static EVP_MD_CTX *EVP_MD_CTX_new(void) -{ - return EVP_MD_CTX_create(); -} -static void EVP_MD_CTX_free(EVP_MD_CTX *ctx) -{ - if (ctx == NULL) - return; - - EVP_MD_CTX_destroy(ctx); -} - -static EVP_ENCODE_CTX *EVP_ENCODE_CTX_new(void) -{ - EVP_ENCODE_CTX *ctx = OPENSSL_malloc(sizeof(*ctx)); - - if (ctx != NULL) { - memset(ctx, 0, sizeof(*ctx)); - } - return ctx; -} -static void EVP_ENCODE_CTX_free(EVP_ENCODE_CTX *ctx) -{ - OPENSSL_free(ctx); - return; -} -#endif - typedef struct lak_auth_method { int method; int (*check) (LAK *lak, const char *user, const char *service, const char *realm, const char *password) ; @@ -1741,6 +1712,21 @@ static int lak_check_password( #ifdef HAVE_OPENSSL +#if OPENSSL_VERSION_NUMBER < 0x10100000L +#define EVP_MD_CTX_new() EVP_MD_CTX_create() +#define EVP_MD_CTX_free(ctx) EVP_MD_CTX_destroy((ctx)) + +static EVP_ENCODE_CTX *EVP_ENCODE_CTX_new(void) +{ + return OPENSSL_zalloc(sizeof(EVP_ENCODE_CTX)); +} + +static void EVP_ENCODE_CTX_free(EVP_ENCODE_CTX *ctx) +{ + OPENSSL_free(ctx); +} +#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */ + static int lak_base64_decode( const char *src, char **ret, From d6a3736d1f796c69aae455278ed7a980b0442528 Mon Sep 17 00:00:00 2001 From: Nicola Nye Date: Tue, 8 Nov 2016 11:18:37 +1100 Subject: [PATCH 260/796] [Docs] Updating mechanism list and table SRP, G2, PASSDSS, GSS-SPEGNO Added Bind/http to features. --- docsrc/sasl/authentication_mechanisms.rst | 135 +++++++++++++--------- 1 file changed, 83 insertions(+), 52 deletions(-) diff --git a/docsrc/sasl/authentication_mechanisms.rst b/docsrc/sasl/authentication_mechanisms.rst index ebf8a37e..c32bab92 100644 --- a/docsrc/sasl/authentication_mechanisms.rst +++ b/docsrc/sasl/authentication_mechanisms.rst @@ -1,13 +1,11 @@ .. _authentication_mechanisms: +========================= Authentication Mechanisms ========================= -EXTERNAL --------- - -.. todo:: - Content needed here +Mechanisms +========== ANONYMOUS --------- @@ -15,36 +13,33 @@ ANONYMOUS .. todo:: Content needed here -PLAIN ------ +CRAM-MD5 +-------- .. todo:: Content needed here -LOGIN ------ + +DIGEST-MD5 +---------- .. todo:: Content needed here -CRAM-MD5 +EXTERNAL -------- .. todo:: Content needed here -DIGEST-MD5 ----------- - -.. todo:: - Content needed here -SCRAM-SHA-1 ------------ +G2 +----- .. todo:: Content needed here + GSSAPI ------ @@ -53,14 +48,21 @@ Not sure how to get GSSAPI going? Check out our :ref:`GSSAPI configuration guide .. todo:: Content needed here -GS2-KRB5 --------- + +GSS-SPEGNO +---------- .. todo:: Content needed here -GS2-IAKERB ----------- +KERBEROS_V4 +----------- + +.. todo:: + Content needed here + +LOGIN +----- .. todo:: Content needed here @@ -71,19 +73,31 @@ NTLM .. todo:: Content needed here -SRP +OTP --- .. todo:: Content needed here -PSSDSS ------- +PASSDSS +------- .. todo:: Content needed here -OTP +PLAIN +----- + +.. todo:: + Content needed here + +SCRAM +----- + +.. todo:: + Content needed here + +SRP --- .. todo:: @@ -95,36 +109,51 @@ Non-SASL Authentication .. todo:: Content needed here +---- + +Summary +======= + This table shows what security flags and features are supported by each of the mechanisms provided by the Cyrus SASL Library. -+-------------+---------+----------------------------------------------------------------+---------------------------------------------+ -| | | Security Properties | Features | -+-------------+ +----------------------------------------------------------------+---------------------------------------------+ -| | MAX SSF | NOPLAIN | NOACTIVE | NODICT | FORWARD | NOANON | CRED | MUTUAL | CLT FIRST | SRV FIRST | SRV LAST | PROXY | -+-------------+---------+---------+----------+--------+---------+--------+------+--------+-----------+--------------+----------+-------+ -| ANONYMOUS | 0 | X | | | | | | | X | | | | -+-------------+---------+---------+----------+--------+---------+--------+------+--------+-----------+--------------+----------+-------+ -| CRAM-MD5 | 0 | X | | | | X | | | | X | | | -+-------------+---------+---------+----------+--------+---------+--------+------+--------+-----------+--------------+----------+-------+ -| DIGEST-MD5 | 128 | X | | | | X | | X | reauth | initial auth | X | X | -+-------------+---------+---------+----------+--------+---------+--------+------+--------+-----------+--------------+----------+-------+ -| EXTERNAL | 0 | X | | X | | X | | | X | | | X | -+-------------+---------+---------+----------+--------+---------+--------+------+--------+-----------+--------------+----------+-------+ -| GSSAPI | 56 | X | X | | | X | | X | X | | | X | -+-------------+---------+---------+----------+--------+---------+--------+------+--------+-----------+--------------+----------+-------+ -| KERBEROS_V4 | 56 | X | X | | | X | | X | | X | | X | -+-------------+---------+---------+----------+--------+---------+--------+------+--------+-----------+--------------+----------+-------+ -| LOGIN | 0 | | | | | X | | | | X | | | -+-------------+---------+---------+----------+--------+---------+--------+------+--------+-----------+--------------+----------+-------+ -| NTLM | 0 | X | | | | X | | | X | | | | -+-------------+---------+---------+----------+--------+---------+--------+------+--------+-----------+--------------+----------+-------+ -| OTP | 0 | X | | | X | X | | | X | | | X | -+-------------+---------+---------+----------+--------+---------+--------+------+--------+-----------+--------------+----------+-------+ -| PLAIN | 0 | | | | | X | | | X | | | X | -+-------------+---------+---------+----------+--------+---------+--------+------+--------+-----------+--------------+----------+-------+ -| SRP | 128 | X | X | X | X | X | | X | X | | X | X | -+-------------+---------+---------+----------+--------+---------+--------+------+--------+-----------+--------------+----------+-------+ ++-------------+---------+----------------------------------------------------------------+-----------------------------------------------------------+ +| | MAX SSF | SECURITY PROPERTIES | FEATURES | ++-------------+ +----------------------------------------------------------------+-----------------------------------------------------------+ +| | | NOPLAIN | NOACTIVE | NODICT | FORWARD | NOANON | CRED | MUTUAL | CLT FIRST | SRV FIRST | SRV LAST | PROXY | BIND | HTTP | ++-------------+---------+---------+----------+--------+---------+--------+------+--------+-----------+--------------+----------+-------+------+------+ +| ANONYMOUS | 0 | X | | | | | | | X | | | | | | ++-------------+---------+---------+----------+--------+---------+--------+------+--------+-----------+--------------+----------+-------+------+------+ +| CRAM-MD5 | 0 | X | | | | X | | | | X | | | | | ++-------------+---------+---------+----------+--------+---------+--------+------+--------+-----------+--------------+----------+-------+------+------+ +| DIGEST-MD5 | 128 | X | | | | X | | X | reauth | initial auth | X | X | | X | ++-------------+---------+---------+----------+--------+---------+--------+------+--------+-----------+--------------+----------+-------+------+------+ +| EXTERNAL | 0 | X | | X | | X | | | X | | | X | | | ++-------------+---------+---------+----------+--------+---------+--------+------+--------+-----------+--------------+----------+-------+------+------+ +| G2 | 56 | X | X | | | X | | X | X | | X | X | X | | ++-------------+---------+---------+----------+--------+---------+--------+------+--------+-----------+--------------+----------+-------+------+------+ +| GSSAPI | 56 | X | X | | | X | X | X | X | | | X | | | ++-------------+---------+---------+----------+--------+---------+--------+------+--------+-----------+--------------+----------+-------+------+------+ +| GSS-SPNEGO | 56 | X | X | | | X | X | X | X | | | X | | X | ++-------------+---------+---------+----------+--------+---------+--------+------+--------+-----------+--------------+----------+-------+------+------+ +| KERBEROS_V4 | 56 | X | X | | | X | | X | | X | | X | | | ++-------------+---------+---------+----------+--------+---------+--------+------+--------+-----------+--------------+----------+-------+------+------+ +| LOGIN | 0 | | | | | X | X | | | X | | | | | ++-------------+---------+---------+----------+--------+---------+--------+------+--------+-----------+--------------+----------+-------+------+------+ +| NTLM | 0 | X | | | | X | | | X | | | | | X | ++-------------+---------+---------+----------+--------+---------+--------+------+--------+-----------+--------------+----------+-------+------+------+ +| OTP | 0 | X | | | X | X | | | X | | | X | | | ++-------------+---------+---------+----------+--------+---------+--------+------+--------+-----------+--------------+----------+-------+------+------+ +| PASSDSS | 112 | X | X | X | X | X | X | X | X | | | X | | | ++-------------+---------+---------+----------+--------+---------+--------+------+--------+-----------+--------------+----------+-------+------+------+ +| PLAIN | 0 | | | | | X | X | | X | | | X | | | ++-------------+---------+---------+----------+--------+---------+--------+------+--------+-----------+--------------+----------+-------+------+------+ +| SCRAM | 0 | X | X | | | X | | X | X | | X | X | X | ? | ++-------------+---------+---------+----------+--------+---------+--------+------+--------+-----------+--------------+----------+-------+------+------+ +| SRP | 128 | X | X | X | X | X | | X | X | | X | X | | | ++-------------+---------+---------+----------+--------+---------+--------+------+--------+-----------+--------------+----------+-------+------+------+ + +.. Helpfully generated from http://www.tablesgenerator.com/text_tables# Understanding this table: @@ -145,6 +174,8 @@ Features: * **SRVFIRST** - The server must send first in this mechanism. * **SRVLAST** - This mechanism supports server-send-last configurations. * **PROXY** - This mechanism supports proxy authentication. +* **BIND** - This mechanism supports channel binding. +* **HTTP** - This mechanism has a profile for HTTP. .. toctree:: :hidden: From 2d2d5df2028453d03589501c69dc79e2f2a9fa85 Mon Sep 17 00:00:00 2001 From: Nicola Nye Date: Tue, 8 Nov 2016 11:19:35 +1100 Subject: [PATCH 261/796] Docs. Updating list of RFCs --- docsrc/sasl/faqs/rfcs.rst | 44 +++++++++++++++------------------------ 1 file changed, 17 insertions(+), 27 deletions(-) diff --git a/docsrc/sasl/faqs/rfcs.rst b/docsrc/sasl/faqs/rfcs.rst index 9c8e2851..0c3ed2b2 100644 --- a/docsrc/sasl/faqs/rfcs.rst +++ b/docsrc/sasl/faqs/rfcs.rst @@ -4,32 +4,22 @@ RFCs and drafts =============== -* :rfc:`1321` - The MD5 Message-Digest Algorithm -* :rfc:`1939` - Post Office Protocol - Version 3 (APOP/sasl_checkapop) -* :rfc:`2104` - HMAC: Keyed-Hashing for Message Authentication -* :rfc:`2195` - IMAP/POP AUTHorize Extention for Simple Challenge/Response - -* `draft-ietf-sasl-crammd5-xx `_ - The CRAM-MD5 SASL Mechanism (CRAM-MD5) -* :rfc:`2222` - Simple Authentication and Security Layer (SASL) (KERBEROS_V4) - -* `draft-ietf-sasl-rfc2222bis `_ Simple Authentication and Security Layer (SASL) (EXTERNAL) - (which became :rfc:`4422` ) -* :rfc:`2243` - OTP Extended Responses -* :rfc:`2245` - Anonymous SASL Mechanism - -* `draft-ietf-sasl-anon `_ Anonymous SASL Mechanism (ANONYMOUS) (became :rfc:`4505`) -* :rfc:`2289` - A One-Time Password System -* :rfc:`2444` - The One-Time-Password SASL Mechanism (OTP) -* :rfc:`2595` - Using TLS with IMAP, POP, and ACAP - -* `draft-ietf-sasl-plain `_ Plain SASL Mechanism (PLAIN) -* :rfc:`2831` - Using Digest Authentication as a SASL Mechanism +* :rfc:`4422` - Simple Authentication and Security Layer (SASL) +* `draft-newman-sasl-c-api `_ - The SASL C API +* :rfc:`7613` - Preparation, Enforcement, and Comparison of Internationalized Strings Representing Usernames and Passwords +* :rfc:`4846#section-4` - Base64 Data Encoding -* `draft-ietf-sasl-rfc2831bis `_ - Using Digest Authentication as a SASL Mechanism (DIGEST-MD5) -* :rfc:`2945` - The SRP Authentication and Key Exchange System -* :rfc:`3174` - US Secure Hash Algorithm 1 (SHA1) +* :rfc:`4505` - Anonymous Simple Authentication and Security Layer (SASL) Mechanism +* :rfc:`4616` - The PLAIN Simple Authentication and Security Layer (SASL) Mechanism +* :rfc:`4752` - The Kerberos V5 ("GSSAPI") Simple Authentication and Security Layer (SASL) Mechanism +* :rfc:`5801` - Using Generic Security Service Application Program Interface (GSS-API) Mechanisms in SASL: The GS2 Mechanism Family +* :rfc:`5802` - Salted Challenge Response Authentication Mechanism (SCRAM) SASL and GSS-API Mechanisms +* :rfc:`2444` - The One-Time-Password SASL Mechanism (OTP) +* :rfc:`2808` - The SecurID(r) SASL Mechanism +* :rfc:`2831` - Using Digest Authentication as a SASL Mechanism (historic: :rfc:`6331`) +* :rfc:`2222#section-7.1` - Simple Authentication and Security Layer (SASL) (KERBEROS_V4) +* `draft-ietf-sasl-crammd5 `_ - The CRAM-MD5 SASL Mechanism (CRAM-MD5) +* `draft-murchison-sasl-login `_ - The LOGIN SASL Mechanism * `draft-burdis-cat-srp-sasl `_ - Secure Remote Password SASL Mechanism (SRP) -* `draft-ietf-sasl-gssapi `_ - SASL GSSAPI Mechanisms (GSSAPI) (became :rfc:`4752`) -* `draft-ietf-sasl-saslprep `_ 0 SASLprep: Stringprep profile for user names and passwords (became :rfc:`4013`) -* `draft-murchison-sasl-login `_ - The LOGIN SASL Mechanism (LOGIN) -- *obsolete* -* `draft-newman-sasl-passdss `_ - DSS Secured Password Authentication Mechanism (PASSDSS-3DES-1) -* `draft-newman-sasl-c-api `_ - The SASL C API (very rough draft) +* `draft-newman-sasl-passdss `_ - DSS Secured Password Authentication Mechanism (PASSDSS) +* :rfc:`1939#page-15` - Post Office Protocol - Version 3 (APOP/sasl_checkapop) From c7202463c8e49f2b6dd52e442c0a0be2a569fb17 Mon Sep 17 00:00:00 2001 From: Nicola Nye Date: Mon, 14 Nov 2016 21:45:24 +1100 Subject: [PATCH 262/796] [Docs] Adding cross-links back to imapd plus edit links for GitHub --- docsrc/_templates/layout.html | 1 + docsrc/conf.py | 12 ++++++++++++ docsrc/index.rst | 11 +++++++++-- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/docsrc/_templates/layout.html b/docsrc/_templates/layout.html index 518c15ee..ce132daf 100644 --- a/docsrc/_templates/layout.html +++ b/docsrc/_templates/layout.html @@ -6,6 +6,7 @@

    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 JoZ<2*`445*q+|d9 literal 0 HcmV?d00001 diff --git a/docsrc/exts/themes/sphinx_rtd_theme/static/fonts/RobotoSlab-Regular.ttf b/docsrc/exts/themes/sphinx_rtd_theme/static/fonts/RobotoSlab-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..141d6c08c8ec7248a98ac72c921fc54f823dc75c GIT binary patch literal 36276 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 RSg!Ve%a_?+M=YcCe*u#^n}GlT literal 0 HcmV?d00001 diff --git a/docsrc/exts/themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.eot b/docsrc/exts/themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.eot new file mode 100644 index 0000000000000000000000000000000000000000..7c79c6a6bc9a128a2a8eaffbe49a4338625fdbc2 GIT binary patch literal 38205 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 E0QL`y%>V!Z literal 0 HcmV?d00001 diff --git a/docsrc/exts/themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.svg b/docsrc/exts/themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.svg new file mode 100644 index 00000000..45fdf338 --- /dev/null +++ b/docsrc/exts/themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.svg @@ -0,0 +1,414 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docsrc/exts/themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.ttf b/docsrc/exts/themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..e89738de5eaf8fca33a2f2cdc5cb4929caa62b71 GIT binary patch literal 80652 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 qx{Kk=rVu5YQ9XR<GPS>b$X_& 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 z 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 JoZ<2*`445*q+|d9 literal 0 HcmV?d00001 diff --git a/docsrc/exts/themes/cyrus/static/fonts/RobotoSlab-Regular.ttf b/docsrc/exts/themes/cyrus/static/fonts/RobotoSlab-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..141d6c08c8ec7248a98ac72c921fc54f823dc75c GIT binary patch literal 36276 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 RSg!Ve%a_?+M=YcCe*u#^n}GlT literal 0 HcmV?d00001 diff --git a/docsrc/exts/themes/cyrus/static/fonts/fontawesome-webfont.eot b/docsrc/exts/themes/cyrus/static/fonts/fontawesome-webfont.eot new file mode 100644 index 0000000000000000000000000000000000000000..7c79c6a6bc9a128a2a8eaffbe49a4338625fdbc2 GIT binary patch literal 38205 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 E0QL`y%>V!Z literal 0 HcmV?d00001 diff --git a/docsrc/exts/themes/cyrus/static/fonts/fontawesome-webfont.svg b/docsrc/exts/themes/cyrus/static/fonts/fontawesome-webfont.svg new file mode 100644 index 00000000..45fdf338 --- /dev/null +++ b/docsrc/exts/themes/cyrus/static/fonts/fontawesome-webfont.svg @@ -0,0 +1,414 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docsrc/exts/themes/cyrus/static/fonts/fontawesome-webfont.ttf b/docsrc/exts/themes/cyrus/static/fonts/fontawesome-webfont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..e89738de5eaf8fca33a2f2cdc5cb4929caa62b71 GIT binary patch literal 80652 zcmd4434B!5y$62Jx!dgfl1wJaOp=*N2qchXlCUL1*hxS(1pzUj2!bdoh~hR1qKGRh zwYF;1y3o}w_SLrdruJ!H7kRd|tG>S2R@?Wq7TP{rA#?eEf9K95lK|TG|33fEKg+%6 z+hTSaAdmL)uWh^R%I%Bq{=#vIHGE2vyyxxQ zu>PXwf4+35#HOMTl7@fkt@MNGkN*dqzrXxudarck;ms?=9TzfXbVcIGGxh+E^d!f> ztp1kWBdO@h9ZDcN>E)O$)*L%OUQ<(5(?2L3bseob+I4i% z(X~e}J$l2@yN*6`^z%o*bo9v4Umbn#sBz47tm;_Pv94o_j;%d*>9HG*-F57d|CLTs zlc>gL3N=cjYLt$8j>eB>jxIjhe{|c??9qFU4jg^^^s&K$J;*W3T~FTeWV|2+Pm&&ML33QxpS<_UX3 zo}ee-@q2t8ugBw&J>0`QlKZ6FaOd4a?i23g?ho95bN|)-zJuoA|NMsm7K+s}nqB%Y z{lQI|ivK_S=vvsKmRk#edAb%6i2hSQfN{*f8@=C#{(3MdvZPB=N8B5iy>ag#%Ndz% zd|;azJHAbmj*E8`hfQQA(J-EOQqrDKvr;880iAi{Eunx`8?Q;WwYSE-ESYZWVy*F( zDyBWrn7@r>BFSWAC`(6{$=}vkS07fh;rcptPAzWdrDR(Yf3n1{ZmbPgSS%G{s_+g8 z?`TBE8*uTOCf?S?TU)|jb#%6^y@R#4wuCfk)~1cCHg1}Q(}asx@ZVV6;lsib{$)h;3&X! zv#^nE>r1k8t{W+F*LfUs0DkxY35 zA&hmqcN%Y!F$Y>O5DtZ_l&QR>OYUgz=wcmSb8^yNnjQ>PHkL5{@qN#TZq2kl zV*Di$^E=g?)6Z1RVL6_0`tSSJtJ;*Bj-~)(fu@d{DcY;wYCkW#w&!@JXYJY^HP^E? zCQEfyNA@&MoHS`-XZ2cas^9s{_6MI-Cq)uIUm`L|ee%J^d;3q| zxwSnC)nU#t^(_m0Cn*@xCMAs)wp8(Omy8LeF_j-`^X2cc)%HzmHU_(Hx@>V>-Qvq` z>KZiO%HNyy@l}?(^Dn$><{N)&oS&(y%gk^5+Z+G+R{j~Y?$2TF2BjKgP>~{l@+5#xb#STNuZ8r?=WCN#*;G43z#WbeP}pXPs)z27Nc6N(s* z7!KVTtaQBluA?%jx!7OW`ifw}I-h-~p~09u-%4wQ;KqEnm7v$k5_U|!oKTDHICC?U z%UO%D>hNJ>6>FK#cCl;NcSO4y&fF{>U=3aD2IJ-~<7dX|?|etL6`R@eA+4k~0kR8WvKfSYMJobh>0d z!tvr{#Gs=xQsl%)QZ6lGj9fo`gtklOnC+PFB5q~+|H?r@3FXkQznBmY53W~ekX>W(B9tH3|SwvWJ~1XLheJ)N0I z(>o?V_Wu8Me(d|W)LC!j>N`8@S%!`yX`U_3UsHzz6Au-Z2`g~&4=#RcvTJE15t5HKCG3gq~ zrQNE0NeW>%!QQ27HO-7A+qxMxD=QAwOuIFjAAehPar8FhU^GezmgM(PUjEZ!aVvTo z+f4ar)c6Iz7iCcIr6=E0eaZm|+(=!(&9s`76^CY2-C-SFe<+|^nd%cY8^1JuY1YJ& zNEP13l7-rTiL2s0XS!=XLA99lj7d|~VsD&Yr5kF;8J`tNS3NtP z3km=mX{w2Vehi0vgtJWyPIUIJBgSuye>Z-6WY=Q{8ZWMnxyP;FvgG!|uO7aA$(Hrw z+_CD-;|@HQ&-QKV!ynInl1lD6!lIx2D(l%Ab2W~;IJV%Y*K9&@JhkbXpDu`9Jg(6d z+iJYP7vu#V=X4}m3WTqqe@p2FDIs8{2q`V01X>50LF_ODG-LDB`qKNS2O{^EnaD-4lj8PxQryhw9Ovnz(^f)Ef8uU z2*Uc*F(U!YNG;Z=rsJ1-f#sUgX(1$2M8Sf-$E7Al%LWLdqj6bc7WX_~h3j9O9*_O&uJZbsHf!YGkkdK3@Lg87({WRsC>(L4Fb~li4zjJka)fxa zJ<+n#5wRuivR)E)-_{cKI=|)#Zn4_0Xty~X_TcLBmPr*n=oDp}nkFxCIBd?kyKP%a z3)^)xWl9 z2=r7xK?qCFaWA6%eUW<(OS^n>tOSf)XGrI(tU^jX@g7V5_k36_LmfzD;9cZ2Bt60U(mW+|v56fMdYE1^I$# zYn;WCDXavVH)nd^#bB7oM%}kFw5ay^Kq2z{plQ z*kp&z*ff+Sx=PK|ch*OZe~qcIBxv>_<;k*S^aT##S!CCW3BP%kt1v!dz`J42aRDEB3Q^9 zD21}(34VTQ(IZF1Jhn)Zz6j{i3uu>ET5e**HtBLu3lZPM0<{ndq;MH6#$^pcf*PO; zMvz-W$VC(*%z=WTFr*hN%2>epb!UK;F`wfv4j+HNDW7rrSOAxeqqrVmK4(7D6k(59 z>H=&TuDEgKDHL&|2wN7Yv#`e^JgPA4Vt%KQQyd--xMIJPNp#^Pj`Q2Qlz>0#cjjo8 zb50~ryxS#YuAmFBly%H=0lx0*)XAQmQFc zVkB8gwmsEZe;gBw3IE}(Q$9K6HufsO;~U;;BjaoL8JTLYcN~)dnc$I_H0~)Ok20lF zEH*-E-`3fATPOE6R2mt-pXDkWQY&S}~TyokXyw@6buLX;*ub6eMzw9v-7(QKA+|L8-TdVjzepa!yjpUdH3-BzoS z^RN#-q^Xcm5ON2MJ89*!I0RmDT*l@V565YbFRc3xzln{*{*Zi$V6!2au+0Bx*H7*XCt+j>rd*JFSa16?@c(S!c!QKzj4ghXs#(BNfx8MKW zBJs8JwfVZoW#4CImaWG3K089H-N*b}ZU%&_l97od>r+*??<+P0u+n#%g zsAHWhdSusS8*aiP8m2FSuj{0_Xk|d>QoN=P1j~p30GtQ5SzQ}+72XTOe%Vit(OY{CQQmf*S4a-!rCL=&B z(CJbN?hlE3G6w2QX%r&SuPF&0CF^DV!xjJeG^zaQE{7S&Sbe7~`Fyx7${c(L58e zQHg&n=5!keg~5Y?YTC|+Ni!3LPbVIMqgMshgqEEacs{gm38lO<&kG^fB@*scroW@{W9O-ROG z?Ki$`92a<4V+*lVm4Oqq!r4Ns(=2x7h2|P0c!?=lQP+gi*9Iv8O(X`OOKxkDF*?Ne zobDYgd-fcgJCZD`sVSrXWW;TobD9?$z6W_|Am$cJq`G6!Mus~mfQn}2SD_BIBt{9=O676JNwgjI2{$qRA*qp zvSkYbovCER>AZt|+W4^(V4Bja^`^ROZ@>N8x+WyW%^&~$qtIa-G4fN@WF!@+bhkh8 zwI|x$m4OtXf9h9_Hsi+CxKkHaoJx6QHS@3*=2;ynM>brCBC90_4WiIPkRH+w+RqOe zN(FF1EwlrzVyy;i(|-KN@y|g0(=VMF60C3?yj!}~TkDMnThnx%epwbjau%!?u^sde zS&;zAY~an5J+Sao@ENtSReJH*(HOgzJIJ)h-SLtH00GoIooB1?3c{;3Nd zItcmYsr^Vn(q;B#D)b#vYpu7{|Nr8@8$Yqw+Un|u@z>RLLv?kx_zn@U-bhFpUq!UIUk>Ec_WYcV*tuLL-w-b>i$yiSh=vxZ!f`sbB z-=>;v02>IL2n8amC4Bu+tzcQvxVok)_R|ElFqg}#JPB|&a9k?c0rhlyvZITWpoS78Q5&7WEiJ5reQ7B^2Lk}GYoL%= zdn%+7>()ZDog}I(uyQ4NZDW1N_=Eq-8ABTu-W@FqX$*TJcLcTYc#EuZIVuOoDNI+C zI>q0tFbn6dkY@2Z{egH2Qe!9oV8P;$@m}5B^M*cAVYl1Lu9iPh*=}Lub)G!&2gTvy z{mybFh(vw>iA|?mQEDd78@ej9V#}hL)08Hcr9!g@Ds0IuNn5?eUZd4*tFbnz&RR9H zBWbC%S^^P^BN0!PhnOZ?w=EdDYUgaXr(#ZZM1DO~>#m~xQcw#9Q43}gLkhU~n2-ZN zSIk-+8nHbWxKEwL8t%nvp~o20mvgBjMit)x|{(&v217kK;Gm%Ge*DDkEd}3 zEcC!xm-842CmxLU*PoOw7i%S}X9dq3hdfu3$P5EU7$6d8bf|e|%Z9~Ok|{^`$n)Pj zbm+Z9@*t5+$Fp=CZ1rzQb1A*S-a;nkyjT2|&-h^`Q0)lX6-|y- zd2IoUi~3Kv3m6l4zz+$=258kmIHE^D78r%v8a=4{12SEsE6Br81A-H=yVLljW!mAz zZ!?>~I$A&okdQ`<6<~_!8j=WO#3+Sdi03dcjeVKjpH3tjrYu|h^nwZ|^TwVpeCh1v zpJ`hJI}?`wEuRox*yL5LTveEj*?p~5%N0oAuA89xRMrq!uySK#dh&$v<1*cm>%O>Z zO=Ym9XTkiNmu`P)`A_5S*wT4(F1w;K@(28nZKh;Nq5U>8jB7UBSrvR=yRd(vYP`*;+HPhnDTHj9A0I9 zUwx&cqSImVx$JtSCuC{Z7`6G?^i)mH{qZ@BE4tRvo=G?yR%Lu>da}{Mn7+e%c4ZViB0LPC|dWSDQ?y(zK%Ro0605Cgn)Hvx}3u07gM+AOX_w zkpve4C?F}UF31K#B34<&_qDw-vEY2y_hr!QjHD)jLV?bWz1 za6@1U{(bSqi%T==jTI_t<;-KTFcx_@ec_at-z_(uUAC~DyA{sWb*Tr9uNWV{uPIfo z+dPWJHbKSg*(@$4q(rQ7Ptp;r%^hQ(?YewTNKu(qVYg1aDDIC`cv-_aCwLp zzmL_AXI7`3hCXU58T#XYKJA3l> zv2a47oQfj}bB~LhhNHNbrF#mFIgz3RyXYg5{~xv6G>w$e7}0LgC>2Lx6(n*T$N%eg zkF|yPsQl>hE*4my+5|EWAjXcl7&dJ%nBi$iu?x{ z2ftGj%|0QHinvmm9w{RalF0@=9;Ji-BYRfTUkOT$Q~OxZF_@NeWa$HlDaDXu`|weD z)=wQ25=a-Cs2=)9yU343sRq+51u4TSMuiR~ojH9{&~~Dal923rLE_K^7Wz~a8B{Ww z&TvSVQjk&kjID=u<}*7F9oorrI}fq@d=(C7iiA<)ysDqw_f+xDp`A~%1AY}62U7+I zJ_z)c4!@QvsR`EvAJpCg_ASjYkl>ra5eYsTFHVL_xFce_d3M{twrvB-w&Pir8Q|b# zJ`f$%GU(}jrPh{;hYD`X!%RLWin5sBd4h^L6+99f}e!kWQ(MMn=A)U zAjLaUdayOf+CarI@Hn7s!Q!KRUdVeHI03TS2(c}z-&vjISA}eP{?|H=yh?9p14B8Z zUwtR>l+piGU3)tDP6DO2WaWVnm9mAX)c1`3p&T3FgXzRmY~aac@_!&z5qz1Tv31DS zMoCm$z(-h9LclJY#vtrq+_>M>s!2{I zYjl@PtYN67JwZBoGJlc58$jk$C5K^&5nz>}sIJr~dK83K0HP*H>|Qfg8m}$UE|H?nvgB=pa{W}siM-Fvh3iT%GguL@o^=lx>; z6V@Be^{V|1{nP+slcg?c9$ID2rj*27hB}ykG-wld0`d&8Fzg@i{<-` zL1oPvV{i>@@g9t_epJ)h&vV1|NQK~+4u zhQ-!IQ42X9(Y%r_0IOI3=q_E|S>6$+z zRy|qvcj=_bArOavE}&+MU6f8b{gH*8Hf>w6cfM%E;}8D9$coiJU>v@3=L9)yQ9L$V zX!5vPJy<(+(Pg(kw|M|4BjRUSKd&|N#eVvo6>6kLDfaTGew(w*W3jR~j4bfQxZLi2 z#5K?ckHqy#+;;WeUAdxtjswo~89U-m~%dGnMrGy#Pjk^B_V zmR$w8Wcg{@LX#uvigl>K^jWfHYOmA7YJe zI{s=n9uKP%!+c%7${C2Lxk$i?R2{*T*jEHkO?G!Cg*J>MOpPj0FU6f+*dItV&g76V z1b)pJ&Z!wP(E#rzjwNY&55X=l5!R#o)VENrBjrccGxDs4XEAo+;jV=ttEC~7{vmN(Hc`<9+{#fpHLj)Nd9eTcO~l4NgU1bOrQL!VpqQp zib+yUYF})TFh>{Clp6kaemgWrcOVVJ5D~Q z^rB8sKjecYq+-~LVDp})?U-e;_|57^a!dOlcUVjWQBca@2J(2{ZyU8X`l3 z!ZKqBCZ5TXguooG(a*5PF(lMTyU2d2(5_-@PHjVp@6l=BYJ$lrZz=76qtMm1H8T=; zL)Zn0K6KS|1i=Ogr#OaMVYNs06d3hV8d164|J-wa|0;h)gc6YoBu~A$=ZzS1s)}zl0NU8}YaCa@jC(V+kyrbM#+k?(iPn;jyOUHEk1n>nCMH%%UO0z z>j#QY`}pTq9$fm9GT()oV^&#NTRhnmitd5??kC*r}T6#G;# zT{4>ua-y&#TH0ZnA=XK;L!+!AC74DR4QTuOh2bC?SJFX#O5+DyJ}yy7B#fLm`Q*Eh zF_YgK+uo5i(hMI&X~g#gMiv-qQ}zODLySC{h&;4W71rlt+aHv#vZ#wET>Bzi;ca&u1rSmPQ3G&xc}HYiM#26F&DUrAx`u3aCK}v z5XBiDFVsi4Yh=C%cTL3z2uCAvAX#O!28fAe3N0efEC^aMGBB5Io|*; znm#!N-*Pp!BJbKaaM^bcoHJC;|9tC{V5ij>OsjqaADrKikrhxvC#!sg?|y7=-hJ+h z1KA#I_y(psW-K8JT^i~i=~ohErf-5MqY3uB9yQZHd2 zvjZa~Xp3ZD8@!%alE$wWbO-JULWg8MMCtqzV+|Kq%teyO5p!I#pgnWsn^55C(m=2- zc&&s31%G#_6ye;};fuGT2`1lW5MwsD{u3X+e0^7~s(RfXhwgC8H>Mxw-yH;Z#wB>& z`%#L>5l40V**gX{bj;Fft?q!=8o^Fk`P6szvipbKFk7%?rwBtNM2*2;N z&8GHYeSp@@0(J;^#d;j(7lv2JFaTl1RM?0Z{hjqWI5G4KuZ97UVXzgE$y@i7tD=12 zT^#R{O_6XaY>I zy0Q0#)#3Ig+TkVzzd}|0UQ?E8H^PXK&+) zOL6<-#w)_ZyY=IEnDis^28kc{4fX92q8$_?LW8qXYst__)tzbG_lR*${^0d6!=uONX5J;|nf-!1;nR z;Aa={tq#p%(H!~vY;JI`5@f>Qp(NlYC%k*B$?74I_QJLiviuMzi+0vZL^FH<;r2qr zb8Cy~r-q?6ndySL5uA8v{a|qk(va@Lkaobx)kSmBI-~R3H$)mSllep!x+h^|kYM?>=wK^lWze7D}H+0pF!brYsPI zmJ3$apq9uww+rYAb{>=fIg39EKmqTa$Y+f=ezOaUzARX=Hn5NBUybl&pvidW^`8#j zf4loY*wftDRarGI;N=!s?pn|l<<=D+dtqzGSHAqE2U50Fpe9w8>W+D2*iv0^=+?;y6u&ad)|$TZN008T^SNbfDq%}` z!`3x>whKNF>jv^OH>^@6@(ZNtFn2F#qXGiyrouwdsRDzCQ&kG-ltwgcC#6Ye_4l7O zX{N$f-LY>~hnee<&D?;{A<#kbFWPh7vU&4XxAtclYgoShrq8Y~URir{;R+2o=rOw`ynAzQsbu|GY)=^OFN;>mcZ!a(H*m zl+Fg^cfe||twYm&W80aacA6VEAOpqB7ROtJ7c0s7{osYbwWA#Qx&XvrY1RQkn>Q|6 zu^xSSn(rIw1-q49Y^>Ql$>wwH@{GUx*vdfQzRXUduRN7Uv*#g zJIv!<=W)Q7hue&a``>C|?@!n>rzW%HvoGxNz4y&8U%4&wC9oPacOKx=qXM4d1X0-a zKLRJoFe@FlDg}-OMVWU@qh6w3BEioP=-Z6|I)(Xwx=JWE z8X376kOPuHLlCBjbXbK#M(rP;>3eKI^=5U4BD*!?zm0rab@p3b+-*HPWarF=w8md# zvZ1(OFP3$A_{RtOa%z8DuJ5t@Jin`7W3rPC8Tl8zu6`@G4;|J$PRBYcOT#KDY=IYY z)~P-^(3c^pAjN6ISe|NoO%~*2b$ym}CFFl`({em9<_syfuqYSThlMu3e8!`ERRiZnEi zMP$Jc5#>1f%D2H?2YMl9o^VB!WU&lY2fq~-8LZDFXYwY7KrAnja($5jo!gQVAv zZSGvv*4NV0Hl<=}p$K_k7u^e~$VqA9qG{vGVoj9|GpDaO@9J4*9b+yQpHiyVJU5|Z zUPGl2lMK0_{?0-DonuVaUE!Lh>8bO+BJN{DguAA^vsj>NT6a^|)}B>YFFvO=E*>6r z#Vn3-!@43p4A3EwrXWbbnrJF;STdDPwkK&1R68gfLl?uQsp!&C3!KaK52%x zLXlNwgU_NqG1yR6Wqc3<> zX3R4ldkN$@#175VmNt!RS~{)S%u>K3auYXm6bxx3$8*{58ZSKe9P9b6C;_NVh7=`4 zj1ZpS7mXAxeT)VU;<$pz<`P{_!7K{Odzd(O@dmU)eAILyQ)mUZN;_K`=7elaJYN3f@5 z0o&xm4S7;s!3skuoXKlZSF7N+rh`~5z!4z5Lq^vHGgzgBaffH2xbNL8e_x!wA1goc zF4NUA`9XrCAt{m!CHNPAAb?8pl)LSU&Xg}kl4;>vBA)4$bB0uwkay{oWj4=5GN+HY zT4yP82a---bts`HX)S^l&tfe=*Dw~&q57mqd3)BJ$gJ73XAQ%V53JcE59CE&&e7Ev zOi7D#x&rn1rEw!o^AX@&xu@3x|%IUO3Bou zjYC7ZwMV8KUr<@$#WB2mUUjXpy>)J+s=Ailfis&jaQ-}FyQX-RlE#p1N8&l`h0w^s z3I;#~@E~+6q+!6!1ZE`S0hI9^1dUi~rRrPC7Sy%MFWV?!S&23m>sRP;@c@1>ek`L) za?X4gy@N11KzEb|8DMM59fZF4v=xqMgG*iy(!bC+ybB$I|0c~HOntCJ_XS1*?35_xct%NR#)2>jcL0W$O{82u=(lp6e? zog*^kiBbmb({!kWb>iqClK~k^rzE7yuv-UW0liA65afU0gi`Hefe?YFX3Q#|F?;%& z71yda{rarR)y?S(=U0ZDk>HkD+wYB(-T(P*|8~cQN#ME1!JIDRZfYw5gVIxFYBJ6sl}dnsEbubsQ|6Ni@jtP>a?dFs%p_WOl2qN7$|owN|! z*9Kd~SdZQT)Qa%S)t#4q;lVw-cQcLMU)m79`Sq=nQm@~0=kC|@xA1G(`=xKw#hgl* zQ;M5Zf%m1LH|Rnuh=VNQTG|Wv1D4Zq$&-v}o=}X^avb2Mmxclm0wsCC=jvJOi~2h2 zU4MeN@WI!H4pJ;rC0mG7IP@m@0cJI6=-)E=>$Gfd`nUw+AIL=0z5Gj2-`XCcGwM4n zB6Q8ri&H}FSVPY}CB5Ejv zaXMM@)1;GB5-8n=Z5~%(3RHAety1I+Ow9ZZ;}(;t8J*>CulHJ0HH~ur8_`AM>ZAE} z&mMl_l^0mcz!R_RW*79!O*OIgUZ+i4y!_nB^0P2eTRg78kB7zCki6?-HBIzz{kTO@ z{^;&ko)};)FTC=^;b)D9`{hOid-1NfX$zOG>Ou3xT61Hq9R(iuVqR{P4ofEr{i4`J zX8+JLki&&(BB>SFgMxPoupc%l5H({176Bmw+e1|JcZVy&$P|MW;T@=v#)?KR1tdf7 z5iyX!d4OI4)kqsC#jXs6fpg$82Xh>hhanckEC2k%a#lc*d=TNRu)UZ^BkQt$!XB*Y z)b;RAzuk6aqTcS%!(X@iSh%L)D&1+f-J{#OJYmO!HrH^`(A8A5rm?iB#X&_K)7)V@ zit_9O4qvOXi(C3!fk433XW_e)R-fa62b|tkMd|7++-Pmkl&h6iuk(R_w0t2X(@8Z|;YOPb5vwvXF_=jxVQDy%lwqR{wc8S~nQ zi`uOYOVw5SDxd3;rcp&beW8gpVeZWj-r;dqlwV%1$aB{QIS;O#D=WxWxIMU08KxWX zXFm_O<~Hy-bT3@#mXH23PZ9hI94u(;gpfyhC>TbHz>(l4i5RCOXd=-A#qPzz)IoMs zX#{D)i$kl8(Tc4DtYYm_xT9|x-}u*aR$cc{U5jk@b1(y3m0<``=cx?ZuDk1-Y&N@r z&F0hYy3Q7?^whyIg8VK~EZ}IVd+54V=NQMnJEiI|R=@rFz2Tb<%KMG~d3T>@WxW*~ zE$kUJMVGO8CWDFkvUxw+x&PgL`||s){^7i``b03PG2B!%O_yCBrd#V*diE%*majRw zcVX|`pAOUW*dBHGD{dW$nuAqZ8*c;hN!AW?SRe(^QxY?xUtO@Nq}xbzV2RK&p??j5 zg)vAYBtAJAfh_^uOD<@n426vX=&3g4sYNZuK!2t`QkG~4btuX5@pTO;#658)Dx1R- z)gSM^CZ|@_`qBY+tT8*ungo^m**ojb>;J~J+e5}6AzbFG+c0HPSvc94YF)l}&ctUo zJ@^z=o#ffpg;Tyib^Y4NRkt*TXQ?f*bZwn4pVf4?#mnbE9jWrnUl41VT|V8**3_N5 zAYQj{W-zp2;r_=aG}iZ~c{bf!w!1f7e$Ae7i5a)=IPZc70T)D{0=WTC>ySVp{=h!qkX`Q5q$w(Sf?HcBtUOu}ewqU-eDsuMH z`P^%9>smhRtE)}NTGUzL##^q6tX)6#`%@OSY<%#7^RAjTdqyI@e%U#}mW8|FM@ger zKYsip`_zRSLcy5}>*5QD#yj~rIinJv4{Ga_;K_1kY_Mc?@c2uo21hPkmlW@LGHOF` z2EqNqc^3&8lo8k~z@ng4Nsvk~SBM3zWgBPqui13h z!x;FPdMQJ^S_oq6k(tH>n->Zuuv2)IETkU9EDskmwQfAind(MFEHdGw=vaj;NmW=3 zD9EeX6nVg(A0(5?j9_hYq>796E3sh2X_~{s#+)*1d-4$Vz>U$)TVRehNQ$wT$zZb> z$oKqU!6sh7x(w$GARxE3WmM!9;#~glyWhRf z=4_uocQTtgkI(+IP>PqVuodSu6j zp8OqbPtsRA>0y3lDeXr%T2hFfx0Ag-^rJ*dz)XrFmqEaQC{I{~DVfF*aNsTQhr~2` zfq@1=-QkaeS2dQka<79`sC~vIk>tY{&|W6ON48z?Fdtx$yugekgQM|zFte2oZv}fR z8M*c)E}8Ku4e2FJHrhid6nHd6F&f4a;$;7UsUJ3WF4~t;IgmQ0+@VCLIbz++MFVKU zOv`OE7F-r{`)q!@soUgtJc}tLqe$LwLWm4XUKA`^F_X&0CoeTnMm#4}ob(*2I7Qnr z*AQ?@8FWLepi^MbI^3r=h?y|8?dSyX{5XV-2Wk_SLdxktkX?CbCpqH_m}R0TkQACQ zTe!CK5V3Hl14Y(K?i|CA%X22=T1>DOI5{hLa19!<`51X1SuCtXIv&umGX)X(9~(E> zMPN%7b~v;Ig>*`wWFX(Bg0PAJ1rRGZYxcbbC#A#6w@*q7?mV1bcIPXXk4q;jr_b!& z;d2dPN_OYwze-=J)5S%m6^SIL3``Mnud1utnK&A&DMAJ3+X7-q!c3xG7xi*aY4gZg|#;U zlD0d6KQu&xfPH)lCh# zMKzmM$Nw(Hja|bt4Ik<7PT?^HU+Q@I(9S`RH)Ly@yn5Y?hO-hAqMK96^IksBlfI&I zeB!Kz%(~T+>#f0wJu|}osewSyqd9av)M&FgyXMWLU>u>)ps-vA^81?AVYlEv?a;M| zsy9O`tgEuxpxf*a>e_cWG&uRH9+>CbxooqP$z1*-p$%>cdjGg?f>zdk*6y>fIeYcx z*7~xtNW>nSV7+`bF5JAhy-ceE)!Nt)t5;;J%cZKe&Tu%{?1X!A@@6>{mf=i+7J$hW zemQ`-92UIWT<^sggT?b`xj_}laN0Xajsq+(EC7vz`6yV%LtjaB3nSX4G}_>2f)`9@ z()0_0>@yt+tR8S^w1lvy;s{*t>p<*Z z!AhBB#e+b$MC%EavRM|72^a$ze51?muvu(2#p+)anD+arjT>in?wiqnTowzoCL#VuNe)gP2552f++V7_L`vOZA*tmjV1RfuM zdHnv0s_2ABcy%b@W7dh`vQYb^`TzaLo9YJ|!YjsChN|l({EP+mKWTj9M928b%FE`L ztqj*c)^OQRj(l~-)ai>R+BPf?uL|3|URy}3f0)Ju^h&{&0-9*xDD)l!VNz*Od!~r2 zAc7WKok`b`G?K;#ga)KBRru}%@sE_`lbE?Kb|$QR<5%9 z^w!Rn@)Z>>-B)W*#@uqHYx2y=Ha*Dt{%s$xaaCA-oh{P>uF7#r`Q$nNIhxGsD^`@Z zbhhd~dzD-}@hs-eE?jS2T%BpHShIFR&>nzSm4D9Ua%EhlD=@94(`T)4)$o1)*2jXn z4RyOJWp^xTuk}H0V&Z&ZGh*7_kKUV3ad1=mNBm6I{;KGCL)(lh755nOD;g+z9nnG| z_%dUzXhIeQQCmlt`9C!H3Pfb=>2uFzPdm;Sg+)4%WCzba+t{qG`tW!x0=@+RG)q;Tx{ps|lRu?R^fi>%c_!Z%1ou-)@~{~s`kaj@M*sd*~ zc|Pm=#7~VMebzYkW^Ln}&tCjgbv)WQZrgpc7WFI|e+^sxvgPpJJNmcwCoVou*|dJP zD|)k$fA3$m-mBcsuV1Iy!(ZH?B<1mUEnC_9z?W^wy1j=l3QoSV+h(qdpO0e5|xWW4_Sit>MUpNdrc-gvzbj`s-9o-i(3 zh-e@`{^xg{i)3G!x{%#_;)kXw5uql5p9H;=K*rqNX>$hkD*_yn^TY^`A^bA6Y!YTt zNr<3?1&;Yq0#LRh_Kut@`VCMFpIm2sN%X_#DKrn>31BM7&fU;zk(9L&?>4`XqHj#mxYMseX72QVfMY+CvMj4YY(63d$K}C6r~iZm zr{R7CjPhschv>WlUZ!s;A-eCdhc2igB2X}mSkFR=Hx+grh&itg-{Df-$UO(F4}8pY z*yY=}-&c8Sc^wZK-*~GWR#XvnfYn`o#jV`Q1HS0pkpy#m35K%Q|E#<=;ETwRPyg4~ zzwuM%5njB;OVL0uUj7!F9pZK6w^sVR&Regz+<4>hia?;Y{AX-8tNfCaCCcvxv*G;d zH@+-1e=*DZ{cgxJw56C<1GTW?}m&l3+@XpkAMc^tne=-T)-_ZhV9Pd^bBb)df zd&OYjRSl!{xwbx9WPNRqv0pIl$rl4YKM`tvU*N?jjpK&U@4~YYG?}4ZFL)WawS!ov zV>8iVphW0QVb$qK7WU?`1EOkT4#=3#JceO3Nz4L0jpx<=+pBDj`fsKk)s+ojpJ;1v z=+%K+Z;g&?uuc4WLuIui{mpuZt?KqMr5Y-4y|uDobQzu<^B51&WA=uT%Ev`VSKVN9 zRPWzkWw(tgBjzP5U`U62VbfUIqcH3v7Z&r^l%|31DwRDJG^e6Fgl>fE_-b#>Oyn_D$|ZY(zMg_o8bE=U|%FQD#Y7avmMLh5+S z;ZIF1h#X_KFf0mPWqd}hv%aReJ9+&RA$C=%;4v^cy{vKO^!?+5nI%igC+D-7OsT-J zFMaWYU6V~|%WGV}4&KXqkI1Ml7FeS%h$my{05mS+`>O%P+7^CfCxNHU_7D z>V+HcdX};2a$Grd@y8zA#I6cGaecD8xu)J(JA;?GDuQKU8;hlTvpieYGA=I58eftL zfx?a_!_#LrE=x}iEQCGouqd)DcJ|Ut#^h}%US_&?>g-S4q4r%A3Qq2N@ZyaRPMfuB zZ*8V)X|Q8~j6wAJtuTxz$ZCaLTfml590>}Y04bIZ=0?*A(Gs4;sEVNs{lz}7)I zUKmgCNKn-Y{fN*@f*3&#Fx4f~+S7`5KNv>hhBBGFn0Bjrx=C-EY>J<0&LQFw9C2Z; z+h@>Rw=cNn)-iJ}#LiP^^9&$yUIB0|${E16mgMKkI(fPn+WagNRIBt42h{>#W7x#L zXUb=)1rF(eH4fq_Bn~G()R$7UO+pjUDyUV_C}0S(R&R}qCWhdj z*iq{Fr>dfEvoVHE$dBJIG?i^$&75PKwgE-a`a)wOBMn7qV~nHR2p?8xR|=aI+9euB zgEj2kDn80Es$I&dJs*Amb+9Bwc25bkTT6!G6 zI{i~=sIyQluMMH@j&=yJLWm?QN@(Gv3(PW0)lik~NTC`Mc2MjgRUPKNFc{hpe2KMGTN4M0Mq{Zl7$q%OlR~e$WNHmHn(mOr zq`1mLAp1Z?gwU>zwq!@BL%bYVkJ{Mzrw-0@KS02|i9RWBIV8)@#wQkj^SZ#jQC0iX7Hsm&?_{R*=3X9F*Rozj&&d*i5&ee#Df(Wo$?NepMIka+wHwLXAQe{NflsU6% z+zxRIBNcg#jyPUWzB?3zI>jf3WSQxWnp;;nj0ekA89h^N+-}hkc@jTv9e!mluM)%; zbs2`+3Td=zg=AW-mUV>h3~{e4`e~y7{DULJWhZV z$Ix5LWYw+$yj2?_apDWI9Lg3Aky~NUU`60ftD;%`vgT5CuhW7!nL&*!G)8L3U9MWJ zPN!96_~?`tripbs6t`N2v9ytsgAXsTVuZqgyK?5XxR?W>H&xw=DACNOFwCnGP}Fk8 zDl>)a77Qqc+Z{m@tjwjW9;+g2nnROa7|F$VAi$DUmD3=fPeSJa>)<86A-6XIG$z-Fn_bf<X~j}>pSeswiai#x7;04^a=|o zHdzXu3~D!k_twGB!iup-<%>wx!n(HuDjeATlAIHvY9Un}`;FJJc|{`9 z-^eP`5K?4)M{evN9gQ)Ivh+8UDT=wU1GBf!lmQtmso=k_g?xr&l!&KZ3_Az9*8E0P zi+U}-`{WnV=3tR(`03+Msx(gd1-|R#&qqX{Imr*3ZT1Iz{{}+=eG!d^m^rdjB)d}@ zhv6|Gg(Yc-5b`RBcykb*k*rxTX9aa6^#76}DUg)W_p?cD%^=e2hYDQ!00MXh&pi5I z3G44!t4i6tWW-GI$p8@?0~mrqGDd}bo&*j9YpI__JtHg*t=Pz5=w`NuBnsrA174Bj zAoLZJYFr@J5w>!s6rAJ=Rv~d9ei09fyQ*wF%r3YGod%I3J`{A1@v!mmJv2b1fr9qw z9(DmP_#+NSJ-UFHS>9?~!b9Q7|;*yG03lx9S&g z2w#aT#@!2P_+)8@v`ku!t_wS^w1>1bU}!)Hfrk-&9rN|-g4Jm8E7m9lmnE|A5eBz- zmKRF!C6901yL8)iTJP0UXZEPd=+9l-dKT}!ZSUe9Tj6upLuQ;j`J93^sT|+7bnnK; zm#956r(WHwU1u5#azNpdMQq);#&Du?f8KS5Ph+bs!p797E_@+7|LCG6*Qz`AS0=)Z zCdBjmI$D>Co8tS9>Me{SF zN22wq%KM_xS1TIEmXdEg`@UsYU$gAUvXv{(*>&~uSC@~;;}eIdJtkK>BIWM-PTg-u z8g{M!Q4u*1<-bQFT5%wnLZOQ4(S`DF9$j`|+1dZG?CNXJS-BE5kIvG%z*@}$cU54F z1YAHpAOwLxqYCxS6bI_rHy=Hb1G>CxJ4eL7M;Mzrr+@RohMS&Y*+<`mW8IA#nxI7`cA~EsZ zB0@lmq&3oJ>1t`ObO&yc#1>XDDv%tR-ePrQje|G`4N4jDr3v(wtYAU4(j_8a+ex)6 zsBQWJXkpTUEL70BNfOp!r)h1GK}%E41v~=NWkfweB~&y1@Dzf0!i*WUAl*T4m7fy) zIJ<bgFWYnPZRf1A>+6^9Ik0S&)wyez(>iO}fjvvt>uN*e z+57I@vuwSNl9o&Pmt0jd^0O{|Znre2adYkAvU3nxxuN)Ov@(KDXfy1?z@_Owo|qeFgb>z;9S;=l){ z*y{q8=7{V8S;YQ3#xogX$>sePsI@&x#K>jXgSX4rG_VN)f6=~Cji?X_Sb^Y+5+p(& z**FA(#%DgDj~0lyy%jMx5F64@n+QR#*h_{pn!x|00m={3mmnB@3WB`;XHCl*KVgm7 zVsZR8HqFSA$3K_q<)52L1s6=$eikcya{>>e4&!U}KQVs7KV$sF_!PdKH$ZOQ_!5p( z-#_#>C2QsYZA?;5?oqE(uOod2c`X6lOu?h+tR(WL2##0X*y-ktwOq^2@i&K`mRHNMSxQTG)~ zS5D`%FZ|e!M=q2tSAO!*UtOMm+~)91xAF5A9^8C!-_T#XmuHrC^Vwy|%2C;m4gEiK{lgY8LcUti zW04jM6b(hIrcKn;^qA49KP*2w?p`q@oth;ycU&APof9cKu(wZ_q{VSE2U;^DnfkO8 z^gEzvik@S>!VV3&_^8$uHEv_CkBx|2&=Zm$#kK+UXsKrHxT!)MeX+E_t3pS}?h&W_ z01V*Fxs-o1_6i$`bd702pWL+W)xW~}Yns#ttbK`e9ngVTHA48BZqrkcKBOTT5g)LE zddeS+3!y6sBx`UNLVvzaYCzjYcn4rdyRuUK-&WPDEpeB(v#Dz{oYp|NY~{7mn{3C&AtI6|43)`Tu!rgp-*)z4*b^gHU3 zi?5yLs{l{=KY(m8KR9{7|DU06X@Cnq#sM0b@sRo831Zd6+f((G}2m25mpZIv36j}4j( z;C=Nq(4g@E8s1cNzlZRAGc8BzL@rXqqENp@K`qic>gu|&5uIobG}rDcTrg*AenUPJ zniI{)VZ~5_UGPkp^bfra@_w(r&L)I^kP0?6IokinDX1=M@ z)?IMu{%zZvTRb*fKcvzFhupsB+hh9Y2r0a}cxS?e<~qsHpj78{-N{vTg3y<&XhxL~NFa@zFmU3ak= z$8(BK?8)>E+}_FeMa6wK6k17W0?SmC_w#zy5m3%ib+?Z?AKfvaV(w zp81BXm$8}InMH{X2Tt9Q#)WV~9tcB^Q9}r~F;>KVq)G502hIW(@e-wgk>D(Q>Dw%_ z4rpg3juR(fH+a$EP-|#^;^pPb^Yih?c0T`nb2I+L->0vnzL`D{zssL}tB#(g=riiT;) zg!eRU!GI}(9~hZd_ybdHN?I);B)R*${0d8c)2#ooUah#pv*|jgC1i?;C2XscFoAw0Y5=wuX+8! zTOPc6UCUI9E`nIW)&)5$?9!`pCL8-~ZqW&zJE`zHv2j;_dU*3oyBm9UUD?t5&7di$ z9SgmF%Q?6F=H9&zeY~(Gylrtob^GS|Q>x_diR+fIoqyr}UfFd6V#W~PpQ)V#l_OV1 zrE+u?HiR#!92sSaF_i|0kxP}%_v*{sYnqS!dE%u{ukAgy>zvYAGt6$upw`%{e{uiK z_wQfZOqKJ*t6Jv!miz3_&|^F<0i56^iwYl$HL%zp=iRkq%DA3OuV`O&XHadhl-a$` z)w|VpmA%|qWY00^<==gH%j$=MQTN{#o>#LpG1j~K-1fDtLGcZQDU`*^I%af~ zRkV+F*a2@ zlYQqRbxTeMJGyd5?cCnp%ANyrc3+vF3T}UJ%DnbXQzle5cvfJL|~-hkLbp`M02S`iMdZr((3Y9evH-jHK2a+cexH1<$k@5Xs`leX+m zG_C8dzc|#guKnCq-m!_LHRmnd%Z}~eKWSz~dwWGFo=C()*WN1sSJRG5yPG4y{zv;s7K452_o-6#ymjR42ds~zQd zO>VwvMv0kpt|c>eAKpEqMA-=?YY(4H5>1klhd+e+88j^F*J8_(J*@xgu82z>c>mgi zJ7><^c~IHOCCE382V}k#6DO1O2<0{c@dE8)2}va;5xD{%KqYQX!La}`lbnF%ADgHj ziJioA_^}h-`?W;&__G)&BH_T{SuWh9Q5gs%We{KBH)F%N9|@h|b;`2|RZ>Vw{JSLg zku1(1266@hi||q9LsBC9Jv@Oj%8X|d%Ckd}LL8w%NboYlX#-DFI8UbVKzU54@E_;D zhhlYryANDzXem4qY@z)g-4lKA|3u1#3jm$a12@oYUO-Bo>;rm_)N?ZF90{R7ylX!& z%&A?V!5i7CkOoO49cm|D-r-`7YPR2IwZs|PkbeiC`^vs!*)O7YKpTqaJ6^`G=sWbg z(w>>Vf;Usag$L2NAdyk>e?;``4su8rH1jPEdaM?-ny33@rEVxLxrsu&Yhv|AHPg& z9DJYHG0|TY{nv_;%Brf$l1qOdV+&>-tdUP9w3T^94o6X5r8e=AujIzInZ4b-&mV`s z>v|kn!9StI2m_!bf}9+|C66>zplpx|-1d;e2Dce^nAQOgJ6C?1En}3b&Xm=6RnxwxbjUsJ z2bM)xiPIW1M52SAL6mWNSXXFpUn^o4xZVuCizi=&29j$k6^K|rDwVoTENq9-OW^`q`_Mk ziAUB05TC4ur3~M)z+{5=*$h#<+vw5jNd;MK##fC2d>^)0$t~bB_}1ySqEu(Nb@wS% zDe4j<4i|g{pBtnLqKvj=^?@^BhQZD3nX|3}JO*M!$rlD|Vl-nx&D@dk7GyR)24Ycr zt%HL7$#a|o1Tmws`}}-Opt?ePesj0Y)ph#;m#s`#&VNZM;6pz7adJ}>Vb zrg@rPa^0u$Q#7uLE}#KG7d*87!CQ#rbArv+Vr-M_UQ}m`5<)u04FQIM9T`wLpyHiR6ePH9uQ>%NH z%x+sB)#$GI8*}{aC&S=kZu=Rq#U5p`haXO_54;X8(6*J?wHT^HZIpW9OAr~@mt!%2 z?-v&%aq-5_CtLEI=&@j*C zEHGGlpLpeo53c^(SHL!${Nk$-8!o;0b@SXo)qOB5y&dB4_GD;iiR`>|T3&1A5NQAqrVQ@)sSb{in6v}%w; z7jq-#7E3Tdc9XZhb}Q_4Ggr>c1@9?d204?MTNm>RtwKC`&C^x{^@`qys=ymmJ?G-b`H=HsMU4Q76d3-LJjVW zIxTdX;t7_f^hki`aCW~UYB!&WDv{fN;CX;xo>YSL-vV^A7`~;j7@@Z_hA7}gqo3SX zS_{CKqI>#Skl#<6)CIVIehPgI*9FCdL1rhj73)C{h=jsd^1L-RAT2CK-*M#yaTOfm z7|o9*o#M+}+;Zuyf$tu9PhuGrhLKB1CBWmLsoP0v;(zeg!y$zlA)|AGA*CUhFc7?S4q%t`D!ldH>{nx)E|oN{wpg{!N(%T>{4F3-uSl$x8$S1-Qd zneRVy!(tJQ;51iM<88s|wUc+wDleb4bMpDKjAh2#Zn)t#>}H*R$EK?3TdH&GB7s1p zHqYy;s4lCmEvv5ZdGl)NT3v4Smg!ZS?pX2grt#x9JH+b;BuyGJuxc)&V^oP%f#DKti~TMtPKgC4pFD#B*e+D0d zmYLq<_W3<;*XNsIpMUfq?DNxG3&=h{s*GqlCCwrrZ-#u7A#G!PfiXN=8R;`8C;4U+A(-|$01{+vA5IHI1%=+ zN#k<%v5EU~)*cQb=qU)*9p6uAf}YQy>x3=CDEFsbTmS?JGPP^Rfde}_cOTxe#9G_= zvTJ1v@X5MbR=QqpE$HnnXiXemyEw0eW_d~8VnX2ZR{Y|=k^ z_gx^Wp)H8-Nv7KZy3Gv#29O=C-30*a7T9LF+N;{jO=9S|LL_qSR6kl;(qkM235Qb{pzL8ZmeAT*`^r`AXlt}529YAF z+Ld9%`5ev-@VGz>B;pL{SZRIgn4#VwAks^a!|@{42vGxvcA#B|L*5FHCR~1;J)KgV*D`=XsnQpsTdad4%C3J0>d`> z_^5LzOVcZRh_bly94Bdsmyao0#U;?(RDw(|86=v_@nBL?kAO70kMp8vgmqkN&rAl+W~;;gX%WkpM{t z6oxFz4Vtu(UovN&QTz^AeF@tnnmanF#=BSQkLTEFh-I|W)NgR;SNlpclrJ6YvX4#}ro z8JjEt>IgbYUf%ypWArOV)ZmR$GDsvicrwYymDsPikM;C$2D+cN{J4C0`Vig~sy0CD zPa=&Gq1c(5VYeEJOF$on$;VWiVb7er`_g@g-c%evnlMf>y$L3pFTDz{!M6&xhQ(H~ zL#LhW(pcZ}%dkURbU#MKj|wc+w6!mT`{wQf1GHWZ9U=nU-=DEfCy5OBoi92Q{yxPj z!ylbSCTT(YW0N6ulHJS5ogqcwV z&qu;1`#M$sT3jBNhR#q$*h`4}OLERe>Oa}vH_ZJ7agmWH#Tjbz@s~1%;Jz6CRNADJ zP4aed&_&*k}kB9L;+<$O24wD4k!dQ)04Ok9slF9GNeFF*k zcN3`jd-@WIzW$zIFxlUq3AZ)2nZP260oKFR2pdWS@jv7$i$2Ku27>)ToiFLr zVL!n7g18D^H`s_QCE(!_XQmYc+LH;6!ad}E?8W~W<%dZ;YgV}w z70pnQU>H}Te$!+Ug;OTh=yJ*ZO4;Ze_?A*Ce12rfgapc>lxp+?LgUDS3E-h;i2syo zfQ>(fBvefQAu}V-4X9_*nJx-j4Ap=&lq(Qh_XZBC4F-8TyP6$1VgutLrd|1(oA#XiXWc#waFCwugwTx5zJby1j0Wl}zOHNL>V#oj=<&U9Ir zp;UpYg2Gc)OR5OHfND1SGL>tF>KjsxGlizwGwt9yo45YUs5uCq*sF1eJyU4{vp=pSg<}f+wRamPUl?Nd;5Db!1!ygR>Qv+l)*1+a01Vzq) z4H7pY&LDTY$m|v~5gki&SF{`HD{w0+rGg%s>kBDg8leV&=0dE?2r4`R0t|wO%7%-) zti%HH!hso7SJ#3lyJ}b;eVV_u{bV0dMEU1W;`8dBJ_VAhPuys;^&!3%c5wj(QqXb5 zo?(Txb8v1C@i{$MrKng~W>CN+)&eaed0=?VSPyAcIK9<|i=B=sVc$lw6>0%9wFVp; zhOzZlajnsSq9Gon!iqm1;grbR1sH0i6Y(mZ_hZrx7FAIx zKogz))C7HOER;5|r;v@McKR|73-u}K?9=*taYis09OO4hv?aQgS$~Wuk4hD^Fk3zg zBKb8pHU^7;(+G>5c$55V%4^HB+n$!aSL(}3l>5EYz!30_^qNkwYgp5V*40*lgnaVh zrX`q`Iyxs+OnQMk^9`bEW0#!l+DImQEOLmbT6?&mc%W;e2<_1se-ILMd1IH*Po{pp zJRV*P=2yA>4A-g1r5tX5LKs@cw-ks!NlZQevtZ8iP0sd z2R3${aX4Vy1VyD7q%~LZ(o`cRv%iu`jAi$73#)5;ULc-c`F~UgBQ=6ckw*=&zvI{ z+UcS0)T{JRySSJhTHV9rDh5B`Str@$eDqR%Sk@TjKBAdX$^AUDhnuMQZDv6HUQIs> z9-imOWiAm0BT^ef=^7_DM8bGSLu6JRm^5pGaB){%CR&jb*Jib=)#29Vn{K;f`2aaq zsgTQEMagr8pWYK^eczVS11fQ40 zyr+3q1-(BgKde<143rp|{IZU{WcVUS5$vGq&lfQ#T16*}U9kOENMz39mMul^O=@w9 zXMnCUr)6GC4sC?nh7O-QaM76CCp|Lh*3yd(B$gk#a?S&Dt~|6nG0+m-f8!4iFP)jZ z|G-siL#NwdyluQbeTz}m;9;v_a zP4NleYHgHnj!%HLpFbPix3sUSB1rAZcvf<6z56qP^efdl)#xu zoB=3Q*(!vfMX==yp!7p&amjz=!pP6$pG9;&e@>+?Xa58Hb97^?eX@a1bpc{I{;_GR z9{xxk{OI9T*fZ&)huwU5K9H@_2e-@Q|G@?H=VC~Y`RvJIewpx>MGa&_v%)YQ)$aoOQ);M zK~)9)|FmvKcqxN=E%D$aIJ-PWt8Of3GHrQI8$_Zxuex*I}nb zQ_y<;H8dg_f2@oGsmP{+9WM-0Oz;+=YB2#th{KY!IH23eIusJ=A(!6CZ@$@o=|9SX3zi2DzN8bFE_?N%l>~g9b%+<~ce_6Q9z zLB2-vnp(|fiEUF3gm0X&0#{Rw6ctli@bZ+6Z}R!by{X$BH;XYP?Q0 z%9mVyV^igp&4zbTtS5!2uPW{QN^f3fAkdhHbUlQCoDaZ|L!At>0wBtv-kXyx<{ zDq#o_#J^JL6;tm>CGEv(gC~&c_k;}&ms(}E1sqnb^sSSsu%HfmghZgM7*1DOrv-{# z@Wqrn8+@?EO@np+h9kbjmR*lnZlV zx|o|fDkU=po58*jmI`t1zc5Pm`p*a8*QLU(zr|lq|L{Fx4;Jst>F0Vq?*7-{QJO4V ze&RlYd_JJ){$I}-8h`}XJ zz7?KTMAq6eVW4w=a&B2IB-z@s^sa7Y{rKr6F*`r?@u#F``ED}b_S7!Uk>9;6T3XyX z!Jo6ZmIQTN5^IN#Wvd@pV3CsMS?P-zc^y^&l?72DQQ#b%3xuC-;6#Wf(Ns|s$R3xM zgjKF@sP+JIdx&9FlVXxjwHP6XL6b<{`}LH31qfeJB}^1^PfKnh1m;461t{xTui$cU z`qgUENDh6JJ#$KBFq@3BR}DGf5Pm6IRO9z$saqyZq_v~ zb;~F6Cuy)C=D;=i@iZO~o9Py=%X&@fAIhuQEvHmQ-_Qq{{*;Q31q7O6NYrEnGY{}I zP<wD4m;$J15AMqV$M(8_|yWS+rb=ZI3fAtPu(cef{XYA@^{>8lr&PRtXJMQ z;$sR;=)pu8#Jsce*fc&jGLr%NIHG9et4B&KK1CpxkSGZuo@g5<-VS7I7KDBuI2s?{ zu;zl;q_WtUdYoC^duBFOpW8CNG(6etFq!W)t98)jb=|XP4)bLm@ClRax|^B<9`C#y zdqKomKKI6Ops}(fk(YChO}ERCZ)S$p-dj*$E^iAor}HVd7Wuf)NKqzlW*UQCC2a@X znX`VTi%@cMy)U$CT(?F^y>Wo6!>DWhT;{-r;W9r?^+%;u{UnLdhRU!Un|zdk^uMQh zGC2{uL1l`GQDs?GWxqZ@m&NF7F_z0BWQ~om-~hdwHj*Z#qGOS^oNB3nx4uqQNVp*p zcbL!%!UTx~kPN37j)yp)Lrq2u1*^(nB$b%4i0}UP{2)5HJ7Yhz~e| zdV}>2Sx&z2+||fGBe-!z)a6{u*sf<^5k5@GqEtKcoSC&vV`?fao;Ci++%*?oRW)tV z^m_4w`|lqt(VN^Z---KKnAsk9Pl^J2(^T@_1M+9`uZ8XQXy|TgENu>TDdSB|c?!insMEx+Qz!M=>m+{7I{hsrOXA2nb*;bfstGGrPL;l* zO22tEP|i-TQTv*X#?Ba32tYQFw=To{5ka|C5kfffkm`kx04$>*M;Lfwl63+3?s3g$ zR%6a!GTN9@McZsR7I7@%I7x6hQoL|l?x3n{Od<9X_OvdlPQA_j9eZ(t!OqdZ;ftVk z1HuX{K6%s*1&Z_ZgG!eh>l%1!R*qCLauNHpj)fdN*kd2|I)$%kYyX zxp>x?DdnA!3xmvKEWE6@qGeuqOnCk5c^BnJ@+%@;%MR-!dNYtRg@TB9cv)AZ0@p8^ z-?bih&1*?~P{{!P>I;{Zd&X6DmCjkho}NuV?Tpy86sa*x@#9eyQ3S4jR|V6@ zvYP~j)AFuBmainBzWc#9Gp@em%lhpKC@yX`HuXYZyzq=-##Ck z^iGl>)~i=^C{8Ux0@-M; zZ=3q8_;^aS;K98+=S=Zy0e9=4GH2)B2Nx)W5Z@ynNi~Fb5hi-*h4eFc<)tvcr|6r0Qou5{qQ8d=5+2 z@ywIl45h}lhm3YT$`&Rm&-_J zT2LYdxsv!JgqV4XqJmVRc!P`IHUZC8loLkFDbl*Mk>ieS^mNi8nPUTiaa?IyLe zVf>ng9GEC9tiobs{UU&jO=@L$_sIP=y_WR|4&y5C<68y?Xrzn5wGZZRsBD@V(uK9A zYM&uEZTtjBNg35GRA6)nJpc`+x)q%Ya(-J23;0mo0BHz48-Jm~#US556Kl@rwLM+TJD&p8uVu<`Us#N-ZWDf}z1l;&b%JCe5BQ zYaTHHwY@tcKTjZ!L){yshpc9JyyjL^_O`4)3xF6Rw~IxHvm&wV02;G=mt1L zA7q*z-ZM%=j4FdzepWH+~Hh68Nu+sCw^XA7qY^}srSEqJb|56j*sRE-RI73=B-s^mpI1f&srlt6cX;4&{f_^EL{KTQGabEI<2!#br0& z{{N{}bDL1%2W+yLx$vNa8Q;F$ zYce2TDR=_#yd$PR<2u#_Hl2-gp8jo_iajks@JL_83|Lpa$LS%-EQ zURM=apCoJ8))mjyGyAJ5PO;=Ddj=0xMWry(BbASBzHTV7M5k*MzQT8ll#-PA85(+U zKO>yBk{Bhxh6277kgFX-VN5+7Ha)NTh%z zJsvoJ(^Mut7~fFQXmf)1;`$n}3#3!8CvqI(ykcFDT)g^=ivn^#UJ6HJJ3a}Oma)&Q z2e6ydGI;mYpp5sjWI;3{B#r$R7nr@_ek1z>#~A#&dS8{69IH z<77A!S7pz%k8qE|is2sR=G&d(mD#gtnC@#p-Q9{O9P?_)@ti{<@b*L64dRl(5Q90% zmQzSyz;3#=wxNf;VX@2a*v%F@Fnr~cLQoz^4T#C5xw*IIcI7S=`mzhg9=Wx)r-A*4 znI5s2>5)`I2r|q~c|hn{iYIQ(&0X4)UDE7!${}B9ihD*^Yc)W>PIGP?pyPC!MIPgF zkb~r>K2#b)@EmjmOy=0AVc)|BfSo@k?;!5uEryNHUOp3{E;jFSTzNV1_Yn5p4& z0`ZS~7mi4)MZp>rSR<>%V3r%|3tGc9MB zRe2<3@d2ew8VnrgC`vK9m82aGuiWo!cgp=v!4q&yh_e+?~~wsDa#{`WsnE(@%)6X15aq-BXGG z1P{{#iUb?H75Qf1B@!F5K1DP6NSjz4ApJ?Zi+jjKs)oOumau=x7!uNWl|xcA=MyfJ z1k&vFh_8i3lTj_1oxT7%!1VyWmcOOn-<6DY9k zeyN(hY111-pE@A>knZJWD>wunbO7?Mu`gfdC@RQxBVCNyZ2I#Nlbh1cAe9pG=rHv= zPV*+SbKF>mWwXWc22*+Qee)4A$s)ZHGRY)20y$u_KhkM3SvMN3+pb2+7&Tsifmf5E=#u-pSB!S(VDbmw6V`^%i>y%xtG9{&90 zBNO!M+@kL3zj9dinw|0$$M7JE%2c($ws`|G({h}^)HcL&lIJ3N0GUe0QlD{*ctD#~ z=uo=)Azc&Df2jMY8t`@`_ea2@X~Z{va>QZTZ+5m{+SQq(wp&+gZC1UoX-_0F`_lYK zS8ZLad}d|)n2H?x^LIJT`z?-f>pGep8oOz>&T27>-ul*sCCe_hmqeyjRK^>6>L99Pm zDGZg^G!EAxEAm%~j&PoLL8reg76>B^thX}SI(|{Q&-S3tTG0l)0f08+p+pVfzGL8m zl@5exCSZHWvQ=~+X7XqWW$6M?)J#@ zsc+a_POCG_X7@)xfU?0B!rThb(&fxfw)9@>2#4twt1D*Q^c7t9g|KwME%>AAfDtlCg zO?6mSo1OC=mR_?{Xt&vH4tZg8p>L6$-Rrbj?5XcL&Ak@Ke5ZLeFgKnyJBgPeVG?x! z3=s}#iAJy#5C+1b;gSsv#vy7#ct+{z#2q{&=N?F=FlVq0sh8wO*uSZrWUbSDf5t35 zKvxD3P9JzlT>a8cIl=ChcmLN#qn+1q;bxS5o5ev21X3ZOY&sxZ+Tf9$r@9a$!x?tM zqzed3M6`u!Vqv-fpj+jFA|r}?#E4Dc0sQe>_iBAdeA;inen0j`yU_O<)%CH^ zb+o%+G4hbvuJ)_XVXM#6`gZ%Y%h?6zs{L2n3`hn+()V%^pE? zUJ9Z#vQnsFzhFm`$sk5)>Q@`SZj^ntux;|dxuB*W&Uj*c; z1jKy+hgP?0=mbjxPFgk6^^TjjZ8d9aW^TP~&h1?#w>u^~Un*#N^Y{a}QrL zY5l}Xk96uJ8wA3^Gd1iGV+Eb}GB)_R@Y$fYpy|BST}2H=IVO!DKgvY4$>xV6#}}cR zkQZ418PsSDDCpjT3WZPSW81F8L=LNDAZox&6$#nN)DQoS40uBjA)|S+IH#I5REw&? z0a7jyHUp&%NwSo+T7Ico;nnziNv5izdGnQ6=2_~X5#K&L%mh1gsropzq756u!FR9= z&r(#BwGg(AU6@J+$SUosIha2+kPG5rEfyK1N=y4caIr`+TySX#rqMV<#4)8>z+A#W z3Aq`V3OC&tN798jCZ4v2_RboobpLlIn9FN96S&_mhSV0$e}$O%*#+&$3O( z^@rqcCdUUC3-$8#8mrNwcYpDQJTR^DpOw?(cPGAo&-+sEZ!2w*ixrwq=4SwzpkY(@ z&_p@W=eXi8=LmL(9yrrZ!AqwXtkWGDMmso+J{Jbg+|^PrTVsF`kV;bD3E1L9PS6SK z=O?FB`~=&cGu3(+j6Ro8o8bz` z!85mp&^M~iBU)ovvl1Mt;N~+m1=~FI`&k=+k9qa0>ABuP-n|iW)_{5oT;titd<2d- zq12QRqv-h8?Aeum_jj@CK-m;Rw`?bOZF>lU1;&h@R^FPKwh z(`h$pCG)n0-rVcYUvubtLgnVo>~XD6Z8Mo2jSHSjZ62EMLv^p`p3TE`|8hDvs(Q{Z zYmTo`_t&!P_v0^V2q|6plMkJ#_JgCVsjfL=d(iq$a(e>nJLy+}1E}=6;)pRCT^hpx z=}3_8jB=i7w1ksPdCp*OK_^260(ihys6vn#keR(_b;AGGv7} zsMCQ|rV?|{+}uwu!8?V(P%s8AENCkWPH$;w85h|&VY*Nd@B>33;ukK@i3q~x#KMrH zIZ_fUYj!!^1=YpP`M&7%vOp<oB$@JDx<&+A))0Jz~>h*p{ zsI#iqms1q=hcBJ6@XmJo^r9;gjry3?Zm$rDVPj+*8g6=!5aBbr96hWnUc}0@ zU}UUB?v-m*-&8%J`VmG+8~|rpH)ec2z|;!e@Bu>(fp8o+Yw@&kt|qOPw__l1gB@-m zwve<3bVV`ZK@Q*!tpGGZP*`<+ZCx$pUZUWRYF10m%F$4eBZWe}1``Gl`DmPhZP&&q z!!_PjgTheU9=B&G3ONGN;IRo1tB_@kU(5*d83z#YmOMKQ19{K3x2Im{nu;_89kEDA zuW3iZ9G8c+X-#9op^lDV(HN8Vq#&9C@!CAMD{oc6eMO;9!{o~o3Bm0&w3l9m)Pf&f zRW{z>asdYXY9V?xAi!NI^EuOM;xlzYZP+-Kh1_{nH37FfP*auXKGxB}p`|-CM!cPU zo~{1-%U#uo_IS9krsji*@?v)X#NF}@#pSuSC@Ylz;S;O{%(vlCt-EAQ5&P)w;u81M z`aFxrQ5+34UEUOkMspjdkFW7FliMgZ+*wm|XKhOS&fKylwbiO_DqDE;@p+}qblhAz z4-t;VKmM_Isdsh#PcPonm=}%aHS%4cnQfN;TwoJ?4C!nm4mg_Wvb9Bgb^tHw&sZyl z$Hx+2*X&YVt-3??7?;1XCQwL-8q8m9b)<%{ZS6IoGjvO)^WqpCaT-r`k$9L77=)ys z*0Jb$3^xc^)jU(LRukky1ksr^DuR53uo@AaPI;1QoSCslj0#aDFM#t;AEDyQF|Wtt zjj=iBoHN+CPJU_4N)}waI3LN2*EgxZW9#6nJ!c8XTE&xrSVw0p zH!n6}G6WDI)wf`Q@C(0XQRA~I|FeyY&3+s=JtMr&j|cs$cC55iMsn9qVo&ErCUit| zbE6#-BDrkVl6ZB6S+|6VjzB&u`p*szEBAC(RCFHh?oR!LeJo#D;ueE!y}YB!7isB! zVT!+@?l-A5W9#b!bImn|q6rIE&x+L4L}neuE*=Qz#UH&fVZs{|Qwu-b+SH|SyER=+ z8$YIFt;?mwv1Eb4`|r#;^}ykVr-bJ2e(wx*gtKmvYJUy9Qw9K7Rwy-)z7lrwT&jZm<+%7|kvAf~R?ER$J zFaFGEOnu6_j0S_}lM-F&BfKE!BO@L2~kRm+3yHr?;CCn&h(cM6Rr`>&b&ZHvWR zB+fR4Q!zmfg&{bzx0&#twyQ=?7e!A3T?F|u!>XuKEC?C1CGsNCItkQqK9(ux1_fEB zM>C=eRQa;1pfD7&SrO_EMZ93O+SX3`{owB3Pg-ZQScUYtxF>zSWU8GdTncvfBk*qr>xZF1t-VNG9xeqd> z31h`^tC8gy?uao;78$YwNh#t~;}0%gNDLlvA}f4fszrQ?oxCZ`c8Gn0zlMb_)iy_X zIF_3KGvT}$sUz$dyKbkvNoe13^N#(uuv^%YR7V))8Au%#)-D=r@(a&FCd{mfiroyFVNeqCU>qrZxaLwe8j*-c2 zvKWvIYsh&NJw|=*kwufdU4*PdBuG5=+@aM56s@W zb+&ZT?5!6HSG9HSerqSQ_II|WF7}7R?8z@4d+dwHgd6Y69Wy5PK0Nf%@aUNR zBPar~gR&sOs~JlGRNP<&Drg>I4Z!qqf)guJgZm^$V{l}@TqfZ zI5q)N7(!7Fy*TBCs4qec5rDWWb=%^xyxeHfl==;p7niq96QvuMF1h4A*W|J)`5pPA z(u#y5e`$U5dvCYJmoCs*&1FRke(}QUib-=4uAHF8@du%Pz^$ z>vfe?T0@~fH>}s@nzSUUah%Bs_?rJ3=KW(eiaVpvfS$_>tQrI=Yr`FZ;kZ&H& z?nDcseFe&#SqDznS&N*-AXHX{8Tm)o@C-NUqOL1mKA4@P2u*^3Xf}z1KC*GFElOfs9NMI zn8O;~evR4%%~g)e>C?h+rPk)8L~SfbTDw+by1ij`pkjq{{955BaZi1yEnq6Ny2j>r zUi-5mb*-z=*yYMyVs=H{@K>uIo(1qqK*OnK!ta~bB+w~jw}tYXcuvlBy3>3vH4=Ey zI0h-RHYmWQ#`sqq!o)6)I{>& zvV#bodyRQ{Rbx9ZgVDLPrFCXU>p1pdc9ULqtifx~&0oP{$5{BBapOvgz2B18&nzt| zinv@Bv!p()O~g|PA%&ra=mS+c-@<5>neds-EZ<`=TMY7DW}V(OphTiUNV3UE#6~7< zPNy_L%A1oxyoG!-R614X(fEZd8m0(n%gaK$(28O?}+`?G7v zra%2o(xH*{X-GQ+-3a(4O+OW3RH=l$XbM0wW>*0Xgm?1(R&PRkMtQ_wdRURv6D|}H zLZNWC#6NQh3%^5#2a~Lf1R8cAkS>pUQ*7Sl$*Ls_#<$F#U32TrH*VVa$mBJ>h2_gv zP1@dFTRST}{($^$UVd9$U8F;tHuZ6aq=Ibxu3gUugP}s4sQ>Zap@aGPg@xmb5*;<& zn|8h^UD7gbT3emNsJVIlx-p^+ZrekC@t6}L)^sD*a#&I$a7m!(d1Ws=lv+T4n&jX% za*+}oscqeeX#78^3xs%T`{2jBgqy_+2j3U&Lj8$mVTP%9<84;>|I`EfZ3(VdlQ)*e zC8hUjWpz{7JcRCpQAKx>o)Y3ES}GbRBTn2-L5k$14rhS60`eIGb;BT~6 z(CZC)*zusp6Z8(AENO09(A+G|N|aA)UeJ7?xwNF2O|3`>kFHA&u1Kz*q&1nflb5}@ zY_isD(z3(!dvi%?vy|th_bC5<(Oe?WDQ#{pWsjCLJ5#GF5`UtzKPlTpg>XB&x&DQ1 z+g_;OYu0K^`$|gonKW8+>gLQ-rAbur|yq$=ZoR~y3#^aB=%C-|g?SZg@QjkuR%X<@ z9cDAL6y|s&$z_aLn>0F&Cnu6?Fgn0%*mFF#bq=N+v z8wwe`O_{;6z@G1O$AdM6db2|?!RwblTkl7!l>*!cL`qHz;|PgS_0ez6rSh|v%T)D=1c4!uS2L>)Gl)6j5EaZ}5b_*i2s z7z&9NX0iHh0qK0^WExb3Sw*8+BhO(vz+CAJ0<#&A!3*6j$hSLu)|`MX&rql>Rgb;U zzw=|k9&NfPDDn=>RKkY=Qt5#o>1o(yY-@Ow^c7n+Hp`{ zjVrL06$qkH&+?p}d{$Br71LGX4bUt@MTW&65WyYUx3QFGndTT|oXl<&h z@OA2JIzg@1*4nI-qdHARPKP&-IkyJgYZm(*k)Tm5vHJzMurRCZM>?dC77ef>3buNQ zIR=b&9X$JBuMUXnzX=+hU}a{rMl!3RY%qyTI`NVz$LsOHbJ!s{rv_|Vhd$4PVT?}7 z4dyV`Y{sxQ*^S3#%p-3qoN8jjnT=^3)N_ zy!wf|#!pg*s=_&_R*um)b&{!|CO=@rBA3B|OCqj32n|IAkV0BvQCJRnF)D`1a2|t} zON_>(5UtQ&B}FhO3CKiH9fhK}l|h|Rrv^!)6UiBk(Nmo60DB3(Id#ZLmVslFR3*y= z!B%(E?yJJqXFuH6;tt9`l@GH;UDY=pxHKA(9IG$hd7wYYD#W+n_{qXC8*Uo>I~H_d z)^lG>pS5?(gi9thTi+88F}ekhSkfwhUH8PiovV7G5{Q zcv!fxs`Xs0W#_w#7vIs{X)!bPFW5ig#LlYM~ue%Ondf@LQPFGVK5yDu$0Q2 zb7znQxJ7j64927rNwNc}vF(>s#NQ9nmR%<#>4e)$Ma%F_Q8X{-rJ?jv55WHd2r%5r z12-SHlLiy_Dj$+6Fo2wKcmi>grV=xaX3xaRkn=}P-k-`p*CR@(y`rz89kv+#=jDIO zt0`^(IO>$uEV+6LaGd0xz5lUy?|(3Of|RoP`{eVj4uD#JN~wVX`ssIA*&X}jhf5oZ z^L#A1Zk?R;i9PhdUZt#%EeDXvhP-OQp;FsG+jPb~%&us&O!*`gViywtd*pvO2IwY$ zEad@S8ZkkcNPwB&Gq{nLAy?!>u?K z0@x^zw^GjNJq3PnD88}C>V!dgSW-4>K^%3cxh?6zc8D>=+?lEi&gii zt#;EFUzlz9l~pUhnoP>C@~imOX8z&}6Yuk+`um7;aA1V0B1FrGlxaBCLsrTN&%nwv zuh$iE)|j9$$l(?zz{UBvuHk9ZjUS+v=-p0JI?9vEh#uUu_#g>~+ z9I9~?Sc);H6@9T{GcKjxfaf1qdWNb;YZ*q{kflTx>V&W=dj{i|6Dpd{8f=Ac^VmA3 z8cfh7Zsla(9)`ofOcqqZQ+=8q=mXl}o2J63FNMHMl#qr2kUKF=083Dr9;AS1f$I{% z{UM42@jEmeLKqZjFdYVYFzC_r0P&*ZH5i)f951R}iT34VlQrj0X|hQ;ul4_`q6(R&HjxqyI1yQva2L&u&tVUoq#0+?C@u`5(4><-(Yfw69 zM)MgY7ZOL19zyU&Ah&3Dd5`+W%rw~x>1rsWDOzjI#D7EHj)J{%2hL6 zQDg6v;&!vCP%n6#M!&#JYI{Mbv37CP*jiXwpcf>6>5|so9R@4RJNPH4t$K1FRh@cB z^SOE&^vy)|DiM*o23BxYWJnH%w1eu-W1?9RFJA=tjV2?)$l)YI92>=@ zI&extAX4bUF`K-3Efl>9FbVRiuWbGgJjqzpE~ph`F9q5A7h99z#=R<_23WXl>EN@ zUvKTXCix&+Jav4zq_J2vnrnVpQC=>nEe6xLrJY;nB_F(UYT^cq3By2WYH8bIwg6<#(YQuf)_rLM zzK$}q^_cN>-x#%dR!?e6!0)II%z3JFLfoM#XsFcq0bns~ci0TAh!Z}(DhlC`L2#$6 z^$75%B*aC?NDN|WN2H^4!NV^+|L}ny7lwZ<-;sLd7+k!i__0?~PqL!>3%k1)esS>N z7wQ%{Fesn5;#bV~T{hvDsS^2vU#(zA2HBtUe<@>%LT5<2s7s)KK_nith{U35R8WUt z^#wh)2v8^h0aozV(XpD2)lf3UE7XwoB@09wkf>IyK^B_I8ah;85?s{XyP|tmv(3Iq zKJuCqDOQfM(p5#1yB95AFgLXMrTv@Ra^iliXHw^~ISUfynu(V!U(iw$@~8ol5SY|Z zYl+rOxuCg7t#QGo3AxBpS+{7}<()#TW#;^O)0^yeZ?(oZt!w+%>)3a?wzdRCOMZ^Q z@Sgl{=8xvEw~kvJI&<07-E%8l;hEFR_VzJR5bb#lQ@2dawL8Z&wY61QZI?{ZxF$^9 zxak|6Ia9jMSu}TI9efFv__f})cw>R!oq5@umV5{1k9gx%T5nTDRH%a8%nkqHzryxO zUf3=ko5Z;+3Z#Qt4r(|%{YBs^rZ6wkU$@L2Cl97RnY~5&<;jxF-RMMf>bHYgs8rClzow^(gBx zJF|h|PmAb+)*4}pNHNOVC=;lXfmA;ArKJ^z>_wS4P_8E(F6L++el!mtsiJotLDZL&koA%;!_`kmrnBt0xYObF z6~0_^F8Fe{st#1Z%ULpTX^wiV13>-COsED**bl=NE-u?zfMH z#mLsxp;cFw=9ZOu^Ylg$+P=!bxQTW572BL9cSn`o2x?(3Dsq>!l+G*MyS?}7kybl# z@BGT~F40+1Kfg*_F}-%lOn0!tH+%eQ=;k8-x3a5&v!lA|bME`x_p!T4^PK=oNJ9uA zY<82)hZHtp2}wvoNMlGs!ppq(?t5?Y=FLpzW50l~4IiaIDMri>u|-5gtcW!#(we3b z5h)_piY?-=h_PaeNU^rH@{7U$xihob1*|{c?wxz?x#ymH?z!ilduQg(On(+DsR!m| zvI_(*9-cGxqLsy^pFPrBnNyfPeaj>F;3XXkPmkZ5#$7r1XxxMtOO0s*NK6yS@RUxS zuD~B)p|oNm9PZ*i2d4-8^hPE%JqD)q@h59>`+i1p?5k&vf9;X>sozedb8W?$-;d*| z?Lg8{$DEn?c1jo>r=-G)lV3Y?{Hxf%TvU>w@P&;TzoVqy6Tx>raPIfPeTpAie~;mO8eXHHKb*@F z(Eji_kp2JX6WSl5SDb#<6Wd`wVDH4?8{K-TQQ@m+ zLS?IRY3i}F;_uj2pl75 zClU7|W+4OzMtv1JxRn2tGcyuK8(vLzQ~JZVj6V8c>NRG_K`5?Sq3f>$4Yj_BPe;0 z7vV-#dm`G2`Dwg^E;**HKnOnArk|1SS9vH0UMo}`A@3sBqv{&dc`Lmiz_>;X>^O){3BW5ywLa2(5ma&wXHpGX($ zhi!m^7}NR@xDJ($@#B0z19%aqP&F}J*hn4L0^o=C*TC|3luLdKOu1YfiG}g5-{g6jv|=T$m@&o zs6WABB9D)PS28mWAbI81ze`xF2P@cxGT8if&BNPG@*h z0G`uH#9Rl{f5dMF_LKd8|IXF6X-BkIXdOB96!v9amROKDoZOInIr(1dvee_L)9D@Q z=Q6d->Fkc|k?b378`_>|JA=0s-k*Cdza;-qVW2Qvc(K@5+*^FCeW3k`ju{=BJ09=c z)p>X4sVR%6d~xc))Tci-JZ;sq2d2F{ebe;EW^A2ta%RuW+RS4!e==*qtZlO%oZUJ5 zzS%#WvwzP0bG|hf`u16c)=+=7{@ty;pq$a zUwH3@#}_SLba>I@i{8Fy{zbbkdUA1L@w&y2U);XLTJl}omYlY9&C(-F-@UZ|(z`Bw zvwNWX$z_L@o$4`r-sqj$yS?|N<#U!_zWn&|pR8E5;`4o4-_E`#SI%E~3|FDwSbg*A z7uU>KQ(p6>Pn@{C{c`j2qnE#N#r7*+?Kk@$>VIYJv30Z74X-xZv@ zZdd27y}O>+^`qVWyASMsVE2jL-`mr@=g^+xHzaT9yWz+U@9f>V*WdfhzP^3K`%dxS zjoWTKQJPmew15Bp*Y(5tv*pF*d&{p?u$ijzeD!Gc9oa3b^5t4ztyX)t-d{gff2*;z zaoi{vYm8CjE5_*qmmM$<9BCGs1I@>qZ<$NXhs~%;)OyWcVq5kz zj&L?RuN+)*@F_R#Hr%JZJ>Iu`;qUTa3AP3=4{jZNX=u~XH->kNR7dxYK012(rp-4U zx#{(r*W7H~{Kzc>x4eC5;i17pj~sgO(2s6C_twE%A0At9_=mS0xqaI0qqjeI$DBKE zyyM|Jr`=h-^NCMS{q(DMeetgEerEJDU%ESe_ujjoxckj}`tN!A-dXpKe)tcghwy(? z%*NR~|AfK-r}ZO*zoPaihB_s25e@f0dDt^d7-KyVEO38xLj)(Z`M5(G(%@848;;-< zo;rOvg3~DbYy@Y({nZH0YO`oGg4?udbR>fDjRtx=f?v?^{k91Hy4Fo^;=3ao@s`Uj z?OLoLC7uiK($;G>Vjs|ET;r=KtcPP4t|Kf(i1XLtYb8?iK;1&T9ifi5hMSs>uR*K_ zzpdI1a9E2g(rb{~0o+yi?$kEG+f^#8Wipqp5AfLut}f~@luTXt#?Vr&Tir?Sg8sT8 zP4E9A&o)RRAxkK^3%I6ub)jW8+Tv>sq`Pn~VWZ_EsKtQ%4b^TgQvnp$S_6$cp$w-( z4f(+9cpgYX2i)!^sC1NMyn#F2!2~WAN-yyeYRq|eslI3xVu+O@&LySvwp-*h^?!q6xN^co7xCY1NIQAkw zt5ddQ{N5kc_Jq*nBOOH=uh7?UeOS9syGOfQ`>e({SCV+pK8;;iS>B$5{h{yyfvuHNWp}Ba?Hoq$WJnEwJX+GXsy@0RL(uK5$E~3SB zG2VrD2`>F!O5NDm)r0ff<@^)_zDTi(R?`~1$n7%v1a87zLH)EAbI_GEKv&Uv>;cJLv$;R(WmGz-A1?59dsvs zn(iWeewOZ`d+D=uAAOGQr(eMH1HVWQ&@a(Z?7V-FewiMkU!l*_7wBR7ReFSejUJ_6 zr^o0w@RG>i#8-oUi@r#|O;6JA&{Oog^d7VIM`WN~heV^W9s0liEAPCumoz$YSp zOh2Ljq@U7%(R+mV4A6hm8G0Y{KXz*2T6R*TL|SA7UI!_1c(F-A6a}vMicaiznkqgf zritldhM1|%7qi4{F-Oc5^TauLrsF)(CC(S~#RX!4__$aoE)d1fAg&VY#nobi*eEuMYs6-; zMQjz<~XMc8cr8F0ote5jTjvVxPECl*E3ai?a4jQ4v)kMNQO2L*T7+ z*c@Prmav2^9C1*%!V|s-#Gn`w!(v2?ikrmE;udj8+$zSzr^I1#o48%vp*@fZETg-7 zZ8yg~-Q97#EK2u8ac>kakKz?k+!w_wqj*&mua4riVcfGmj8~}mD%6vzo4V(vT7hR& z(w@}aN+T<+L225KOf``9lb)};IX;wR%kf8&fhXN$%`jV8zfm%Ew=RX>$S`bpzOb8V zSGMdynHjb1R>`okDz*bZVb^MD&!}6vnW)(Hl<(?ZBiXQ9G7E09q?>-yH(E03+IqE6 zwTCPd0Hd>UA{{u4OBq(#9?mVuWpr0S@R1aSdo@5-F%pE znYrwJJPBcX0D|>C6-mX zX}!t}p<&1=tA?NQ8oDb}m4<|dxWkH`FP&0ZuQZ2rw_2>}P+^?P#z2ylo^o^;0Sv=- zGBw*}@`56d6N*!mNXY}T;ulcQplgRMFUASggf_Emu4Pyem=BFep)+<<#l?ex zgi64KiQ5dTW{1VRiYuk%HEh2a6$`DR4Fy9eSJtf<)LqveQku+%ppqgR!hw?u0c8)H_@==0C=!gU#l&)`}#wk&{VY|jC%vU$tVDY62?7}bjLxvB#3>D8t z#%8Zlh0x+lsNA&^O*xXpX!f#^$X?NJ1g)}H3LI8kN0ef5Io+llNkcbldF5R~pOWDY zg^MVfhSh{|hCQ5d0e3%3CeV>OivF|0HycN!!4x`7(Xp&f+YfvZWG@Ih8e zjrY7V@vx%yc<_eFoFY(#Gf{)Haa+?N=X3x!RB7g6Vi+{6;A+D4yhNi~&6Z&eP@a`6 zOVi9(SgkcE)|a^ky0H{mw*q;*XA~4TZ7ODkObLy%bk-uLPQoY#9g|RjGr176fe*LK zGCkyC%r{cL?lrwMJSue7R(1_ptLUE0vE_#2Bvp6qz=2z_nkg7$P)(Pm4iAy21U|ab z8Ob@iqwL3UlAb;&bKEsCdk zTe8|T{Ctf?LM;a*M3< zf~sIPgxRAi{!E&wO0S7&BW>yqN6JwALd!05yVPhbME0)iEq5@m{ZO=g2!{QP)>;-C z6Vj$I`#$>j8{~9O4m&(V0it)&fsUsZAStf}K~go$5LTik8<{$0 zcSo;g;pUWGWO*&Y#o861Tnp^FnuU%rd+8=dP*t`mfk0+&}oBi3yY$@+znO zEXWI;wAV1CS#6Ienoyc4JVlk@USUIl;WeO97tT)d#4}u}!a+r|w(gT%B;25!Xu3m*vR~n4vTPe4vz^Khl}8|= z)6mNpk)__A)l4}z6F?W*k<4x#5}-16yR1L8T@442@X)z@CNu^v#TACdA`t||;-DUMaCk_l9+ qx{Kk=rVu5YQ9XR<GPS>b$X_& zr@E%wRZdI{1Qg`ERKc?6xc~A0WB<2^i7Cl^2Z(%A-2Y_45ThzCA}aRH^uB$9 zZxMnHfc%hCWMKYgf4_bHZ|OyVd7v9w>)U;^-fxkDfPgv7S$2Y(>N|cju!HXysQ(p` zsg=9QH@g46Jsf$-2G#R*$WrR zL!siQ#}&N%w0_klvWRwyOkEG73-*c8@-muo+C7K=Bo3EnwJa2(a7H43$lf1EY>~q! z3mwbDz*EeaKAD%~!kO0Da<=BcLYl9Y|AkDJC@+d9(`X+~b8i5nitUFHth3Kob^|K4b^+um zCzkfUZBhJvn6ir5@{`bg_*ZV3kqLJlv+x=L&aJNfHpm5oTk-ekfPQ^}Ai4oNyP&<4 z4wo2xW*l46c-}VDn{&eVe+u%qqksC#~wFzVQ80u_cqNWek zbBc>7*?S&wJP1z?ZJE|9HFP$>!(E>9#}Ap1>aQYQ5{}2y3E|wz7&jtHxVVwn=%hQY z;qjf|^^)n)ldPiv0xXz?KE!&$l;lHOUw3+jrV$bPMc!^m7S$1Rb@bVn8fpmcJZb(dkg+ z@wt!x9qkVViWH;cz*ZTCEDchhtu|2t*sFa#t3yk{U5eg*0j@NXFmdy2gmq4a;U4d| zw+Ti^aFMFVRuw{sgP`21@$TBW+f}ke)6b9Z<4V}1tn9->HAsph=1duR5}waeP+aCN z1b`;+bQy!4; zWAS1tVL8em;&*91yvo~$NY~6YK5>+OOFn+brPzsWhB3F&7ys+#>6ZD2yZHTs%Ji0= zjCppcIO<-@cdXvbX^m{?~DK#d`OOh>+l3d&lcz&JI$C>^4TZZGWx^seZ;RM^z0S&l$GBd=)kwB*_S zSXrWfaCYlS=$YSNz+arKAJVqi*_9oqUFIN|rWr%9cE`qOEaNL{q%rE%+s zn2dxp#y2Aq;f!?q{U%gOA|zcRnZLcxrJ*5oaG}C#G4(h2+({}3sph5Z2uOp-=!o*B zvEA_9ALloGI)X^c)m(a2E5LtrP?2Evl#}0E5>wYM+8hc2bEEL!HNWYx0kza0h|D9(I|EO;H%cx zz&r5VY7r(XD=R9tV1|ifO!Y1NrEH(yW88w{M_K~^&I-Dz{p6S&w#WDnvMCUSFP)>nOjbYLi|+d@eZ-Z0-%(Fmv3*onRo_phiTs z*<<^mNoMQ!%PQ@?Uhq?_e$0(YE&Eh_s4zh9olq|UZWT^@hGr3?9#o~~Zhw0Bgzl_y z%H`~0d!wFfltQ z$ewvMz({&pSbm{NXgKFsWu{mPKwAiCyhT80(2RL^sx&hTQo!9G_w7YIwv87L z&EL*@oRfq;GY+a+UUK-Waj8`cl^LSY%|AanbldO`&1_#UL?&Gbxjnim(w8aUAjIVq zu|-rOsAxqMq2V8p-K$xe5QHuvgte({1?@P|@VYDdm^F`yM)nTT>aVON_|Km*Ei~*E zr@%m~S~`bi^{S;B==r(ZDUmxOG?I6IGIODeHC|I zJ&$?qS=jo=;M8<93Vp@EsFe-9Yj<>r(oDS@Oi%cI4b899W&FS2lSCq36kv`XNT#5( zpf0w(hgHuqXm0Enj+ok?MKGml&6~4ty}XBn1~e9Zt0uln;j9wIc@smE2+wNneD<2`b!F@FG2KIL~R0*pnjCX3Y1jQ$Li(HUa|jkS+am1C+1#x zVak2~*An~Ocr8A&@`1ozi)qJ~=ZadctMC>cv$s5bg<#t0V8Hnxwhu4orpP2nrw00Uc zlYMcu%$^icmD1$$?a0GpmcTTGc8mkzC2wJS)DQ{I^2LK?l9dLSJjWY_aZ77^Zz*tt zc4P(+XwBGLj^^Qs$q4Kwi9Fe1^twrXJU4_y z#19xYv^)I`6b6c2=B4QPH|!#FW)RF#+X?IEmFkxV6yY9Jo)t254Ib5j-xd|M@^K>p zxg_qYevP4}x&G$P+7BmmPUzK>x*Y8cT$IJ)0OZEv6lcKx7ITe;!eNi8Ee2>Mm(bCd zf|k4xm{7R)G^I9h_679;JFu?6N{Uh~ANmG@OJP+ELg9t+M@ZSF!DzJQ!Fex8d_Y&n z3ekTwY)0P~TY!#Z*Jkz}?@7n(D14NQZgbF`@P4|;rA5b5qL}R)XmJ=&7IoFWtBg!F zt}M*`RwZyV3Lp8!`&(U(8?F^E4?+HzS}?N<|JsUoIF|MKRHlKS@7%=gXW#x$@qlDU zlT3~3zFji_>C|5oU9G!)Dn87QfE}zYS4WCZWO2o=WJP7lMGmsu-jiZ2^vXp$`C#x? z>dW%K;p=gOm-#PUPkl-6N+NdDF?csf5y-%Tda7O1YRB@LcON{EcN#?Tz}) zWAI#6CM@^ZQ5t;+1YQz~&;iilU}`7hA%AE{pOIohR7Y{bqXdOjmRt>M&UWQ~Vcy(G z)t#ez39hKek_g*xGi{VwY|GE{^B@1Fxn7LNt+~0WHlZ+4a1()LoIberY?m~&=G4-B zcXnOET5IJVC(3i<*C3XWkJ}7sC|D>MR4Rd1{B+;i4%%ocroOwg=sGW%aBgmY92bTR23baR4$iRyZ*1Y=A z|M>#^7&ln6VZ&qe-zB~j*ToWEx&n1xhlkoFE;;nN9TwS11}8(aolu8i+A=6re%zE% z6ry<61v-u$o!cWT@3Y9;5NSdL!Uh$D)<#;-Nx1JYt;-9_j>GZ{wJY>Fw)c$%sjc5u zexe>U(gArOn|f?IbY$jE`;$uW)t(<3p1$1u%6|6EQlPZpgns>a6?`}J`lDx zZ~k4=6Cni(G}dT)Z9SChi0~HSpJ+M_6h%9BQP<30U^z^H^7Rr2`~=ilT4eg?>r457 zLZULx-&4J#p8j_|`%#_bfr2ST@uS!S3QJ&|mzRWv+|@AOa8j77Z{MwpQHkp6I-xb( z_v_|_bY`QVkzciuol;93a`vQ zs^MiHr->$DQ-p`P6~Q3&^mI)f-sHTTwV<$ofW6QE&t%rJs>fj2s)=g}mtnhsk-I*p zc~%VR)-`5C{`@usmN<*JbqT4Z!Vmu#eX$bGP=W;MLOHBA@t=0Jtvf;`-hddU4t}=k zSK%YgWd*P%yD|r}+iO>C0|=gN+t&UV^9u$*$X1`T@$b2dMTn*aVkCBEr=R{#J>v@E zbRlOsdb8t{)^VkO2TK8aqnVj?e``bll#StP?Job(v`beo8&wSH*ys%dKLUMqC}4PC zU%kpgcOkmYTg_iktGxflzP(=`NtiO7tF%TChCz^MW;~tW-8_>&E-`JYM8n;sXeX-? zVKk@vSKZ4V+pZn_$B;L>aUUtV<@A8(he74E_I0&&)`~{Nb$hDX$S=&N4%^*KI-^VV zN$WRG>wc0ZwDBwR*e#R6^+C?U8ziJGm-yTt?qoyaSIC*4ZR@m0?QZ!CO-6^~WYyCm z8>V#|fSd&%8$m{yQFsT-`*Ka2HfmtFEXK=S3_pzeC0P}xX5<@6wTI@>oGpKP-BJe% z)JH>4UQy%uvZ3@Mjas0_wnwcn&k<%9tcihE2Pp7k|Ne&!TjFH`M@mZsUn~&437G!W%z(AAI(q~1`EakbK07<{iGOlA)ML4}J-oG5fWt9w)YWD1x%#l@ z{Iwi29pO{FP0>B{c=Ae(FA7Z}1Y;2S{O=bi$H-?@{~^;PiK-l2|VRp-*vxy!A<(dM`QNPyViJ12&Wy%n%&V|>03~VFw9YCiaPALOch&Q z_Sf+HlkGG4DYzM>{*71uF7m2BFdpH}--V8$WO8LN+A}QFO48--nJf4Z?XsFaIqKv2 zV8e&LktQ{1Imj~E5$%6-cWnTvClrBbk^uoHQi(CLQ&Uo<+zn|B@~SmT6ZfQOznPqq zTS}9bnnHgsIb#8&k|#Xh_CT4?{H$Muv2j8RnX5Z2L?YsKoI5#eV_Q$2zC_We3g#X= zC|BHD-;*lnLrczI9~f4dLqYcL*b5Gw+xho%vhGj*GB}FuMz_)Zzs)=A$94#K{!eAO zL5$K|I*q)&#cM|aqU5Xaya5~#*VEqONEoj(J-_27yNne)DN-Q|Yfll)Qo6|IQ=b;q zNgTSYUBfRpR}DD9=gMYwk&k@jkKunh*(vv3qmit>m?Lbb8PNN0f#bQU&WUQv+`$-B z1T$o{h0h!X_aLr0^6&5q9T-G4sQKl_A|u*jv}e%^NHIhMQNo`CpTisGJbw#3Wli_( zx4we*8a7aDxTEM|-irl=W4U zo@ZTrZh6F`I~@ZF@+cSTc)g=Zm!{17i#RIA_FfF%jeJg^WTY?%fZXHrx6hsK!~H=l zHvHKk;kW}>wrSBhahlN$gCvqdYjH?p%vu5!{Z_w-r+BV<*2zfFQK8qNx_n1X6s$>u zQ6~zqxWRHMLdQ^EhK?}=c+IL1U5X-_Z1&QegVztgU>EO8WEirqWhd{+EYf)~a@=TeOSqCgDZeKe;1KeHv;S1$F3%t3$6ssViVjB>yc&f9=GcMRY z!>x#FTAOw}*Y0dGo1Cx0e*%I9n4oo&IBSXBA<9$=avYwP3#!EvBjM)A@7y0m7f3UNp(@Q9L-?jk@MC*ca za)TGEoDh_~W0540;KZk2>x9wZ3(T?WZ*6Lw=F8*8a4U{H1sPIFX336^8PJI#5P5;@E1hu7-Q@pkx!tLSdB2wSzf zyBFmixHW$o47%2X`R=H`T!$6RrYEZd(U;(m=BFpk;-E*~+A?FOJ24Vlm2->Ne>WUE zSK9l?a3p=Rf20haZOOpi%OhCL6rf~@bY-0{ zxcKfP9A-1jZo4ZF;@1!LaT5oohBZp*JEsxN$-o)o0?=5aJv7TqG3Bnupkka9El=*! za+>50^vO2!iG?T|x7?@V=vHy!123AsIi)3!7>nk0Y!lfCU*C+!0m$ui`VOmj%H~d`w$yZxFsI;3Z8v9|2&wx3J1jhEa$ts1jZdApJKqFL^;fH4 z*M%w)tma4khE+iV8R?njIXpXfo!Vg#M@yhEOdc=VU8ESwMI(e3v8}TFL?Eb&|m{K!{Ucg{@(mQf;V3>w2T4#* zAEt+k)eRJ}gfqF}n>*2x>ha&=r4h-=r%=Q%129#WsN~1uk4T2Ppmo(W@Y_Vk*iQ+^ z9f?)c1Q}3cXNmih-lp|p-CAPk5LTOE&2%s~43FZ}fV-Z>M*DIuwcD`MrbDh+5usH$ zr}rU^G|<}zg_VkseUd0|i}<{jP(xu~5bP4aIfH!RYt{1L&(&>;EW5K^r_U?SE$EJ+ zx9g3=39XGM&;+SCDHPU`G_;7()Yk81^HD;p0`70Bod!noMTae_%&!<=RfO2T7ln>A zIojV4Oaw0kW-a@MuOlrT9*q?vuiN;iUli8-O>c(HFT!sAsJ3NzB{y;a4gw6{@^0`F z4J;VGA>saK!$}h2c<;yzY7^=wi6YikE9T>qZ5mnq`Ps3CI-akDVWnf&g}1~+`b*d^ znbBNa#R_>GCTt?JMhzw84}w~JsY3+vn13 zj^9Tp7>-$r9Veq#1~yM|Bps6aPspt!>ZZ-4lq}_IMCEof`-iC{9RvXZP5g57Pm~U~Pt5$1zovU{%mi^zw!`_V;rZ~V3ioY? z7?+xP1upW+&=6%FNUY5oK?aOS@jP*Z2_iI}uMYh!A)95{Uh$NAI%8*xE#0GT48P0`L;pO2L*9U*c z*=IzuX@##EkH^~8Y3B;zD*6yh0~c`zNkfW`!-S${i2cM(S!+TDjs zIi|HnX6Bv3up*wc^6j^nlw#a-8)GqaSca$^#UWzJYJsTF%HkR^O?gE}rfxxUj@|P; z?0R`mn|CGZLgplF*`j`&9rQ^}a9x9+7LACEG<1c91CC%Rl+(u>^IQXJ8i_K>7)pAy zv{Ge>a_a3|EL*DTxPQllq`|3X`~$cUFUbL>0@v_L}9+ z^~Svk=y*7LSu1;imj@*3ztdAAunHDWT#g#OLuUvzQEI)GSmRhVihHUlGPe+zF=(|k;PwrEOd zBvUSPFVblcER<6&Y6=UMv>cejqse}Fu(;*6Cs>+hB<_>y7+O9_He~P=CaPJzA~VGV z$4HT*eb&No5^b}uk7%BU7P$I@PEn3$PX-TOY|WTn^BC5~R9=z}7M`NtqBSGgB(YCf zY=0Pem~>xvr_z2z_wdK0E9v0W>0}hv>BLU&O5&bEvw}e0Y6m=U( zdM^gqaBpy)UkOFrbR&_`y`hx_gQR7sdFa)UX$sPIc(#sC%w~yTvf!n${aMB7%=n7? zHgPt_*ki&$-CFv5Tq38-gCp=0E4hP>9VwzOBb@;QCsYS(NJD}siSnvn;q(Eq6WVsx z)t5I~e}4s}tLC7TU7qw{RylYhI<}f45su60Fs~6@F5G@z2mfZc zPpC~{a?CyV&}glU`lU#rW4wy14PLojJYiWQ-&>PBPMCIOq5sN4(fZfVEo-It5kO>( z-0cP+c5NZy;sk=hGun25?MzXw?2Nl7RTBt5yf?w6X(yOadjZaX;{9 z&eGWy=Dx4J5J{naM2Z=u+ZCTy&ik=?;4n39C#Y1&XrfTYliB&nzt5`j?2v2EUqi?4 zXW5A8Tkl*)@)mmw#GaOhN?fO-Z6VB1Me6m92vF z!H!j>Qb&j6K2qbyI7;y6T&?&-93O)4q?XwY(%nACKdVU3*6fp+*ZnD%JGN)aVkx~T zzYjA=%u@?RcO_F8`;m-TXF$(pDjSa0s9N{wMvXUunti~`5a=1=5N>GPo;@huZ7Blw-Kq0(b4S{JP+f3PgUE{qHl{~6mn+njuxTv9vj zrM}(Cn_6U}Y*#zKYEaaeV(zsk!L&ilA3I(GAe0@cA-Iipk`{NOtO+sT?is4X$I5j? zE;$*+x>C=*(aAq8eQ#DC6rNO`ceN#h_V;!Uj*n*EES8tDFj^?#Z!=Vs6G6jc?@(u7 ze?Fg&i6w|8Y!cQiVJ^AG-pb6P5RGI{88{h8sQh5OCGAV7|}0x%8|ZtpsoZ0Vr^u3RfP?`l_m(qr|C`chpN*<7A4R#7tAsY)7P ze(o8b(g^jk@{#LK8u^+7q^}KsD%{3T<{l1S?rjfE+&{`JMVA4m4lc;eN6{|H+az&> zuF@LU(BH80t5MZ8V$k)fDq~?lCXc8v09z02tRoo~76 z*!*;*C-|lZErNu~3hNchWdjtr!!6(;dV?W#4Wwse6P=XvPTc^Hduzw&G?!7vrH^T( z5qmKj=U!afFIB)dxcR0h%^7iDZ5qmx#e!dRn0^Z3^IIVtOwR_9pM{Uaikq@NC<6?` z&u`ZZBfsL!1A5fL%J>l}tC+JSqqrw{K1H&8b!5oQK=w+@@r8i*bRC_C2{qhw5D^nW zh!pnJ;SX#T`J7tIw(83E#P|;HH8UE@DTnG2zk}{ZMNP)^Vkd_@(K4#MMuINK?J=eU zlhBOH+>fVSq zO<(JrTlS@q^juk4-D=-yk?@AOC02tM87gk`I$m$Fv^XE%ZLXKXcAGor#SEF4h#&S!P5*RR`0exopuGp@Ue$7luUpBn5xa#G?)#Bl@1h7*%(#8 z`>}yaCVLD4wxk;R=Z;JXMMaghD8BB;ocenKfKo)np*y$hF@&$R(_+IJM;r3jXK>7* zb`?;w=F{O|OVbLn>#;dG`}J4DgdiO6c0=KaT%;xc?S<%Cjqhc}6Io&)O=hX&J>b%d z7hT|ZROSj>%aILdsiNht({eHLWm^Qj6>7=>zyV*kOD~Dm!HALNH~JCP*uAlUrPbYP_9W6wc%2qIF+rB7sE#5OZ%Z0|Rs22~}tK1kE1ui5v{9OA)(+fv0bZ)7tE$ z@uwq%n(Mlsv-;-B$a(i}cw=WS{if^DxM;*OMaVx8nF<%3uOOMj*eH%fA*t3Mc&>iq zjUlP}*=}I2-dPOvWB5N@*fF^WG9}?1oiO}yZQR%3y1NuUZ*Vr-b5);kLTm#&cF|iq zo)fp7r&ivhKKUxN--D{x8%1vU=zWeJ`<7wy!n1#NXCBM>Bw$JMJXR4F3Rbjb9!Cr?&_bN`Q^gC5O!ott+R%cPpCO zVs46N7O{2py?O%}>IZ2}+%r9m%EXl#V!A*j9z$VRHwE#ATM-Oo>-l=8De{X6)Pr6% zh8^(2N@_6gtl1dFemr>#EDWl3>d#7O&#YMNJv8NWxcHz>xs!0`$sHUN7ItYhD*L*2Pt zWDaQST>!q7(`_rr+42rMbLH55cUhy|%=fg^aNpLj|9MXzP=XXxx=Qs#iqGpHT8?&7 z6!OQ}G@>JZ=stZ+0hmO~iy6jc5)xy-yB4h$c#NwJ+m1gRCD}9&c@aR6VVoe@Y@t46 zu$#l1e0^Dk7;;|LYA4L9!JR;l#!%=H-0Hpli_WnNRZI`}1|!!3padFbEi5*>se_!- z$;nE`adT69GCE=6*CGl0nhQ6dV>W6;$+$f!4g2eF6UGbKNv`H@Fs^xdkT3uaVNa=y z<<{CN(S#t`tEs0%!+%_h@H5Q(zSOEEb%tFC+wBJX!bNe5n4gt5wt!*{`lEW!Xzjdy z@xgq<826Y?GJ1r(GY_b%zm@p7U+%O9ZC?kiK~3hspk&<9n-G%A4kjGC00X=c;rOY4 z#q0eK7k+LNc$0dDP+S%WPD96u0sZ2)$W+Xfv%Q*fz7F*YD}3(}z?Dpw60k#=j0o`& zl}8FCNN)T)3NO+pjx6sdjB;PVNSYrya*ptQy1s-jLgERQ*32H10+YH8GRaxf>;CS9;>dp6+duUCX~A^mJqr&MvJ39p$&%X_BjC zgVm1gi9G(*d17rKP+5dSL03~s4)W1vON_ACdjP`KEu!-vOZT!TyDGBYVjw;k%tlNm z?H8dtp{pThq&; zQKo;LPJ(;9^zV*G7TzU`xh`CoDoefMcRx{gcs!oR$6TbUKktA8K;p~YV`rJT=4$k+ zsVbUwpc4a|Tj6Q)w$yO!uvcO1SKi}=qMYD1qBDk}1>qI)4@9y+%ADuUy27QkaW4a# zltqU72AoTjDAUYeKxImvoFf`kXKrVhj%EdN`pB06y@+N@;5!{RzE)DBCouxJ*Q z1lz_Frhk_*Zi*!v&zZ7Iahel}8Pf%_N>|E#GG4-ej$AzK>s{Wq z2x3@14@^cA#%E|&chd@$?Gb)r zu!%HgjRkf868>Q`z%hx6tK3pwJ6?|6_x9JKUo>%4d3$0GEp$)B>$2|NZB1;_2Y+Q55ay(j^PTTI%pHkj? z=n<&$@z#9Z7<#~unCY_Kn(pvsd-5@Vd$L*Q1vkGsBIyuM+d$J@^$zr{U0&tHYPr{L zD%MGI&EA}IH|JQ4|I}6qnC$>tzQw`3`do}tmfd$EG;E8GwCovgMP7qicb<>5Ca|Yi z!;&*I%6bY4o{s48a@*eOBJAs0f+y0{?J^VFTk5dcezUk0b3pIZ)y~i|UJu!`R8p)? zI;WD4RbKp6Ogn`x6~gJsOS#4;cy=TVW#iC91+w`UcfM39bZ~9W%sXa`H3~n!SvtsT zOm_F=T&V%EgX^_R>(+v5JBNR`=-$kP2B8)m9eg5?)cv<2w%;@B-of` z(1h*SaZCdov3EU_Ch6wD$#xLg3pMvtWTfdhKEBi!^Wk3L1s&6olVndKi$=Xu8eK&Y z;0J$;w_68rvD3=)bjsH?VIUQ%i5S%UKayDHyqwf_w&gdMH6K3GX^gg zUIv=E-B5e?zwZN{8lIS@qkeY|c&>>&I%FKhPl%pJrLE-`=xqXndUGQjs!GO{P^pvh zk^q71UYX$Kf%=iMR%CPm17mq*YlbT>wQe1-=JDI@vB~3~XtyDNX1JZTe1WFUrDv)H zo(-yrt<7@DHriz~=83Hm8QGiQ4Ehv0@l+o5OhnjvSXNZ)(wTMMZIFlDQ)%| z=!E!pZxd66Rbe=Am6Qo%JjPf)p?UM}YyJolDk#3JqEMp*QY|7e_QQnmH@G!B!z}qa`UmNVmA?Z@k`~PA z@O~4A&a&r0Rr~QkNZw0*275Gdn}+o>3)e-M_x>mwp$#0&e_$TxRxXjHPxDYH@Y!MV zuo?$y1ZqyGA8Q16Rmc=YCr?JN=2smrxRD^Qjmi zXwdWMIHIM4O~0q`yfrS{xqmwu4{n=q4$&UA3xO z&oAYXNy}Zs#_}2RFGSEEp zE`VO_(PKBHgWnTM8=rLf2K5Umfp|(us$Qrf?)V9-+qM#GTN&5pEDD_vMqQRT$t#3M z0(S>~DBWvtRFUv@Hwxq6kHf!M7|3K-BGqJJSWB%22>!0@o?55>^tw)hU_!Dl)^67O z?Gwxtt#*ZJ6O+w#KdH>a2ZY)b==-_JYbh4Ru@x^-4eZJN7^4euUgsgr!OeWwU&~;B zrSGX5;*q<6DkhOPWnvg(4+x<3>Bp>P&_TIK)m^{*3qQw_9GD;AxS2f_(8AB#Ra7S+ z^Y8RCz3bx?Nb|%ta z9y79_M3F+Qe5f5QS)`z-pR@q!7ks5x-@%-pv}*wk)G{|ECA85<*nV@Y+gw*6X!sHE zD5B`3VXZalk#4}ok1L0Drj{A2SK5SRq^5&62d`*K`;ASdfR)bmwJ`>l{zETY_%RE%KV!$b;9cUhOO$ zUfZu!Z+r=-!wEiW<`q6laNnNpk?&mR3d%D3gq^6-*|3m9n11l&{cH=6^gQ3INb!A4 z+nXr7T+b;Q&d*9ni^EUwgWuzym#}Y3oiHR@atrQ2`_s>E8V91=7F0pHV7n=i{nxC) zOd2dvV}#nB>I!Nxzg1Y_hmRUv^dBN|69zn(dun=4(jS}r5%l-f8mXp+x^a6Y{#L|z zROt|?kiT89{X-cs#mCzx+xfsO}H^+UK`i=@#P!c|kTtFDOfRT2Uy{wvGV9PaN`{`EqZ~eI=^PA6nF7A|(5?HQ zkgnEOG+ThTz3I_N$Wh~^R)YN!mJSAT>Ka6D>Rr9oAJ!nYMMsk;yaoBplHy_fg(3yu zuDQsAS2r<)RpnLEC?P-320<@{bl?3PsgFn$k9mIu`-Md?u3G?8VpFR)c+PgBTCdBG zp-a|F7F&;LSaCPSQ4`h}t5>YiRB4cvXeDJ`QaH)4eyf3pw}o4=u-u9TY2?seE!Loo zS<98TW0C%xhcPD7O|GTgnTVA7M^oBMIx%8{Vb1R{#AQM;@q5<^28&hYH8GqdS#drv zG%y`nl=p!!hVds`G)lHVcHnYaf>}FJ_>cGGiQejWF}u9fWVsW%F}#3=gFg?o*VB)d zgU5oGq?Vr60xrCo>+JQO33I$5sMHinfoq90ar8qKk^9v?|^E-ahz(2~neOa1OT#p4KDp|p?ZTL$#XuHFw(=Bw6 ze94Q3l@ng|gxJD18tHFR@AQ1%;m#MXp-WSDUR=-q?Eb{H+3TFMA3Vbn5HO`=mmp=G zy;DlWPRYq4OUXJ|!pOPWW+rb+@za8qVMJ_D47R-d5G?6ViPx`|J%A@AyF|&ID~nnk zGnax5oie{7q&1BbN?Yi@K6P`PyMaC*hirbKKJt~VlHR(sWXK9`7zw_6+Jcz|Ac`D$ zrl7i#W7?7_&~n$CnRjlo=wZRjX1X%%<$a`htos$Q`LZr1;QSC{^4X0#fMNT%D292g z%Fy-I#;5I@UWCw^%pf01h!wUesgvqrsog8Ed8~aM#?`laRds7*Li;J;+tqE~I@V#L z(N#jk{h_+k{=jsZw!dcn@Q^}Vt$uFp)p{DQ+j$?w)zFdBOp~GNzT%D^B77?mg&3Jq zl*=73X#iH#@iTdNu1kpWr=~%(9dbwRh6FeNBJ>tWO~z}!tPmUDVCTfaR;RtNHuFmD zWUD!2&BsIIBNPE6*P)TA_+>hG#YJT5o*<5{Z5EenF>#0fjwhtVs)nhPi;GiR<-?TF z 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

  • clientin - Initial client challenge bytes. Note: some protocols do not allow this. If this is the case passing NULL is valid
  • diff --git a/docsrc/sasl/developer/programming.rst b/docsrc/sasl/developer/programming.rst index 8aa95ef0..faece5aa 100644 --- a/docsrc/sasl/developer/programming.rst +++ b/docsrc/sasl/developer/programming.rst @@ -267,7 +267,7 @@ see). * For IMAP this might look like:: {tag} "AUTHENTICATE" {mechusing}\r\n - A01 AUTHENTICATE KERBEROS_V4\r\n + A01 AUTHENTICATE GSSAPI\r\n * SMTP looks like:: @@ -444,7 +444,7 @@ be called when the socket is accepted. When a client requests the list of mechanisms supported by the server, use :saslman:`sasl_listmech(3)`. This particular call might -produce the string: ``{PLAIN, KERBEROS_V4, CRAM-MD5, DIGEST-MD5}`` +produce the string: ``{PLAIN, GSSAPI, CRAM-MD5, DIGEST-MD5}`` .. code-block:: C diff --git a/docsrc/sasl/developer/testing.rst b/docsrc/sasl/developer/testing.rst index 567450ec..c543555a 100644 --- a/docsrc/sasl/developer/testing.rst +++ b/docsrc/sasl/developer/testing.rst @@ -23,7 +23,7 @@ the sample-client on the "client" machine, and sample-server on the "server" machine. Both programs take a -m MECH command line argument; this can be used -to force the mechanism used in the exchange. KERBEROS_V4 requires +to force the mechanism used in the exchange. GSSAPI requires that the IP addresses of both client and server be set, along with the service name, and the server's fully-qualified hostname; these are done through more command line arguments. @@ -32,7 +32,7 @@ Example ------- Here's the client side of an exchange. The mechanism selection code -chooses KERBEROS_V4; negotiation takes place, and the client is +chooses GSSAPI; negotiation takes place, and the client is authenticated. This is being run on the machine SPOOKY.ANDREW.CMU.EDU (128.2.121.162), pretending to be talking to an "rcmd" service running on port 23 (note the semicolons in the IP address. There is a strong @@ -43,8 +43,8 @@ chance these will need to be escaped for proper interpretation by the shell): > ./sample-client -i local=128.2.121.162;23,remote=128.2.121.162;23 -s rcmd -n SPOOKY.ANDREW.CMU.EDU Waiting for mechanism list from server... S: UExBSU4gQU5PTllNT1VTIEtFUkJFUk9TX1Y0IERJR0VTVC1NRDUgQ1JBTS1NRDUgAAAAAED5EEA= - Choosing best mechanism from: PLAIN ANONYMOUS KERBEROS_V4 DIGEST-MD5 CRAM-MD5 - Using mechanism KERBEROS_V4 + Choosing best mechanism from: PLAIN ANONYMOUS GSSAPI DIGEST-MD5 CRAM-MD5 + Using mechanism GSSAPI Preparing initial. Sending initial response... C: S0VSQkVST1NfVjQA diff --git a/docsrc/sasl/installation.rst b/docsrc/sasl/installation.rst index df551127..640853a2 100644 --- a/docsrc/sasl/installation.rst +++ b/docsrc/sasl/installation.rst @@ -75,7 +75,7 @@ installation: 1. What mechanisms do you want to support? Are they plaintext (LOGIN, PLAIN), -shared secret (SCRAM, DIGEST-MD5, CRAM-MD5), or Kerberos (KERBEROS_V4, GSSAPI)? +shared secret (SCRAM, DIGEST-MD5, CRAM-MD5), or Kerberos (GSSAPI)? Perhaps you will use some combination (generally plaintext with one of the other two types). 2. Given the answer to the previous question, how will the mechanisms @@ -143,11 +143,11 @@ resources to load a given plugin, even if that plugin is otherwise unused As of this writing, modules that are enabled by default but may not be applicable to all systems include CRAM-MD5, DIGEST-MD5, SCRAM, OTP, -KERBEROS_V4, GSSAPI, PLAIN, and ANONYMOUS. These can be disabled with:: +GSSAPI, PLAIN, and ANONYMOUS. These can be disabled with:: ``--disable-cram``, ``--disable-digest``, ``--disable-scram``, ``--disable-otp``, - ``--disable-krb4``, ``--disable-gssapi``, + ``--disable-gssapi``, ``--disable-plain``, and ``--disable-anon`` respectively. If you are using an SQL auxprop plugin, you may want to specify one or more @@ -212,7 +212,7 @@ saslauthd as a password verifier, you'll want to be sure to set ``pwcheck_method: saslauthd``). If you are using saslauthd, you will want to arrange for -``saslauthd -a pam`` (or ldap, or kerberos4, etc) to be run +``saslauthd -a pam`` (or ldap, etc) to be run at boot. If you are not going to be using saslauthd, then this is not necessary. diff --git a/docsrc/sasl/macosx.rst b/docsrc/sasl/macosx.rst index 63c9d4a8..ce31e1be 100644 --- a/docsrc/sasl/macosx.rst +++ b/docsrc/sasl/macosx.rst @@ -74,21 +74,6 @@ you should upgrade to more recent patchlevels of these tools. The easiest way to do this is to install the Fink environment and then ``apt-get install autoconf2.5 automake1.7 libtool14``. -Recent versions of SASL ship with Kerberos v4 disabled by default. -If you need Kerberos v4 for some reason, and you are using MIT Kerberos -for Macintosh 4.0 or later, you should ``./configure`` with -the added options ``"--enable-krb4=/usr --without-openssl ---disable-digest"`` so that it finds the -correct location for the header files, and does not use OpenSSL or -build anything that depends on it (such as the digest-md5 plugin), -since OpenSSL provides its own DES routines which do not work with -Kerberos v4. - -.. warning:: - - Please read the "Known Problems" section at the end of - this document for more information on this issue. - You must be root to make install, since ``/usr/local`` is only modifiable by root. You need not enable the root account using NetInfo; the recommended (but underdocumented) method is to use @@ -169,13 +154,6 @@ Changes to the Mac OS 9 projects to support Carbon API. This folder must be in your CodeWarrior access paths, the old ``mac_kclient`` folder must not, and it must precede the project's main folder. -* The kerberos4 plugin uses this new code. The kerberos4 plugin - also - statically links the Carbon ``libdes``, and no other part of - Carbon SASL uses ``libdes`` directly. *Your application should - **not** link against* ``libdes.shlb`` *under Carbon!* - (It causes problems due to DES symbols also existing in the MIT - Kerberos library, which loads first.) * To build the projects, you should have the MIT Kerberos for Macintosh 3.5 installation disk images mounted, since the access paths include the absolute paths to the library directories from that @@ -185,20 +163,6 @@ Changes to the Mac OS 9 projects to support Carbon Known Problems ============== -* The Kerberos v4 headers bundled with Mac OS X (and Kerberos for - Macintosh) are not compatible with OS X's OpenSSL headers. (Kerberos v4 - support is disabled by default.) If you actually need krb4 support, the - easiest solution is to build without using OpenSSL's - ``libcrypto``. To do this, specify the ``--without-openssl`` - option to ``configure``. As of version 2.1.18, this automatically - disables using ``libcrypto`` for DES as well. You will probably - also need to specify ``--disable-digest`` since the digestmd5 plugin - does not build against Kerberos v4's DES headers or library. Note that - this disables several features (DIGEST-MD5, NTLM, OTP, PASSDSS, SCRAM, SRP) - which require OpenSSL. If both Kerberos v4 and functionality that requires - OpenSSL are needed, it is possible to build the Kerberos v4 plugin against - the correct K4 DES libraries, and everything else against OpenSSL; - however, we do not support that configuration. * Versions of Cyrus SASL prior to 2.1.14 with support for Carbon CFM applications on Mac OS X have a known bug involving the CFM glue code (in ``mac/osx_cfm_glue``). If ``sasl_done`` is called diff --git a/docsrc/sasl/quickstart.rst b/docsrc/sasl/quickstart.rst index fab36b87..ae969fce 100644 --- a/docsrc/sasl/quickstart.rst +++ b/docsrc/sasl/quickstart.rst @@ -21,7 +21,6 @@ this distribution: * DIGEST-MD5 (requires OpenSSL libcrypto) * EXTERNAL * GSSAPI (MIT Kerberos 5, Heimdal Kerberos 5 or CyberSafe) -* KERBEROS_V4 (requires OpenSSL libcrypto) * LOGIN * NTLM (requires OpenSSL libcrypto) * OTP (requires OpenSSL libcrypto) diff --git a/docsrc/sasl/reference/manpages/library/sasl_getopt_t.rst b/docsrc/sasl/reference/manpages/library/sasl_getopt_t.rst index 3542c314..d6f8f4e4 100644 --- a/docsrc/sasl/reference/manpages/library/sasl_getopt_t.rst +++ b/docsrc/sasl/reference/manpages/library/sasl_getopt_t.rst @@ -30,7 +30,7 @@ Description **sasl_getopt_t** is used to retrieve an option, often mechanism specific, from the application. An example of this is - requesting what KERBEROS_V4 srvtab file to use. + requesting what GSSAPI keytab file to use. :param context: is the SASL connection context :param plugin_name: is the plugin this value is for. diff --git a/docsrc/sasl/reference/manpages/library/sasl_listmech.rst b/docsrc/sasl/reference/manpages/library/sasl_listmech.rst index 33f25db5..41b711fe 100644 --- a/docsrc/sasl/reference/manpages/library/sasl_listmech.rst +++ b/docsrc/sasl/reference/manpages/library/sasl_listmech.rst @@ -63,7 +63,7 @@ Example may give the following string as a result: - `(ANONYMOUS,KERBEROS_V4,DIGEST‐MD5)` + `(ANONYMOUS,GSSAPI,DIGEST‐MD5)` Return Value ============ diff --git a/docsrc/sasl/sysadmin.rst b/docsrc/sasl/sysadmin.rst index 13ddcaab..50d83252 100644 --- a/docsrc/sasl/sysadmin.rst +++ b/docsrc/sasl/sysadmin.rst @@ -101,9 +101,9 @@ To add users of different realms to sasldb, you can use the ``-u`` option to saslpasswd2. The SQL plugin has a way of integrating the realm name into the query string with the '%r' macro. -The Kerberos mechanisms treat the SASL realm as the Kerberos -realm. Thus, the realm for Kerberos mechanisms defaults to the -default Kerberos realm on the server. They may support cross-realm +The Kerberos GSSAPI mechanism treats the SASL realm as the Kerberos +realm. Thus, the realm for Kerberos GSSAPI mechanism defaults to the +default Kerberos realm on the server. It may support cross-realm authentication; check your application on how it deals with this. Realms will be passed to saslauthd as part of the saslauthd protocol, @@ -276,24 +276,18 @@ no point in enabling this option if "pwcheck_method" is "auxprop", and the sasldb plugin is installed, since you'll be transitioning from a plaintext store to a plaintext store) -Kerberos mechanisms +Kerberos mechanism ------------------- -The Cyrus SASL library also comes with two mechanisms that make use of -Kerberos: KERBEROS_V4, which should be able to use any Kerberos v4 -implementation, and GSSAPI (tested against MIT Kerberos 5, Heimdal -Kerberos 5 and CyberSafe Kerberos 5). These mechanisms make use of the kerberos infrastructure -and thus have no password database. +The Cyrus SASL library also comes with a mechanism that make use of +Kerberos: GSSAPI (tested against MIT Kerberos 5, Heimdal +Kerberos 5 and CyberSafe Kerberos 5). This mechanism makes use of the +kerberos infrastructure and thus has no password database. Applications that wish to use a kerberos mechanism will need access -to a service key, stored either in a :option:`srvtab` file (Kerberos 4) or a -:option:`keytab` file (Kerberos 5). +to a service key, stored in a :option:`keytab` file. -The Kerberos 4 :option:`srvtab` file location is configurable; by default it is -``/etc/srvtab``, but this is modifiable by the "srvtab" option. -Different SASL applications can use different srvtab files. - -A SASL application must be able to read its srvtab or keytab file. +A SASL application must be able to read its keytab file. You may want to consult the :ref:`GSSAPI Tutorial `. @@ -403,12 +397,6 @@ SASL_DBNAME Troubleshooting =============== -Why doesn't KERBEROS_V4 doesn't appear as an available mechanism? - Check that the ``srvtab`` file is readable by the - user running as the daemon. For Cyrus imapd, it must be readable by - the Cyrus user. By default, the library looks for the srvtab in - ``/etc/srvtab``, but it's configurable using the :option:`srvtab` - option. Why doesn't OTP doesn't appear as an available mechanism? If using OPIE, check that the ``opiekeys`` file is readable by the user running the daemon. For Cyrus imapd, it must diff --git a/docsrc/sasl/windows.rst b/docsrc/sasl/windows.rst index af3b29e1..6c836eb5 100644 --- a/docsrc/sasl/windows.rst +++ b/docsrc/sasl/windows.rst @@ -140,7 +140,7 @@ multiple parameters described above, for example ``nmake /f NTMakefile NTLM=1 SR Limitations ----------- -Currently all plugins except KerberosV4 (kerberos4.c) and PASSDSS (passdss.c) can be built on Windows. +Currently all plugins except PASSDSS (passdss.c) can be built on Windows. However limited testings was done for some plugins as listed below: * GSSAPI - tested using CyberSafe, diff --git a/lib/staticopen.h b/lib/staticopen.h index d1983163..03ca342a 100644 --- a/lib/staticopen.h +++ b/lib/staticopen.h @@ -96,10 +96,6 @@ extern SPECIFIC_CLIENT_PLUG_INIT_PROTO( scram ); extern SPECIFIC_SERVER_PLUG_INIT_PROTO( gssapiv2 ); extern SPECIFIC_CLIENT_PLUG_INIT_PROTO( gssapiv2 ); #endif -#ifdef STATIC_KERBEROS4 -extern SPECIFIC_SERVER_PLUG_INIT_PROTO( kerberos4 ); -extern SPECIFIC_CLIENT_PLUG_INIT_PROTO( kerberos4 ); -#endif #ifdef STATIC_LOGIN extern SPECIFIC_SERVER_PLUG_INIT_PROTO( login ); extern SPECIFIC_CLIENT_PLUG_INIT_PROTO( login ); @@ -147,10 +143,6 @@ _sasl_plug_rec _sasl_static_plugins[] = { SPECIFIC_SERVER_PLUG_INIT( gssapiv2, "GSSAPI" ), SPECIFIC_CLIENT_PLUG_INIT( gssapiv2, "GSSAPI" ), #endif -#ifdef STATIC_KERBEROS4 - SPECIFIC_SERVER_PLUG_INIT( kerberos4, "KERBEROS_V4" ), - SPECIFIC_CLIENT_PLUG_INIT( kerberos4, "KERBEROS_V4" ), -#endif #ifdef STATIC_LOGIN SPECIFIC_SERVER_PLUG_INIT( login, "LOGIN" ), SPECIFIC_CLIENT_PLUG_INIT( login, "LOGIN" ), diff --git a/m4/kerberos_v4.m4 b/m4/kerberos_v4.m4 deleted file mode 100644 index 2c83dbe6..00000000 --- a/m4/kerberos_v4.m4 +++ /dev/null @@ -1,155 +0,0 @@ -dnl checking for kerberos 4 libraries (and DES) - -AC_DEFUN([SASL_DES_CHK], [ -AC_ARG_WITH(des, [ --with-des=DIR with DES (look in DIR) [yes] ], - with_des=$withval, - with_des=yes) - -LIB_DES="" -if test "$with_des" != no; then - if test -d $with_des; then - CPPFLAGS="$CPPFLAGS -I${with_des}/include" - LDFLAGS="$LDFLAGS -L${with_des}/lib" - fi - - if test "$with_openssl" != no; then - dnl check for openssl installing -lcrypto, then make vanilla check - AC_CHECK_LIB(crypto, des_cbc_encrypt, [ - AC_CHECK_HEADER(openssl/des.h, [AC_DEFINE(WITH_SSL_DES,[],[Use OpenSSL DES Implementation]) - LIB_DES="-lcrypto"; - with_des=yes], - with_des=no)], - with_des=no, $LIB_RSAREF) - - dnl same test again, different symbol name - if test "$with_des" = no; then - AC_CHECK_LIB(crypto, DES_cbc_encrypt, [ - AC_CHECK_HEADER(openssl/des.h, [AC_DEFINE(WITH_SSL_DES,[],[Use OpenSSL DES Implementation]) - LIB_DES="-lcrypto"; - with_des=yes], - with_des=no)], - with_des=no, $LIB_RSAREF) - fi - else - with_des=no - fi - - if test "$with_des" = no; then - AC_CHECK_LIB(des, des_cbc_encrypt, [LIB_DES="-ldes"; - with_des=yes], with_des=no) - fi - - if test "$with_des" = no; then - AC_CHECK_LIB(des425, des_cbc_encrypt, [LIB_DES="-ldes425"; - with_des=yes], with_des=no) - fi - - if test "$with_des" = no; then - AC_CHECK_LIB(des524, des_cbc_encrypt, [LIB_DES="-ldes524"; - with_des=yes], with_des=no) - fi - - if test "$with_des" = no; then - dnl if openssl is around, we might be able to use that for des - - dnl if openssl has been compiled with the rsaref2 libraries, - dnl we need to include the rsaref libraries in the crypto check - LIB_RSAREF="" - AC_CHECK_LIB(rsaref, RSAPublicEncrypt, - LIB_RSAREF="-lRSAglue -lrsaref"; cmu_have_rsaref=yes, - cmu_have_rsaref=no) - - AC_CHECK_LIB(crypto, des_cbc_encrypt, [ - AC_CHECK_HEADER(openssl/des.h, [AC_DEFINE(WITH_SSL_DES,[],[Use OpenSSL DES Implementation]) - LIB_DES="-lcrypto"; - with_des=yes], - with_des=no)], - with_des=no, $LIB_RSAREF) - fi -fi - -if test "$with_des" != no; then - AC_DEFINE(WITH_DES,[],[Use DES]) -fi - -AC_SUBST(LIB_DES) -]) - -AC_DEFUN([SASL_KERBEROS_V4_CHK], [ - AC_REQUIRE([SASL_DES_CHK]) - - AC_ARG_ENABLE(krb4, [ --enable-krb4 enable KERBEROS_V4 authentication [[no]] ], - krb4=$enableval, - krb4=no) - - if test "$krb4" != no; then - dnl In order to compile kerberos4, we need libkrb and libdes. - dnl (We've already gotten libdes from SASL_DES_CHK) - dnl we might need -lresolv for kerberos - AC_CHECK_LIB(resolv,res_search) - - dnl if we were ambitious, we would look more aggressively for the - dnl krb4 install - if test -d ${krb4}; then - AC_CACHE_CHECK(for Kerberos includes, cyrus_cv_krbinclude, [ - for krbhloc in include/kerberosIV include/kerberos include - do - if test -f ${krb4}/${krbhloc}/krb.h ; then - cyrus_cv_krbinclude=${krb4}/${krbhloc} - break - fi - done - ]) - - if test -n "${cyrus_cv_krbinclude}"; then - CPPFLAGS="$CPPFLAGS -I${cyrus_cv_krbinclude}" - fi - LDFLAGS="$LDFLAGS -L$krb4/lib" - fi - - if test "$with_des" != no; then - AC_CHECK_HEADER(krb.h, [ - AC_CHECK_LIB(com_err, com_err, [ - AC_CHECK_LIB(krb, krb_mk_priv, - [COM_ERR="-lcom_err"; SASL_KRB_LIB="-lkrb"; krb4lib="yes"], - krb4lib=no, $LIB_DES -lcom_err)], [ - AC_CHECK_LIB(krb, krb_mk_priv, - [COM_ERR=""; SASL_KRB_LIB="-lkrb"; krb4lib="yes"], - krb4lib=no, $LIB_DES)])], krb4="no") - - if test "$krb4" != "no" -a "$krb4lib" = "no"; then - AC_CHECK_LIB(krb4, krb_mk_priv, - [COM_ERR=""; SASL_KRB_LIB="-lkrb4"; krb4=yes], - krb4=no, $LIB_DES) - fi - if test "$krb4" = no; then - AC_WARN(No Kerberos V4 found) - fi - else - AC_WARN(No DES library found for Kerberos V4 support) - krb4=no - fi - fi - - if test "$krb4" != no; then - cmu_save_LIBS="$LIBS" - LIBS="$LIBS $SASL_KRB_LIB" - AC_CHECK_FUNCS(krb_get_err_text) - LIBS="$cmu_save_LIBS" - fi - - AC_MSG_CHECKING(KERBEROS_V4) - if test "$krb4" != no; then - AC_MSG_RESULT(enabled) - SASL_MECHS="$SASL_MECHS libkerberos4.la" - SASL_STATIC_SRCS="$SASL_STATIC_SRCS \$(top_srcdir)/plugins/kerberos4.c" - SASL_STATIC_OBJS="$SASL_STATIC_OBJS kerberos4.o" - AC_DEFINE(STATIC_KERBEROS4,[],[User KERBEROS_V4 Staticly]) - AC_DEFINE(HAVE_KRB,[],[Do we have Kerberos 4 Support?]) - SASL_KRB_LIB="$SASL_KRB_LIB $LIB_DES $COM_ERR" - else - AC_MSG_RESULT(disabled) - fi - AC_SUBST(SASL_KRB_LIB) -]) - diff --git a/man/legacy/sasl_listmech.3 b/man/legacy/sasl_listmech.3 index d5884977..71cf471b 100644 --- a/man/legacy/sasl_listmech.3 +++ b/man/legacy/sasl_listmech.3 @@ -84,7 +84,7 @@ Example: sasl_listmech(conn,NULL,"(",",",")",&mechlist,NULL,NULL); may give the string -.BI (ANONYMOUS,KERBEROS_V4,DIGEST-MD5) +.BI (ANONYMOUS,DIGEST-MD5) as a result .PP diff --git a/plugins/Makefile.am b/plugins/Makefile.am index 95b825b3..1662f2c3 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -66,7 +66,7 @@ LIB_MYSQL = @LIB_MYSQL@ plugindir = @plugindir@ plugin_LTLIBRARIES = @SASL_MECHS@ -EXTRA_LTLIBRARIES = libplain.la libanonymous.la libkerberos4.la libcrammd5.la \ +EXTRA_LTLIBRARIES = libplain.la libanonymous.la libcrammd5.la \ libgs2.la libgssapiv2.la libdigestmd5.la liblogin.la libsrp.la libotp.la \ libscram.la libntlm.la libpassdss.la libsasldb.la libsql.la libldapdb.la @@ -78,10 +78,6 @@ libanonymous_la_SOURCES = anonymous.c anonymous_init.c libanonymous_la_DEPENDENCIES = $(COMPAT_OBJS) $(PLUGIN_COMMON_OBJS) libanonymous_la_LIBADD = $(LIB_SOCKET) $(COMPAT_OBJS) $(PLUGIN_COMMON_OBJS) -libkerberos4_la_SOURCES = kerberos4.c kerberos4_init.c -libkerberos4_la_DEPENDENCIES = $(COMPAT_OBJS) $(PLUGIN_COMMON_OBJS) -libkerberos4_la_LIBADD = $(SASL_KRB_LIB) $(LIB_SOCKET) $(COMPAT_OBJS) $(PLUGIN_COMMON_OBJS) - libgs2_la_SOURCES = gs2.c gs2_init.c gs2_token.c gs2_token.h libgs2_la_DEPENDENCIES = $(COMPAT_OBJS) $(PLUGIN_COMMON_OBJS) libgs2_la_LIBADD = $(GSSAPIBASE_LIBS) $(GSSAPI_LIBS) $(LIB_SOCKET) $(COMPAT_OBJS) $(PLUGIN_COMMON_OBJS) @@ -141,7 +137,7 @@ libsql_la_LIBADD = $(COMPAT_OBJS) $(PLUGIN_COMMON_OBJS) # Instructions for making the _init files init_src=anonymous_init.c crammd5_init.c digestmd5_init.c scram_init.c gs2_init.c gssapiv2_init.c \ -kerberos4_init.c login_init.c plain_init.c srp_init.c otp_init.c ntlm_init.c \ +login_init.c plain_init.c srp_init.c otp_init.c ntlm_init.c \ passdss_init.c sasldb_init.c sql_init.c ldapdb_init.c diff --git a/plugins/kerberos4.c b/plugins/kerberos4.c deleted file mode 100644 index 197edcc3..00000000 --- a/plugins/kerberos4.c +++ /dev/null @@ -1,1399 +0,0 @@ -/* Kerberos4 SASL plugin - * Rob Siemborski - * Tim Martin - */ -/* - * Copyright (c) 1998-2016 Carnegie Mellon University. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name "Carnegie Mellon University" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For permission or any other legal - * details, please contact - * Carnegie Mellon University - * Center for Technology Transfer and Enterprise Creation - * 4615 Forbes Avenue - * Suite 302 - * Pittsburgh, PA 15213 - * (412) 268-7393, fax: (412) 268-7395 - * innovation@andrew.cmu.edu - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Computing Services - * at Carnegie Mellon University (http://www.cmu.edu/computing/)." - * - * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE - * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include - -#ifdef WITH_DES -# ifdef WITH_SSL_DES -# include -# else -# include -# endif /* WITH_SSL_DES */ -#endif /* WITH_DES */ - -#ifdef WIN32 -# include -#elif defined(macintosh) -#include -#else -# include -# include -# include -# include -# include -#endif /* WIN32 */ -#ifdef HAVE_UNISTD_H -#include -#endif -#include -#include -#include -#include - -#include -#include - -#include "plugin_common.h" - -#ifdef macintosh -/* - * krb.h doenst include some functions and mac compiler is picky - * about declartions - */ -#include -#include -#endif - -#ifdef WIN32 -/* This must be after sasl.h, saslutil.h */ -# include "saslKERBEROSV4.h" - -/* KClient doesn't define this */ -typedef struct krb_principal { - char name[ANAME_SZ]; - char instance[INST_SZ]; - char realm[REALM_SZ]; -} krb_principal; - -/* This isn't defined under WIN32. For access() */ -#ifndef R_OK -#define R_OK 04 -#endif -/* we also need io.h for access() prototype */ -#include -#endif /* WIN32 */ - -/***************************** Common Section *****************************/ - -#ifndef KEYFILE -#define KEYFILE "/etc/srvtab"; -#endif - -#define KRB_SECFLAG_NONE (1) -#define KRB_SECFLAG_INTEGRITY (2) -#define KRB_SECFLAG_ENCRYPTION (4) -#define KRB_SECFLAGS (7) -#define KRB_SECFLAG_CREDENTIALS (8) - -#define KRB_DES_SECURITY_BITS (56) -#define KRB_INTEGRITY_BITS (1) - -typedef enum Krb_sec { - KRB_SEC_NONE = 0, - KRB_SEC_INTEGRITY = 1, - KRB_SEC_ENCRYPTION = 2 -} Krb_sec_t; - -typedef struct context { - int state; - - int challenge; /* this is the challenge (32 bit int) used - for the authentication */ - - char *service; /* kerberos service */ - char instance[ANAME_SZ]; - char pname[ANAME_SZ]; - char pinst[INST_SZ]; - char prealm[REALM_SZ]; - char *hostname; /* hostname */ - char *realm; /* kerberos realm */ - char *auth; /* */ - - CREDENTIALS credentials; - - des_cblock key; /* session key */ - des_cblock session; /* session key */ - - des_key_schedule init_keysched; /* key schedule for initialization */ - des_key_schedule enc_keysched; /* encryption key schedule */ - des_key_schedule dec_keysched; /* decryption key schedule */ - - - struct sockaddr_in ip_local; /* local ip address and port. - needed for layers */ - struct sockaddr_in ip_remote; /* remote ip address and port. - needed for layers */ - - const sasl_utils_t *utils; /* this is useful to have around */ - - Krb_sec_t sec_type; - char *encode_buf; /* For encoding/decoding mem management */ - char *decode_buf; - char *decode_once_buf; - unsigned encode_buf_len; - unsigned decode_buf_len; - unsigned decode_once_buf_len; - buffer_info_t *enc_in_buf; - - decode_context_t decode_context; - - char *out_buf; /* per-step mem management */ - unsigned out_buf_len; - - const char *user; /* used by client */ - - int secflags; /* client/server supports layers? */ - - long time_sec; /* These are used to make sure we are getting */ - char time_5ms; /* strictly increasing timestamps */ - -} context_t; - -#define KRB_LOCK_MUTEX(utils) \ - if(((sasl_utils_t *)(utils))->mutex_lock(krb_mutex) != 0) { \ - ((sasl_utils_t *)(utils))->seterror(((sasl_utils_t *)(utils))->conn, \ - 0, "error locking mutex"); \ - return SASL_FAIL; \ - } -#define KRB_UNLOCK_MUTEX(utils) \ - if(((sasl_utils_t *)(utils))->mutex_unlock(krb_mutex) != 0) { \ - ((sasl_utils_t *)(utils))->seterror(((sasl_utils_t *)(utils))->conn, \ - 0, "error unlocking mutex"); \ - return SASL_FAIL; \ - } - -/* Mutex for not-thread-safe kerberos 4 library */ -static void *krb_mutex = NULL; -static char *srvtab = NULL; -static unsigned refcount = 0; - -static int kerberosv4_encode(void *context, - const struct iovec *invec, - unsigned numiov, - const char **output, - unsigned *outputlen) -{ - int len, ret; - context_t *text = (context_t *)context; - struct buffer_info *inblob, bufinfo; - - if(numiov > 1) { - ret = _plug_iovec_to_buf(text->utils, invec, numiov, &text->enc_in_buf); - if(ret != SASL_OK) return ret; - inblob = text->enc_in_buf; - } else { - bufinfo.data = invec[0].iov_base; - bufinfo.curlen = invec[0].iov_len; - inblob = &bufinfo; - } - - ret = _plug_buf_alloc(text->utils, &(text->encode_buf), - &text->encode_buf_len, inblob->curlen+40); - - if(ret != SASL_OK) return ret; - - KRB_LOCK_MUTEX(text->utils); - - if (text->sec_type == KRB_SEC_ENCRYPTION) { - /* Type incompatibility on 4th arg probably means you're - building against krb4 in MIT krb5, but got the OpenSSL - headers in your way. You need to not use openssl/des.h with - MIT kerberos. */ - len=krb_mk_priv(inblob->data, (text->encode_buf+4), - inblob->curlen, text->init_keysched, - &text->session, &text->ip_local, - &text->ip_remote); - } else if (text->sec_type == KRB_SEC_INTEGRITY) { - len=krb_mk_safe(inblob->data, (text->encode_buf+4), - inblob->curlen, - &text->session, &text->ip_local, &text->ip_remote); - } else { - len = -1; - } - - KRB_UNLOCK_MUTEX(text->utils); - - /* returns -1 on error */ - if (len==-1) return SASL_FAIL; - - /* now copy in the len of the buffer in network byte order */ - *outputlen=len+4; - len=htonl(len); - memcpy(text->encode_buf, &len, 4); - - /* Setup the const pointer */ - *output = text->encode_buf; - - return SASL_OK; -} - -static int kerberosv4_decode_packet(void *context, - const char *input, unsigned inputlen, - char **output, unsigned *outputlen) -{ - context_t *text = (context_t *) context; - int result; - MSG_DAT data; - - memset(&data,0,sizeof(MSG_DAT)); - - KRB_LOCK_MUTEX(text->utils); - - if (text->sec_type == KRB_SEC_ENCRYPTION) { - result=krb_rd_priv(input, inputlen, text->init_keysched, - &text->session, &text->ip_remote, - &text->ip_local, &data); - } else if (text->sec_type == KRB_SEC_INTEGRITY) { - result = krb_rd_safe(input, inputlen, - &text->session, &text->ip_remote, - &text->ip_local, &data); - } else { - KRB_UNLOCK_MUTEX(text->utils); - text->utils->seterror(text->utils->conn, 0, - "KERBEROS_4 decode called with KRB_SEC_NONE"); - return SASL_FAIL; - } - - KRB_UNLOCK_MUTEX(text->utils); - - /* see if the krb library gave us a failure */ - if (result != 0) { - text->utils->seterror(text->utils->conn, 0, get_krb_err_txt(result)); - return SASL_FAIL; - } - - /* check to make sure the timestamps are ok */ - if ((data.time_sec < text->time_sec) || /* if an earlier time */ - (((data.time_sec == text->time_sec) && /* or the exact same time */ - (data.time_5ms < text->time_5ms)))) - { - text->utils->seterror(text->utils->conn, 0, "timestamps not ok"); - return SASL_FAIL; - } - - text->time_sec = data.time_sec; - text->time_5ms = data.time_5ms; - - result = _plug_buf_alloc(text->utils, &text->decode_once_buf, - &text->decode_once_buf_len, - data.app_length + 1); - if(result != SASL_OK) - return result; - - *output = text->decode_once_buf; - *outputlen = data.app_length; - memcpy(*output, data.app_data, data.app_length); - (*output)[*outputlen] = '\0'; - - return SASL_OK; -} - -static int kerberosv4_decode(void *context, - const char *input, unsigned inputlen, - const char **output, unsigned *outputlen) -{ - context_t *text = (context_t *) context; - int ret; - - ret = _plug_decode(&text->decode_context, input, inputlen, - &text->decode_buf, &text->decode_buf_len, outputlen, - kerberosv4_decode_packet, text); - - *output = text->decode_buf; - - return ret; -} - -static int new_text(const sasl_utils_t *utils, context_t **text) -{ - context_t *ret = (context_t *) utils->malloc(sizeof(context_t)); - - if (ret == NULL) { - MEMERROR(utils); - return SASL_NOMEM; - } - - memset(ret, 0, sizeof(context_t)); - - ret->state = 1; - ret->utils = utils; - - *text = ret; - - return SASL_OK; -} - -static void kerberosv4_common_mech_dispose(void *conn_context, - const sasl_utils_t *utils) -{ - context_t *text = (context_t *)conn_context; - - if(!text) return; - - _plug_decode_free(&text->decode_context); - if (text->encode_buf) utils->free(text->encode_buf); - if (text->decode_buf) utils->free(text->decode_buf); - if (text->decode_once_buf) utils->free(text->decode_once_buf); - if (text->out_buf) utils->free(text->out_buf); - if (text->enc_in_buf) { - if(text->enc_in_buf->data) utils->free(text->enc_in_buf->data); - utils->free(text->enc_in_buf); - } - /* no need to free userid, it's just the interaction result */ - - utils->free(text); -} - -static void -kerberosv4_common_mech_free(void *glob_context __attribute__((unused)), - const sasl_utils_t *utils) -{ - if (krb_mutex) { - utils->mutex_free(krb_mutex); - krb_mutex = NULL; /* in case we need to re-use it */ - } - refcount--; - if (srvtab && !refcount) { - utils->free(srvtab); - srvtab = NULL; - } -} - -/***************************** Server Section *****************************/ - -static int cando_sec(sasl_security_properties_t *props, - int external_ssf, - int secflag) -{ - int need; - int musthave; - - if(props->maxbufsize == 0) { - need = musthave = 0; - } else { - need = props->max_ssf - external_ssf; - musthave = props->min_ssf - external_ssf; - } - - switch (secflag) { - case KRB_SECFLAG_NONE: - if (musthave <= 0) - return 1; - break; - case KRB_SECFLAG_INTEGRITY: - if ((musthave <= KRB_INTEGRITY_BITS) - && (KRB_INTEGRITY_BITS <= need)) - return 1; - break; - case KRB_SECFLAG_ENCRYPTION: - if ((musthave <= KRB_DES_SECURITY_BITS) - && (KRB_DES_SECURITY_BITS <= need)) - return 1; - break; - case KRB_SECFLAG_CREDENTIALS: - if (props->security_flags & SASL_SEC_PASS_CREDENTIALS) - return 1; - break; - } - return 0; -} - -static int ipv4_ipfromstring(const sasl_utils_t *utils, const char *addr, - struct sockaddr_in *out) -{ - struct sockaddr_storage ss; - int result; - - result = _plug_ipfromstring(utils, addr, - (struct sockaddr *)&ss, sizeof(ss)); - if (result != SASL_OK) { - /* couldn't get local IP address */ - return result; - } - /* Kerberos_V4 supports only IPv4 */ - if (((struct sockaddr *)&ss)->sa_family != AF_INET) - return SASL_FAIL; - memcpy(out, &ss, sizeof(struct sockaddr_in)); - - return SASL_OK; -} - -#ifndef macintosh -static int -kerberosv4_server_mech_new(void *glob_context __attribute__((unused)), - sasl_server_params_t *sparams, - const char *challenge __attribute__((unused)), - unsigned challen __attribute__((unused)), - void **conn_context) -{ - return new_text(sparams->utils, (context_t **) conn_context); -} - -static int kerberosv4_server_mech_step(void *conn_context, - sasl_server_params_t *sparams, - const char *clientin, - unsigned clientinlen, - const char **serverout, - unsigned *serveroutlen, - sasl_out_params_t *oparams) -{ - context_t *text = (context_t *) conn_context; - int result; - - *serverout = NULL; - *serveroutlen = 0; - - switch (text->state) { - - case 1: { - /* random 32-bit number */ - int randocts, nchal; - - /* shouldn't we check for erroneous client input here?!? */ - - sparams->utils->rand(sparams->utils->rpool,(char *) &randocts , - sizeof(randocts)); - text->challenge=randocts; - nchal = htonl(text->challenge); - - result = _plug_buf_alloc(text->utils, &text->out_buf, - &text->out_buf_len, 5); - if (result != SASL_OK) return result; - - memcpy(text->out_buf,&nchal,4); - *serverout = text->out_buf; - *serveroutlen = 4; - - text->state = 2; - - return SASL_CONTINUE; - } - - case 2: { - int nchal; - unsigned char sout[8]; - AUTH_DAT ad; - KTEXT_ST ticket; - unsigned lup; - struct sockaddr_in addr; - char *dot; - - /* received authenticator */ - - /* create ticket */ - if (clientinlen > MAX_KTXT_LEN) { - text->utils->seterror(text->utils->conn,0, - "request larger than maximum ticket size"); - return SASL_FAIL; - } - - ticket.length=clientinlen; - for (lup = 0; lup < clientinlen; lup++) - ticket.dat[lup] = clientin[lup]; - - KRB_LOCK_MUTEX(sparams->utils); - - text->realm = krb_realmofhost(sparams->serverFQDN); - - /* get instance */ - strncpy (text->instance, krb_get_phost (sparams->serverFQDN), - sizeof (text->instance)); - - KRB_UNLOCK_MUTEX(sparams->utils); - - text->instance[sizeof(text->instance)-1] = 0; - - /* At some sites, krb_get_phost() sensibly but - * atypically returns FQDNs, versus the first component, - * which is what we need for RFC2222 section 7.1 - */ - dot = strchr(text->instance, '.'); - if (dot) *dot = '\0'; - - memset(&addr, 0, sizeof(struct sockaddr_in)); - -#ifndef KRB4_IGNORE_IP_ADDRESS - /* (we ignore IP addresses in krb4 tickets at CMU to facilitate moving - from machine to machine) */ - - /* get ip number in addr*/ - result = ipv4_ipfromstring(sparams->utils, sparams->ipremoteport, &addr); - if (result != SASL_OK || !sparams->ipremoteport) { - SETERROR(text->utils, "couldn't get remote IP address"); - return result; - } -#endif - - /* check ticket */ - - KRB_LOCK_MUTEX(sparams->utils); - result = krb_rd_req(&ticket, (char *) sparams->service, text->instance, - addr.sin_addr.s_addr, &ad, srvtab); - KRB_UNLOCK_MUTEX(sparams->utils); - - if (result) { /* if fails mechanism fails */ - text->utils->seterror(text->utils->conn,0, - "krb_rd_req failed service=%s instance=%s error code=%s (%i)", - sparams->service, text->instance,get_krb_err_txt(result),result); - return SASL_BADAUTH; - } - - /* 8 octets of data - * 1-4 checksum+1 - * 5 security layers - * 6-8max cipher text buffer size - * use DES ECB in the session key - */ - - nchal=htonl(text->challenge+1); - memcpy(sout, &nchal, 4); - sout[4]= 0; - if (cando_sec(&sparams->props, sparams->external_ssf, - KRB_SECFLAG_NONE)) - sout[4] |= KRB_SECFLAG_NONE; - if (cando_sec(&sparams->props, sparams->external_ssf, - KRB_SECFLAG_INTEGRITY)) - sout[4] |= KRB_SECFLAG_INTEGRITY; - if (cando_sec(&sparams->props, sparams->external_ssf, - KRB_SECFLAG_ENCRYPTION)) - sout[4] |= KRB_SECFLAG_ENCRYPTION; - if (cando_sec(&sparams->props, sparams->external_ssf, - KRB_SECFLAG_CREDENTIALS)) - sout[4] |= KRB_SECFLAG_CREDENTIALS; - - if(sparams->props.maxbufsize) { - int tmpmaxbuf = (sparams->props.maxbufsize > 0xFFFFFF) ? 0xFFFFFF : sparams->props.maxbufsize; - - sout[5]=((tmpmaxbuf >> 16) & 0xFF); - sout[6]=((tmpmaxbuf >> 8) & 0xFF); - sout[7]=(tmpmaxbuf & 0xFF); - } else { - /* let's say we can support up to 64K */ - /* no inherent inability with our layers to support more */ - - sout[5]=0x00; /* max ciphertext buffer size */ - sout[6]=0xFF; - sout[7]=0xFF; - } - - memcpy(text->session, ad.session, 8); - memcpy(text->pname, ad.pname, sizeof(text->pname)); - memcpy(text->pinst, ad.pinst, sizeof(text->pinst)); - memcpy(text->prealm, ad.prealm, sizeof(text->prealm)); - des_key_sched(&ad.session, text->init_keysched); - - /* make keyschedule for encryption and decryption */ - des_key_sched(&ad.session, text->enc_keysched); - des_key_sched(&ad.session, text->dec_keysched); - - des_ecb_encrypt((des_cblock *)sout, - (des_cblock *)sout, - text->init_keysched, - DES_ENCRYPT); - - result = _plug_buf_alloc(text->utils, &text->out_buf, - &text->out_buf_len, 9); - if(result != SASL_OK) - return result; - - memcpy(text->out_buf,&sout,8); - *serverout = text->out_buf; - *serveroutlen = 8; - - text->state = 3; - - return SASL_CONTINUE; - } - - case 3: { - int result; - int testnum; - int flag; - unsigned char *in; - - if ((clientinlen == 0) || (clientinlen % 8 != 0)) { - text->utils->seterror(text->utils->conn,0, - "Response to challengs is not a multiple of 8 octets (a DES block)"); - return SASL_FAIL; - } - - /* we need to make a copy because des does in place decrpytion */ - in = sparams->utils->malloc(clientinlen + 1); - if (in == NULL) { - MEMERROR(sparams->utils); - return SASL_NOMEM; - } - - memcpy(in, clientin, clientinlen); - in[clientinlen] = '\0'; - - /* decrypt; verify checksum */ - - des_pcbc_encrypt((des_cblock *)in, - (des_cblock *)in, - clientinlen, - text->init_keysched, - &text->session, - DES_DECRYPT); - - testnum = (in[0]*256*256*256)+(in[1]*256*256)+(in[2]*256)+in[3]; - - if (testnum != text->challenge) { - SETERROR(sparams->utils, "incorrect response to challenge"); - return SASL_BADAUTH; - } - - if (!cando_sec(&sparams->props, sparams->external_ssf, - in[4] & KRB_SECFLAGS)) { - SETERROR(sparams->utils, - "invalid security property specified"); - return SASL_BADPROT; - } - - oparams->encode = &kerberosv4_encode; - oparams->decode = &kerberosv4_decode; - - switch (in[4] & KRB_SECFLAGS) { - case KRB_SECFLAG_NONE: - text->sec_type = KRB_SEC_NONE; - oparams->encode = NULL; - oparams->decode = NULL; - oparams->mech_ssf = 0; - break; - case KRB_SECFLAG_INTEGRITY: - text->sec_type = KRB_SEC_INTEGRITY; - oparams->mech_ssf = KRB_INTEGRITY_BITS; - break; - case KRB_SECFLAG_ENCRYPTION: - text->sec_type = KRB_SEC_ENCRYPTION; - oparams->mech_ssf = KRB_DES_SECURITY_BITS; - break; - default: - /* Mark that we tried */ - oparams->mech_ssf = 2; - SETERROR(sparams->utils, "not a supported encryption layer"); - return SASL_BADPROT; - } - - /* get ip data */ - /* get ip number in addr*/ - result = ipv4_ipfromstring(sparams->utils, - sparams->iplocalport, &(text->ip_local)); - if (result != SASL_OK) { - SETERROR(sparams->utils, "couldn't get local ip address"); - /* couldn't get local IP address */ - return result; - } - - result = ipv4_ipfromstring(sparams->utils, - sparams->ipremoteport, &(text->ip_remote)); - if (result != SASL_OK) { - SETERROR(sparams->utils, "couldn't get remote ip address"); - /* couldn't get remote IP address */ - return result; - } - - /* fill in oparams */ - oparams->maxoutbuf = (in[5] << 16) + (in[6] << 8) + in[7]; - if(oparams->mech_ssf) { - /* FIXME: Likely to be too large */ - oparams->maxoutbuf -= 50; - } - - if (sparams->canon_user) { - char *user=NULL, *authid=NULL; - size_t ulen = 0, alen = strlen(text->pname); - int ret, cflag = SASL_CU_AUTHID | SASL_CU_EXTERNALLY_VERIFIED; - - if (text->pinst[0]) { - alen += strlen(text->pinst) + 1 /* for the . */; - } - flag = 0; - if (strcmp(text->realm, text->prealm)) { - alen += strlen(text->prealm) + 1 /* for the @ */; - flag = 1; - } - - authid = sparams->utils->malloc(alen + 1); - if (!authid) { - MEMERROR(sparams->utils); - return SASL_NOMEM; - } - - strcpy(authid, text->pname); - if (text->pinst[0]) { - strcat(authid, "."); - strcat(authid, text->pinst); - } - if (flag) { - strcat(authid, "@"); - strcat(authid, text->prealm); - } - - if (in[8]) { - user = sparams->utils->malloc(strlen((char *) in + 8) + 1); - if (!user) { - MEMERROR(sparams->utils); - return SASL_NOMEM; - } - - strcpy(user, (char *) in + 8); - ulen = strlen(user); - } else { - cflag |= SASL_CU_AUTHZID; - } - - ret = sparams->canon_user(sparams->utils->conn, authid, alen, - cflag, oparams); - sparams->utils->free(authid); - if (ret != SASL_OK) { - if (user) - sparams->utils->free(user); - return ret; - } - - if (user) { - ret = sparams->canon_user(sparams->utils->conn, user, ulen, - SASL_CU_AUTHZID, oparams); - - sparams->utils->free(user); - } - - if (ret != SASL_OK) return ret; - } - - /* nothing more to do; authenticated */ - oparams->doneflag = 1; - oparams->param_version = 0; - - /* used by layers */ - _plug_decode_init(&text->decode_context, text->utils, - (sparams->props.maxbufsize > 0xFFFFFF) ? 0xFFFFFF : - sparams->props.maxbufsize); - - sparams->utils->free(in); - - return SASL_OK; - } - - default: - sparams->utils->log(NULL, SASL_LOG_ERR, - "Invalid Kerberos server step %d\n", text->state); - return SASL_FAIL; - } - - return SASL_FAIL; /* should never get here */ -} - -static int kerberosv4_mech_avail(void *glob_context __attribute__((unused)), - sasl_server_params_t *sparams, - void **conn_context __attribute__((unused))) -{ - struct sockaddr_in addr; - - if (!sparams->iplocalport || !sparams->ipremoteport - || ipv4_ipfromstring(sparams->utils, - sparams->iplocalport, &addr) != SASL_OK - || ipv4_ipfromstring(sparams->utils, - sparams->ipremoteport, &addr) != SASL_OK) { - SETERROR(sparams->utils, - "KERBEROS_V4 unavailable due to lack of IPv4 information"); - return SASL_NOMECH; - } - - return SASL_OK; -} - - -static sasl_server_plug_t kerberosv4_server_plugins[] = -{ - { - "KERBEROS_V4", /* mech_name */ - KRB_DES_SECURITY_BITS, /* max_ssf */ - SASL_SEC_NOPLAINTEXT - | SASL_SEC_NOACTIVE - | SASL_SEC_NOANONYMOUS - | SASL_SEC_MUTUAL_AUTH, /* security_flags */ - SASL_FEAT_SERVER_FIRST - | SASL_FEAT_ALLOWS_PROXY, /* features */ - NULL, /* glob_context */ - &kerberosv4_server_mech_new, /* mech_new */ - &kerberosv4_server_mech_step, /* mech_step */ - &kerberosv4_common_mech_dispose,/* mech_dispose */ - &kerberosv4_common_mech_free, /* mech_free */ - NULL, /* setpass */ - NULL, /* user_query */ - NULL, /* idle */ - &kerberosv4_mech_avail, /* mech_avail */ - NULL /* spare */ - } -}; -#endif /* macintosh */ - -int kerberos4_server_plug_init(const sasl_utils_t *utils, - int maxversion, - int *out_version, - sasl_server_plug_t **pluglist, - int *plugcount) -{ -#ifdef macintosh - return SASL_BADVERS; -#else - const char *ret; - unsigned int rl; - - if (maxversion < SASL_SERVER_PLUG_VERSION) { - return SASL_BADVERS; - } - - - if (!krb_mutex) { - krb_mutex = utils->mutex_alloc(); - if(!krb_mutex) { - return SASL_FAIL; - } - } - - if (!srvtab) { - utils->getopt(utils->getopt_context, - "KERBEROS_V4", "srvtab", &ret, &rl); - - if (ret == NULL) { - ret = KEYFILE; - rl = strlen(ret); - } - - srvtab = utils->malloc(sizeof(char) * (rl + 1)); - if(!srvtab) { - MEMERROR(utils); - return SASL_NOMEM; - } - - strcpy(srvtab, ret); - } - - refcount++; - - /* fail if we can't open the srvtab file */ - if (access(srvtab, R_OK) != 0) { - utils->log(NULL, SASL_LOG_ERR, - "can't access srvtab file %s: %m", srvtab, errno); - if(!(--refcount)) { - utils->free(srvtab); - srvtab=NULL; - } - return SASL_FAIL; - } - - *out_version = SASL_SERVER_PLUG_VERSION; - *pluglist = kerberosv4_server_plugins; - *plugcount = 1; - - return SASL_OK; -#endif -} - -/***************************** Client Section *****************************/ - -static int -kerberosv4_client_mech_new(void *glob_context __attribute__((unused)), - sasl_client_params_t *params, - void **conn_context) -{ - return new_text(params->utils, (context_t **) conn_context); -} - -static int kerberosv4_client_mech_step(void *conn_context, - sasl_client_params_t *cparams, - const char *serverin, - unsigned serverinlen, - sasl_interact_t **prompt_need, - const char **clientout, - unsigned *clientoutlen, - sasl_out_params_t *oparams) -{ - context_t *text = (context_t *) conn_context; - KTEXT_ST authent; - int ret; - - *clientout = NULL; - *clientoutlen = 0; - - authent.length = MAX_KTXT_LEN; - - switch (text->state) { - - case 1: { - /* We should've just received a 32-bit number in network byte order. - * We want to reply with an authenticator. */ - int result; - KTEXT_ST ticket; - char *dot; - - memset(&ticket, 0L, sizeof(ticket)); - ticket.length = MAX_KTXT_LEN; - - if (serverinlen != 4) { - text->utils->seterror(text->utils->conn, 0, - "server challenge not 4 bytes long"); - return SASL_BADPROT; - } - - memcpy(&text->challenge, serverin, 4); - - text->challenge=ntohl(text->challenge); - - if (cparams->serverFQDN == NULL) { - cparams->utils->log(NULL, SASL_LOG_ERR, - "no 'serverFQDN' set"); - SETERROR(text->utils, "paramater error"); - return SASL_BADPARAM; - } - if (cparams->service == NULL) { - cparams->utils->log(NULL, SASL_LOG_ERR, - "no 'service' set"); - SETERROR(text->utils, "paramater error"); - return SASL_BADPARAM; - } - - KRB_LOCK_MUTEX(cparams->utils); - text->realm=krb_realmofhost(cparams->serverFQDN); - text->hostname=(char *) cparams->serverFQDN; - - /* the instance of the principal we're authenticating with */ - strncpy (text->instance, krb_get_phost (cparams->serverFQDN), - sizeof (text->instance)); - - /* text->instance is NULL terminated unless it was too long */ - text->instance[sizeof(text->instance)-1] = '\0'; - - /* At some sites, krb_get_phost() sensibly but - * atypically returns FQDNs, versus the first component, - * which is what we need for RFC2222 section 7.1 - */ - dot = strchr(text->instance, '.'); - if (dot) *dot = '\0'; - -#ifndef macintosh - if ((result = krb_mk_req(&ticket, (char *) cparams->service, - text->instance, text->realm, text->challenge))) -#else - memset(&text->credentials,0,sizeof(text->credentials)); - if (kcglue_krb_mk_req(ticket.dat, - &ticket.length, - cparams->service, - text->instance, - text->realm, - text->challenge, - &text->credentials.session, - text->credentials.pname, - text->credentials.pinst) != 0) -#endif - { - KRB_UNLOCK_MUTEX(cparams->utils); - - text->utils->seterror(text->utils->conn,SASL_NOLOG, - "krb_mk_req() failed"); - - cparams->utils->log(NULL, SASL_LOG_ERR, - "krb_mk_req() failed: %s (%d)", - get_krb_err_txt(result), result); - return SASL_FAIL; - } - - KRB_UNLOCK_MUTEX(cparams->utils); - - ret = _plug_buf_alloc(text->utils, &(text->out_buf), - &(text->out_buf_len), ticket.length); - if (ret != SASL_OK) return ret; - - memcpy(text->out_buf, ticket.dat, ticket.length); - - *clientout = text->out_buf; - *clientoutlen = ticket.length; - - text->state = 2; - - return SASL_CONTINUE; - } - - /* challenge #2 */ - case 2: { - int need = 0; - int musthave = 0; - int testnum; - int nchal; - unsigned char *sout = NULL; - unsigned len; - unsigned char in[8]; - int result; - int servermaxbuf; - char *buf; - int user_result = SASL_OK; - - /* try to get the authid */ - if (text->user == NULL) { - user_result = _plug_get_userid(cparams->utils, &text->user, - prompt_need); - - if (user_result != SASL_OK && user_result != SASL_INTERACT) - return user_result; - } - - /* free prompts we got */ - if (prompt_need && *prompt_need) { - cparams->utils->free(*prompt_need); - *prompt_need = NULL; - } - - /* if there are prompts not filled in */ - if (user_result == SASL_INTERACT) { - /* make the prompt list */ - int result = - _plug_make_prompts(cparams->utils, prompt_need, - user_result == SASL_INTERACT ? - "Please enter your authorization name" : NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, NULL, - NULL, NULL, NULL); - if (result!=SASL_OK) return result; - - return SASL_INTERACT; - } - - /* must be 8 octets */ - if (serverinlen!=8) { - SETERROR(cparams->utils, - "server response not 8 bytes long"); - return SASL_BADAUTH; - } - - memcpy(in, serverin, 8); - -#ifndef macintosh - /* get credentials */ - KRB_LOCK_MUTEX(cparams->utils); - result = krb_get_cred((char *)cparams->service, - text->instance, - text->realm, - &text->credentials); - KRB_UNLOCK_MUTEX(cparams->utils); - - if(result != 0) { - cparams->utils->log(NULL, SASL_LOG_ERR, - "krb_get_cred() failed: %s (%d)", - get_krb_err_txt(result), result); - SETERROR(cparams->utils, "krb_get_cred() failed"); - return SASL_BADAUTH; - } -#endif - memcpy(text->session, text->credentials.session, 8); - - /* make key schedule for encryption and decryption */ - des_key_sched(&text->session, text->init_keysched); - des_key_sched(&text->session, text->enc_keysched); - des_key_sched(&text->session, text->dec_keysched); - - /* decrypt from server */ - des_ecb_encrypt((des_cblock *)in, (des_cblock *)in, - text->init_keysched, DES_DECRYPT); - - /* convert to 32bit int */ - testnum = (in[0]*256*256*256)+(in[1]*256*256)+(in[2]*256)+in[3]; - - /* verify data 1st 4 octets must be equal to chal+1 */ - if (testnum != text->challenge+1) { - SETERROR(cparams->utils,"server response incorrect"); - return SASL_BADAUTH; - } - - /* construct 8 octets - * 1-4 - original checksum - * 5 - bitmask of sec layer - * 6-8 max buffer size - */ - if (cparams->props.min_ssf > - KRB_DES_SECURITY_BITS + cparams->external_ssf) { - SETERROR(cparams->utils, - "minimum ssf too strong for this mechanism"); - return SASL_TOOWEAK; - } else if (cparams->props.min_ssf > cparams->props.max_ssf) { - SETERROR(cparams->utils, - "minimum ssf larger than maximum ssf"); - return SASL_BADPARAM; - } - - /* create stuff to send to server */ - sout = (char *) - cparams->utils->malloc(9+(text->user ? strlen(text->user) : 0)+9); - if (!sout) { - MEMERROR(cparams->utils); - return SASL_NOMEM; - } - - nchal = htonl(text->challenge); - memcpy(sout, &nchal, 4); - - /* need bits of layer */ - if(cparams->props.maxbufsize == 0) { - need = musthave = 0; - } else { - need = cparams->props.max_ssf - cparams->external_ssf; - musthave = cparams->props.min_ssf - cparams->external_ssf; - } - - oparams->decode = &kerberosv4_decode; - oparams->encode = &kerberosv4_encode; - - if ((in[4] & KRB_SECFLAG_ENCRYPTION) - && (need>=56) && (musthave <= 56)) { - /* encryption */ - text->sec_type = KRB_SEC_ENCRYPTION; - oparams->mech_ssf = 56; - sout[4] = KRB_SECFLAG_ENCRYPTION; - /* using encryption layer */ - } else if ((in[4] & KRB_SECFLAG_INTEGRITY) - && (need >= 1) && (musthave <= 1)) { - /* integrity */ - text->sec_type = KRB_SEC_INTEGRITY; - oparams->mech_ssf=1; - sout[4] = KRB_SECFLAG_INTEGRITY; - /* using integrity layer */ - } else if ((in[4] & KRB_SECFLAG_NONE) && (musthave <= 0)) { - /* no layer */ - text->sec_type = KRB_SEC_NONE; - oparams->encode=NULL; - oparams->decode=NULL; - oparams->mech_ssf=0; - sout[4] = KRB_SECFLAG_NONE; - } else { - /* Mark that we tried */ - oparams->mech_ssf=2; - SETERROR(cparams->utils, - "unable to agree on layers with server"); - return SASL_BADPROT; - } - - servermaxbuf = in[5]*256*256+in[6]*256+in[7]; - oparams->maxoutbuf = servermaxbuf; - if (oparams->mech_ssf) { - /* FIXME: Likely to be too large */ - oparams->maxoutbuf -= 50; - } - - if(cparams->props.maxbufsize) { - int tmpmaxbuf = ( cparams->props.maxbufsize > 0xFFFFFF ) ? 0xFFFFFF : cparams->props.maxbufsize; - - sout[5]=((tmpmaxbuf >> 16) & 0xFF); - sout[6]=((tmpmaxbuf >> 8) & 0xFF); - sout[7]=(tmpmaxbuf & 0xFF); - } else { - /* let's say we can support up to 64K */ - /* no inherent inability with our layers to support more */ - - sout[5]=0x00; /* max ciphertext buffer size */ - sout[6]=0xFF; - sout[7]=0xFF; - } - - sout[8] = 0x00; /* just to be safe */ - - /* append userid */ - len = 9; /* 8 + trailing NULL */ - if (text->user) { - strcpy((char *)sout + 8, text->user); - len += strlen(text->user); - } - - /* append 0 based octets so is multiple of 8 */ - while(len % 8) { - sout[len]=0; - len++; - } - sout[len]=0; - - des_pcbc_encrypt((des_cblock *)sout, - (des_cblock *)sout, - len, - text->init_keysched, - (des_cblock *)text->session, - DES_ENCRYPT); - - result = _plug_buf_alloc(text->utils, &text->out_buf, - &text->out_buf_len, len); - if (result != SASL_OK) return result; - - memcpy(text->out_buf, sout, len); - - *clientout = text->out_buf; - *clientoutlen = len; - - /* nothing more to do; should be authenticated */ - if(cparams->iplocalport) { - result = ipv4_ipfromstring(cparams->utils, - cparams->iplocalport, - &(text->ip_local)); - if (result != SASL_OK) { - /* couldn't get local IP address */ - return result; - } - } - - if (cparams->ipremoteport) { - result = ipv4_ipfromstring(cparams->utils, - cparams->ipremoteport, - &(text->ip_remote)); - if (result != SASL_OK) { - /* couldn't get local IP address */ - return result; - } - } - - buf = cparams->utils->malloc(strlen(text->credentials.pname) - + strlen(text->credentials.pinst) - + 2); - if (!buf) { - MEMERROR(cparams->utils); - return SASL_NOMEM; - } - strcpy(buf, text->credentials.pname); - if (text->credentials.pinst[0]) { - strcat(buf, "."); - strcat(buf, text->credentials.pinst); - } - - if (text->user && !text->user[0]) { - text->user = NULL; - } - - ret = cparams->canon_user(cparams->utils->conn, buf, 0, - SASL_CU_AUTHID, oparams); - if (ret != SASL_OK) { - cparams->utils->free(buf); - cparams->utils->free(sout); - return ret; - } - - if (!text->user) { - /* 0 in length fields means use strlen() */ - ret = cparams->canon_user(cparams->utils->conn, buf, 0, - SASL_CU_AUTHZID, oparams); - } else { - ret = cparams->canon_user(cparams->utils->conn, text->user, 0, - SASL_CU_AUTHZID, oparams); - } - - cparams->utils->free(buf); - - oparams->doneflag = 1; - oparams->param_version = 0; - - /* used by layers */ - _plug_decode_init(&text->decode_context, text->utils, - (cparams->props.maxbufsize > 0xFFFFFF) ? 0xFFFFFF : - cparams->props.maxbufsize); - - if (sout) cparams->utils->free(sout); - - return SASL_OK; - } - - default: - cparams->utils->log(NULL, SASL_LOG_ERR, - "Invalid Kerberos client step %d\n", text->state); - return SASL_FAIL; - } - - return SASL_FAIL; /* should never get here */ -} - -static const long kerberosv4_required_prompts[] = { - SASL_CB_LIST_END -}; - -static sasl_client_plug_t kerberosv4_client_plugins[] = -{ - { - "KERBEROS_V4", /* mech_name */ - KRB_DES_SECURITY_BITS, /* max_ssf */ - SASL_SEC_NOPLAINTEXT - | SASL_SEC_NOACTIVE - | SASL_SEC_NOANONYMOUS - | SASL_SEC_MUTUAL_AUTH, /* security_flags */ - SASL_FEAT_NEEDSERVERFQDN - | SASL_FEAT_SERVER_FIRST - | SASL_FEAT_ALLOWS_PROXY, /* features */ - kerberosv4_required_prompts, /* required_prompts */ - NULL, /* glob_context */ - &kerberosv4_client_mech_new, /* mech_new */ - &kerberosv4_client_mech_step, /* mech_step */ - &kerberosv4_common_mech_dispose,/* mech_dispose */ - &kerberosv4_common_mech_free, /* mech_free */ - NULL, /* idle */ - NULL, /* spare */ - NULL /* spare */ - } -}; - -int kerberos4_client_plug_init(const sasl_utils_t *utils, - int maxversion, - int *out_version, - sasl_client_plug_t **pluglist, - int *plugcount) -{ - if (maxversion < SASL_CLIENT_PLUG_VERSION) { - SETERROR(utils, "Wrong KERBEROS_V4 version"); - return SASL_BADVERS; - } - - if(!krb_mutex) { - krb_mutex = utils->mutex_alloc(); - if(!krb_mutex) { - return SASL_FAIL; - } - } - - *out_version = SASL_CLIENT_PLUG_VERSION; - *pluglist = kerberosv4_client_plugins; - *plugcount = 1; - - refcount++; - - return SASL_OK; -} diff --git a/plugins/makeinit.sh b/plugins/makeinit.sh index 3131877a..4b1bd449 100644 --- a/plugins/makeinit.sh +++ b/plugins/makeinit.sh @@ -1,6 +1,6 @@ plugin_init="$1" # mechanism plugins -for mech in anonymous crammd5 digestmd5 scram gssapiv2 kerberos4 login ntlm otp passdss plain srp gs2; do +for mech in anonymous crammd5 digestmd5 scram gssapiv2 login ntlm otp passdss plain srp gs2; do if [ ${plugin_init} = "${mech}_init.c" ];then echo " diff --git a/plugins/ntlm.c b/plugins/ntlm.c deleted file mode 100644 index abcb31fe..00000000 --- a/plugins/ntlm.c +++ /dev/null @@ -1,2221 +0,0 @@ -/* NTLM SASL plugin - * Ken Murchison - * - * References: - * http://www.innovation.ch/java/ntlm.html - * http://www.opengroup.org/comsource/techref2/NCH1222X.HTM - * http://www.ubiqx.org/cifs/rfc-draft/draft-leach-cifs-v1-spec-02.html - */ -/* - * Copyright (c) 1998-2016 Carnegie Mellon University. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name "Carnegie Mellon University" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For permission or any other legal - * details, please contact - * Carnegie Mellon University - * Center for Technology Transfer and Enterprise Creation - * 4615 Forbes Avenue - * Suite 302 - * Pittsburgh, PA 15213 - * (412) 268-7393, fax: (412) 268-7395 - * innovation@andrew.cmu.edu - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Computing Services - * at Carnegie Mellon University (http://www.cmu.edu/computing/)." - * - * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE - * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include - -#ifdef WIN32 -# include /* for getpid */ - typedef int pid_t; -#else -# include -# include -# include -# include -# include - -#ifndef SYS_NMLN - struct utsname dummy; -# define SYS_NMLN sizeof(dummy.sysname) -#endif - -# define closesocket(sock) close(sock) - typedef int SOCKET; -#endif /* WIN32 */ - -#ifndef sasl_getpid /* for some reason VS doesn't like #define getpid */ -# define sasl_getpid getpid -#endif - -#include -#ifdef OPENSSL_NO_MD4 -#error No MD4 support in OpenSSL -#endif -#include -#include -#include -#include -#if (OPENSSL_VERSION_NUMBER >= 0x0090700f) && \ - !defined(OPENSSL_ENABLE_OLD_DES_SUPPORT) -# define des_cblock DES_cblock -# define des_key_schedule DES_key_schedule -# define des_set_odd_parity(k) \ - DES_set_odd_parity((k)) -# define des_set_key(k,ks) \ - DES_set_key((k),&(ks)) -# define des_key_sched(k,ks) \ - DES_key_sched((k),&(ks)) -# define des_ecb_encrypt(i,o,k,e) \ - DES_ecb_encrypt((i),(o),&(k),(e)) -#endif /* OpenSSL 0.9.7+ w/o old DES support */ - -/* for legacy libcrypto support */ -#include "crypto-compat.h" - -#include -#include - -#include "plugin_common.h" - -/***************************** Common Section *****************************/ - -#ifdef WIN32 -static ssize_t writev (SOCKET fd, const struct iovec *iov, size_t iovcnt); - -ssize_t writev (SOCKET fd, const struct iovec *iov, size_t iovcnt) -{ - ssize_t nwritten; /* amount written */ - ssize_t nbytes; - size_t i; - - nbytes = 0; - - for (i = 0; i < iovcnt; i++) { - if ((nwritten = send (fd, iov[i].iov_base, iov[i].iov_len, 0)) == SOCKET_ERROR) { -/* Unless socket is nonblocking, we should always write everything */ - return (-1); - } - - nbytes += nwritten; - - if (nwritten < iov[i].iov_len) { - break; - } - } - return (nbytes); -} -#endif /* WIN32 */ - -#ifndef UINT16_MAX -#define UINT16_MAX 65535U -#endif - -#if UINT_MAX == UINT16_MAX -typedef unsigned int uint16; -#elif USHRT_MAX == UINT16_MAX -typedef unsigned short uint16; -#else -#error dont know what to use for uint16 -#endif - -#ifndef UINT32_MAX -#define UINT32_MAX 4294967295U -#endif - -#if UINT_MAX == UINT32_MAX -typedef unsigned int uint32; -#elif ULONG_MAX == UINT32_MAX -typedef unsigned long uint32; -#elif USHRT_MAX == UINT32_MAX -typedef unsigned short uint32; -#else -#error dont know what to use for uint32 -#endif - -#define NTLM_SIGNATURE "NTLMSSP" - -enum { - NTLM_TYPE_REQUEST = 1, - NTLM_TYPE_CHALLENGE = 2, - NTLM_TYPE_RESPONSE = 3 -}; - -enum { - NTLM_USE_UNICODE = 0x00001, - NTLM_USE_ASCII = 0x00002, - NTLM_ASK_TARGET = 0x00004, - NTLM_AUTH_NTLM = 0x00200, - NTLM_ALWAYS_SIGN = 0x08000, - NTLM_TARGET_IS_DOMAIN = 0x10000, - NTLM_TARGET_IS_SERVER = 0x20000, - NTLM_FLAGS_MASK = 0x0ffff -}; - -enum { - NTLM_NONCE_LENGTH = 8, - NTLM_HASH_LENGTH = 21, - NTLM_RESP_LENGTH = 24, - NTLM_SESSKEY_LENGTH = 16, -}; - -enum { - NTLM_SIG_OFFSET = 0, - NTLM_TYPE_OFFSET = 8, - - NTLM_TYPE1_FLAGS_OFFSET = 12, - NTLM_TYPE1_DOMAIN_OFFSET = 16, - NTLM_TYPE1_WORKSTN_OFFSET = 24, - NTLM_TYPE1_DATA_OFFSET = 32, - NTLM_TYPE1_MINSIZE = 16, - - NTLM_TYPE2_TARGET_OFFSET = 12, - NTLM_TYPE2_FLAGS_OFFSET = 20, - NTLM_TYPE2_CHALLENGE_OFFSET = 24, - NTLM_TYPE2_CONTEXT_OFFSET = 32, - NTLM_TYPE2_TARGETINFO_OFFSET= 40, - NTLM_TYPE2_DATA_OFFSET = 48, - NTLM_TYPE2_MINSIZE = 32, - - NTLM_TYPE3_LMRESP_OFFSET = 12, - NTLM_TYPE3_NTRESP_OFFSET = 20, - NTLM_TYPE3_DOMAIN_OFFSET = 28, - NTLM_TYPE3_USER_OFFSET = 36, - NTLM_TYPE3_WORKSTN_OFFSET = 44, - NTLM_TYPE3_SESSIONKEY_OFFSET= 52, - NTLM_TYPE3_FLAGS_OFFSET = 60, - NTLM_TYPE3_DATA_OFFSET = 64, - NTLM_TYPE3_MINSIZE = 52, - - NTLM_BUFFER_LEN_OFFSET = 0, - NTLM_BUFFER_MAXLEN_OFFSET = 2, - NTLM_BUFFER_OFFSET_OFFSET = 4, - NTLM_BUFFER_SIZE = 8 -}; - -/* return the length of a string (even if it is NULL) */ -#define xstrlen(s) (s ? strlen(s) : 0) - -/* machine-independent routines to convert to/from Intel byte-order */ -#define htois(is, hs) \ - (is)[0] = hs & 0xff; \ - (is)[1] = hs >> 8 - -#define itohs(is) \ - ((is)[0] | ((is)[1] << 8)) - -#define htoil(il, hl) \ - (il)[0] = hl & 0xff; \ - (il)[1] = (hl >> 8) & 0xff; \ - (il)[2] = (hl >> 16) & 0xff; \ - (il)[3] = hl >> 24 - -#define itohl(il) \ - ((il)[0] | ((il)[1] << 8) | ((il)[2] << 16) | ((il)[3] << 24)) - -/* convert string to all upper case */ -static const char *ucase(const char *str, size_t len) -{ - char *cp = (char *) str; - - if (!len) len = xstrlen(str); - - while (len && cp && *cp) { - *cp = toupper((int) *cp); - cp++; - len--; - } - - return (str); -} - -/* copy src to dst as unicode (in Intel byte-order) */ -static void to_unicode(u_char *dst, const char *src, int len) -{ - for (; len; len--) { - *dst++ = *src++; - *dst++ = 0; - } -} - -/* copy unicode src (in Intel byte-order) to dst */ -static void from_unicode(char *dst, u_char *src, int len) -{ - for (; len; len--) { - *dst++ = *src & 0x7f; - src += 2; - } -} - -/* load a string into an NTLM buffer */ -static void load_buffer(u_char *buf, const u_char *str, uint16 len, - int unicode, u_char *base, uint32 *offset) -{ - if (len) { - if (unicode) { - to_unicode(base + *offset, (const char *) str, len); - len *= 2; - } - else { - memcpy(base + *offset, str, len); - } - } - - htois(buf + NTLM_BUFFER_LEN_OFFSET, len); - htois(buf + NTLM_BUFFER_MAXLEN_OFFSET, len); - htoil(buf + NTLM_BUFFER_OFFSET_OFFSET, *offset); - *offset += len; -} - -/* unload a string from an NTLM buffer */ -static int unload_buffer(const sasl_utils_t *utils, const u_char *buf, - u_char **str, unsigned *outlen, - int unicode, const u_char *base, unsigned msglen) -{ - uint16 len = itohs(buf + NTLM_BUFFER_LEN_OFFSET); - - if (len) { - uint32 offset; - - *str = utils->malloc(len + 1); /* add 1 for NUL */ - if (*str == NULL) { - MEMERROR(utils); - return SASL_NOMEM; - } - - offset = itohl(buf + NTLM_BUFFER_OFFSET_OFFSET); - - /* sanity check */ - if (offset > msglen || len > (msglen - offset)) return SASL_BADPROT; - - if (unicode) { - len /= 2; - from_unicode((char *) *str, (u_char *) base + offset, len); - } - else - memcpy(*str, base + offset, len); - - (*str)[len] = '\0'; /* add NUL */ - } - else { - *str = NULL; - } - - if (outlen) *outlen = len; - - return SASL_OK; -} - -/* - * NTLM encryption/authentication routines per section 2.10 of - * draft-leach-cifs-v1-spec-02 - */ -static void E(unsigned char *out, unsigned char *K, unsigned Klen, - unsigned char *D, unsigned Dlen) - -{ - unsigned k, d; - des_cblock K64; - des_key_schedule ks; - unsigned char *Dp; -#define KEY_SIZE 7 -#define BLOCK_SIZE 8 - - for (k = 0; k < Klen; k += KEY_SIZE, K += KEY_SIZE) { - /* convert 56-bit key to 64-bit */ - K64[0] = K[0]; - K64[1] = ((K[0] << 7) & 0xFF) | (K[1] >> 1); - K64[2] = ((K[1] << 6) & 0xFF) | (K[2] >> 2); - K64[3] = ((K[2] << 5) & 0xFF) | (K[3] >> 3); - K64[4] = ((K[3] << 4) & 0xFF) | (K[4] >> 4); - K64[5] = ((K[4] << 3) & 0xFF) | (K[5] >> 5); - K64[6] = ((K[5] << 2) & 0xFF) | (K[6] >> 6); - K64[7] = (K[6] << 1) & 0xFF; - - des_set_odd_parity(&K64); /* XXX is this necessary? */ - des_set_key(&K64, ks); - - for (d = 0, Dp = D; d < Dlen; - d += BLOCK_SIZE, Dp += BLOCK_SIZE, out += BLOCK_SIZE) { - des_ecb_encrypt((void *) Dp, (void *) out, ks, DES_ENCRYPT); - } - } -} - -static unsigned char *P16_lm(unsigned char *P16, sasl_secret_t *passwd, - const sasl_utils_t *utils __attribute__((unused)), - char **buf __attribute__((unused)), - unsigned *buflen __attribute__((unused)), - int *result) -{ - char P14[14]; - unsigned char S8[] = { 0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 }; - - strncpy(P14, (const char *) passwd->data, sizeof(P14)); - ucase(P14, sizeof(P14)); - - E(P16, (unsigned char *) P14, sizeof(P14), S8, sizeof(S8)); - *result = SASL_OK; - return P16; -} - -static unsigned char *P16_nt(unsigned char *P16, sasl_secret_t *passwd, - const sasl_utils_t *utils, - char **buf, unsigned *buflen, int *result) -{ - if (_plug_buf_alloc(utils, buf, buflen, 2 * passwd->len) != SASL_OK) { - SETERROR(utils, "cannot allocate P16_nt unicode buffer"); - *result = SASL_NOMEM; - } - else { - to_unicode((unsigned char *) *buf, (const char *) passwd->data, passwd->len); - MD4((unsigned char *) *buf, 2 * passwd->len, P16); - *result = SASL_OK; - } - return P16; -} - -static unsigned char *P21(unsigned char *P21, sasl_secret_t *passwd, - unsigned char * (*P16)(unsigned char *, - sasl_secret_t *, - const sasl_utils_t *, - char **, unsigned *, int *), - const sasl_utils_t *utils, - char **buf, unsigned *buflen, int *result) -{ - memset(P16(P21, passwd, utils, buf, buflen, result) + 16, 0, 5); - return P21; -} - -static unsigned char *P24(unsigned char *P24, unsigned char *P21, - unsigned char *C8) - -{ - E(P24, P21, NTLM_HASH_LENGTH, C8, NTLM_NONCE_LENGTH); - return P24; -} - -static HMAC_CTX *_plug_HMAC_CTX_new(const sasl_utils_t *utils) -{ - utils->log(NULL, SASL_LOG_DEBUG, "_plug_HMAC_CTX_new()"); - -#if OPENSSL_VERSION_NUMBER >= 0x10100000L - return HMAC_CTX_new(); -#else - return utils->malloc(sizeof(HMAC_CTX)); -#endif -} - -static void _plug_HMAC_CTX_free(HMAC_CTX *ctx, const sasl_utils_t *utils) -{ - utils->log(NULL, SASL_LOG_DEBUG, "_plug_HMAC_CTX_free()"); - -#if OPENSSL_VERSION_NUMBER >= 0x10100000L - HMAC_CTX_free(ctx); -#else - HMAC_cleanup(ctx); - utils->free(ctx); -#endif -} - -static unsigned char *V2(unsigned char *V2, sasl_secret_t *passwd, - const char *authid, const char *target, - const unsigned char *challenge, - const unsigned char *blob, unsigned bloblen, - const sasl_utils_t *utils, - char **buf, unsigned *buflen, int *result) -{ - HMAC_CTX *ctx = NULL; - unsigned char hash[EVP_MAX_MD_SIZE]; - char *upper; - unsigned int len; - - /* Allocate enough space for the unicode target */ - len = (unsigned int) (strlen(authid) + xstrlen(target)); - if (_plug_buf_alloc(utils, buf, buflen, 2 * len + 1) != SASL_OK) { - SETERROR(utils, "cannot allocate NTLMv2 hash"); - *result = SASL_NOMEM; - } - else if ((ctx = _plug_HMAC_CTX_new(utils)) == NULL) { - SETERROR(utils, "cannot allocate HMAC CTX"); - *result = SASL_NOMEM; - } - else { - /* NTLMv2hash = HMAC-MD5(NTLMhash, unicode(ucase(authid + domain))) */ - P16_nt(hash, passwd, utils, buf, buflen, result); - - /* Use the tail end of the buffer for ucase() conversion */ - upper = *buf + len; - strcpy(upper, authid); - if (target) strcat(upper, target); - ucase(upper, len); - to_unicode((unsigned char *) *buf, upper, len); - - HMAC(EVP_md5(), hash, MD5_DIGEST_LENGTH, - (unsigned char *) *buf, 2 * len, hash, &len); - - /* V2 = HMAC-MD5(NTLMv2hash, challenge + blob) + blob */ - HMAC_CTX_reset(ctx); - HMAC_Init_ex(ctx, hash, len, EVP_md5(), NULL); - HMAC_Update(ctx, challenge, NTLM_NONCE_LENGTH); - HMAC_Update(ctx, blob, bloblen); - HMAC_Final(ctx, V2, &len); - - /* the blob is concatenated outside of this function */ - - *result = SASL_OK; - } - - if (ctx) _plug_HMAC_CTX_free(ctx, utils); - - return V2; -} - -/***************************** Server Section *****************************/ - -typedef struct server_context { - int state; - - uint32 flags; - unsigned char nonce[NTLM_NONCE_LENGTH]; - - /* per-step mem management */ - char *out_buf; - unsigned out_buf_len; - - /* socket to remote authentication host */ - SOCKET sock; - -} server_context_t; - -#define N(a) (sizeof (a) / sizeof (a[0])) - -#define SMB_HDR_PROTOCOL "\xffSMB" - -typedef struct { - unsigned char protocol[4]; - unsigned char command; - uint32 status; - unsigned char flags; - uint16 flags2; - uint16 PidHigh; - unsigned char extra[10]; - uint16 tid; - uint16 pid; - uint16 uid; - uint16 mid; -} SMB_Header; - -typedef struct { - uint16 dialect_index; - unsigned char security_mode; - uint16 max_mpx_count; - uint16 max_number_vcs; - uint32 max_buffer_size; - uint32 max_raw_size; - uint32 session_key; - uint32 capabilities; - uint32 system_time_low; - uint32 system_time_high; - uint16 server_time_zone; - unsigned char encryption_key_length; -} SMB_NegProt_Resp; - -typedef struct { - unsigned char andx_command; - unsigned char andx_reserved; - uint16 andx_offset; - uint16 max_buffer_size; - uint16 max_mpx_count; - uint16 vc_number; - uint32 session_key; - uint16 case_insensitive_passwd_len; - uint16 case_sensitive_passwd_len; - uint32 reserved; - uint32 capabilities; -} SMB_SessionSetup; - -typedef struct { - unsigned char andx_command; - unsigned char andx_reserved; - uint16 andx_offset; - uint16 action; -} SMB_SessionSetup_Resp; - -enum { - NBT_SESSION_REQUEST = 0x81, - NBT_POSITIVE_SESSION_RESP = 0x82, - NBT_NEGATIVE_SESSION_RESP = 0x83, - NBT_ERR_NO_LISTEN_CALLED = 0x80, - NBT_ERR_NO_LISTEN_CALLING = 0x81, - NBT_ERR_CALLED_NOT_PRESENT = 0x82, - NBT_ERR_INSUFFICIENT_RESRC = 0x83, - NBT_ERR_UNSPECIFIED = 0x8F, - - SMB_HDR_SIZE = 32, - - SMB_COM_NEGOTIATE_PROTOCOL = 0x72, - SMB_COM_SESSION_SETUP_ANDX = 0x73, - SMB_COM_NONE = 0xFF, - - SMB_FLAGS_SERVER_TO_REDIR = 0x80, - - SMB_FLAGS2_ERR_STATUS = 0x4000, - SMB_FLAGS2_UNICODE = 0x8000, - - SMB_NEGPROT_RESP_SIZE = 34, - - SMB_SECURITY_MODE_USER = 0x1, - SMB_SECURITY_MODE_ENCRYPT = 0x2, - SMB_SECURITY_MODE_SIGN = 0x4, - SMB_SECURITY_MODE_SIGN_REQ = 0x8, - - SMB_CAP_UNICODE = 0x0004, - SMB_CAP_STATUS32 = 0x0040, - SMB_CAP_EXTENDED_SECURITY = 0x80000000, - - SMB_SESSION_SETUP_SIZE = 26, - SMB_SESSION_SETUP_RESP_SIZE = 6, - - SMB_REQUEST_MODE_GUEST = 0x1 -}; - -static const char *SMB_DIALECTS[] = { -#if 0 - "\x02PC NETWORK PROGRAM 1.0", - "\x02PCLAN1.0", - "\x02MICROSOFT NETWORKS 1.03", - "\x02MICROSOFT NETWORKS 3.0", - "\x02LANMAN1.0", - "\x02Windows for Workgroups 3.1a", - "\x02LM1.2X002", - "\x02DOS LM1.2X002", - "\x02DOS LANLAM2.1", - "\x02LANMAN2.1", -#endif - "\x02NT LM 0.12" -}; - -static void load_smb_header(unsigned char buf[], SMB_Header *hdr) -{ - unsigned char *p = buf; - - memcpy(p, SMB_HDR_PROTOCOL, 4); p += 4; - *p++ = hdr->command; - htoil(p, hdr->status); p += 4; - *p++ = hdr->flags; - htois(p, hdr->flags2); p += 2; - htois(p, hdr->PidHigh); p += 2; - memcpy(p, hdr->extra, 10); p += 10; - htois(p, hdr->tid); p += 2; - htois(p, hdr->pid); p += 2; - htois(p, hdr->uid); p += 2; - htois(p, hdr->mid); -} - -static void unload_smb_header(unsigned char buf[], SMB_Header *hdr) -{ - unsigned char *p = buf; - - memcpy(hdr->protocol, p, 4); p += 4; - hdr->command = *p++; - hdr->status = itohl(p); p += 4; - hdr->flags = *p++; - hdr->flags2 = itohs(p); p += 2; - hdr->PidHigh = itohs(p); p += 2; - memcpy(hdr->extra, p, 10); p += 10; - hdr->tid = itohs(p); p += 2; - hdr->pid = itohs(p); p += 2; - hdr->uid = itohs(p); p += 2; - hdr->mid = itohs(p); -} - -static void unload_negprot_resp(unsigned char buf[], SMB_NegProt_Resp *resp) -{ - unsigned char *p = buf; - - resp->dialect_index = itohs(p); p += 2; - resp->security_mode = *p++; - resp->max_mpx_count = itohs(p); p += 2; - resp->max_number_vcs = itohs(p); p += 2; - resp->max_buffer_size = itohl(p); p += 4; - resp->max_raw_size = itohl(p); p += 4; - resp->session_key = itohl(p); p += 4; - resp->capabilities = itohl(p); p += 4; - resp->system_time_low = itohl(p); p += 4; - resp->system_time_high = itohl(p); p += 4; - resp->server_time_zone = itohs(p); p += 2; - resp->encryption_key_length = *p; -} - -static void load_session_setup(unsigned char buf[], SMB_SessionSetup *setup) -{ - unsigned char *p = buf; - - *p++ = setup->andx_command; - *p++ = setup->andx_reserved; - htois(p, setup->andx_offset); p += 2; - htois(p, setup->max_buffer_size); p += 2; - htois(p, setup->max_mpx_count); p += 2; - htois(p, setup->vc_number); p += 2; - htoil(p, setup->session_key); p += 4; - htois(p, setup->case_insensitive_passwd_len); p += 2; - htois(p, setup->case_sensitive_passwd_len); p += 2; - htoil(p, setup->reserved); p += 4; - htoil(p, setup->capabilities); p += 4; -} - -static void unload_session_setup_resp(unsigned char buf[], - SMB_SessionSetup_Resp *resp) -{ - unsigned char *p = buf; - - resp->andx_command = *p++; - resp->andx_reserved = *p++; - resp->andx_offset = itohs(p); p += 2; - resp->action = itohs(p); -} - -/* - * Keep calling the writev() system call with 'fd', 'iov', and 'iovcnt' - * until all the data is written out or an error occurs. - */ -static int retry_writev(SOCKET fd, struct iovec *iov, int iovcnt) -{ - int n; - int i; - int written = 0; - static int iov_max = -#ifdef MAXIOV - MAXIOV -#else -#ifdef IOV_MAX - IOV_MAX -#else - 8192 -#endif -#endif - ; - - for (;;) { - while (iovcnt && iov[0].iov_len == 0) { - iov++; - iovcnt--; - } - - if (!iovcnt) return written; - - n = (int) writev(fd, iov, iovcnt > iov_max ? iov_max : iovcnt); - if (n == -1) { -#ifndef WIN32 - if (errno == EINVAL && iov_max > 10) { - iov_max /= 2; - continue; - } - if (errno == EINTR) continue; -#endif - return -1; - } - - written += n; - - for (i = 0; i < iovcnt; i++) { - if ((int) iov[i].iov_len > n) { - iov[i].iov_base = (char *) iov[i].iov_base + n; - iov[i].iov_len -= n; - break; - } - n -= iov[i].iov_len; - iov[i].iov_len = 0; - } - - if (i == iovcnt) return written; - } -} - -/* - * Keep calling the read() system call with 'fd', 'buf', and 'nbyte' - * until all the data is read in or an error occurs. - */ -static int retry_read(SOCKET fd, char *buf0, unsigned nbyte) -{ - int n; - int nread = 0; - char *buf = buf0; - - if (nbyte == 0) return 0; - - for (;;) { -/* Can't use read() on sockets on Windows, but recv works on all platforms */ - n = recv (fd, buf, nbyte, 0); - if (n == -1 || n == 0) { -#ifndef WIN32 - if (errno == EINTR || errno == EAGAIN) continue; -#endif - return -1; - } - - nread += n; - - if (n >= (int) nbyte) return nread; - - buf += n; - nbyte -= n; - } -} - -static void make_netbios_name(const char *in, unsigned char out[]) -{ - size_t i, j = 0, n; - - /* create a NetBIOS name from the DNS name - * - * - use up to the first 16 chars of the first part of the hostname - * - convert to all uppercase - * - use the tail end of the output buffer as temp space - */ - n = strcspn(in, "."); - if (n > 16) n = 16; - strncpy((char *) out+18, in, n); - in = (char *) out+18; - ucase(in, n); - - out[j++] = 0x20; - for (i = 0; i < n; i++) { - out[j++] = ((in[i] >> 4) & 0xf) + 0x41; - out[j++] = (in[i] & 0xf) + 0x41; - } - for (; i < 16; i++) { - out[j++] = ((0x20 >> 4) & 0xf) + 0x41; - out[j++] = (0x20 & 0xf) + 0x41; - } - out[j] = 0; -} - -static SOCKET smb_connect_server(const sasl_utils_t *utils, const char *client, - const char *server) -{ - struct addrinfo hints; - struct addrinfo *ai = NULL, *r; - SOCKET s = (SOCKET) -1; - int err; - char * error_str; -#ifdef WIN32 - DWORD saved_errno; -#else - int saved_errno; -#endif - int niflags; - char *port = "139"; - char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV]; - - unsigned char called[34]; - unsigned char calling[34]; - struct iovec iov[3]; - uint32 pkt; - int rc; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_CANONNAME; - if ((err = getaddrinfo(server, port, &hints, &ai)) != 0) { - utils->log(NULL, SASL_LOG_ERR, - "NTLM: getaddrinfo %s/%s: %s", - server, port, gai_strerror(err)); - return -1; - } - - /* Make sure we have AF_INET or AF_INET6 addresses. */ - if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) { - utils->log(NULL, SASL_LOG_ERR, "NTLM: no IP address info for %s", - ai->ai_canonname ? ai->ai_canonname : server); - freeaddrinfo(ai); - return -1; - } - - /* establish connection to authentication server */ - for (r = ai; r; r = r->ai_next) { - s = socket(r->ai_family, r->ai_socktype, r->ai_protocol); - if (s < 0) - continue; - if (connect(s, r->ai_addr, r->ai_addrlen) >= 0) - break; -#ifdef WIN32 - saved_errno = WSAGetLastError(); -#else - saved_errno = errno; -#endif - closesocket (s); - s = -1; - niflags = (NI_NUMERICHOST | NI_NUMERICSERV); -#ifdef NI_WITHSCOPEID - if (r->ai_family == AF_INET6) - niflags |= NI_WITHSCOPEID; -#endif - if (getnameinfo(r->ai_addr, r->ai_addrlen, hbuf, sizeof(hbuf), - pbuf, sizeof(pbuf), niflags) != 0) { - strcpy(hbuf, "unknown"); - strcpy(pbuf, "unknown"); - } - - /* Can't use errno (and %m), as it doesn't contain - * the socket error on Windows */ - error_str = _plug_get_error_message (utils, saved_errno); - utils->log(NULL, SASL_LOG_WARN, "NTLM: connect %s[%s]/%s: %s", - ai->ai_canonname ? ai->ai_canonname : server, - hbuf, - pbuf, - error_str); - utils->free (error_str); - } - if (s < 0) { - if (getnameinfo(ai->ai_addr, ai->ai_addrlen, NULL, 0, - pbuf, sizeof(pbuf), NI_NUMERICSERV) != 0) { - strcpy(pbuf, "unknown"); - } - utils->log(NULL, SASL_LOG_ERR, "NTLM: couldn't connect to %s/%s", - ai->ai_canonname ? ai->ai_canonname : server, pbuf); - freeaddrinfo(ai); - return -1; - } - - freeaddrinfo(ai); - - /*** send NetBIOS session request ***/ - - /* get length of data */ - pkt = sizeof(called) + sizeof(calling); - - /* make sure length is less than 17 bits */ - if (pkt >= (1 << 17)) { - closesocket(s); - return -1; - } - - /* prepend the packet type */ - pkt |= (NBT_SESSION_REQUEST << 24); - pkt = htonl(pkt); - - /* XXX should determine the real NetBIOS name */ - make_netbios_name(server, called); - make_netbios_name(client, calling); - - iov[0].iov_base = (void *) &pkt; - iov[0].iov_len = sizeof(pkt); - iov[1].iov_base = called; - iov[1].iov_len = sizeof(called); - iov[2].iov_base = calling; - iov[2].iov_len = sizeof(calling); - - rc = retry_writev(s, iov, N(iov)); - if (rc == -1) { - utils->log(NULL, SASL_LOG_ERR, - "NTLM: error sending NetBIOS session request"); - closesocket(s); - return -1; - } - - rc = retry_read(s, (char *) &pkt, sizeof(pkt)); - pkt = ntohl(pkt); - if (rc == -1 || pkt != (uint32) (NBT_POSITIVE_SESSION_RESP << 24)) { - unsigned char ec = NBT_ERR_UNSPECIFIED; - char *errstr; - - retry_read(s, (char *) &ec, sizeof(ec)); - switch (ec) { - case NBT_ERR_NO_LISTEN_CALLED: - errstr = "Not listening on called name"; - break; - case NBT_ERR_NO_LISTEN_CALLING: - errstr = "Not listening for calling name"; - break; - case NBT_ERR_CALLED_NOT_PRESENT: - errstr = "Called name not present"; - break; - case NBT_ERR_INSUFFICIENT_RESRC: - errstr = "Called name present, but insufficient resources"; - break; - default: - errstr = "Unspecified error"; - } - utils->log(NULL, SASL_LOG_ERR, - "NTLM: negative NetBIOS session response: %s", errstr); - closesocket(s); - return -1; - } - - return s; -} - -static int smb_negotiate_protocol(const sasl_utils_t *utils, - server_context_t *text, char **domain) -{ - SMB_Header hdr; - SMB_NegProt_Resp resp; - unsigned char hbuf[SMB_HDR_SIZE], *p; - unsigned char wordcount = 0; - unsigned char bc[sizeof(uint16)]; - uint16 bytecount; - uint32 len, nl; - int n_dialects = N(SMB_DIALECTS); - struct iovec iov[4+N(SMB_DIALECTS)]; - int i, n; - int rc; - pid_t current_pid; - - /*** create a negotiate protocol request ***/ - - /* create a header */ - memset(&hdr, 0, sizeof(hdr)); - hdr.command = SMB_COM_NEGOTIATE_PROTOCOL; -#if 0 - hdr.flags2 = SMB_FLAGS2_ERR_STATUS; - if (text->flags & NTLM_USE_UNICODE) hdr.flags2 |= SMB_FLAGS2_UNICODE; -#endif - current_pid = sasl_getpid(); - if (sizeof(current_pid) <= 2) { - hdr.pid = (uint16) current_pid; - hdr.PidHigh = 0; - } else { - hdr.pid = (uint16) (((uint32) current_pid) & 0xFFFF); - hdr.PidHigh = (uint16) (((uint32) current_pid) >> 16); - } - - load_smb_header(hbuf, &hdr); - - /* put together all of the pieces of the request */ - n = 0; - iov[n].iov_base = (void *) &nl; - iov[n++].iov_len = sizeof(len); - iov[n].iov_base = hbuf; - iov[n++].iov_len = SMB_HDR_SIZE; - iov[n].iov_base = &wordcount; - iov[n++].iov_len = sizeof(wordcount); - iov[n].iov_base = (void *) &bc; - iov[n++].iov_len = sizeof(bc); - - /* add our supported dialects */ - for (i = 0; i < n_dialects; i++) { - iov[n].iov_base = (char *) SMB_DIALECTS[i]; - iov[n++].iov_len = (long) strlen(SMB_DIALECTS[i]) + 1; - } - - /* total up the lengths */ - len = bytecount = 0; - for (i = 1; i < 4; i++) len += iov[i].iov_len; - for (i = 4; i < n; i++) bytecount += (uint16) iov[i].iov_len; - len += bytecount; - nl = htonl(len); - htois((char *) &bc, bytecount); - - /* send it */ - rc = retry_writev(text->sock, iov, n); - if (rc == -1) { - utils->log(NULL, SASL_LOG_ERR, - "NTLM: error sending NEGPROT request"); - return SASL_FAIL; - } - - /*** read the negotiate protocol response ***/ - - /* read the total length */ - rc = retry_read(text->sock, (char *) &nl, sizeof(nl)); - if (rc < (int) sizeof(nl)) { - utils->log(NULL, SASL_LOG_ERR, - "NTLM: error reading NEGPROT response length"); - return SASL_FAIL; - } - - /* read the data */ - len = ntohl(nl); - if (_plug_buf_alloc(utils, &text->out_buf, &text->out_buf_len, - len) != SASL_OK) { - SETERROR(utils, "cannot allocate NTLM NEGPROT response buffer"); - return SASL_NOMEM; - } - - rc = retry_read(text->sock, text->out_buf, len); - if (rc < (int) len) { - utils->log(NULL, SASL_LOG_ERR, - "NTLM: error reading NEGPROT response"); - return SASL_FAIL; - } - p = (unsigned char *) text->out_buf; - - /* parse the header */ - if (len < SMB_HDR_SIZE) { - utils->log(NULL, SASL_LOG_ERR, - "NTLM: not enough data for NEGPROT response header"); - return SASL_FAIL; - } - unload_smb_header(p, &hdr); - p += SMB_HDR_SIZE; - len -= SMB_HDR_SIZE; - - /* sanity check the header */ - if (memcmp(hdr.protocol, SMB_HDR_PROTOCOL, 4) /* correct protocol */ - || hdr.command != SMB_COM_NEGOTIATE_PROTOCOL /* correct command */ - || hdr.status /* no errors */ - || !(hdr.flags & SMB_FLAGS_SERVER_TO_REDIR)) { /* response */ - utils->log(NULL, SASL_LOG_ERR, - "NTLM: error in NEGPROT response header: %u", - hdr.status); - return SASL_FAIL; - } - - /* get the wordcount */ - if (len < 1) { - utils->log(NULL, SASL_LOG_ERR, - "NTLM: not enough data for NEGPROT response wordcount"); - return SASL_FAIL; - } - wordcount = *p++; - len--; - - /* parse the parameters */ - if (wordcount != SMB_NEGPROT_RESP_SIZE / sizeof(uint16)) { - utils->log(NULL, SASL_LOG_ERR, - "NTLM: incorrect NEGPROT wordcount for NT LM 0.12"); - return SASL_FAIL; - } - unload_negprot_resp(p, &resp); - p += SMB_NEGPROT_RESP_SIZE; - len -= SMB_NEGPROT_RESP_SIZE; - - /* sanity check the parameters */ - if (resp.dialect_index != 0 - || !(resp.security_mode & SMB_SECURITY_MODE_USER) - || !(resp.security_mode & SMB_SECURITY_MODE_ENCRYPT) - || resp.security_mode & SMB_SECURITY_MODE_SIGN_REQ - || resp.capabilities & SMB_CAP_EXTENDED_SECURITY - || resp.encryption_key_length != NTLM_NONCE_LENGTH) { - utils->log(NULL, SASL_LOG_ERR, - "NTLM: error in NEGPROT response parameters"); - return SASL_FAIL; - } - - /* get the bytecount */ - if (len < 2) { - utils->log(NULL, SASL_LOG_ERR, - "NTLM: not enough data for NEGPROT response bytecount"); - return SASL_FAIL; - } - bytecount = itohs(p); - p += 2; - len -= 2; - if (len != bytecount) { - utils->log(NULL, SASL_LOG_ERR, - "NTLM: incorrect bytecount for NEGPROT response data"); - return SASL_FAIL; - } - - /* parse the data */ - memcpy(text->nonce, p, resp.encryption_key_length); - p += resp.encryption_key_length; - len -= resp.encryption_key_length; - - /* if client asked for target, send domain */ - if (text->flags & NTLM_ASK_TARGET) { - *domain = utils->malloc(len); - if (*domain == NULL) { - MEMERROR(utils); - return SASL_NOMEM; - } - memcpy(*domain, p, len); - from_unicode(*domain, (unsigned char *) *domain, len); - - text->flags |= NTLM_TARGET_IS_DOMAIN; - } - - return SASL_OK; -} - -static int smb_session_setup(const sasl_utils_t *utils, server_context_t *text, - const char *authid, char *domain, - unsigned char *lm_resp, unsigned lm_resp_len, - unsigned char *nt_resp, unsigned nt_resp_len) -{ - SMB_Header hdr; - SMB_SessionSetup setup; - SMB_SessionSetup_Resp resp; - unsigned char hbuf[SMB_HDR_SIZE], sbuf[SMB_SESSION_SETUP_SIZE], *p; - unsigned char wordcount = SMB_SESSION_SETUP_SIZE / sizeof(uint16); - unsigned char bc[sizeof(uint16)]; - uint16 bytecount; - uint32 len, nl; - struct iovec iov[12]; - int i, n; - int rc; -#ifdef WIN32 - char osbuf[80]; -#else - char osbuf[2*SYS_NMLN+2]; -#endif - char lanman[20]; - pid_t current_pid; - - /*** create a session setup request ***/ - - /* create a header */ - memset(&hdr, 0, sizeof(hdr)); - hdr.command = SMB_COM_SESSION_SETUP_ANDX; -#if 0 - hdr.flags2 = SMB_FLAGS2_ERR_STATUS; - if (text->flags & NTLM_USE_UNICODE) hdr.flags2 |= SMB_FLAGS2_UNICODE; -#endif - current_pid = sasl_getpid(); - if (sizeof(current_pid) <= 2) { - hdr.pid = (uint16) current_pid; - hdr.PidHigh = 0; - } else { - hdr.pid = (uint16) (((uint32) current_pid) & 0xFFFF); - hdr.PidHigh = (uint16) (((uint32) current_pid) >> 16); - } - - load_smb_header(hbuf, &hdr); - - /* create a the setup parameters */ - memset(&setup, 0, sizeof(setup)); - setup.andx_command = SMB_COM_NONE; - setup.max_buffer_size = 0xFFFF; - if (lm_resp) setup.case_insensitive_passwd_len = lm_resp_len; - if (nt_resp) setup.case_sensitive_passwd_len = nt_resp_len; -#if 0 - if (text->flags & NTLM_USE_UNICODE) - setup.capabilities = SMB_CAP_UNICODE; -#endif - load_session_setup(sbuf, &setup); - - _plug_snprintf_os_info (osbuf, sizeof(osbuf)); - - snprintf(lanman, sizeof(lanman), "Cyrus SASL %u.%u.%u", - SASL_VERSION_MAJOR, SASL_VERSION_MINOR, - SASL_VERSION_STEP); - - /* put together all of the pieces of the request */ - n = 0; - iov[n].iov_base = (void *) &nl; - iov[n++].iov_len = sizeof(len); - iov[n].iov_base = hbuf; - iov[n++].iov_len = SMB_HDR_SIZE; - iov[n].iov_base = &wordcount; - iov[n++].iov_len = sizeof(wordcount); - iov[n].iov_base = sbuf; - iov[n++].iov_len = SMB_SESSION_SETUP_SIZE; - iov[n].iov_base = (void *) &bc; - iov[n++].iov_len = sizeof(bc); - if (lm_resp) { - iov[n].iov_base = lm_resp; - iov[n++].iov_len = NTLM_RESP_LENGTH; - } - if (nt_resp) { - iov[n].iov_base = nt_resp; - iov[n++].iov_len = NTLM_RESP_LENGTH; - } - iov[n].iov_base = (char*) authid; - iov[n++].iov_len = (long) strlen(authid) + 1; - if (!domain) domain = ""; - iov[n].iov_base = domain; - iov[n++].iov_len = (long) strlen(domain) + 1; - iov[n].iov_base = osbuf; - iov[n++].iov_len = (long) strlen(osbuf) + 1; - iov[n].iov_base = lanman; - iov[n++].iov_len = (long) strlen(lanman) + 1; - - /* total up the lengths */ - len = bytecount = 0; - for (i = 1; i < 5; i++) len += iov[i].iov_len; - for (i = 5; i < n; i++) bytecount += (uint16) iov[i].iov_len; - len += bytecount; - nl = htonl(len); - htois((char *) &bc, bytecount); - - /* send it */ - rc = retry_writev(text->sock, iov, n); - if (rc == -1) { - utils->log(NULL, SASL_LOG_ERR, - "NTLM: error sending SESSIONSETUP request"); - return SASL_FAIL; - } - - /*** read the session setup response ***/ - - /* read the total length */ - rc = retry_read(text->sock, (char *) &nl, sizeof(nl)); - if (rc < (int) sizeof(nl)) { - utils->log(NULL, SASL_LOG_ERR, - "NTLM: error reading SESSIONSETUP response length"); - return SASL_FAIL; - } - - /* read the data */ - len = ntohl(nl); - if (_plug_buf_alloc(utils, &text->out_buf, &text->out_buf_len, - len) != SASL_OK) { - SETERROR(utils, - "cannot allocate NTLM SESSIONSETUP response buffer"); - return SASL_NOMEM; - } - - rc = retry_read(text->sock, text->out_buf, len); - if (rc < (int) len) { - utils->log(NULL, SASL_LOG_ERR, - "NTLM: error reading SESSIONSETUP response"); - return SASL_FAIL; - } - p = (unsigned char *) text->out_buf; - - /* parse the header */ - if (len < SMB_HDR_SIZE) { - utils->log(NULL, SASL_LOG_ERR, - "NTLM: not enough data for SESSIONSETUP response header"); - return SASL_FAIL; - } - unload_smb_header(p, &hdr); - p += SMB_HDR_SIZE; - len -= SMB_HDR_SIZE; - - /* sanity check the header */ - if (memcmp(hdr.protocol, SMB_HDR_PROTOCOL, 4) /* correct protocol */ - || hdr.command != SMB_COM_SESSION_SETUP_ANDX /* correct command */ - || !(hdr.flags & SMB_FLAGS_SERVER_TO_REDIR)) { /* response */ - utils->log(NULL, SASL_LOG_ERR, - "NTLM: error in SESSIONSETUP response header"); - return SASL_FAIL; - } - - /* check auth success */ - if (hdr.status) { - utils->log(NULL, SASL_LOG_ERR, - "NTLM: auth failure: %u", hdr.status); - return SASL_BADAUTH; - } - - /* get the wordcount */ - if (len < 1) { - utils->log(NULL, SASL_LOG_ERR, - "NTLM: not enough data for SESSIONSETUP response wordcount"); - return SASL_FAIL; - } - wordcount = *p++; - len--; - - /* parse the parameters */ - if (wordcount < SMB_SESSION_SETUP_RESP_SIZE / sizeof(uint16)) { - utils->log(NULL, SASL_LOG_ERR, - "NTLM: incorrect SESSIONSETUP wordcount"); - return SASL_FAIL; - } - unload_session_setup_resp(p, &resp); - - /* check auth success */ - if (resp.action & SMB_REQUEST_MODE_GUEST) { - utils->log(NULL, SASL_LOG_ERR, - "NTLM: authenticated as guest"); - return SASL_BADAUTH; - } - - return SASL_OK; -} - -/* - * Create a server challenge message (type 2) consisting of: - * - * signature (8 bytes) - * message type (uint32) - * target name (buffer) - * flags (uint32) - * challenge (8 bytes) - * context (8 bytes) - * target info (buffer) - * data - */ -static int create_challenge(const sasl_utils_t *utils, - char **buf, unsigned *buflen, - const char *target, uint32 flags, - const u_char *nonce, unsigned *outlen) -{ - uint32 offset = NTLM_TYPE2_DATA_OFFSET; - u_char *base; - - if (!nonce) { - SETERROR(utils, "need nonce for NTLM challenge"); - return SASL_FAIL; - } - - *outlen = offset + 2 * (unsigned) xstrlen(target); - - if (_plug_buf_alloc(utils, buf, buflen, *outlen) != SASL_OK) { - SETERROR(utils, "cannot allocate NTLM challenge"); - return SASL_NOMEM; - } - - base = (unsigned char *) *buf; - memset(base, 0, *outlen); - memcpy(base + NTLM_SIG_OFFSET, NTLM_SIGNATURE, sizeof(NTLM_SIGNATURE)); - htoil(base + NTLM_TYPE_OFFSET, NTLM_TYPE_CHALLENGE); - load_buffer(base + NTLM_TYPE2_TARGET_OFFSET, - (const unsigned char *) ucase(target, 0), (uint16) xstrlen(target), flags & NTLM_USE_UNICODE, - base, &offset); - htoil(base + NTLM_TYPE2_FLAGS_OFFSET, flags); - memcpy(base + NTLM_TYPE2_CHALLENGE_OFFSET, nonce, NTLM_NONCE_LENGTH); - - return SASL_OK; -} - -static int ntlm_server_mech_new(void *glob_context __attribute__((unused)), - sasl_server_params_t *sparams, - const char *challenge __attribute__((unused)), - unsigned challen __attribute__((unused)), - void **conn_context) -{ - server_context_t *text; - const char *serv; - unsigned int len; - SOCKET sock = (SOCKET) -1; - - /* holds state are in: allocate early */ - text = sparams->utils->malloc(sizeof(server_context_t)); - if (text == NULL) { - MEMERROR( sparams->utils ); - return SASL_NOMEM; - } - - sparams->utils->getopt(sparams->utils->getopt_context, - "NTLM", "ntlm_server", &serv, &len); - if (serv) { - unsigned int i,j; - char *tmp, *next; - - /* strip any whitespace */ - if(_plug_strdup(sparams->utils, serv, &tmp, NULL) != SASL_OK) { - MEMERROR( sparams->utils ); - return SASL_NOMEM; - } - for(i=0, j=0; iutils, sparams->serverFQDN, serv); - } while(sock == (SOCKET) -1 && next); - - sparams->utils->free(tmp); - if (sock == (SOCKET) -1) return SASL_UNAVAIL; - } - - memset(text, 0, sizeof(server_context_t)); - - text->state = 1; - text->sock = sock; - - *conn_context = text; - - return SASL_OK; -} - -static int ntlm_server_mech_step1(server_context_t *text, - sasl_server_params_t *sparams, - const char *clientin, - unsigned clientinlen, - const char **serverout, - unsigned *serveroutlen, - sasl_out_params_t *oparams __attribute__((unused))) -{ - char *domain = NULL; - int result; - - if (!clientin || clientinlen < NTLM_TYPE1_MINSIZE || - memcmp(clientin, NTLM_SIGNATURE, sizeof(NTLM_SIGNATURE)) || - itohl(clientin + NTLM_TYPE_OFFSET) != NTLM_TYPE_REQUEST) { - SETERROR(sparams->utils, "client didn't issue valid NTLM request"); - return SASL_BADPROT; - } - - text->flags = itohl(clientin + NTLM_TYPE1_FLAGS_OFFSET); - sparams->utils->log(NULL, SASL_LOG_DEBUG, - "client flags: %x", text->flags); - - text->flags &= NTLM_FLAGS_MASK; /* mask off the bits we don't support */ - - /* if client can do Unicode, turn off ASCII */ - if (text->flags & NTLM_USE_UNICODE) text->flags &= ~NTLM_USE_ASCII; - - if (text->sock == -1) { - /* generate challenge internally */ - - /* if client asked for target, use FQDN as server target */ - if (text->flags & NTLM_ASK_TARGET) { - result = _plug_strdup(sparams->utils, sparams->serverFQDN, - &domain, NULL); - if (result != SASL_OK) return result; - - text->flags |= NTLM_TARGET_IS_SERVER; - } - - /* generate a nonce */ - sparams->utils->rand(sparams->utils->rpool, - (char *) text->nonce, NTLM_NONCE_LENGTH); - } - else { - /* proxy the response/challenge */ - result = smb_negotiate_protocol(sparams->utils, text, &domain); - if (result != SASL_OK) goto cleanup; - } - - result = create_challenge(sparams->utils, - &text->out_buf, &text->out_buf_len, - domain, text->flags, text->nonce, serveroutlen); - if (result != SASL_OK) goto cleanup; - - *serverout = text->out_buf; - - text->state = 2; - - result = SASL_CONTINUE; - - cleanup: - if (domain) sparams->utils->free(domain); - - return result; -} - -static int ntlm_server_mech_step2(server_context_t *text, - sasl_server_params_t *sparams, - const char *clientin, - unsigned clientinlen, - const char **serverout __attribute__((unused)), - unsigned *serveroutlen __attribute__((unused)), - sasl_out_params_t *oparams) -{ - unsigned char *lm_resp = NULL, *nt_resp = NULL; - char *domain = NULL, *authid = NULL; - unsigned lm_resp_len, nt_resp_len, domain_len, authid_len; - int result; - - if (!clientin || clientinlen < NTLM_TYPE3_MINSIZE || - memcmp(clientin, NTLM_SIGNATURE, sizeof(NTLM_SIGNATURE)) || - itohl(clientin + NTLM_TYPE_OFFSET) != NTLM_TYPE_RESPONSE) { - SETERROR(sparams->utils, "client didn't issue valid NTLM response"); - return SASL_BADPROT; - } - - result = unload_buffer(sparams->utils, - (const unsigned char *) clientin + NTLM_TYPE3_LMRESP_OFFSET, - (u_char **) &lm_resp, &lm_resp_len, 0, - (const unsigned char *) clientin, clientinlen); - if (result != SASL_OK) goto cleanup; - - result = unload_buffer(sparams->utils, - (const unsigned char *) clientin + NTLM_TYPE3_NTRESP_OFFSET, - (u_char **) &nt_resp, &nt_resp_len, 0, - (const unsigned char *) clientin, clientinlen); - if (result != SASL_OK) goto cleanup; - - result = unload_buffer(sparams->utils, - (const unsigned char *) clientin + NTLM_TYPE3_DOMAIN_OFFSET, - (u_char **) &domain, &domain_len, - text->flags & NTLM_USE_UNICODE, - (const unsigned char *) clientin, clientinlen); - if (result != SASL_OK) goto cleanup; - - result = unload_buffer(sparams->utils, - (const unsigned char *) clientin + NTLM_TYPE3_USER_OFFSET, - (u_char **) &authid, &authid_len, - text->flags & NTLM_USE_UNICODE, - (const unsigned char *) clientin, clientinlen); - if (result != SASL_OK) goto cleanup; - - /* require at least one response and an authid */ - if ((!lm_resp && !nt_resp) || - (lm_resp && lm_resp_len < NTLM_RESP_LENGTH) || - (nt_resp && nt_resp_len < NTLM_RESP_LENGTH) || - !authid) { - SETERROR(sparams->utils, "client issued incorrect/nonexistent responses"); - result = SASL_BADPROT; - goto cleanup; - } - - sparams->utils->log(NULL, SASL_LOG_DEBUG, - "client user: %s", authid); - if (domain) sparams->utils->log(NULL, SASL_LOG_DEBUG, - "client domain: %s", domain); - - if (text->sock == -1) { - /* verify the response internally */ - - sasl_secret_t *password = NULL; - size_t pass_len; - const char *password_request[] = { SASL_AUX_PASSWORD, - NULL }; - struct propval auxprop_values[2]; - unsigned char hash[NTLM_HASH_LENGTH]; - unsigned char resp[NTLM_RESP_LENGTH]; - - /* fetch user's password */ - result = sparams->utils->prop_request(sparams->propctx, password_request); - if (result != SASL_OK) goto cleanup; - - /* this will trigger the getting of the aux properties */ - result = sparams->canon_user(sparams->utils->conn, authid, authid_len, - SASL_CU_AUTHID | SASL_CU_AUTHZID, oparams); - if (result != SASL_OK) goto cleanup; - - result = sparams->utils->prop_getnames(sparams->propctx, - password_request, - auxprop_values); - if (result < 0 || - (!auxprop_values[0].name || !auxprop_values[0].values)) { - /* We didn't find this username */ - SETERROR(sparams->utils, "no secret in database"); - result = sparams->transition ? SASL_TRANS : SASL_NOUSER; - goto cleanup; - } - - pass_len = strlen(auxprop_values[0].values[0]); - if (pass_len == 0) { - SETERROR(sparams->utils, "empty secret"); - result = SASL_FAIL; - goto cleanup; - } - - password = sparams->utils->malloc(sizeof(sasl_secret_t) + pass_len); - if (!password) { - result = SASL_NOMEM; - goto cleanup; - } - - password->len = (unsigned) pass_len; - strncpy((char *) password->data, auxprop_values[0].values[0], pass_len + 1); - - /* erase the plaintext password */ - sparams->utils->prop_erase(sparams->propctx, password_request[0]); - - /* calculate our own response(s) and compare with client's */ - result = SASL_OK; - if (nt_resp && (nt_resp_len > NTLM_RESP_LENGTH)) { - /* Try NTv2 response */ - sparams->utils->log(NULL, SASL_LOG_DEBUG, - "calculating NTv2 response"); - V2(resp, password, authid, domain, text->nonce, - nt_resp + MD5_DIGEST_LENGTH, nt_resp_len - MD5_DIGEST_LENGTH, - sparams->utils, &text->out_buf, &text->out_buf_len, - &result); - - /* No need to compare the blob */ - if (memcmp(nt_resp, resp, MD5_DIGEST_LENGTH)) { - SETERROR(sparams->utils, "incorrect NTLMv2 response"); - result = SASL_BADAUTH; - } - } - else if (nt_resp) { - /* Try NT response */ - sparams->utils->log(NULL, SASL_LOG_DEBUG, - "calculating NT response"); - P24(resp, P21(hash, password, P16_nt, sparams->utils, - &text->out_buf, &text->out_buf_len, &result), - text->nonce); - if (memcmp(nt_resp, resp, NTLM_RESP_LENGTH)) { - SETERROR(sparams->utils, "incorrect NTLM response"); - result = SASL_BADAUTH; - } - } - else if (lm_resp) { - /* Try LMv2 response */ - sparams->utils->log(NULL, SASL_LOG_DEBUG, - "calculating LMv2 response"); - V2(resp, password, authid, domain, text->nonce, - lm_resp + MD5_DIGEST_LENGTH, lm_resp_len - MD5_DIGEST_LENGTH, - sparams->utils, &text->out_buf, &text->out_buf_len, - &result); - - /* No need to compare the blob */ - if (memcmp(lm_resp, resp, MD5_DIGEST_LENGTH)) { - /* Try LM response */ - sparams->utils->log(NULL, SASL_LOG_DEBUG, - "calculating LM response"); - P24(resp, P21(hash, password, P16_lm, sparams->utils, - &text->out_buf, &text->out_buf_len, &result), - text->nonce); - if (memcmp(lm_resp, resp, NTLM_RESP_LENGTH)) { - SETERROR(sparams->utils, "incorrect LMv1/v2 response"); - result = SASL_BADAUTH; - } - } - } - - _plug_free_secret(sparams->utils, &password); - - if (result != SASL_OK) goto cleanup; - } - else { - /* proxy the response */ - result = smb_session_setup(sparams->utils, text, authid, domain, - lm_resp, lm_resp_len, nt_resp, nt_resp_len); - if (result != SASL_OK) goto cleanup; - - result = sparams->canon_user(sparams->utils->conn, authid, authid_len, - SASL_CU_AUTHID | SASL_CU_AUTHZID, oparams); - if (result != SASL_OK) goto cleanup; - } - - /* set oparams */ - oparams->doneflag = 1; - oparams->mech_ssf = 0; - oparams->maxoutbuf = 0; - oparams->encode_context = NULL; - oparams->encode = NULL; - oparams->decode_context = NULL; - oparams->decode = NULL; - oparams->param_version = 0; - - result = SASL_OK; - - cleanup: - if (lm_resp) sparams->utils->free(lm_resp); - if (nt_resp) sparams->utils->free(nt_resp); - if (domain) sparams->utils->free(domain); - if (authid) sparams->utils->free(authid); - - return result; -} - -static int ntlm_server_mech_step(void *conn_context, - sasl_server_params_t *sparams, - const char *clientin, - unsigned clientinlen, - const char **serverout, - unsigned *serveroutlen, - sasl_out_params_t *oparams) -{ - server_context_t *text = (server_context_t *) conn_context; - - *serverout = NULL; - *serveroutlen = 0; - - if (text == NULL) { - return SASL_BADPROT; - } - - sparams->utils->log(NULL, SASL_LOG_DEBUG, - "NTLM server step %d\n", text->state); - - switch (text->state) { - - case 1: - return ntlm_server_mech_step1(text, sparams, clientin, clientinlen, - serverout, serveroutlen, oparams); - - case 2: - return ntlm_server_mech_step2(text, sparams, clientin, clientinlen, - serverout, serveroutlen, oparams); - - default: - sparams->utils->log(NULL, SASL_LOG_ERR, - "Invalid NTLM server step %d\n", text->state); - return SASL_FAIL; - } - - return SASL_FAIL; /* should never get here */ -} - -static void ntlm_server_mech_dispose(void *conn_context, - const sasl_utils_t *utils) -{ - server_context_t *text = (server_context_t *) conn_context; - - if (!text) return; - - if (text->out_buf) utils->free(text->out_buf); - if (text->sock != -1) closesocket(text->sock); - - utils->free(text); -} - -static sasl_server_plug_t ntlm_server_plugins[] = -{ - { - "NTLM", /* mech_name */ - 0, /* max_ssf */ - SASL_SEC_NOPLAINTEXT - | SASL_SEC_NOANONYMOUS, /* security_flags */ - SASL_FEAT_WANT_CLIENT_FIRST - | SASL_FEAT_SUPPORTS_HTTP, /* features */ - NULL, /* glob_context */ - &ntlm_server_mech_new, /* mech_new */ - &ntlm_server_mech_step, /* mech_step */ - &ntlm_server_mech_dispose, /* mech_dispose */ - NULL, /* mech_free */ - NULL, /* setpass */ - NULL, /* user_query */ - NULL, /* idle */ - NULL, /* mech_avail */ - NULL /* spare */ - } -}; - -int ntlm_server_plug_init(sasl_utils_t *utils, - int maxversion, - int *out_version, - sasl_server_plug_t **pluglist, - int *plugcount) -{ - if (maxversion < SASL_SERVER_PLUG_VERSION) { - SETERROR(utils, "NTLM version mismatch"); - return SASL_BADVERS; - } - - *out_version = SASL_SERVER_PLUG_VERSION; - *pluglist = ntlm_server_plugins; - *plugcount = 1; - - return SASL_OK; -} - -/***************************** Client Section *****************************/ - -typedef struct client_context { - int state; - - /* per-step mem management */ - char *out_buf; - unsigned out_buf_len; - -} client_context_t; - -/* - * Create a client request (type 1) consisting of: - * - * signature (8 bytes) - * message type (uint32) - * flags (uint32) - * domain (buffer) - * workstation (buffer) - * data - */ -static int create_request(const sasl_utils_t *utils, - char **buf, unsigned *buflen, - const char *domain, const char *wkstn, - unsigned *outlen) -{ - uint32 flags = ( NTLM_USE_UNICODE | NTLM_USE_ASCII | - NTLM_ASK_TARGET | NTLM_AUTH_NTLM ); - uint32 offset = NTLM_TYPE1_DATA_OFFSET; - u_char *base; - - *outlen = (unsigned) (offset + xstrlen(domain) + xstrlen(wkstn)); - if (_plug_buf_alloc(utils, buf, buflen, *outlen) != SASL_OK) { - SETERROR(utils, "cannot allocate NTLM request"); - return SASL_NOMEM; - } - - base = (unsigned char *) *buf; - memset(base, 0, *outlen); - memcpy(base + NTLM_SIG_OFFSET, NTLM_SIGNATURE, sizeof(NTLM_SIGNATURE)); - htoil(base + NTLM_TYPE_OFFSET, NTLM_TYPE_REQUEST); - htoil(base + NTLM_TYPE1_FLAGS_OFFSET, flags); - load_buffer(base + NTLM_TYPE1_DOMAIN_OFFSET, - (const unsigned char *) domain, (uint16) xstrlen(domain), 0, base, &offset); - load_buffer(base + NTLM_TYPE1_WORKSTN_OFFSET, - (const unsigned char *) wkstn, (uint16) xstrlen(wkstn), 0, base, &offset); - - return SASL_OK; -} - -/* - * Create a client response (type 3) consisting of: - * - * signature (8 bytes) - * message type (uint32) - * LM/LMv2 response (buffer) - * NTLM/NTLMv2 response (buffer) - * domain (buffer) - * user name (buffer) - * workstation (buffer) - * session key (buffer) - * flags (uint32) - * data - */ -static int create_response(const sasl_utils_t *utils, - char **buf, unsigned *buflen, - const u_char *lm_resp, const u_char *nt_resp, - const char *domain, const char *user, - const char *wkstn, const u_char *key, - uint32 flags, unsigned *outlen) -{ - uint32 offset = NTLM_TYPE3_DATA_OFFSET; - u_char *base; - - if (!lm_resp && !nt_resp) { - SETERROR(utils, "need at least one NT/LM response"); - return SASL_FAIL; - } - - *outlen = (unsigned) (offset + (flags & NTLM_USE_UNICODE ? 2 : 1) * - (xstrlen(domain) + xstrlen(user) + xstrlen(wkstn))); - if (lm_resp) *outlen += NTLM_RESP_LENGTH; - if (nt_resp) *outlen += NTLM_RESP_LENGTH; - if (key) *outlen += NTLM_SESSKEY_LENGTH; - - if (_plug_buf_alloc(utils, buf, buflen, *outlen) != SASL_OK) { - SETERROR(utils, "cannot allocate NTLM response"); - return SASL_NOMEM; - } - - base = (unsigned char *) *buf; - memset(base, 0, *outlen); - memcpy(base + NTLM_SIG_OFFSET, NTLM_SIGNATURE, sizeof(NTLM_SIGNATURE)); - htoil(base + NTLM_TYPE_OFFSET, NTLM_TYPE_RESPONSE); - load_buffer(base + NTLM_TYPE3_LMRESP_OFFSET, - lm_resp, lm_resp ? NTLM_RESP_LENGTH : 0, 0, base, &offset); - load_buffer(base + NTLM_TYPE3_NTRESP_OFFSET, - nt_resp, nt_resp ? NTLM_RESP_LENGTH : 0, 0, base, &offset); - load_buffer(base + NTLM_TYPE3_DOMAIN_OFFSET, - (const unsigned char *) ucase(domain, 0), (uint16) xstrlen(domain), - flags & NTLM_USE_UNICODE, - base, &offset); - load_buffer(base + NTLM_TYPE3_USER_OFFSET, - (const unsigned char *) user, (uint16) xstrlen(user), - flags & NTLM_USE_UNICODE, base, &offset); - load_buffer(base + NTLM_TYPE3_WORKSTN_OFFSET, - (const unsigned char *) ucase(wkstn, 0), (uint16) xstrlen(wkstn), - flags & NTLM_USE_UNICODE, - base, &offset); - load_buffer(base + NTLM_TYPE3_SESSIONKEY_OFFSET, - key, key ? NTLM_SESSKEY_LENGTH : 0, 0, base, &offset); - htoil(base + NTLM_TYPE3_FLAGS_OFFSET, flags); - - return SASL_OK; -} - -static int ntlm_client_mech_new(void *glob_context __attribute__((unused)), - sasl_client_params_t *params, - void **conn_context) -{ - client_context_t *text; - - /* holds state are in */ - text = params->utils->malloc(sizeof(client_context_t)); - if (text == NULL) { - MEMERROR( params->utils ); - return SASL_NOMEM; - } - - memset(text, 0, sizeof(client_context_t)); - - text->state = 1; - - *conn_context = text; - - return SASL_OK; -} - -static int ntlm_client_mech_step1(client_context_t *text, - sasl_client_params_t *params, - const char *serverin __attribute__((unused)), - unsigned serverinlen __attribute__((unused)), - sasl_interact_t **prompt_need __attribute__((unused)), - const char **clientout, - unsigned *clientoutlen, - sasl_out_params_t *oparams __attribute__((unused))) -{ - int result; - - /* check if sec layer strong enough */ - if (params->props.min_ssf > params->external_ssf) { - SETERROR(params->utils, "SSF requested of NTLM plugin"); - return SASL_TOOWEAK; - } - - /* we don't care about domain or wkstn */ - result = create_request(params->utils, &text->out_buf, &text->out_buf_len, - NULL, NULL, clientoutlen); - if (result != SASL_OK) return result; - - *clientout = text->out_buf; - - text->state = 2; - - return SASL_CONTINUE; -} - -static int ntlm_client_mech_step2(client_context_t *text, - sasl_client_params_t *params, - const char *serverin, - unsigned serverinlen, - sasl_interact_t **prompt_need, - const char **clientout, - unsigned *clientoutlen, - sasl_out_params_t *oparams) -{ - const char *authid = NULL; - sasl_secret_t *password = NULL; - unsigned int free_password; /* set if we need to free password */ - char *domain = NULL; - int auth_result = SASL_OK; - int pass_result = SASL_OK; - uint32 flags = 0; - unsigned char hash[NTLM_HASH_LENGTH]; - unsigned char resp[NTLM_RESP_LENGTH], *lm_resp = NULL, *nt_resp = NULL; - int result; - const char *sendv2; - - if (!serverin || serverinlen < NTLM_TYPE2_MINSIZE || - memcmp(serverin, NTLM_SIGNATURE, sizeof(NTLM_SIGNATURE)) || - itohl(serverin + NTLM_TYPE_OFFSET) != NTLM_TYPE_CHALLENGE) { - SETERROR(params->utils, "server didn't issue valid NTLM challenge"); - return SASL_BADPROT; - } - - /* try to get the authid */ - if (oparams->authid == NULL) { - auth_result = _plug_get_authid(params->utils, &authid, prompt_need); - - if ((auth_result != SASL_OK) && (auth_result != SASL_INTERACT)) - return auth_result; - } - - /* try to get the password */ - if (password == NULL) { - pass_result = _plug_get_password(params->utils, &password, - &free_password, prompt_need); - - if ((pass_result != SASL_OK) && (pass_result != SASL_INTERACT)) - return pass_result; - } - - /* free prompts we got */ - if (prompt_need && *prompt_need) { - params->utils->free(*prompt_need); - *prompt_need = NULL; - } - - /* if there are prompts not filled in */ - if ((auth_result == SASL_INTERACT) || (pass_result == SASL_INTERACT)) { - /* make the prompt list */ - result = - _plug_make_prompts(params->utils, prompt_need, - NULL, NULL, - auth_result == SASL_INTERACT ? - "Please enter your authentication name" : NULL, - NULL, - pass_result == SASL_INTERACT ? - "Please enter your password" : NULL, NULL, - NULL, NULL, NULL, - NULL, NULL, NULL); - if (result != SASL_OK) goto cleanup; - - return SASL_INTERACT; - } - - result = params->canon_user(params->utils->conn, authid, 0, - SASL_CU_AUTHID | SASL_CU_AUTHZID, oparams); - if (result != SASL_OK) goto cleanup; - - flags = itohl(serverin + NTLM_TYPE2_FLAGS_OFFSET); - params->utils->log(NULL, SASL_LOG_DEBUG, - "server flags: %x", flags); - - flags &= NTLM_FLAGS_MASK; /* mask off the bits we don't support */ - - result = unload_buffer(params->utils, - (const unsigned char *) serverin + NTLM_TYPE2_TARGET_OFFSET, - (u_char **) &domain, NULL, - flags & NTLM_USE_UNICODE, - (u_char *) serverin, serverinlen); - if (result != SASL_OK) goto cleanup; - params->utils->log(NULL, SASL_LOG_DEBUG, - "server domain: %s", domain); - - /* should we send a NTLMv2 response? */ - params->utils->getopt(params->utils->getopt_context, - "NTLM", "ntlm_v2", &sendv2, NULL); - if (sendv2 && - (sendv2[0] == '1' || sendv2[0] == 'y' || - (sendv2[0] == 'o' && sendv2[1] == 'n') || sendv2[0] == 't')) { - - /* put the cnonce in place after the LMv2 HMAC */ - char *cnonce = (char *) resp + MD5_DIGEST_LENGTH; - - params->utils->log(NULL, SASL_LOG_DEBUG, - "calculating LMv2 response"); - - params->utils->rand(params->utils->rpool, cnonce, NTLM_NONCE_LENGTH); - - V2(resp, password, oparams->authid, domain, - (const unsigned char *) serverin + NTLM_TYPE2_CHALLENGE_OFFSET, - (const unsigned char *) cnonce, NTLM_NONCE_LENGTH, - params->utils, &text->out_buf, &text->out_buf_len, &result); - - lm_resp = resp; - } - else if (flags & NTLM_AUTH_NTLM) { - params->utils->log(NULL, SASL_LOG_DEBUG, - "calculating NT response"); - P24(resp, P21(hash, password, P16_nt, params->utils, - &text->out_buf, &text->out_buf_len, &result), - (unsigned char *) serverin + NTLM_TYPE2_CHALLENGE_OFFSET); - nt_resp = resp; - } - else { - params->utils->log(NULL, SASL_LOG_DEBUG, - "calculating LM response"); - P24(resp, P21(hash, password, P16_lm, params->utils, - &text->out_buf, &text->out_buf_len, &result), - (unsigned char *) serverin + NTLM_TYPE2_CHALLENGE_OFFSET); - lm_resp = resp; - } - if (result != SASL_OK) goto cleanup; - - /* we don't care about workstn or session key */ - result = create_response(params->utils, &text->out_buf, &text->out_buf_len, - lm_resp, nt_resp, domain, oparams->authid, - NULL, NULL, flags, clientoutlen); - if (result != SASL_OK) goto cleanup; - - *clientout = text->out_buf; - - /* set oparams */ - oparams->doneflag = 1; - oparams->mech_ssf = 0; - oparams->maxoutbuf = 0; - oparams->encode_context = NULL; - oparams->encode = NULL; - oparams->decode_context = NULL; - oparams->decode = NULL; - oparams->param_version = 0; - - result = SASL_OK; - - cleanup: - if (domain) params->utils->free(domain); - if (free_password) _plug_free_secret(params->utils, &password); - - return result; -} - -static int ntlm_client_mech_step(void *conn_context, - sasl_client_params_t *params, - const char *serverin, - unsigned serverinlen, - sasl_interact_t **prompt_need, - const char **clientout, - unsigned *clientoutlen, - sasl_out_params_t *oparams) -{ - client_context_t *text = (client_context_t *) conn_context; - - *clientout = NULL; - *clientoutlen = 0; - - params->utils->log(NULL, SASL_LOG_DEBUG, - "NTLM client step %d\n", text->state); - - switch (text->state) { - - case 1: - return ntlm_client_mech_step1(text, params, serverin, serverinlen, - prompt_need, clientout, clientoutlen, - oparams); - - case 2: - return ntlm_client_mech_step2(text, params, serverin, serverinlen, - prompt_need, clientout, clientoutlen, - oparams); - - default: - params->utils->log(NULL, SASL_LOG_ERR, - "Invalid NTLM client step %d\n", text->state); - return SASL_FAIL; - } - - return SASL_FAIL; /* should never get here */ -} - -static void ntlm_client_mech_dispose(void *conn_context, - const sasl_utils_t *utils) -{ - client_context_t *text = (client_context_t *) conn_context; - - if (!text) return; - - if (text->out_buf) utils->free(text->out_buf); - - utils->free(text); -} - -static sasl_client_plug_t ntlm_client_plugins[] = -{ - { - "NTLM", /* mech_name */ - 0, /* max_ssf */ - SASL_SEC_NOPLAINTEXT - | SASL_SEC_NOANONYMOUS, /* security_flags */ - SASL_FEAT_WANT_CLIENT_FIRST - | SASL_FEAT_SUPPORTS_HTTP, /* features */ - NULL, /* required_prompts */ - NULL, /* glob_context */ - &ntlm_client_mech_new, /* mech_new */ - &ntlm_client_mech_step, /* mech_step */ - &ntlm_client_mech_dispose, /* mech_dispose */ - NULL, /* mech_free */ - NULL, /* idle */ - NULL, /* spare */ - NULL /* spare */ - } -}; - -int ntlm_client_plug_init(sasl_utils_t *utils, - int maxversion, - int *out_version, - sasl_client_plug_t **pluglist, - int *plugcount) -{ - if (maxversion < SASL_CLIENT_PLUG_VERSION) { - SETERROR(utils, "NTLM version mismatch"); - return SASL_BADVERS; - } - - *out_version = SASL_CLIENT_PLUG_VERSION; - *pluglist = ntlm_client_plugins; - *plugcount = 1; - - return SASL_OK; -} diff --git a/saslauthd/Makefile.am b/saslauthd/Makefile.am index b78b8c2c..4db605f4 100644 --- a/saslauthd/Makefile.am +++ b/saslauthd/Makefile.am @@ -13,13 +13,13 @@ endif saslauthd_SOURCES = mechanisms.c globals.h \ mechanisms.h auth_dce.c auth_dce.h auth_getpwent.c \ - auth_getpwent.h auth_krb5.c auth_krb5.h auth_krb4.c \ - auth_krb4.h auth_pam.c auth_pam.h auth_rimap.c auth_httpform.c \ + auth_getpwent.h auth_krb5.c auth_krb5.h \ + auth_pam.c auth_pam.h auth_rimap.c auth_httpform.c \ auth_rimap.h auth_shadow.c auth_shadow.h auth_sia.c auth_httpform.h \ auth_sia.h auth_sasldb.c auth_sasldb.h lak.c lak.h \ auth_ldap.c auth_ldap.h cache.c cache.h cfile.c cfile.h \ - krbtf.c krbtf.h utils.c utils.h \ - ipc_unix.c ipc_doors.c saslauthd-main.c saslauthd-main.h + utils.c utils.h \ + ipc_unix.c ipc_doors.c saslauthd-main.c saslauthd-main.h saslauthd_DEPENDENCIES = saslauthd-main.o $(LTLIBOBJS_FULL) saslauthd_LDADD = @SASL_KRB_LIB@ \ @GSSAPIBASE_LIBS@ @LIB_CRYPT@ @LIB_SIA@ \ diff --git a/saslauthd/auth_krb4.c b/saslauthd/auth_krb4.c deleted file mode 100644 index 51b43b6a..00000000 --- a/saslauthd/auth_krb4.c +++ /dev/null @@ -1,293 +0,0 @@ -/* MODULE: auth_krb4 */ - -/* COPYRIGHT - * Copyright (c) 1997 Messaging Direct Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY MESSAGING DIRECT LTD. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MESSAGING DIRECT LTD. OR - * ITS EMPLOYEES OR AGENTS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * END COPYRIGHT */ - -/* PUBLIC DEPENDENCIES */ -#include -#include "mechanisms.h" -#include "globals.h" -#include "cfile.h" -#include "krbtf.h" - -#ifdef AUTH_KRB4 - -# include - -# ifdef WITH_DES -# ifdef WITH_SSL_DES -# include -# else -# include -# endif /* WITH_SSL_DES */ -# endif /* WITH_DES */ - -#endif /* AUTH_KRB4 */ - -#include -#include -#include -#include -#include -#include -#include "auth_krb4.h" - -#ifdef DEADCODE -extern int swap_bytes; /* from libkrb.a */ -#endif /* DEADCODE */ -/* END PUBLIC DEPENDENCIES */ - -/* PRIVATE DEPENDENCIES */ -#ifdef AUTH_KRB4 -static char default_realm[REALM_SZ]; -static cfile config = 0; -static char myhostname[BUFSIZ]; /* Is BUFSIZ right here? */ -static char *srvtabname = ""; /* "" means "system default srvtab" */ -static char *verify_principal = "rcmd"; /* A principal in the default srvtab */ -#endif /* AUTH_KRB4 */ -/* END PRIVATE DEPENDENCIES */ - -#define TF_NAME_LEN 128 - -/* Kerberos for Macintosh doesn't define this, so we will. (Thanks Fink!) */ -#ifndef KRB_TICKET_GRANTING_TICKET -#define KRB_TICKET_GRANTING_TICKET "krbtgt" -#endif /* !defined(KRB_TICKET_GRANTING_TICKET) */ - - -/* FUNCTION: auth_krb4_init */ - -/* SYNOPSIS - * Initialize the Kerberos IV authentication environment. - * - * krb4 proxy authentication has a side effect of creating a ticket - * file for the user we are authenticating. We keep these in a private - * directory so as not to override a system ticket file that may be - * in use. - * - * This function tries to create the directory, and initializes the - * global variable tf_dir with the pathname of the directory. - * END SYNOPSIS */ - -int /* R: -1 on failure, else 0 */ -auth_krb4_init ( - /* PARAMETERS */ - void /* no parameters */ - /* END PARAMETERS */ - ) -{ -#ifdef AUTH_KRB4 - /* VARIABLES */ - int rc; /* return code holder */ - char *configname = 0; - /* END VARIABLES */ - - if (mech_option) - configname = mech_option; - else if (access(SASLAUTHD_CONF_FILE_DEFAULT, F_OK) == 0) - configname = SASLAUTHD_CONF_FILE_DEFAULT; - - if (configname) { - char complaint[1024]; - - config = cfile_read(configname, complaint, sizeof(complaint)); - if (!config) { - syslog(LOG_ERR, "auth_krb4_init %s", complaint); - return -1; - } - } - - if (config) { - srvtabname = cfile_getstring(config, "krb4_srvtab", srvtabname); - verify_principal = cfile_getstring(config, "krb4_verify_principal", - verify_principal); - } - - if (krbtf_init() == -1) { - syslog(LOG_ERR, "auth_krb4_init krbtf_init failed"); - return -1; - } - - rc = krb_get_lrealm(default_realm, 1); - if (rc) { - syslog(LOG_ERR, "auth_krb4: krb_get_lrealm: %s", - krb_get_err_text(rc)); - return -1; - } - - if (gethostname(myhostname, sizeof(myhostname)) < 0) { - syslog(LOG_ERR, "auth_krb4: gethoanem(): %m"); - return -1; - } - myhostname[sizeof(myhostname) - 1] = '\0'; - - return 0; -#else /* ! AUTH_KRB4 */ - return -1; -#endif /* ! AUTH_KRB4 */ -} - -/* END FUNCTION: auth_krb4_init */ - -/* FUNCTION: auth_krb4 */ - -/* SYNOPSIS - * Authenticate against Kerberos IV. - * END SYNOPSIS */ - -#ifdef AUTH_KRB4 - -char * /* R: allocated response string */ -auth_krb4 ( - /* PARAMETERS */ - const char *login, /* I: plaintext authenticator */ - const char *password, /* I: plaintext password */ - const char *service, - const char *realm_in, - const char *remote /* I: remote host address */ - /* END PARAMETERS */ - ) -{ - /* VARIABLES */ - char aname[ANAME_SZ]; /* Kerberos principal */ - const char *realm; /* Kerberos realm to authenticate in */ - int rc; /* return code */ - char tf_name[TF_NAME_LEN]; /* Ticket file name */ - char *instance, *user_specified; - KTEXT_ST ticket; - AUTH_DAT kdata; - /* END VARIABLES */ - - /* - * Make sure we have a password. If this is NULL the call - * to krb_get_pw_in_tkt below would try to prompt for - * one interactively. - */ - if (password == NULL) { - syslog(LOG_ERR, "auth_krb4: NULL password?"); - return strdup("NO saslauthd internal error"); - } - - if (krbtf_name(tf_name, sizeof(tf_name)) != 0) { - syslog(LOG_ERR, "auth_krb4: could not generate ticket file name"); - return strdup("NO saslauthd internal error"); - } - krb_set_tkt_string(tf_name); - - strncpy(aname, login, ANAME_SZ-1); - aname[ANAME_SZ-1] = '\0'; - - instance = ""; - - if (config) { - char keyname[1024]; - - snprintf(keyname, sizeof(keyname), "krb4_%s_instance", service); - instance = cfile_getstring(config, keyname, ""); - } - - user_specified = strchr(aname, '.'); - if (user_specified) { - if (instance && instance[0]) { - /* sysadmin specified a (mandatory) instance */ - if (strcmp(user_specified + 1, instance)) { - return strdup("NO saslauthd principal name error"); - } - /* nuke instance from "aname"-- matches what's already in "instance" */ - *user_specified = '\0'; - } else { - /* sysadmin has no preference, so we shift - * instance name from "aname" to "instance" - */ - *user_specified = '\0'; - instance = user_specified + 1; - } - } - - if(realm_in && *realm_in != '\0') { - realm = realm_in; - } else { - realm = default_realm; - } - - rc = krb_get_pw_in_tkt(aname, instance, realm, - KRB_TICKET_GRANTING_TICKET, - realm, 1, password); - - if (rc == INTK_BADPW || rc == KDC_PR_UNKNOWN) { - return strdup("NO"); - } else if (rc != KSUCCESS) { - syslog(LOG_ERR, "ERROR: auth_krb4: krb_get_pw_in_tkt: %s", - krb_get_err_text(rc)); - - return strdup("NO saslauthd internal error"); - } - - /* if the TGT wasn't spoofed, it should entitle us to an rcmd ticket... */ - rc = krb_mk_req(&ticket, verify_principal, myhostname, default_realm, 0); - - if (rc != KSUCCESS) { - syslog(LOG_ERR, "ERROR: auth_krb4: krb_get_pw_in_tkt: %s", - krb_get_err_text(rc)); - dest_tkt(); - return strdup("NO saslauthd internal error"); - } - - /* .. and that ticket should match our secret host key */ - rc = krb_rd_req(&ticket, verify_principal, myhostname, 0, &kdata, srvtabname); - - if (rc != RD_AP_OK) { - syslog(LOG_ERR, "ERROR: auth_krb4: krb_rd_req:%s", - krb_get_err_text(rc)); - dest_tkt(); - return strdup("NO saslauthd internal error"); - } - - dest_tkt(); - - return strdup("OK"); -} - -#else /* ! AUTH_KRB4 */ - -char * -auth_krb4 ( - const char *login __attribute__((unused)), - const char *password __attribute__((unused)), - const char *service __attribute__((unused)), - const char *realm __attribute__((unused)), - const char *remote __attribute__((unused)) - ) -{ - return NULL; -} - -#endif /* ! AUTH_KRB4 */ - -/* END FUNCTION: auth_krb4 */ - -/* END MODULE: auth_krb4 */ diff --git a/saslauthd/auth_krb4.h b/saslauthd/auth_krb4.h deleted file mode 100644 index 7ffa3902..00000000 --- a/saslauthd/auth_krb4.h +++ /dev/null @@ -1,29 +0,0 @@ -/* COPYRIGHT - * Copyright (c) 1997 Messaging Direct Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY MESSAGING DIRECT LTD. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MESSAGING DIRECT LTD. OR - * ITS EMPLOYEES OR AGENTS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * END COPYRIGHT */ - -char *auth_krb4(const char *, const char *, const char *, const char *, const char *); -int auth_krb4_init(void); diff --git a/saslauthd/krbtf.c b/saslauthd/krbtf.c deleted file mode 100644 index 5efba56c..00000000 --- a/saslauthd/krbtf.c +++ /dev/null @@ -1,192 +0,0 @@ -/* MODULE: krbtf */ -/* - * Copyright (c) 2001-2016 Carnegie Mellon University. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name "Carnegie Mellon University" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For permission or any other legal - * details, please contact - * Carnegie Mellon University - * Center for Technology Transfer and Enterprise Creation - * 4615 Forbes Avenue - * Suite 302 - * Pittsburgh, PA 15213 - * (412) 268-7393, fax: (412) 268-7395 - * innovation@andrew.cmu.edu - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Computing Services - * at Carnegie Mellon University (http://www.cmu.edu/computing/)." - * - * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE - * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * Dec 4, 2002 by Dave Eckhardt - * This is inspired by code which was identical in both - * auth_krb4.c and auth_krb5.c. This code contains protection - * against a race condition. - */ - -/* PUBLIC DEPENDENCIES */ -#include -#include -#include -#include - -#ifdef SASLAUTHD_THREADED /* is this really used??? */ -#include -#endif /* SASLAUTHD_THREADED */ - -#include "mechanisms.h" - -#include -#include -#include -#include - -#ifdef AUTH_KRB4 -#include -#define WANT_KRBTF -#endif /* WANT_KRBTF */ - -#ifdef WANT_KRBTF - -/* PRIVATE DEPENDENCIES */ -/* globals */ - -/* privates */ -static char tf_dir[] = PATH_SASLAUTHD_RUNDIR "/.tf"; -static char pidstring[80]; -size_t pidstring_len = 0; -/* END PRIVATE DEPENDENCIES */ - -#endif /* WANT_KRBTF */ - -/* FUNCTION: krbtf_init */ - -/* SYNOPSIS - * Initialize the Kerberos IV/V ticket-file/credential-cache common code - * - * When possible, use Heimdal krb5's memory-only credential caches-- - * this saves a whole bunch of useless disk i/o's to create and destroy - * a file which we don't want anybody to see anyway. - * - * If not, this function will create a private directory for ticket - * files and cache getpid() for later use. Therefore, we must be - * called AFTER main() does whatever fork()ing it wants. - * - * END SYNOPSIS */ - -int /* R: -1 on failure, else 0 */ -krbtf_init ( - /* PARAMETERS */ - void /* no parameters */ - /* END PARAMETERS */ - ) -{ -#ifdef WANT_KRBTF - /* VARIABLES */ - int rc; /* return code holder */ - struct stat sb; /* stat() work area */ - /* END VARIABLES */ - authmech_t *authmech; - - if (((rc = mkdir(tf_dir, 0700)) == 0) || (errno == EEXIST)) { - if ((rc = lstat(tf_dir, &sb)) == 0) { - if (sb.st_mode & S_IFLNK) { - syslog(LOG_ERR, "krbtf_init: %s is a symbolic link", tf_dir); - return -1; - } - } - } - - if (rc != 0) { - syslog(LOG_ERR, "krbtf_init %s: %m", tf_dir); - return -1; - } - - /* cache getpid() for use in filenames */ - if ((pidstring_len = snprintf(pidstring, sizeof (pidstring), "%d", getpid())) >= sizeof (pidstring)) { - syslog(LOG_ERR, "krbtf_init pidstring too long(!?)"); - return -1; - } - - return 0; -#else /* WANT_KRBTF */ - syslog(LOG_ERR, "krbtf_init: not compiled!"); - return -1; -#endif /* WANT_KRBTF */ -} - -/* END FUNCTION: krbtf_init */ - -/* FUNCTION: krbtf_name */ - -/* SYNOPSIS - * Spit a ticket-file/credentical-cache name into caller's array. - * - * END SYNOPSIS */ - -int /* R: -1 on failure, else 0 */ -krbtf_name ( - /* PARAMETERS */ - char *tfname, /* O: where caller wants name */ - int len /* I: available length */ - /* END PARAMETERS */ - ) -{ -#ifdef WANT_KRBTF - int dir_len = sizeof (tf_dir) - 1; /* don't count the null */ - int want_len = dir_len + 1 + pidstring_len + 1; - - if (want_len > len) { - syslog(LOG_ERR, "krbtf_name: need room for %d bytes, got %d", want_len, len); - return -1; - } - - strcpy(tfname, tf_dir); - tfname += dir_len; len -= dir_len; - - *tfname++ = '/'; len--; - - strcpy(tfname, pidstring); - -#ifdef SASLAUTHD_THREADED /* is this really used??? */ - tfname += pidstring_len; - len -= pidstring_len; - - if (snprintf(tfname, len, "_%d", pthread_self() >= len)) { - syslog(LOG_ERR, "krbtf_name: no room for thread id"); - return -1; - } -#endif /* SASLAUTHD_THREADED */ - - return 0; -#else /* WANT_KRBTF */ - syslog(LOG_ERR, "krbtf_name: not compiled!"); - return -1; -#endif /* WANT_KRBTF */ -} -/* END FUNCTION: krbtf_name */ - -/* END MODULE: krbtf */ diff --git a/saslauthd/krbtf.h b/saslauthd/krbtf.h deleted file mode 100644 index 03ef05df..00000000 --- a/saslauthd/krbtf.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2001 Carnegie Mellon University. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name "Carnegie Mellon University" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For permission or any other legal - * details, please contact - * Office of Technology Transfer - * Carnegie Mellon University - * 5000 Forbes Avenue - * Pittsburgh, PA 15213-3890 - * (412) 268-4387, fax: (412) 268-7395 - * tech-transfer@andrew.cmu.edu - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Computing Services - * at Carnegie Mellon University (http://www.cmu.edu/computing/)." - * - * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE - * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -int krbtf_init (void); -int krbtf_name (char *, int); diff --git a/saslauthd/mechanisms.c b/saslauthd/mechanisms.c index 48cc5513..661d4dce 100644 --- a/saslauthd/mechanisms.c +++ b/saslauthd/mechanisms.c @@ -42,7 +42,6 @@ #ifdef AUTH_SIA # include "auth_sia.h" #endif /* AUTH_SIA */ -#include "auth_krb4.h" #include "auth_krb5.h" #include "auth_getpwent.h" #include "auth_sasldb.h" @@ -67,9 +66,6 @@ authmech_t mechanisms[] = { "dce", 0, auth_dce }, #endif /* AUTH_DCE */ { "getpwent", 0, auth_getpwent }, -#ifdef AUTH_KRB4 - { "kerberos4", auth_krb4_init, auth_krb4 }, -#endif /* AUTH_KRB4 */ #ifdef AUTH_KRB5 { "kerberos5", auth_krb5_init, auth_krb5 }, #endif /* AUTH_KRB5 */ diff --git a/saslauthd/saslauthd.mdoc b/saslauthd/saslauthd.mdoc index 0c2209ec..49179b36 100644 --- a/saslauthd/saslauthd.mdoc +++ b/saslauthd/saslauthd.mdoc @@ -150,7 +150,7 @@ dependent upon the facilities provided by the underlying operating system. The mechanism is selected by the .Fl a flag from the following list of choices: -.Bl -tag -width "kerberos4" +.Bl -tag -width "kerberos5" .It Li dce .Em (AIX) .Pp @@ -164,12 +164,6 @@ library function. Typically this authenticates against the local password file. See your system's .Xr getpwent 3 man page for details. -.It Li kerberos4 -.Em (All platforms) -.Pp -Authenticate against the local Kerberos 4 realm. (See the -.Sx NOTES -section for caveats about this driver.) .It Li kerberos5 .Em (All platforms) .Pp diff --git a/utils/testsuite.c b/utils/testsuite.c index 39f8fe74..2330805b 100644 --- a/utils/testsuite.c +++ b/utils/testsuite.c @@ -2904,9 +2904,8 @@ void test_checkpass(void) void notes(void) { printf("NOTE:\n"); - printf("-For KERBEROS_V4 must be able to read srvtab file (usually /etc/srvtab)\n"); printf("-For GSSAPI must be able to read srvtab (/etc/krb5.keytab)\n"); - printf("-For both KERBEROS_V4 and GSSAPI you must have non-expired tickets\n"); + printf("-For GSSAPI you must have non-expired tickets\n"); printf("-For OTP (w/OPIE) must be able to read/write opiekeys (/etc/opiekeys)\n"); printf("-For OTP you must have a non-expired secret\n"); printf("-Must be able to read sasldb, which needs to be setup with a\n"); diff --git a/win32/makeinit.ps1 b/win32/makeinit.ps1 index 7300ba44..56c3a53c 100644 --- a/win32/makeinit.ps1 +++ b/win32/makeinit.ps1 @@ -1,4 +1,4 @@ -$mechanism = @("anonymous", "crammd5", "digestmd5", "scram", "gssapiv2", "kerberos4", "login", "ntlm", "otp", "passdss", "plain", "srp", "gs2") +$mechanism = @("anonymous", "crammd5", "digestmd5", "scram", "gssapiv2", "login", "ntlm", "otp", "passdss", "plain", "srp", "gs2") $pluginsDir = "..\plugins\" for ($i = 0; $i -le $mechanism.Count - 1; $i++) @@ -20,4 +20,4 @@ for ($i = 0; $i -le $auxprop.Count - 1; $i++) } } -"SASL_CANONUSER_PLUG_INIT( ldapdb )" | Add-Content "$($pluginsDir)ldapdb_init.c" \ No newline at end of file +"SASL_CANONUSER_PLUG_INIT( ldapdb )" | Add-Content "$($pluginsDir)ldapdb_init.c" From 60f2b06ca13f8f1390a11139083104e5a52e1ab0 Mon Sep 17 00:00:00 2001 From: Quanah Gibson-Mount Date: Tue, 18 Jul 2023 17:00:42 +0000 Subject: [PATCH 714/796] Fix #708 - Remove NTLM support Signed-off-by: Quanah Gibson-Mount --- configure.ac | 21 ---- docsrc/index.rst | 2 +- docsrc/sasl/components.rst | 2 +- docsrc/sasl/faqs/openldap-sasl-gssapi.rst | 6 +- docsrc/sasl/options.rst | 16 --- docsrc/sasl/quickstart.rst | 1 - docsrc/sasl/resources.rst | 1 - docsrc/sasl/sysadmin.rst | 7 -- docsrc/sasl/windows.rst | 7 +- lib/staticopen.h | 8 -- plugins/Makefile.am | 8 +- plugins/NTMakefile | 18 +-- plugins/makeinit.sh | 2 +- win32/cyrus-sasl-all-in-one.sln | 2 - win32/cyrus-sasl-core.sln | 2 - win32/include/config.h | 1 - win32/makeinit.ps1 | 2 +- win32/plugin_ntlm.vcxproj | 142 ---------------------- win32/sasl2.vcxproj | 3 - 19 files changed, 13 insertions(+), 238 deletions(-) delete mode 100644 win32/plugin_ntlm.vcxproj diff --git a/configure.ac b/configure.ac index ce0b1f38..7be3c6c9 100644 --- a/configure.ac +++ b/configure.ac @@ -632,27 +632,6 @@ else AC_MSG_RESULT(disabled) fi -dnl NTLM -AC_ARG_ENABLE(ntlm, [ --enable-ntlm enable unsupported NTLM authentication [[no]] ], - ntlm=$enableval, - ntlm=no) - -AC_MSG_CHECKING(NTLM) -if test "$ntlm" != no; then - AC_MSG_RESULT(enabled) - NTLM_LIBS="-lcrypto $LIB_RSAREF" - AC_SUBST(NTLM_LIBS) - - SASL_MECHS="$SASL_MECHS libntlm.la" - if test "$enable_static" = yes; then - SASL_STATIC_SRCS="$SASL_STATIC_SRCS \$(top_srcdir)/plugins/ntlm.c" - SASL_STATIC_OBJS="$SASL_STATIC_OBJS ntlm.o" - AC_DEFINE(STATIC_NTLM,[],[Link NTLM Statically]) - fi -else - AC_MSG_RESULT(disabled) -fi - dnl PASSDSS AC_ARG_ENABLE(passdss, [ --enable-passdss enable PASSDSS authentication (experimental) [[no]] ], passdss=$enableval, diff --git a/docsrc/index.rst b/docsrc/index.rst index 87d5f26e..b8d63459 100644 --- a/docsrc/index.rst +++ b/docsrc/index.rst @@ -18,7 +18,7 @@ Features -------- Cyrus SASL provides a number of authentication plugins out of the box. - Berkeley DB, GDBM, or NDBM (sasldb), PAM, MySQL, PostgreSQL, SQLite, LDAP, Active Directory (LDAP), DCE, Kerberos 4 and 5, proxied IMAP auth, getpwent, shadow, SIA, Courier Authdaemon, httpform, APOP and SASL mechanisms: ANONYMOUS, CRAM-MD5, DIGEST-MD5, EXTERNAL, GSSAPI, LOGIN, NTLM, OTP, PASSDSS, PLAIN, SCRAM, SRP + Berkeley DB, GDBM, or NDBM (sasldb), PAM, MySQL, PostgreSQL, SQLite, LDAP, Active Directory (LDAP), DCE, Kerberos 4 and 5, proxied IMAP auth, getpwent, shadow, SIA, Courier Authdaemon, httpform, APOP and SASL mechanisms: ANONYMOUS, CRAM-MD5, DIGEST-MD5, EXTERNAL, GSSAPI, LOGIN, OTP, PASSDSS, PLAIN, SCRAM, SRP .. _SASL: https://en.wikipedia.org/wiki/Simple_Authentication_and_Security_Layer diff --git a/docsrc/sasl/components.rst b/docsrc/sasl/components.rst index b4fb57f0..2e3d0cbb 100644 --- a/docsrc/sasl/components.rst +++ b/docsrc/sasl/components.rst @@ -106,7 +106,7 @@ of the SASL negotiation. If the given mechanism supports a security layer negotiation is complete), the plugin provides that functionality as well. SASL mechanisms are generally defined by the IETF standards process, -however, some mechanisms are not (For example, NTLM). This is in contrast +however, some mechanisms are not. This is in contrast to the other types of plugins, which provide database and username canonicalization services to other plugins and thus aren't standardized in their behavior (they are specific to our implementation). Password verifiers diff --git a/docsrc/sasl/faqs/openldap-sasl-gssapi.rst b/docsrc/sasl/faqs/openldap-sasl-gssapi.rst index 7e31de05..8635e839 100644 --- a/docsrc/sasl/faqs/openldap-sasl-gssapi.rst +++ b/docsrc/sasl/faqs/openldap-sasl-gssapi.rst @@ -6,10 +6,10 @@ This article assumes that you have read and followed the SASL chapter of the `Op To verify that you have the Cyrus :ref:`GSSAPI ` mechanism properly installed, use the pluginviewer command. For instance:: server:~# pluginviewer | grep -i gssapi - CRAM-MD5 PLAIN NTLM GSSAPI OTP DIGEST-MD5 ANONYMOUS LOGIN EXTERNAL + CRAM-MD5 PLAIN GSSAPI OTP DIGEST-MD5 ANONYMOUS LOGIN EXTERNAL Plugin "gssapiv2" [loaded], API version: 4 SASL mechanism: GSSAPI, best SSF: 56, supports setpass: no - CRAM-MD5 PLAIN NTLM GSSAPI OTP DIGEST-MD5 ANONYMOUS LOGIN EXTERNAL + CRAM-MD5 PLAIN GSSAPI OTP DIGEST-MD5 ANONYMOUS LOGIN EXTERNAL Plugin "gssapiv2" [loaded], API version: 4 SASL mechanism: GSSAPI, best SSF: 56 @@ -20,7 +20,6 @@ On your client system, search the Root DSE of the server to view advertised mech client:~# ldapsearch -LLL -x -H ldap://ldap.example.org -s "base" -b "" supportedSASLMechanisms dn: supportedSASLMechanisms: DIGEST-MD5 - supportedSASLMechanisms: NTLM supportedSASLMechanisms: GSSAPI supportedSASLMechanisms: OTP supportedSASLMechanisms: CRAM-MD5 @@ -48,7 +47,6 @@ Once you have verified that the server is advertising GSSAPI support, then try:: SASL SSF: 56 SASL data security layer installed. dn: supportedSASLMechanisms: DIGEST-MD5 - supportedSASLMechanisms: NTLM supportedSASLMechanisms: GSSAPI supportedSASLMechanisms: OTP supportedSASLMechanisms: CRAM-MD5 diff --git a/docsrc/sasl/options.rst b/docsrc/sasl/options.rst index dc4e1c91..f21f00c7 100644 --- a/docsrc/sasl/options.rst +++ b/docsrc/sasl/options.rst @@ -236,22 +236,6 @@ stored. The slapd.conf will need to map these usernames to LDAP DNs: sasl-regexp uid=(.*),cn=external,cn=auth ldap:///dc=example,dc=com??sub?(uid=$1) -NTLM -==== - -.. option:: ntlm_server [] - - Comma separated list of servernames (WinNT, Win2K, Samba, etc) to - which authentication will be proxied. - - Default: empty - perform authentication internally - -.. option:: ntlm_v2 [yes|no] - - (Client) Send NTLMv2 responses to the server. - - Default: no (send NTLMv1) - OTP === diff --git a/docsrc/sasl/quickstart.rst b/docsrc/sasl/quickstart.rst index ae969fce..bc54b78d 100644 --- a/docsrc/sasl/quickstart.rst +++ b/docsrc/sasl/quickstart.rst @@ -22,7 +22,6 @@ this distribution: * EXTERNAL * GSSAPI (MIT Kerberos 5, Heimdal Kerberos 5 or CyberSafe) * LOGIN -* NTLM (requires OpenSSL libcrypto) * OTP (requires OpenSSL libcrypto) * PASSDSS (requires OpenSSL libcrypto) * PLAIN diff --git a/docsrc/sasl/resources.rst b/docsrc/sasl/resources.rst index b7b4553e..5f0ae987 100644 --- a/docsrc/sasl/resources.rst +++ b/docsrc/sasl/resources.rst @@ -11,5 +11,4 @@ Other Documentation & Resources * `FAQ from Sendmail `_ * `The Secure Remote Password Protocol `_ paper by Thomas Wu * `TCL extensions for SASL `_ -* `The NTLM Authentication Protocol `_ (NTLM) * `Common Internet File System (CIFS) Technical Reference `_ (SMB/NTLM) diff --git a/docsrc/sasl/sysadmin.rst b/docsrc/sasl/sysadmin.rst index 50d83252..08a374ed 100644 --- a/docsrc/sasl/sysadmin.rst +++ b/docsrc/sasl/sysadmin.rst @@ -434,13 +434,6 @@ Is LOGIN supported? for sites that need it to interoperate with old clients; we don't support it. Don't enable it unless you know you need it. -Is NTLM supported? - The NTLM mechanism is a non-standard, undocumented - mechanism developed by Microsoft. It's included in the SASL - distribution purely for sites that need it to interoperate with - Microsoft clients (ie, Outlook) and/or servers (ie, Exchange); we - don't support it. Don't enable it unless you know you need it. - How can I get a non-root application to check plaintext passwords? Use the "saslauthd" daemon and setting "pwcheck_method" to "saslauthd". diff --git a/docsrc/sasl/windows.rst b/docsrc/sasl/windows.rst index 6c836eb5..942dfd7a 100644 --- a/docsrc/sasl/windows.rst +++ b/docsrc/sasl/windows.rst @@ -121,21 +121,18 @@ that links against SQLITE (www.sqlite.org). SQL= depends on ``SQLITE_INCLUDES`` and ``SQLITE_LIBPATH`` parameters. You can either specify them on the command line or edit the defaults in win32\common.mak -Specify "NTLM=1" parameter if you want to enable NTLM plugin. -I.e. ``nmake /f NTMakefile NTLM=1`` - Specify "SRP=1" parameter if you want to enable SRP plugin. You can also specify "DO_SRP_SETPASS=1" if you want to enable SRP setpass functionality. Specify "OTP=1" parameter if you want to enable OTP plugin. -NTLM, SRP and OTP plugins depend on OpenSSL. You can either specify +The SRP and OTP plugins depend on OpenSSL. You can either specify ``OPENSSL_INCLUDE`` and ``OPENSSL_LIBPATH`` parameters on the command line or edit the defaults in win32\common.mak Note, that unless you are building one of those plugins, OpenSSL is not required! If you want to build multiple additional plugins at once, you can specify -multiple parameters described above, for example ``nmake /f NTMakefile NTLM=1 SRP=1 OPT=1`` +multiple parameters described above, for example ``nmake /f NTMakefile SRP=1 OPT=1`` Limitations ----------- diff --git a/lib/staticopen.h b/lib/staticopen.h index 03ca342a..281b3066 100644 --- a/lib/staticopen.h +++ b/lib/staticopen.h @@ -100,10 +100,6 @@ extern SPECIFIC_CLIENT_PLUG_INIT_PROTO( gssapiv2 ); extern SPECIFIC_SERVER_PLUG_INIT_PROTO( login ); extern SPECIFIC_CLIENT_PLUG_INIT_PROTO( login ); #endif -#ifdef STATIC_NTLM -extern SPECIFIC_SERVER_PLUG_INIT_PROTO( ntlm ); -extern SPECIFIC_CLIENT_PLUG_INIT_PROTO( ntlm ); -#endif #ifdef STATIC_OTP extern SPECIFIC_SERVER_PLUG_INIT_PROTO( otp ); extern SPECIFIC_CLIENT_PLUG_INIT_PROTO( otp ); @@ -147,10 +143,6 @@ _sasl_plug_rec _sasl_static_plugins[] = { SPECIFIC_SERVER_PLUG_INIT( login, "LOGIN" ), SPECIFIC_CLIENT_PLUG_INIT( login, "LOGIN" ), #endif -#ifdef STATIC_NTLM - SPECIFIC_SERVER_PLUG_INIT( ntlm, "NTLM" ), - SPECIFIC_CLIENT_PLUG_INIT( ntlm, "NTLM" ), -#endif #ifdef STATIC_OTP SPECIFIC_SERVER_PLUG_INIT( otp, "OTP" ), SPECIFIC_CLIENT_PLUG_INIT( otp, "OTP" ), diff --git a/plugins/Makefile.am b/plugins/Makefile.am index 1662f2c3..62e2b454 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -68,7 +68,7 @@ plugin_LTLIBRARIES = @SASL_MECHS@ EXTRA_LTLIBRARIES = libplain.la libanonymous.la libcrammd5.la \ libgs2.la libgssapiv2.la libdigestmd5.la liblogin.la libsrp.la libotp.la \ - libscram.la libntlm.la libpassdss.la libsasldb.la libsql.la libldapdb.la + libscram.la libpassdss.la libsasldb.la libsql.la libldapdb.la libplain_la_SOURCES = plain.c plain_init.c libplain_la_DEPENDENCIES = $(COMPAT_OBJS) $(PLUGIN_COMMON_OBJS) @@ -110,10 +110,6 @@ libotp_la_SOURCES = otp.c otp_init.c otp.h libotp_la_DEPENDENCIES = $(COMPAT_OBJS) $(PLUGIN_COMMON_OBJS) libotp_la_LIBADD = $(OTP_LIBS) $(LIB_SOCKET) $(COMPAT_OBJS) $(PLUGIN_COMMON_OBJS) -libntlm_la_SOURCES = ntlm.c ntlm_init.c -libntlm_la_DEPENDENCIES = $(COMPAT_OBJS) $(PLUGIN_COMMON_OBJS) $(CRYPTO_COMPAT_OBJS) -libntlm_la_LIBADD = $(NTLM_LIBS) $(LIB_SOCKET) $(COMPAT_OBJS) $(PLUGIN_COMMON_OBJS) $(CRYPTO_COMPAT_OBJS) - libpassdss_la_SOURCES = passdss.c passdss_init.c libpassdss_la_DEPENDENCIES = $(COMPAT_OBJS) $(PLUGIN_COMMON_OBJS) $(CRYPTO_COMPAT_OBJS) libpassdss_la_LIBADD = $(PASSDSS_LIBS) $(LIB_SOCKET) $(COMPAT_OBJS) $(PLUGIN_COMMON_OBJS) $(CRYPTO_COMPAT_OBJS) @@ -137,7 +133,7 @@ libsql_la_LIBADD = $(COMPAT_OBJS) $(PLUGIN_COMMON_OBJS) # Instructions for making the _init files init_src=anonymous_init.c crammd5_init.c digestmd5_init.c scram_init.c gs2_init.c gssapiv2_init.c \ -login_init.c plain_init.c srp_init.c otp_init.c ntlm_init.c \ +login_init.c plain_init.c srp_init.c otp_init.c \ passdss_init.c sasldb_init.c sql_init.c ldapdb_init.c diff --git a/plugins/NTMakefile b/plugins/NTMakefile index 45a94fb5..6724601e 100755 --- a/plugins/NTMakefile +++ b/plugins/NTMakefile @@ -2,11 +2,7 @@ SCRAM=1 -!IF "$(NTLM)" == "1" -PLUGINS_EXT=saslNTLM.dll -!ELSE PLUGINS_EXT= -!ENDIF !IF "$(GSSAPI)" == "CyberSafe" PLUGINS_EXT=$(PLUGINS_EXT) saslGSSAPI.dll @@ -51,7 +47,7 @@ PLUGINS=saslANONYMOUS.dll \ $(PLUGINS_EXT) \ saslSASLDB.dll -generated_rc=saslANONYMOUS.rc saslPLAIN.rc saslCRAMMD5.rc saslDIGESTMD5.rc saslLOGIN.rc saslNTLM.rc saslSCRAM.rc saslGSSAPI.rc saslSRP.rc saslOTP.rc saslSASLDB.rc saslSQLITE.rc saslLDAPDB.rc +generated_rc=saslANONYMOUS.rc saslPLAIN.rc saslCRAMMD5.rc saslDIGESTMD5.rc saslLOGIN.rc saslSCRAM.rc saslGSSAPI.rc saslSRP.rc saslOTP.rc saslSASLDB.rc saslSQLITE.rc saslLDAPDB.rc # WS2tcpip.h included in Visual Studio 7 provides getaddrinfo, ... # emulation on Windows, so there is no need to build getaddrinfo.c @@ -80,9 +76,6 @@ saslLOGIN_out = saslLOGIN.dll saslLOGIN.exp saslLOGIN.lib saslSCRAM_objs = scram.obj scram_init.obj $(common_objs) saslSCRAM_out = saslSCRAM.dll saslSCRAM.exp saslSCRAM.lib -saslNTLM_objs = ntlm.obj ntlm_init.obj $(common_objs) -saslNTLM_out = saslNTLM.dll saslNTLM.exp saslNTLM.lib - saslGSSAPI_objs = gssapi.obj gssapiv2_init.obj $(common_objs) saslGSSAPI_out = saslGSSAPI.dll saslGSSAPI.exp saslGSSAPI.lib @@ -141,8 +134,8 @@ SCRAM_FLAGS=/DHAVE_SHA512=1 saslSASLDB_objs = sasldb.obj sasldb_init.obj $(libsasldb_objs) $(common_objs) saslSASLDB_out = saslSASLDB.dll saslSASLDB.exp saslSASLDB.lib -all_objs = $(saslANONYMOUS_objs) $(saslPLAIN_objs) $(saslCRAMMD5_objs) $(saslDIGESTMD5_objs) $(saslLOGIN_objs) $(saslSCRAM_objs) $(saslNTLM_objs) $(saslGSSAPI_objs) $(saslSRP_objs) $(saslOTP_objs) $(saslSASLDB_objs) $(saslSQL_objs) $(saslLDAPDB_objs) -all_out = $(saslANONYMOUS_out) $(saslPLAIN_out) $(saslCRAMMD5_out) $(saslDIGESTMD5_out) $(saslLOGIN_out) $(saslSCRAM_out) $(saslNTLM_out) $(saslGSSAPI_out) $(saslSRP_out) $(saslOTP_out) $(saslSASLDB_out) $(saslSQL_out) $(saslLDAPDB_out) +all_objs = $(saslANONYMOUS_objs) $(saslPLAIN_objs) $(saslCRAMMD5_objs) $(saslDIGESTMD5_objs) $(saslLOGIN_objs) $(saslSCRAM_objs) $(saslGSSAPI_objs) $(saslSRP_objs) $(saslOTP_objs) $(saslSASLDB_objs) $(saslSQL_objs) $(saslLDAPDB_objs) +all_out = $(saslANONYMOUS_out) $(saslPLAIN_out) $(saslCRAMMD5_out) $(saslDIGESTMD5_out) $(saslLOGIN_out) $(saslSCRAM_out) $(saslGSSAPI_out) $(saslSRP_out) $(saslOTP_out) $(saslSASLDB_out) $(saslSQL_out) $(saslLDAPDB_out) # LIBSASL_EXPORTS is required to export additional DB routines from sasldb DB_FLAGS = /I "$(DB_INCLUDE)" /I "..\sasldb" /D "LIBSASL_EXPORTS" /D "KEEP_DB_OPEN" @@ -220,11 +213,6 @@ saslSCRAM.dll: $(saslSCRAM_objs) saslSCRAM.res << IF EXIST $@.manifest mt -manifest $@.manifest -outputresource:$@;2 -saslNTLM.dll: $(saslNTLM_objs) saslNTLM.res - $(LINK32DLL) @<< $(OPENSSL_LIBS) $(LINK32DLL_FLAGS) /out:"saslNTLM.dll" /implib:"saslNTLM.lib" $(saslNTLM_objs) saslNTLM.res -<< - IF EXIST $@.manifest mt -manifest $@.manifest -outputresource:$@;2 - saslGSSAPI.dll: $(saslGSSAPI_objs) saslGSSAPI.res $(LINK32DLL) @<< $(GSS_LIBS) $(LINK32DLL_FLAGS) /out:"saslGSSAPI.dll" /implib:"saslGSSAPI.lib" $(saslGSSAPI_objs) saslGSSAPI.res << diff --git a/plugins/makeinit.sh b/plugins/makeinit.sh index 4b1bd449..e44e6deb 100644 --- a/plugins/makeinit.sh +++ b/plugins/makeinit.sh @@ -1,6 +1,6 @@ plugin_init="$1" # mechanism plugins -for mech in anonymous crammd5 digestmd5 scram gssapiv2 login ntlm otp passdss plain srp gs2; do +for mech in anonymous crammd5 digestmd5 scram gssapiv2 login otp passdss plain srp gs2; do if [ ${plugin_init} = "${mech}_init.c" ];then echo " diff --git a/win32/cyrus-sasl-all-in-one.sln b/win32/cyrus-sasl-all-in-one.sln index 380b15ca..e5db6195 100644 --- a/win32/cyrus-sasl-all-in-one.sln +++ b/win32/cyrus-sasl-all-in-one.sln @@ -48,8 +48,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "plugin_anonymous", "plugin_ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "plugin_plain", "plugin_plain.vcxproj", "{B8C5499F-BCB8-409C-8446-0D92DE118020}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "plugin_ntlm", "plugin_ntlm.vcxproj", "{7D694002-B275-4895-A76E-A6ED345FD3C3}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "plugin_sasldb", "plugin_sasldb.vcxproj", "{BAA833AE-8C05-4C1F-AE5A-739241E3765B}" ProjectSection(ProjectDependencies) = postProject {EF82DBE5-D25B-4AC8-989E-68350BD17185} = {EF82DBE5-D25B-4AC8-989E-68350BD17185} diff --git a/win32/cyrus-sasl-core.sln b/win32/cyrus-sasl-core.sln index 190a0b2b..3b2fa5b6 100644 --- a/win32/cyrus-sasl-core.sln +++ b/win32/cyrus-sasl-core.sln @@ -43,8 +43,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "plugin_anonymous", "plugin_ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "plugin_plain", "plugin_plain.vcxproj", "{B8C5499F-BCB8-409C-8446-0D92DE118020}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "plugin_ntlm", "plugin_ntlm.vcxproj", "{7D694002-B275-4895-A76E-A6ED345FD3C3}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "plugin_login", "plugin_login.vcxproj", "{6F556F64-FB73-4E7D-9908-EEBA78D1592E}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "install", "install.vcxproj", "{D0E8D7B3-5466-4BE2-B54B-80A0E1A55101}" diff --git a/win32/include/config.h b/win32/include/config.h index a689bc23..c0e34428 100755 --- a/win32/include/config.h +++ b/win32/include/config.h @@ -102,7 +102,6 @@ typedef int intptr_t; /* #undef STATIC_KERBEROS4 */ #define STATIC_LOGIN 1 /* #undef STATIC_MYSQL */ -#define STATIC_NTLM 1 /* #define STATIC_OTP 1 */ #define STATIC_PLAIN 1 /* #define STATIC_SASLDB 1 */ diff --git a/win32/makeinit.ps1 b/win32/makeinit.ps1 index 56c3a53c..4ecc63c1 100644 --- a/win32/makeinit.ps1 +++ b/win32/makeinit.ps1 @@ -1,4 +1,4 @@ -$mechanism = @("anonymous", "crammd5", "digestmd5", "scram", "gssapiv2", "login", "ntlm", "otp", "passdss", "plain", "srp", "gs2") +$mechanism = @("anonymous", "crammd5", "digestmd5", "scram", "gssapiv2", "login", "otp", "passdss", "plain", "srp", "gs2") $pluginsDir = "..\plugins\" for ($i = 0; $i -le $mechanism.Count - 1; $i++) diff --git a/win32/plugin_ntlm.vcxproj b/win32/plugin_ntlm.vcxproj deleted file mode 100644 index edeef2ea..00000000 --- a/win32/plugin_ntlm.vcxproj +++ /dev/null @@ -1,142 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - - - - - {528f3494-1c30-405f-9fdf-22fa4afe54f4} - - - - {7D694002-B275-4895-A76E-A6ED345FD3C3} - plugin_ntlm - 8.1 - - - - StaticLibrary - true - v140 - Unicode - - - StaticLibrary - false - v140 - true - Unicode - - - StaticLibrary - true - v140 - Unicode - - - StaticLibrary - false - v140 - true - Unicode - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Level3 - Disabled - true - - - - - - Level3 - Disabled - true - - - - - - Level3 - MaxSpeed - true - true - true - - - true - true - - - - - - Level3 - MaxSpeed - true - true - true - - - true - true - - - - - - - \ No newline at end of file diff --git a/win32/sasl2.vcxproj b/win32/sasl2.vcxproj index 3abc23a6..30828622 100644 --- a/win32/sasl2.vcxproj +++ b/win32/sasl2.vcxproj @@ -156,9 +156,6 @@ {6e87064b-9a5e-4f05-a8fb-09fc72e9e3cc} - - {7d694002-b275-4895-a76e-a6ed345fd3c3} - {b8c5499f-bcb8-409c-8446-0d92de118020} From 0b104e52fe8bf125c8d4c78db2ba0fc0fd92da38 Mon Sep 17 00:00:00 2001 From: Quanah Gibson-Mount Date: Tue, 18 Jul 2023 18:17:37 +0000 Subject: [PATCH 715/796] Fix #718 - Remove BDB support Signed-off-by: Quanah Gibson-Mount --- README.release | 2 +- configure.ac | 6 +- docsrc/index.rst | 2 +- docsrc/sasl/faqs/upgrade-saslv2.rst | 22 -- docsrc/sasl/installation.rst | 11 +- docsrc/sasl/quickstart.rst | 2 +- docsrc/sasl/sysadmin.rst | 8 - docsrc/sasl/upgrading.rst | 14 +- m4/berkdb.m4 | 288 --------------- m4/sasldb.m4 | 28 +- plugins/NTMakefile | 6 - sasldb/Makefile.am | 2 +- sasldb/allockey.c | 2 +- sasldb/db_berkeley.c | 545 ---------------------------- utils/dbconverter-2.c | 151 -------- win32/include/config.h | 1 - win32/sasldb.vcxproj | 8 +- 17 files changed, 17 insertions(+), 1081 deletions(-) delete mode 100644 docsrc/sasl/faqs/upgrade-saslv2.rst delete mode 100644 m4/berkdb.m4 delete mode 100644 sasldb/db_berkeley.c diff --git a/README.release b/README.release index b280c4e3..7c771594 100644 --- a/README.release +++ b/README.release @@ -12,7 +12,7 @@ to generate configure etc * MUST build with one of the supported database backends: - bdb gdbm lmdb ndbm + gdbm lmdb ndbm It is recommended to use lmdb Generally using Debian or Ubuntu distributions for the compile steps is useful diff --git a/configure.ac b/configure.ac index 7be3c6c9..d1b79e6c 100644 --- a/configure.ac +++ b/configure.ac @@ -148,7 +148,7 @@ fi AM_CONDITIONAL(SAMPLE, test "$enable_sample" = yes) -dnl call before we do the berkeley DB checks +dnl call before we do the LMDB checks CMU_SOCKETS dnl we extracted this to config/sasldb.m4 @@ -159,8 +159,8 @@ AC_ARG_ENABLE(keep_db_open, [ --enable-keep-db-open keep handle to DB open fo keep_db_open=$enableval, keep_db_open=no) -# Disable if Berkeley DB and LMDB are not used -if test "$dblib" != berkeley -a "$dblib" != lmdb; then +# Disable if LMDB is not used +if "$dblib" != lmdb; then keep_db_open=no fi diff --git a/docsrc/index.rst b/docsrc/index.rst index b8d63459..19b06596 100644 --- a/docsrc/index.rst +++ b/docsrc/index.rst @@ -18,7 +18,7 @@ Features -------- Cyrus SASL provides a number of authentication plugins out of the box. - Berkeley DB, GDBM, or NDBM (sasldb), PAM, MySQL, PostgreSQL, SQLite, LDAP, Active Directory (LDAP), DCE, Kerberos 4 and 5, proxied IMAP auth, getpwent, shadow, SIA, Courier Authdaemon, httpform, APOP and SASL mechanisms: ANONYMOUS, CRAM-MD5, DIGEST-MD5, EXTERNAL, GSSAPI, LOGIN, OTP, PASSDSS, PLAIN, SCRAM, SRP + LMDB, GDBM, or NDBM (sasldb), PAM, MySQL, PostgreSQL, SQLite, LDAP, Active Directory (LDAP), DCE, Kerberos 5, proxied IMAP auth, getpwent, shadow, SIA, Courier Authdaemon, httpform, APOP and SASL mechanisms: ANONYMOUS, CRAM-MD5, DIGEST-MD5, EXTERNAL, GSSAPI, LOGIN, OTP, PASSDSS, PLAIN, SCRAM, SRP .. _SASL: https://en.wikipedia.org/wiki/Simple_Authentication_and_Security_Layer diff --git a/docsrc/sasl/faqs/upgrade-saslv2.rst b/docsrc/sasl/faqs/upgrade-saslv2.rst deleted file mode 100644 index a13b402d..00000000 --- a/docsrc/sasl/faqs/upgrade-saslv2.rst +++ /dev/null @@ -1,22 +0,0 @@ -Why am I having a problem running dbconverter-2 to upgrade from SASLv1 to SASLv2? ---------------------------------------------------------------------------------- - -The migration is documented in the official documentation. - -When migrating the ``/etc/sasldb`` database using the ``utils/dbconverter-2`` -utility, you may encounter the error message "Error opening password -file". This is usually due to the fact your SASL V1 library was compiled -using a different version of Berkeley DB than the SASL V2 library. You -can work around this by using Berkeley DB's db_upgrade utility (possibly -chaining the DB3 and DB4 upgrade utilities) to upgrade a copy of sasldb -prior to conversion using dbconverter-2. - -Here is the script we use at our installation, where SASL has to coexist with SASL2:: - - #!/bin/sh - cp /etc/sasldb /tmp/sasldb.$$ - /usr/local/BerkeleyDB.4/bin/db_upgrade /etc/sasldb - echo ""|/usr/local/sasl/sbin/dbconverter-2 - cp /tmp/sasldb.$$ /etc/sasldb - - diff --git a/docsrc/sasl/installation.rst b/docsrc/sasl/installation.rst index 640853a2..59f2241a 100644 --- a/docsrc/sasl/installation.rst +++ b/docsrc/sasl/installation.rst @@ -87,7 +87,7 @@ perform user verification? * To use Kerberos and Plaintext, you'll want to use saslauthd with a kerberos module for plaintext authentication. To use Shared Secret and plaintext, you'll want to use the auxprop plugin for password verification. 3. If you are using an auxprop plugin, will you be using SASLdb (and -if so, Berkeley DB [recommended], GDBM, or NDBM?), LDAP or an SQL backend +if so, LMDB [recommended], GDBM, or NDBM?), LDAP or an SQL backend (Postgres? MySQL?). 4. If you are using saslauthd, what module will you be using? LDAP? Kerberos? PAM? @@ -107,7 +107,7 @@ Requirements 2. You'll need `GNU make `_. 3. If you are using SASLdb, you will need to pick your backend. - libsasl2 can use `gdbm `_, `Berkeley db `_, or ndbm to implement its user/password lookup. Most systems come with ndbm. + libsasl2 can use `gdbm `_, `LMDB `_, or ndbm to implement its user/password lookup. Most systems come with ndbm. 4. If you are using SQL, you'll need to properly configure your server/tables, and build the necessary client libraries on the system where you will be @@ -164,12 +164,7 @@ OpenLDAP already built with SASL support. One way to solve this issue is to build Cyrus SASL first without ldap support, then build OpenLDAP, and then come back to SASL and build LDAPDB. -Given the myriad of ways that Berkeley DB can be installed on a system, -people using it may want to look at the ``--with-bdb-libdir`` and -``--with-bdb-incdir`` as alternatives to ``--with-dbbase`` for -specifying the paths to the Berkeley DB Library and Include directories. - -In fact, if you're not planning on using SASLdb at all, it may be worth +If you're not planning on using SASLdb at all, it may be worth your time to disable its use entirely with the ``--with-dblib=none`` option. diff --git a/docsrc/sasl/quickstart.rst b/docsrc/sasl/quickstart.rst index bc54b78d..f0cbb35a 100644 --- a/docsrc/sasl/quickstart.rst +++ b/docsrc/sasl/quickstart.rst @@ -30,7 +30,7 @@ this distribution: The library also supports storing user secrets in either a hash -database (e.g. Berkeley DB, gdbm, ndbm), LDAP, or in a SQL database +database (e.g. lmdb, gdbm, ndbm), LDAP, or in a SQL database (MySQL, Postgres). diff --git a/docsrc/sasl/sysadmin.rst b/docsrc/sasl/sysadmin.rst index 08a374ed..356bbba2 100644 --- a/docsrc/sasl/sysadmin.rst +++ b/docsrc/sasl/sysadmin.rst @@ -438,14 +438,6 @@ How can I get a non-root application to check plaintext passwords? Use the "saslauthd" daemon and setting "pwcheck_method" to "saslauthd". -I want to use Berkeley DB, but it's installed in ``/usr/local/BerkeleyDB.3.1`` and ``configure`` can't find it. - Try setting "CPPFLAGS" and "LDFLAGS" environment - variables before running ``configure``, like so:: - - env CPPFLAGS="-I/usr/local/BerkeleyDB.3.1/include" \ - LDFLAGS="-L/usr/local/BerkeleyDB.3.1/lib -R/usr/local/BerkeleyDB.3.1/lib" \ - ./configure --with-dblib=berkeley - It's not working and won't tell me why! Help! Check syslog output (usually stored in ``/var/log``) for more information. You might want to change your diff --git a/docsrc/sasl/upgrading.rst b/docsrc/sasl/upgrading.rst index 77025bd8..18c05bce 100644 --- a/docsrc/sasl/upgrading.rst +++ b/docsrc/sasl/upgrading.rst @@ -98,16 +98,4 @@ Errors on migration When migrating the ``/etc/sasldb`` database using the ``utils/dbconverter-2`` utility, you may encounter the error message "Error opening password file". This is usually due to the fact your SASL V1 library was compiled -using a different version of Berkeley DB than the SASL V2 library. -You can work around this by using Berkeley DB's db_upgrade utility -(possibly chaining the DB3 and DB4 upgrade utilities) to upgrade a copy -of sasldb prior to conversion using dbconverter-2. - -Here is the script we use at our installation, where SASL has to -coexist with SASL2:: - - !/bin/sh - cp /etc/sasldb /tmp/sasldb.$$ - /usr/local/BerkeleyDB.4/bin/db_upgrade /etc/sasldb - echo ""|/usr/local/sasl/sbin/dbconverter-2 - cp /tmp/sasldb.$$ /etc/sasldb +using a different type of database than the SASL V2 library. diff --git a/m4/berkdb.m4 b/m4/berkdb.m4 deleted file mode 100644 index 98e8cb62..00000000 --- a/m4/berkdb.m4 +++ /dev/null @@ -1,288 +0,0 @@ -dnl $Id: berkdb.m4,v 1.24 2010/01/06 17:01:27 murch Exp $ - -AC_DEFUN([CMU_DB_INC_WHERE1], [ -saved_CPPFLAGS=$CPPFLAGS -CPPFLAGS="$saved_CPPFLAGS -I$1" -AC_TRY_COMPILE([#include ], -[DB *db; -db_create(&db, NULL, 0); -db->open(db, "foo.db", NULL, DB_UNKNOWN, DB_RDONLY, 0644);], -ac_cv_found_db_inc=yes, -ac_cv_found_db_inc=no) -CPPFLAGS=$saved_CPPFLAGS -]) - -AC_DEFUN([CMU_DB_INC_WHERE], [ - for i in $1; do - AC_MSG_CHECKING(for db headers in $i) - CMU_DB_INC_WHERE1($i) - CMU_TEST_INCPATH($i, db) - if test "$ac_cv_found_db_inc" = "yes"; then - ac_cv_db_where_inc=$i - AC_MSG_RESULT(found) - break - else - AC_MSG_RESULT(not found) - fi - done -]) - -# -# Test for lib files -# - -AC_DEFUN([CMU_DB3_LIB_WHERE1], [ -AC_REQUIRE([CMU_AFS]) -AC_REQUIRE([CMU_KRB4]) -saved_LIBS=$LIBS - LIBS="$saved_LIBS -L$1 -ldb-3" -AC_TRY_LINK([#include ], -[db_env_create(NULL, 0);], -[ac_cv_found_db_3_lib=yes], -ac_cv_found_db_3_lib=no) -LIBS=$saved_LIBS -]) -AC_DEFUN([CMU_DB4_LIB_WHERE1], [ -AC_REQUIRE([CMU_AFS]) -AC_REQUIRE([CMU_KRB4]) -saved_LIBS=$LIBS -LIBS="$saved_LIBS -L$1 -ldb-4" -AC_TRY_LINK([#include ], -[db_env_create(NULL, 0);], -[ac_cv_found_db_4_lib=yes], -ac_cv_found_db_4_lib=no) -LIBS=$saved_LIBS -]) - -AC_DEFUN([CMU_DB_LIB_WHERE], [ - for i in $1; do - AC_MSG_CHECKING(for db libraries in $i) -if test "$enable_db4" = "yes"; then - CMU_DB4_LIB_WHERE1($i) - CMU_TEST_LIBPATH($i, [db-4]) - ac_cv_found_db_lib=$ac_cv_found_db_4_lib -else - CMU_DB3_LIB_WHERE1($i) - CMU_TEST_LIBPATH($i, [db-3]) - ac_cv_found_db_lib=$ac_cv_found_db_3_lib -fi - if test "$ac_cv_found_db_lib" = "yes" ; then - ac_cv_db_where_lib=$i - AC_MSG_RESULT(found) - break - else - AC_MSG_RESULT(not found) - fi - done -]) - -AC_DEFUN([CMU_USE_DB], [ -AC_REQUIRE([CMU_FIND_LIB_SUBDIR]) -AC_ARG_WITH(db, - [ --with-db=PREFIX Compile with db support], - [if test "X$with_db" = "X"; then - with_db=yes - fi]) -AC_ARG_WITH(db-lib, - [ --with-db-lib=dir use db libraries in dir], - [if test "$withval" = "yes" -o "$withval" = "no"; then - AC_MSG_ERROR([No argument for --with-db-lib]) - fi]) -AC_ARG_WITH(db-include, - [ --with-db-include=dir use db headers in dir], - [if test "$withval" = "yes" -o "$withval" = "no"; then - AC_MSG_ERROR([No argument for --with-db-include]) - fi]) -AC_ARG_ENABLE(db4, - [ --enable-db4 use db 4.x libraries]) - - if test "X$with_db" != "X"; then - if test "$with_db" != "yes"; then - ac_cv_db_where_lib=$with_db/$CMU_LIB_SUBDIR - ac_cv_db_where_inc=$with_db/include - fi - fi - - if test "X$with_db_lib" != "X"; then - ac_cv_db_where_lib=$with_db_lib - fi - if test "X$ac_cv_db_where_lib" = "X"; then - CMU_DB_LIB_WHERE(/usr/athena/$CMU_LIB_SUBDIR /usr/$CMU_LIB_SUBDIR /usr/local/$CMU_LIB_SUBDIR) - fi - - if test "X$with_db_include" != "X"; then - ac_cv_db_where_inc=$with_db_include - fi - if test "X$ac_cv_db_where_inc" = "X"; then - CMU_DB_INC_WHERE(/usr/athena/include /usr/local/include) - fi - - AC_MSG_CHECKING(whether to include db) - if test "X$ac_cv_db_where_lib" = "X" -o "X$ac_cv_db_where_inc" = "X"; then - ac_cv_found_db=no - AC_MSG_RESULT(no) - else - ac_cv_found_db=yes - AC_MSG_RESULT(yes) - DB_INC_DIR=$ac_cv_db_where_inc - DB_LIB_DIR=$ac_cv_db_where_lib - DB_INC_FLAGS="-I${DB_INC_DIR}" - if test "$enable_db4" = "yes"; then - DB_LIB_FLAGS="-L${DB_LIB_DIR} -ldb-4" - else - DB_LIB_FLAGS="-L${DB_LIB_DIR} -ldb-3" - fi - dnl Do not force configure.in to put these in CFLAGS and LIBS unconditionally - dnl Allow makefile substitutions.... - AC_SUBST(DB_INC_FLAGS) - AC_SUBST(DB_LIB_FLAGS) - if test "X$RPATH" = "X"; then - RPATH="" - fi - case "${host}" in - *-*-linux*) - if test "X$RPATH" = "X"; then - RPATH="-Wl,-rpath,${DB_LIB_DIR}" - else - RPATH="${RPATH}:${DB_LIB_DIR}" - fi - ;; - *-*-hpux*) - if test "X$RPATH" = "X"; then - RPATH="-Wl,+b${DB_LIB_DIR}" - else - RPATH="${RPATH}:${DB_LIB_DIR}" - fi - ;; - *-*-irix*) - if test "X$RPATH" = "X"; then - RPATH="-Wl,-rpath,${DB_LIB_DIR}" - else - RPATH="${RPATH}:${DB_LIB_DIR}" - fi - ;; - *-*-solaris2*) - if test "$ac_cv_prog_gcc" = yes; then - if test "X$RPATH" = "X"; then - RPATH="-Wl,-R${DB_LIB_DIR}" - else - RPATH="${RPATH}:${DB_LIB_DIR}" - fi - else - RPATH="${RPATH} -R${DB_LIB_DIR}" - fi - ;; - esac - AC_SUBST(RPATH) - fi - ]) - - - -dnl ---- CUT HERE --- - -dnl These are the Cyrus Berkeley DB macros. In an ideal world these would be -dnl identical to the above. - -dnl They are here so that they can be shared between Cyrus IMAPd -dnl and Cyrus SASL with relative ease. - -dnl The big difference between this and the ones above is that we don't assume -dnl that we know the name of the library, and we try a lot of permutations -dnl instead. We also assume that DB4 is acceptable. - -dnl When we're done, there will be a BDB_LIBADD and a BDB_INCADD which should -dnl be used when necessary. We should probably be smarter about our RPATH -dnl handling. - -dnl Call these with BERKELEY_DB_CHK. - -dnl We will also set $dblib to "berkeley" if we are successful, "no" otherwise. - -dnl this is unbelievably painful due to confusion over what db-3 should be -dnl named and where the db-3 header file is located. arg. -AC_DEFUN([CYRUS_BERKELEY_DB_CHK_LIB], -[ - BDB_SAVE_LDFLAGS=$LDFLAGS - - if test -d $with_bdb_lib; then - CMU_ADD_LIBPATH_TO($with_bdb_lib, LDFLAGS) - CMU_ADD_LIBPATH_TO($with_bdb_lib, BDB_LIBADD) - else - BDB_LIBADD="" - fi - - saved_LIBS=$LIBS - for dbname in ${with_bdb} \ - db-5.2 db5.2 db52 \ - db-5.1 db5.2 db51 \ - db-5.0 db5.2 db50 \ - db-4.8 db4.8 db48 \ - db-4.7 db4.7 db47 \ - db-4.6 db4.6 db46 \ - db-4.5 db4.5 db45 \ - db-4.4 db4.4 db44 \ - db-4.3 db4.3 db43 \ - db-4.2 db4.2 db42 \ - db-4.1 db4.1 db41 \ - db-4.0 db4.0 db40 db-4 db4 \ - db-3.3 db3.3 db33 \ - db-3.2 db3.2 db32 \ - db-3.1 db3.1 db31 \ - db-3.0 db3.0 db30 db-3 db3 \ - db - do - LIBS="$saved_LIBS -l$dbname" - AC_TRY_LINK([#include -#include ], - [db_create(NULL, NULL, 0);], - BDB_LIBADD="$BDB_LIBADD -l$dbname"; dblib="berkeley"; dbname=db, - dblib="no") - if test "$dblib" = "berkeley"; then break; fi - done - if test "$dblib" = "no"; then - LIBS="$saved_LIBS -ldb" - AC_TRY_LINK([#include -#include ], - [db_open(NULL, 0, 0, 0, NULL, NULL, NULL);], - BDB_LIBADD="$BDB_LIBADD -ldb"; dblib="berkeley"; dbname=db, - dblib="no") - fi - LIBS=$saved_LIBS - - LDFLAGS=$BDB_SAVE_LDFLAGS -]) - -AC_DEFUN([CYRUS_BERKELEY_DB_OPTS], -[ -AC_ARG_WITH(bdb-libdir, - [ --with-bdb-libdir=DIR Berkeley DB lib files are in DIR], - with_bdb_lib=$withval, - [ test "${with_bdb_lib+set}" = set || with_bdb_lib=none]) -AC_ARG_WITH(bdb-incdir, - [ --with-bdb-incdir=DIR Berkeley DB include files are in DIR], - with_bdb_inc=$withval, - [ test "${with_bdb_inc+set}" = set || with_bdb_inc=none ]) -]) - -AC_DEFUN([CYRUS_BERKELEY_DB_CHK], -[ - AC_REQUIRE([CYRUS_BERKELEY_DB_OPTS]) - - cmu_save_CPPFLAGS=$CPPFLAGS - - if test -d $with_bdb_inc; then - CPPFLAGS="$CPPFLAGS -I$with_bdb_inc" - BDB_INCADD="-I$with_bdb_inc" - else - BDB_INCADD="" - fi - - dnl Note that FreeBSD puts it in a wierd place - dnl (but they should use with-bdb-incdir) - AC_CHECK_HEADER(db.h, - [CYRUS_BERKELEY_DB_CHK_LIB()], - dblib="no") - - CPPFLAGS=$cmu_save_CPPFLAGS -]) diff --git a/m4/sasldb.m4 b/m4/sasldb.m4 index 5febf146..18e95dc5 100644 --- a/m4/sasldb.m4 +++ b/m4/sasldb.m4 @@ -1,29 +1,21 @@ dnl Functions to check what database to use for libsasldb -dnl Berkeley DB specific checks first.. +dnl LMDB specific checks first.. dnl Figure out what database type we're using AC_DEFUN([SASL_DB_CHECK], [ cmu_save_LIBS="$LIBS" AC_ARG_WITH(dblib, - [AC_HELP_STRING([--with-dblib={berkeley|gdbm|lmdb|ndbm|none|auto_detect}], - [set the DB library to use [[berkeley]]])], + [AC_HELP_STRING([--with-dblib={gdbm|lmdb|ndbm|none|auto_detect}], + [set the DB library to use [[lmdb]]])], dblib=$withval, dblib=auto_detect) -CYRUS_BERKELEY_DB_OPTS() - SASL_DB_LIB="" case "$dblib" in dnl this is unbelievably painful due to confusion over what db-3 should be dnl named. arg. - berkeley) - CYRUS_BERKELEY_DB_CHK() - CPPFLAGS="${CPPFLAGS} ${BDB_INCADD}" - SASL_DB_INC=$BDB_INCADD - SASL_DB_LIB="${BDB_LIBADD}" - ;; gdbm) AC_ARG_WITH(gdbm,[ --with-gdbm=PATH use gdbm from PATH], with_gdbm="${withval}") @@ -59,8 +51,6 @@ dnl named. arg. dblib="no") ;; auto_detect) - dnl How about berkeley db? - CYRUS_BERKELEY_DB_CHK() if test "$dblib" = no; then dnl How about OpenLDAP's lmdb? AC_CHECK_HEADER(lmdb.h, [ @@ -86,12 +76,6 @@ dnl named. arg. SASL_DB_LIB="-lgdbm", dblib="no")], dblib="no") fi - else - dnl we took Berkeley - CPPFLAGS="${CPPFLAGS} ${BDB_INCADD}" - SASL_DB_INC=$BDB_INCADD - SASL_DB_LIB="${BDB_LIBADD}" - fi ;; none) ;; @@ -99,7 +83,7 @@ dnl named. arg. ;; *) AC_MSG_WARN([Bad DB library implementation specified;]) - AC_ERROR([Use either \"berkeley\", \"gdbm\", \"lmdb\", \"ndbm\" or \"none\"]) + AC_ERROR([Use either \"gdbm\", \"lmdb\", \"ndbm\" or \"none\"]) dblib=no ;; esac @@ -127,10 +111,6 @@ case "$dblib" in SASL_MECHS="$SASL_MECHS libsasldb.la" AC_DEFINE(SASL_NDBM,[],[Use NDBM for SASLdb]) ;; - berkeley) - SASL_MECHS="$SASL_MECHS libsasldb.la" - AC_DEFINE(SASL_BERKELEYDB,[],[Use BerkeleyDB for SASLdb]) - ;; *) AC_MSG_WARN([Disabling SASL authentication database support]) dnl note that we do not add libsasldb.la to SASL_MECHS, since it diff --git a/plugins/NTMakefile b/plugins/NTMakefile index 6724601e..6a3209c3 100755 --- a/plugins/NTMakefile +++ b/plugins/NTMakefile @@ -118,11 +118,6 @@ DB_LIBS="/libpath:$(LMDB_LIBPATH)" lmdb.lib # Auxprop Plugin libsasldb_objs = allockey.obj db_lmdb.obj -!ELSE -DB_LIBS="/libpath:$(DB_LIBPATH)" "$(DB_LIB)" - -# Auxprop Plugin -libsasldb_objs = allockey.obj db_berkeley.obj !ENDIF CRAM_FLAGS=/DOBSOLETE_CRAM_ATTR=1 @@ -250,7 +245,6 @@ CLEAN : -@erase "*.manifest" -@erase getaddrinfo.c -@erase allockey.c - -@erase db_berkeley.c -@erase db_lmdb.c -@erase getnameinfo.c -@erase plugin_common.h diff --git a/sasldb/Makefile.am b/sasldb/Makefile.am index 97f4a5be..67614f08 100644 --- a/sasldb/Makefile.am +++ b/sasldb/Makefile.am @@ -46,7 +46,7 @@ sasl_version = 1:25:0 AM_CPPFLAGS=-DLIBSASL_EXPORTS=1 -fPIC -I$(top_srcdir)/include -I$(top_builddir)/include @SASL_DB_INC@ -extra_common_sources = db_none.c db_lmdb.c db_ndbm.c db_gdbm.c db_berkeley.c +extra_common_sources = db_none.c db_lmdb.c db_ndbm.c db_gdbm.c EXTRA_DIST = NTMakefile diff --git a/sasldb/allockey.c b/sasldb/allockey.c index 0c93b17d..9a9496fb 100644 --- a/sasldb/allockey.c +++ b/sasldb/allockey.c @@ -1,4 +1,4 @@ -/* db_berkeley.c--SASL berkeley db interface +/* SASL generic db interface * Rob Siemborski * Tim Martin */ diff --git a/sasldb/db_berkeley.c b/sasldb/db_berkeley.c deleted file mode 100644 index d334f144..00000000 --- a/sasldb/db_berkeley.c +++ /dev/null @@ -1,545 +0,0 @@ -/* db_berkeley.c--SASL berkeley db interface - * Rob Siemborski - * Tim Martin - */ -/* - * Copyright (c) 1998-2016 Carnegie Mellon University. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name "Carnegie Mellon University" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For permission or any other legal - * details, please contact - * Carnegie Mellon University - * Center for Technology Transfer and Enterprise Creation - * 4615 Forbes Avenue - * Suite 302 - * Pittsburgh, PA 15213 - * (412) 268-7393, fax: (412) 268-7395 - * innovation@andrew.cmu.edu - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Computing Services - * at Carnegie Mellon University (http://www.cmu.edu/computing/)." - * - * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE - * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include - -#include - -#include -#include -#include -#include -#include "sasldb.h" - -#define DB_VERSION_FULL ((DB_VERSION_MAJOR << 24) | (DB_VERSION_MINOR << 16) | DB_VERSION_PATCH) - -static int db_ok = 0; -#if defined(KEEP_DB_OPEN) -static DB * g_db = NULL; -#endif - -/* - * Open the database. The pathname for the database can come from - * one of three places: - * - * 1) The value of SASL_DB_PATH. - * 2) The registry value of the string SASL_DB_PATH_ATTR. See - * _sasl_get_registry_value() for a desciption of the semantics. - * 3) The value returned from the sasldb_path callback function. - * - * The last value provided wins. - */ -static int berkeleydb_open(const sasl_utils_t *utils, - sasl_conn_t *conn, - int rdwr, DB **mbdb) -{ - const char *path; - const char *p; - int ret; - int flags; - void *cntxt; - sasl_getopt_t *getopt; - -#if defined(KEEP_DB_OPEN) - if (g_db) { - *mbdb = g_db; - return SASL_OK; - } -#endif - - ret = _sasldb_getpath(utils, &path); - if (ret) return ret; - - if (utils->getcallback(conn, SASL_CB_GETOPT, - (sasl_callback_ft *)&getopt, &cntxt) == SASL_OK) { - if (getopt(cntxt, NULL, "sasldb_path", &p, NULL) == SASL_OK - && p != NULL && *p != 0) { - path = p; - } - } - - if (rdwr) flags = DB_CREATE; - else flags = DB_RDONLY; -#if defined(KEEP_DB_OPEN) -#if defined(DB_THREAD) - flags |= DB_THREAD; -#endif -#endif - -#if DB_VERSION_FULL < 0x03000000 - ret = db_open(path, DB_HASH, flags, 0660, NULL, NULL, mbdb); -#else /* DB_VERSION_FULL < 0x03000000 */ - ret = db_create(mbdb, NULL, 0); - if (ret == 0 && *mbdb != NULL) - { -#if DB_VERSION_FULL >= 0x04010000 - ret = (*mbdb)->open(*mbdb, NULL, path, NULL, DB_HASH, flags, 0660); -#else - ret = (*mbdb)->open(*mbdb, path, NULL, DB_HASH, flags, 0660); -#endif - if (ret != 0) - { - (void) (*mbdb)->close(*mbdb, 0); - *mbdb = NULL; - } - } -#endif /* DB_VERSION_FULL < 0x03000000 */ - - if (ret != 0) { - if (rdwr == 0 && ret == ENOENT) { - /* File not found and we are only reading the data. - Treat as SASL_NOUSER. */ - return SASL_NOUSER; - } - utils->log(conn, SASL_LOG_ERR, - "unable to open Berkeley db %s: %s", - path, db_strerror(ret)); - utils->seterror(conn, SASL_NOLOG, "Unable to open DB"); - SASLDB_FREEPATH(utils, path); - return SASL_FAIL; - } - -#if defined(KEEP_DB_OPEN) - /* Save the DB handle for later use */ - g_db = *mbdb; -#endif - SASLDB_FREEPATH(utils, path); - return SASL_OK; -} - -/* - * Close the database - */ -static void berkeleydb_close(const sasl_utils_t *utils, DB *mbdb) -{ - int ret; - -#if defined(KEEP_DB_OPEN) - /* Prevent other threads from reusing the same handle */ - /* msdb == g_db */ - g_db = NULL; -#endif - - ret = mbdb->close(mbdb, 0); - if (ret!=0) { - /* error closing! */ - utils->log(NULL, SASL_LOG_ERR, - "error closing sasldb: %s", - db_strerror(ret)); - } -} - - -/* - * Retrieve the secret from the database. - * - * Return SASL_NOUSER if the entry doesn't exist, - * SASL_OK on success. - * - */ -int _sasldb_getdata(const sasl_utils_t *utils, - sasl_conn_t *context, - const char *auth_identity, - const char *realm, - const char *propName, - char *out, const size_t max_out, size_t *out_len) -{ - int result = SASL_OK; - char *key; - size_t key_len; - DBT dbkey, data; - DB *mbdb = NULL; - - if(!utils) return SASL_BADPARAM; - - /* check parameters */ - if (!auth_identity || !realm || !propName || !out || !max_out) { - utils->seterror(context, 0, - "Bad parameter in db_berkeley.c: _sasldb_getdata"); - return SASL_BADPARAM; - } - - if (!db_ok) { - utils->seterror(context, 0, - "Database not checked"); - return SASL_FAIL; - } - - /* allocate a key */ - result = _sasldb_alloc_key(utils, auth_identity, realm, propName, - &key, &key_len); - if (result != SASL_OK) { - utils->seterror(context, 0, - "Could not allocate key in _sasldb_getdata"); - return result; - } - - /* zero out */ - memset(&dbkey, 0, sizeof(dbkey)); - memset(&data, 0, sizeof(data)); - - /* open the db */ - result = berkeleydb_open(utils, context, 0, &mbdb); - if (result != SASL_OK) goto cleanup; - - /* create the key to search for */ - dbkey.data = key; - dbkey.size = (u_int32_t) key_len; - dbkey.flags = DB_DBT_USERMEM; - data.flags = DB_DBT_MALLOC; - - /* ask berkeley db for the entry */ - result = mbdb->get(mbdb, NULL, &dbkey, &data, 0); - - switch (result) { - case 0: - /* success */ - break; - - case DB_NOTFOUND: - result = SASL_NOUSER; - utils->seterror(context, SASL_NOLOG, - "user: %s@%s property: %s not found in sasldb", - auth_identity,realm,propName); - goto cleanup; - break; - default: - utils->seterror(context, 0, - "error fetching from sasldb: %s", - db_strerror(result)); - result = SASL_FAIL; - goto cleanup; - break; - } - - if(data.size > max_out + 1) - return SASL_BUFOVER; - - if(out_len) *out_len = data.size; - memcpy(out, data.data, data.size); - out[data.size] = '\0'; - - cleanup: - -#if !defined(KEEP_DB_OPEN) - if (mbdb != NULL) berkeleydb_close(utils, mbdb); -#endif - - utils->free(key); - utils->free(data.data); - - return result; -} - -/* - * Put or delete an entry - * - * - */ - -int _sasldb_putdata(const sasl_utils_t *utils, - sasl_conn_t *context, - const char *authid, - const char *realm, - const char *propName, - const char *data_in, size_t data_len) -{ - int result = SASL_OK; - char *key; - size_t key_len; - DBT dbkey; - DB *mbdb = NULL; - - if (!utils) return SASL_BADPARAM; - - if (!authid || !realm || !propName) { - utils->seterror(context, 0, - "Bad parameter in db_berkeley.c: _sasldb_putdata"); - return SASL_BADPARAM; - } - - if (!db_ok) { - utils->seterror(context, 0, - "Database not checked"); - return SASL_FAIL; - } - - result = _sasldb_alloc_key(utils, authid, realm, propName, - &key, &key_len); - if (result != SASL_OK) { - utils->seterror(context, 0, - "Could not allocate key in _sasldb_putdata"); - return result; - } - - /* open the db */ - result=berkeleydb_open(utils, context, 1, &mbdb); - if (result!=SASL_OK) goto cleanup; - - /* create the db key */ - memset(&dbkey, 0, sizeof(dbkey)); - dbkey.data = key; - dbkey.size = (u_int32_t) key_len; - - if (data_in) { /* putting secret */ - DBT data; - - memset(&data, 0, sizeof(data)); - - data.data = (char *)data_in; - if(!data_len) data_len = strlen(data_in); - data.size = (u_int32_t) data_len; - - result = mbdb->put(mbdb, NULL, &dbkey, &data, 0); - - if (result != 0) - { - utils->log(NULL, SASL_LOG_ERR, - "error updating sasldb: %s", db_strerror(result)); - utils->seterror(context, SASL_NOLOG, - "Couldn't update db"); - result = SASL_FAIL; - goto cleanup; - } - } else { /* removing secret */ - result=mbdb->del(mbdb, NULL, &dbkey, 0); - - if (result != 0) - { - utils->log(NULL, SASL_LOG_ERR, - "error deleting entry from sasldb: %s", db_strerror(result)); - utils->seterror(context, SASL_NOLOG, - "Couldn't update db"); - if (result == DB_NOTFOUND) - result = SASL_NOUSER; - else - result = SASL_FAIL; - goto cleanup; - } - } - - cleanup: - -#if !defined(KEEP_DB_OPEN) - if (mbdb != NULL) berkeleydb_close(utils, mbdb); -#endif - - utils->free(key); - - return result; -} - -LIBSASL_API int _sasl_check_db(const sasl_utils_t *utils, - sasl_conn_t *conn) -{ - const char *path = SASL_DB_PATH; - int ret; - void *cntxt; - sasl_getopt_t *getopt; - sasl_verifyfile_t *vf; - - if (!utils) return SASL_BADPARAM; - - if (utils->getcallback(conn, SASL_CB_GETOPT, - (sasl_callback_ft *)&getopt, &cntxt) == SASL_OK) { - const char *p; - if (getopt(cntxt, NULL, "sasldb_path", &p, NULL) == SASL_OK - && p != NULL && *p != 0) { - path = p; - } - } - - ret = utils->getcallback(conn, SASL_CB_VERIFYFILE, - (sasl_callback_ft *)&vf, &cntxt); - if (ret != SASL_OK) { - utils->seterror(conn, 0, "verifyfile failed"); - return ret; - } - - ret = vf(cntxt, path, SASL_VRFY_PASSWD); - - if (ret == SASL_OK) { - db_ok = 1; - } - - if (ret == SASL_OK || ret == SASL_CONTINUE) { - return SASL_OK; - } else { - return ret; - } -} - -#if defined(KEEP_DB_OPEN) -void sasldb_auxprop_free (void *glob_context, - const sasl_utils_t *utils) -{ - if (g_db != NULL) berkeleydb_close(utils, g_db); -} -#endif - -typedef struct berkeleydb_handle -{ - DB *mbdb; - DBC *cursor; -} berkleyhandle_t; - -LIBSASL_API sasldb_handle _sasldb_getkeyhandle(const sasl_utils_t *utils, - sasl_conn_t *conn) -{ - int ret; - DB *mbdb; - berkleyhandle_t *handle; - - if(!utils || !conn) return NULL; - - if(!db_ok) { - utils->seterror(conn, 0, "Database not OK in _sasldb_getkeyhandle"); - return NULL; - } - - ret = berkeleydb_open(utils, conn, 0, &mbdb); - - if (ret != SASL_OK) { - return NULL; - } - - handle = utils->malloc(sizeof(berkleyhandle_t)); - if(!handle) { -#if !defined(KEEP_DB_OPEN) - (void)mbdb->close(mbdb, 0); -#endif - utils->seterror(conn, 0, "Memory error in _sasldb_gethandle"); - return NULL; - } - - handle->mbdb = mbdb; - handle->cursor = NULL; - - return (sasldb_handle)handle; -} - -LIBSASL_API int _sasldb_getnextkey(const sasl_utils_t *utils __attribute__((unused)), - sasldb_handle handle, char *out, - const size_t max_out, size_t *out_len) -{ - DB *mbdb; - int result; - berkleyhandle_t *dbh = (berkleyhandle_t *)handle; - DBT key, data; - - if(!utils || !handle || !out || !max_out) - return SASL_BADPARAM; - - mbdb = dbh->mbdb; - - memset(&key,0, sizeof(key)); - memset(&data,0,sizeof(data)); - - if(!dbh->cursor) { - /* make cursor */ -#if DB_VERSION_FULL < 0x03060000 - result = mbdb->cursor(mbdb, NULL,&dbh->cursor); -#else - result = mbdb->cursor(mbdb, NULL,&dbh->cursor, 0); -#endif /* DB_VERSION_FULL < 0x03000000 */ - - if (result!=0) { - return SASL_FAIL; - } - - /* loop thru */ - result = dbh->cursor->c_get(dbh->cursor, &key, &data, - DB_FIRST); - } else { - result = dbh->cursor->c_get(dbh->cursor, &key, &data, - DB_NEXT); - } - - if (result == DB_NOTFOUND) return SASL_OK; - - if (result != 0) { - return SASL_FAIL; - } - - if (key.size > max_out) { - return SASL_BUFOVER; - } - - memcpy(out, key.data, key.size); - if (out_len) *out_len = key.size; - - return SASL_CONTINUE; -} - - -LIBSASL_API int _sasldb_releasekeyhandle(const sasl_utils_t *utils, - sasldb_handle handle) -{ - berkleyhandle_t *dbh = (berkleyhandle_t *)handle; - int ret = 0; - - if (!utils || !dbh) return SASL_BADPARAM; - - if (dbh->cursor) { - dbh->cursor->c_close(dbh->cursor); - } - -#if !defined(KEEP_DB_OPEN) - /* This is almost the same berkeleydb_close(), except that - berkeleydb_close logs a message on error and does not return - any error */ - if (dbh->mbdb) { - ret = dbh->mbdb->close(dbh->mbdb, 0); - } -#endif - - utils->free(dbh); - - if (ret) { - return SASL_FAIL; - } else { - return SASL_OK; - } -} diff --git a/utils/dbconverter-2.c b/utils/dbconverter-2.c index 4e1bc137..c52f6605 100644 --- a/utils/dbconverter-2.c +++ b/utils/dbconverter-2.c @@ -196,157 +196,6 @@ int listusers(const char *path, listcb_t *cb) return 0; } -#elif defined(SASL_BERKELEYDB) - -#include - -#define DB_VERSION_FULL ((DB_VERSION_MAJOR << 24) | (DB_VERSION_MINOR << 16) | DB_VERSION_PATCH) -/* - * Open the database - * - */ -static int berkeleydb_open(const char *path,DB **mbdb) -{ - int ret; - -#if DB_VERSION_FULL < 0x03000000 - ret = db_open(path, DB_HASH, DB_CREATE, 0664, NULL, NULL, mbdb); -#else /* DB_VERSION_FULL < 0x03000000 */ - ret = db_create(mbdb, NULL, 0); - if (ret == 0 && *mbdb != NULL) - { -#if DB_VERSION_FULL >= 0x04010000 - ret = (*mbdb)->open(*mbdb, NULL, path, NULL, DB_HASH, DB_CREATE, 0664); -#else - ret = (*mbdb)->open(*mbdb, path, NULL, DB_HASH, DB_CREATE, 0664); -#endif - if (ret != 0) - { - (void) (*mbdb)->close(*mbdb, 0); - *mbdb = NULL; - } - } -#endif /* DB_VERSION_FULL < 0x03000000 */ - - if (ret != 0) { - fprintf(stderr,"Error opening password file %s\n", path); - return SASL_FAIL; - } - - return SASL_OK; -} - -/* - * Close the database - * - */ - -static void berkeleydb_close(DB *mbdb) -{ - int ret; - - ret = mbdb->close(mbdb, 0); - if (ret!=0) { - fprintf(stderr,"error closing sasldb: %s", - db_strerror(ret)); - } -} - -int listusers(const char *path, listcb_t *cb) -{ - int result; - DB *mbdb = NULL; - DBC *cursor; - DBT key, data; - - /* open the db */ - result=berkeleydb_open(path, &mbdb); - if (result!=SASL_OK) goto cleanup; - - /* make cursor */ -#if DB_VERSION_FULL < 0x03060000 - result = mbdb->cursor(mbdb, NULL,&cursor); -#else - result = mbdb->cursor(mbdb, NULL,&cursor, 0); -#endif /* DB_VERSION_FULL < 0x03060000 */ - - if (result!=0) { - fprintf(stderr,"Making cursor failure: %s\n",db_strerror(result)); - result = SASL_FAIL; - goto cleanup; - } - - memset(&key,0, sizeof(key)); - memset(&data,0,sizeof(data)); - - /* loop thru */ - result = cursor->c_get(cursor, &key, &data, - DB_FIRST); - - while (result != DB_NOTFOUND) - { - char *authid; - char *realm; - char *tmp; - unsigned int len; - char mech[1024]; - int numnulls = 0; - unsigned int lup; - - /* make sure there are exactly 2 null's */ - for (lup=0;lupc_get(cursor, &key, &data, DB_NEXT); - continue; - } - - authid = key.data; - realm = authid + strlen(authid)+1; - tmp = realm + strlen(realm)+1; - len = key.size - (tmp - authid); - - /* make sure we have enough space of mech */ - if (len >=sizeof(mech)) { - fprintf(stderr,"warning: absurdly long mech name\n"); - result = cursor->c_get(cursor, &key, &data, DB_NEXT); - continue; - } - - memcpy(mech, tmp, key.size - (tmp - ((char *)key.data))); - mech[key.size - (tmp - ((char *)key.data))] = '\0'; - - if (*authid) { - /* don't check return values */ - cb(authid,realm,mech,data.data,data.size); - } - - result = cursor->c_get(cursor, &key, &data, DB_NEXT); - } - - if (result != DB_NOTFOUND) { - fprintf(stderr,"failure: %s\n",db_strerror(result)); - result = SASL_FAIL; - goto cleanup; - } - - result = cursor->c_close(cursor); - if (result != 0) { - result = SASL_FAIL; - goto cleanup; - } - - result = SASL_OK; - - cleanup: - - if (mbdb != NULL) berkeleydb_close(mbdb); - return result; -} - #else /* ARGSUSED */ diff --git a/win32/include/config.h b/win32/include/config.h index c0e34428..b9ec880f 100755 --- a/win32/include/config.h +++ b/win32/include/config.h @@ -90,7 +90,6 @@ typedef int intptr_t; /* what db package are we using? */ /* #undef SASL_GDBM */ /* #undef SASL_NDBM */ -#define SASL_BERKELEYDB 1 /* static plugins are not yet compatible with building via NTMakeFile */ #ifndef NO_STATIC_PLUGINS diff --git a/win32/sasldb.vcxproj b/win32/sasldb.vcxproj index 265e03f0..a7be0de0 100644 --- a/win32/sasldb.vcxproj +++ b/win32/sasldb.vcxproj @@ -20,12 +20,6 @@ - - true - true - true - true - true true @@ -173,4 +167,4 @@ - \ No newline at end of file + From 251d094e2afc4e043776295c9e01f965193cf871 Mon Sep 17 00:00:00 2001 From: Bastian Germann Date: Fri, 7 Jul 2023 13:38:39 +0200 Subject: [PATCH 716/796] lak.c: Fix misleading indentation Prevent a compiler warning on compiling with GCC. Signed-off-by: Bastian Germann --- saslauthd/lak.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/saslauthd/lak.c b/saslauthd/lak.c index 9e26a6ac..bc34ae7a 100644 --- a/saslauthd/lak.c +++ b/saslauthd/lak.c @@ -374,19 +374,18 @@ static int lak_config_read( } if (conf->version != LDAP_VERSION3 && - (conf->use_sasl || - conf->start_tls)) - conf->version = LDAP_VERSION3; - - if (conf->use_sasl && - conf->auth_method == LAK_AUTH_METHOD_BIND) - conf->auth_method = LAK_AUTH_METHOD_FASTBIND; - - if ( ISSET(conf->group_filter) && - ISSET(conf->search_base) && - EMPTY(conf->group_search_base) ) - strlcpy(conf->group_search_base, conf->search_base, LAK_DN_LEN); - + (conf->use_sasl || conf->start_tls)) + conf->version = LDAP_VERSION3; + + if (conf->use_sasl && + conf->auth_method == LAK_AUTH_METHOD_BIND) + conf->auth_method = LAK_AUTH_METHOD_FASTBIND; + + if (ISSET(conf->group_filter) && + ISSET(conf->search_base) && + EMPTY(conf->group_search_base)) + strlcpy(conf->group_search_base, conf->search_base, LAK_DN_LEN); + fclose(infile); return LAK_OK; From b5adef4aaba1a9efd5782cd5b4be57c56c0c6d66 Mon Sep 17 00:00:00 2001 From: Bastian Germann Date: Fri, 7 Jul 2023 13:58:05 +0200 Subject: [PATCH 717/796] Align buffer type with parse_cb's signature Signed-off-by: Bastian Germann --- tests/t_gssapi_srv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/t_gssapi_srv.c b/tests/t_gssapi_srv.c index 19893627..6152bf08 100644 --- a/tests/t_gssapi_srv.c +++ b/tests/t_gssapi_srv.c @@ -93,7 +93,7 @@ int main(int argc, char *argv[]) const char *data; unsigned int len; sasl_channel_binding_t cb = {0}; - unsigned char cb_buf[256]; + char cb_buf[256]; int sd; int c, r; const char *sasl_mech = "GSSAPI"; From eb77d5baf156e7609c9add92834864b37d3c7fb4 Mon Sep 17 00:00:00 2001 From: Bastian Germann Date: Mon, 17 Jul 2023 22:23:23 +0200 Subject: [PATCH 718/796] Remove support for libdes and OpenSSL < 0.9.7 Use the DES_* functions. OpenSSL is required by now. Drop support for the ancient des_* functions from libdes. Signed-off-by: Bastian Germann --- configure.ac | 2 +- plugins/digestmd5.c | 44 +++++++++++++-------------------------- plugins/passdss.c | 6 ------ plugins/srp.c | 18 ---------------- saslauthd/auth_getpwent.c | 3 --- saslauthd/lak.c | 3 --- 6 files changed, 16 insertions(+), 60 deletions(-) diff --git a/configure.ac b/configure.ac index d1b79e6c..aeb6b521 100644 --- a/configure.ac +++ b/configure.ac @@ -1241,7 +1241,7 @@ AC_CHECK_HEADERS_ONCE([sys/time.h]) AC_HEADER_DIRENT AC_HEADER_SYS_WAIT -AC_CHECK_HEADERS(crypt.h des.h dlfcn.h fcntl.h limits.h malloc.h paths.h strings.h sys/file.h sys/time.h syslog.h time.h unistd.h inttypes.h sys/uio.h sys/param.h sysexits.h stdarg.h varargs.h krb5.h netinet/in.h netdb.h sys/un.h string.h termios.h getopt.h arpa/inet.h sys/socket.h) +AC_CHECK_HEADERS(crypt.h dlfcn.h fcntl.h limits.h malloc.h paths.h strings.h sys/file.h sys/time.h syslog.h time.h unistd.h inttypes.h sys/uio.h sys/param.h sysexits.h stdarg.h varargs.h krb5.h netinet/in.h netdb.h sys/un.h string.h termios.h getopt.h arpa/inet.h sys/socket.h) IPv6_CHECK_SS_FAMILY() IPv6_CHECK_SA_LEN() diff --git a/plugins/digestmd5.c b/plugins/digestmd5.c index 4e6c4e96..ddf9f19c 100644 --- a/plugins/digestmd5.c +++ b/plugins/digestmd5.c @@ -62,22 +62,8 @@ #ifdef WITH_DES # ifdef WITH_SSL_DES # include -# include -# if (OPENSSL_VERSION_NUMBER >= 0x0090700f) && \ - !defined(OPENSSL_ENABLE_OLD_DES_SUPPORT) -# define des_cblock DES_cblock -# define des_key_schedule DES_key_schedule -# define des_key_sched(k,ks) \ - DES_key_sched((k),&(ks)) -# define des_cbc_encrypt(i,o,l,k,iv,e) \ - DES_cbc_encrypt((i),(o),(l),&(k),(iv),(e)) -# define des_ede2_cbc_encrypt(i,o,l,k1,k2,iv,e) \ - DES_ede2_cbc_encrypt((i),(o),(l),&(k1),&(k2),(iv),(e)) -# endif /* OpenSSL 0.9.7+ w/o old DES support */ # else /* system DES library */ -#ifdef HAVE_DES_H # include -#endif # endif #endif /* WITH_DES */ @@ -855,9 +841,9 @@ static void get_pair(char **in, char **name, char **value) #ifdef WITH_DES struct des_context_s { - des_key_schedule keysched; /* key schedule for des initialization */ - des_cblock ivec; /* initial vector for encoding */ - des_key_schedule keysched2; /* key schedule for 3des initialization */ + DES_key_schedule keysched; /* key schedule for des initialization */ + DES_cblock ivec; /* initial vector for encoding */ + DES_key_schedule keysched2; /* key schedule for 3des initialization */ }; typedef struct des_context_s des_context_t; @@ -892,7 +878,7 @@ static int dec_3des(context_t *text, des_context_t *c = (des_context_t *) text->cipher_dec_context; int padding, p; - des_ede2_cbc_encrypt((void *) input, + DES_ede2_cbc_encrypt((void *) input, (void *) output, inputlen, c->keysched, @@ -940,7 +926,7 @@ static int enc_3des(context_t *text, len=inputlen+paddinglen+10; - des_ede2_cbc_encrypt((void *) output, + DES_ede2_cbc_encrypt((void *) output, (void *) output, len, c->keysched, @@ -966,11 +952,11 @@ static int init_3des(context_t *text, /* setup enc context */ slidebits(keybuf, enckey); - if (des_key_sched((des_cblock *) keybuf, c->keysched) < 0) + if (DES_key_sched((DES_cblock *) keybuf, c->keysched) < 0) return SASL_FAIL; slidebits(keybuf, enckey + 7); - if (des_key_sched((des_cblock *) keybuf, c->keysched2) < 0) + if (DES_key_sched((DES_cblock *) keybuf, c->keysched2) < 0) return SASL_FAIL; memcpy(c->ivec, ((char *) enckey) + 8, 8); @@ -979,11 +965,11 @@ static int init_3des(context_t *text, /* setup dec context */ c++; slidebits(keybuf, deckey); - if (des_key_sched((des_cblock *) keybuf, c->keysched) < 0) + if (DES_key_sched((DES_cblock *) keybuf, c->keysched) < 0) return SASL_FAIL; slidebits(keybuf, deckey + 7); - if (des_key_sched((des_cblock *) keybuf, c->keysched2) < 0) + if (DES_key_sched((DES_cblock *) keybuf, c->keysched2) < 0) return SASL_FAIL; memcpy(c->ivec, ((char *) deckey) + 8, 8); @@ -1010,14 +996,14 @@ static int dec_des(context_t *text, des_context_t *c = (des_context_t *) text->cipher_dec_context; int p, padding = 0; - des_cbc_encrypt((void *) input, + DES_cbc_encrypt((void *) input, (void *) output, inputlen, c->keysched, &c->ivec, DES_DECRYPT); - /* Update the ivec (des_cbc_encrypt implementations tend to be broken in + /* Update the ivec (DES_cbc_encrypt implementations tend to be broken in this way) */ memcpy(c->ivec, input + (inputlen - 8), 8); @@ -1061,14 +1047,14 @@ static int enc_des(context_t *text, len = inputlen + paddinglen + 10; - des_cbc_encrypt((void *) output, + DES_cbc_encrypt((void *) output, (void *) output, len, c->keysched, &c->ivec, DES_ENCRYPT); - /* Update the ivec (des_cbc_encrypt implementations tend to be broken in + /* Update the ivec (DES_cbc_encrypt implementations tend to be broken in this way) */ memcpy(c->ivec, output + (len - 8), 8); @@ -1090,7 +1076,7 @@ static int init_des(context_t *text, /* setup enc context */ slidebits(keybuf, enckey); - des_key_sched((des_cblock *) keybuf, c->keysched); + DES_key_sched((DES_cblock *) keybuf, c->keysched); memcpy(c->ivec, ((char *) enckey) + 8, 8); @@ -1099,7 +1085,7 @@ static int init_des(context_t *text, /* setup dec context */ c++; slidebits(keybuf, deckey); - des_key_sched((des_cblock *) keybuf, c->keysched); + DES_key_sched((DES_cblock *) keybuf, c->keysched); memcpy(c->ivec, ((char *) deckey) + 8, 8); diff --git a/plugins/passdss.c b/plugins/passdss.c index 96eb8311..8b520e75 100644 --- a/plugins/passdss.c +++ b/plugins/passdss.c @@ -52,12 +52,6 @@ #include #include -/* check OpenSSL version */ -#include -#if (OPENSSL_VERSION_NUMBER < 0x0090700f) -#error OpenSSL 0.9.7 or later is required -#endif - /* for big number support */ #include diff --git a/plugins/srp.c b/plugins/srp.c index 5079e6f1..a6d75830 100644 --- a/plugins/srp.c +++ b/plugins/srp.c @@ -188,12 +188,7 @@ static layer_option_t cipher_options[] = { { "IDEA", 0, (1<<5), 128, "idea-ofb" }, { NULL, 0, 0, 0, NULL} }; -/* XXX Hack until OpenSSL 0.9.7 */ -#if OPENSSL_VERSION_NUMBER < 0x00907000L -static layer_option_t *default_cipher = &cipher_options[0]; -#else static layer_option_t *default_cipher = &cipher_options[2]; -#endif enum { @@ -1622,12 +1617,7 @@ static int CalculateB(context_t *text __attribute__((unused)), *B = BN_new(); BN_mod_exp(*B, g, *b, N, ctx); -#if OPENSSL_VERSION_NUMBER >= 0x00907000L BN_mod_add(*B, *B, v3, N, ctx); -#else - BN_add(*B, *B, v3); - BN_mod(*B, *B, N, ctx); -#endif BN_clear_free(v3); BN_CTX_free(ctx); @@ -2559,15 +2549,7 @@ static int ClientCalculateK(context_t *text, char *salt, int saltlen, BN_mod_mul(gx3, gx3, gx, N, ctx); /* base = (B - 3(g^x)) % N */ -#if OPENSSL_VERSION_NUMBER >= 0x00907000L BN_mod_sub(base, B, gx3, N, ctx); -#else - BN_sub(base, B, gx3); - BN_mod(base, base, N, ctx); - if (BigIntCmpWord(base, 0) < 0) { - BN_add(base, base, N); - } -#endif /* S = base^aux % N */ BN_mod_exp(S, base, aux, N, ctx); diff --git a/saslauthd/auth_getpwent.c b/saslauthd/auth_getpwent.c index c3ce5453..95e5cb6a 100644 --- a/saslauthd/auth_getpwent.c +++ b/saslauthd/auth_getpwent.c @@ -46,9 +46,6 @@ # ifdef WITH_DES # ifdef WITH_SSL_DES -# ifndef OPENSSL_DISABLE_OLD_DES_SUPPORT -# define OPENSSL_DISABLE_OLD_DES_SUPPORT -# endif # include # else # include diff --git a/saslauthd/lak.c b/saslauthd/lak.c index bc34ae7a..e29c898c 100644 --- a/saslauthd/lak.c +++ b/saslauthd/lak.c @@ -47,9 +47,6 @@ #include #endif -#ifndef OPENSSL_DISABLE_OLD_DES_SUPPORT -#define OPENSSL_DISABLE_OLD_DES_SUPPORT -#endif #include #include From 2e2a1f1f0578b8e9657099237b330206104412bd Mon Sep 17 00:00:00 2001 From: Bastian Germann Date: Tue, 18 Jul 2023 00:02:15 +0200 Subject: [PATCH 719/796] Remove the WITH_[SSL_]DES definitions DIGEST-MD5 is the only module that has optional DES support. However, with the removal of RC4 it is the only available primitive. So we can require it and get rid of every WITH_[SSL_]DES occurence by simply including unconditionally (also in all other modules). Signed-off-by: Bastian Germann --- plugins/digestmd5.c | 22 +--------------------- saslauthd/auth_getpwent.c | 8 +------- saslauthd/auth_shadow.c | 8 +------- 3 files changed, 3 insertions(+), 35 deletions(-) diff --git a/plugins/digestmd5.c b/plugins/digestmd5.c index ddf9f19c..febaa902 100644 --- a/plugins/digestmd5.c +++ b/plugins/digestmd5.c @@ -58,14 +58,7 @@ #include #include -/* DES support */ -#ifdef WITH_DES -# ifdef WITH_SSL_DES -# include -# else /* system DES library */ -# include -# endif -#endif /* WITH_DES */ +#include #ifdef WIN32 # include @@ -839,7 +832,6 @@ static void get_pair(char **in, char **name, char **value) *in = endpair; } -#ifdef WITH_DES struct des_context_s { DES_key_schedule keysched; /* key schedule for des initialization */ DES_cblock ivec; /* initial vector for encoding */ @@ -1101,14 +1093,10 @@ static void free_des(context_t *text) if (text->cipher_enc_context) text->utils->free(text->cipher_enc_context); } -#endif /* WITH_DES */ - struct digest_cipher available_ciphers[] = { -#ifdef WITH_DES { "des", 55, 16, 0x08, &enc_des, &dec_des, &init_des, &free_des }, { "3des", 112, 16, 0x10, &enc_3des, &dec_3des, &init_3des, &free_des }, -#endif { NULL, 0, 0, 0, NULL, NULL, NULL, NULL } }; @@ -2899,11 +2887,7 @@ static sasl_server_plug_t digestmd5_server_plugins[] = { { "DIGEST-MD5", /* mech_name */ -#if defined(WITH_DES) 112, -#else - 1, -#endif SASL_SEC_NOPLAINTEXT | SASL_SEC_NOANONYMOUS | SASL_SEC_MUTUAL_AUTH, /* security_flags */ @@ -4412,11 +4396,7 @@ static sasl_client_plug_t digestmd5_client_plugins[] = { { "DIGEST-MD5", /* mech_name */ -#if defined(WITH_DES) 112, -#else - 1, -#endif SASL_SEC_NOPLAINTEXT | SASL_SEC_NOANONYMOUS | SASL_SEC_MUTUAL_AUTH, /* security_flags */ diff --git a/saslauthd/auth_getpwent.c b/saslauthd/auth_getpwent.c index 95e5cb6a..f6782933 100644 --- a/saslauthd/auth_getpwent.c +++ b/saslauthd/auth_getpwent.c @@ -44,13 +44,7 @@ #include #endif -# ifdef WITH_DES -# ifdef WITH_SSL_DES -# include -# else -# include -# endif /* WITH_SSL_DES */ -# endif /* WITH_DES */ +#include # include "globals.h" /* END PUBLIC DEPENDENCIES */ diff --git a/saslauthd/auth_shadow.c b/saslauthd/auth_shadow.c index 5444f26b..6dd44a3d 100644 --- a/saslauthd/auth_shadow.c +++ b/saslauthd/auth_shadow.c @@ -55,13 +55,7 @@ # ifndef HAVE_GETSPNAM -# ifdef WITH_DES -# ifdef WITH_SSL_DES -# include -# else -# include -# endif /* WITH_SSL_DES */ -# endif /* WITH_DES */ +#include # endif /* ! HAVE_GETSPNAM */ From 727ef6c785caf97d1d2474f5913bc7302074e84e Mon Sep 17 00:00:00 2001 From: Bastian Germann Date: Wed, 19 Jul 2023 22:05:23 +0200 Subject: [PATCH 720/796] mac: Remove unnecessary libdes The libdes support was dropped. There are leftovers in the CodeWarrior build files that I cannot edit properly. Signed-off-by: Bastian Germann --- mac/libdes/libdes_68K/libdes_68K | Bin 40770 -> 0 bytes mac/libdes/libdes_68K/libdes_68K.exp | 29 - mac/libdes/libdes_fat/libdes_fat | Bin 37662 -> 0 bytes mac/libdes/libdes_ppc/libdes_ppc | Bin 39680 -> 0 bytes mac/libdes/libdes_ppc/libdes_ppc.Carbon | Bin 42086 -> 0 bytes mac/libdes/libdes_ppc/libdes_ppc.Carbon.exp | 33 - mac/libdes/libdes_ppc/libdes_ppc.exp | 33 - mac/libdes/public/cfm68k_import_off.h | 10 - mac/libdes/public/des.h | 317 -------- mac/libdes/public/destest.c | 842 -------------------- mac/libdes/src/COPYRIGHT | 1 - mac/libdes/src/ChangeLog | 1 - mac/libdes/src/DES.pm | 19 - mac/libdes/src/DES.pod | 1 - mac/libdes/src/DES.xs | 1 - mac/libdes/src/FILES | 1 - mac/libdes/src/INSTALL | 1 - mac/libdes/src/Imakefile | 1 - mac/libdes/src/KERBEROS | 1 - mac/libdes/src/MODES.DES | 1 - mac/libdes/src/Makefile.PL | 1 - mac/libdes/src/Makefile.am | 1 - mac/libdes/src/Makefile.in | 1 - mac/libdes/src/Makefile.ssl | 1 - mac/libdes/src/Makefile.uni | 1 - mac/libdes/src/PC1 | 1 - mac/libdes/src/PC2 | 1 - mac/libdes/src/README | 1 - mac/libdes/src/VERSION | 1 - mac/libdes/src/cbc3_enc.c | 1 - mac/libdes/src/cbc_cksm.c | 1 - mac/libdes/src/cbc_enc.c | 1 - mac/libdes/src/cfb64ede.c | 1 - mac/libdes/src/cfb64enc.c | 1 - mac/libdes/src/cfb_enc.c | 1 - mac/libdes/src/des.c | 1 - mac/libdes/src/des.def | 1 - mac/libdes/src/des.doc | 505 ------------ mac/libdes/src/des.dsp | 1 - mac/libdes/src/des.mak | 1 - mac/libdes/src/des.man | 1 - mac/libdes/src/des.org | 1 - mac/libdes/src/des.pl | 1 - mac/libdes/src/des_crypt.man | 1 - mac/libdes/src/des_enc.c | 1 - mac/libdes/src/des_locl.h | 1 - mac/libdes/src/des_locl.org | 1 - mac/libdes/src/des_opts.c | 1 - mac/libdes/src/des_ver.h | 1 - mac/libdes/src/dllmain.c | 1 - mac/libdes/src/doIP | 1 - mac/libdes/src/doPC1 | 1 - mac/libdes/src/doPC2 | 1 - mac/libdes/src/ecb3_enc.c | 1 - mac/libdes/src/ecb_enc.c | 1 - mac/libdes/src/ede_enc.c | 1 - mac/libdes/src/enc_read.c | 1 - mac/libdes/src/enc_writ.c | 1 - mac/libdes/src/fcrypt.c | 1 - mac/libdes/src/key_par.c | 1 - mac/libdes/src/makefile.bc | 1 - mac/libdes/src/md4.c | 1 - mac/libdes/src/md4.h | 1 - mac/libdes/src/md5.c | 1 - mac/libdes/src/md5.h | 1 - mac/libdes/src/mdtest.c | 1 - mac/libdes/src/ncbc_enc.c | 1 - mac/libdes/src/ofb64ede.c | 1 - mac/libdes/src/ofb64enc.c | 1 - mac/libdes/src/ofb_enc.c | 1 - mac/libdes/src/passwd_dialog.aps | Bin 30428 -> 0 bytes mac/libdes/src/passwd_dialog.clw | 1 - mac/libdes/src/passwd_dialog.rc | 1 - mac/libdes/src/passwd_dialog.res | Bin 320 -> 0 bytes mac/libdes/src/passwd_dlg.c | 1 - mac/libdes/src/passwd_dlg.h | 1 - mac/libdes/src/pcbc_enc.c | 1 - mac/libdes/src/podd.h | 1 - mac/libdes/src/qud_cksm.c | 1 - mac/libdes/src/rand_key.c | 1 - mac/libdes/src/read_pwd.c | 1 - mac/libdes/src/resource.h | 1 - mac/libdes/src/rnd_keys.c | 1 - mac/libdes/src/rpc_des.h | 1 - mac/libdes/src/rpc_enc.c | 1 - mac/libdes/src/rpw.c | 1 - mac/libdes/src/set_key.c | 1 - mac/libdes/src/sha.c | 1 - mac/libdes/src/sha.h | 1 - mac/libdes/src/shifts.pl | 1 - mac/libdes/src/sk.h | 1 - mac/libdes/src/speed.c | 1 - mac/libdes/src/spr.h | 1 - mac/libdes/src/str2key.c | 1 - mac/libdes/src/supp.c | 1 - mac/libdes/src/testdes.pl | 1 - mac/libdes/src/times | 1 - mac/libdes/src/typemap | 1 - mac/libdes/src/version.h | 1 - mac/libdes/src/vms.com | 90 --- mac/libdes/src/xcbc_enc.c | 1 - 101 files changed, 1964 deletions(-) delete mode 100755 mac/libdes/libdes_68K/libdes_68K delete mode 100755 mac/libdes/libdes_68K/libdes_68K.exp delete mode 100755 mac/libdes/libdes_fat/libdes_fat delete mode 100755 mac/libdes/libdes_ppc/libdes_ppc delete mode 100755 mac/libdes/libdes_ppc/libdes_ppc.Carbon delete mode 100755 mac/libdes/libdes_ppc/libdes_ppc.Carbon.exp delete mode 100755 mac/libdes/libdes_ppc/libdes_ppc.exp delete mode 100755 mac/libdes/public/cfm68k_import_off.h delete mode 100755 mac/libdes/public/des.h delete mode 100755 mac/libdes/public/destest.c delete mode 100755 mac/libdes/src/COPYRIGHT delete mode 100755 mac/libdes/src/ChangeLog delete mode 100755 mac/libdes/src/DES.pm delete mode 100755 mac/libdes/src/DES.pod delete mode 100755 mac/libdes/src/DES.xs delete mode 100755 mac/libdes/src/FILES delete mode 100755 mac/libdes/src/INSTALL delete mode 100755 mac/libdes/src/Imakefile delete mode 100755 mac/libdes/src/KERBEROS delete mode 100755 mac/libdes/src/MODES.DES delete mode 100755 mac/libdes/src/Makefile.PL delete mode 100755 mac/libdes/src/Makefile.am delete mode 100755 mac/libdes/src/Makefile.in delete mode 100755 mac/libdes/src/Makefile.ssl delete mode 100755 mac/libdes/src/Makefile.uni delete mode 100755 mac/libdes/src/PC1 delete mode 100755 mac/libdes/src/PC2 delete mode 100755 mac/libdes/src/README delete mode 100755 mac/libdes/src/VERSION delete mode 100755 mac/libdes/src/cbc3_enc.c delete mode 100755 mac/libdes/src/cbc_cksm.c delete mode 100755 mac/libdes/src/cbc_enc.c delete mode 100755 mac/libdes/src/cfb64ede.c delete mode 100755 mac/libdes/src/cfb64enc.c delete mode 100755 mac/libdes/src/cfb_enc.c delete mode 100755 mac/libdes/src/des.c delete mode 100755 mac/libdes/src/des.def delete mode 100755 mac/libdes/src/des.doc delete mode 100755 mac/libdes/src/des.dsp delete mode 100755 mac/libdes/src/des.mak delete mode 100755 mac/libdes/src/des.man delete mode 100755 mac/libdes/src/des.org delete mode 100755 mac/libdes/src/des.pl delete mode 100755 mac/libdes/src/des_crypt.man delete mode 100755 mac/libdes/src/des_enc.c delete mode 100755 mac/libdes/src/des_locl.h delete mode 100755 mac/libdes/src/des_locl.org delete mode 100755 mac/libdes/src/des_opts.c delete mode 100755 mac/libdes/src/des_ver.h delete mode 100755 mac/libdes/src/dllmain.c delete mode 100755 mac/libdes/src/doIP delete mode 100755 mac/libdes/src/doPC1 delete mode 100755 mac/libdes/src/doPC2 delete mode 100755 mac/libdes/src/ecb3_enc.c delete mode 100755 mac/libdes/src/ecb_enc.c delete mode 100755 mac/libdes/src/ede_enc.c delete mode 100755 mac/libdes/src/enc_read.c delete mode 100755 mac/libdes/src/enc_writ.c delete mode 100755 mac/libdes/src/fcrypt.c delete mode 100755 mac/libdes/src/key_par.c delete mode 100755 mac/libdes/src/makefile.bc delete mode 100755 mac/libdes/src/md4.c delete mode 100755 mac/libdes/src/md4.h delete mode 100755 mac/libdes/src/md5.c delete mode 100755 mac/libdes/src/md5.h delete mode 100755 mac/libdes/src/mdtest.c delete mode 100755 mac/libdes/src/ncbc_enc.c delete mode 100755 mac/libdes/src/ofb64ede.c delete mode 100755 mac/libdes/src/ofb64enc.c delete mode 100755 mac/libdes/src/ofb_enc.c delete mode 100755 mac/libdes/src/passwd_dialog.aps delete mode 100755 mac/libdes/src/passwd_dialog.clw delete mode 100755 mac/libdes/src/passwd_dialog.rc delete mode 100755 mac/libdes/src/passwd_dialog.res delete mode 100755 mac/libdes/src/passwd_dlg.c delete mode 100755 mac/libdes/src/passwd_dlg.h delete mode 100755 mac/libdes/src/pcbc_enc.c delete mode 100755 mac/libdes/src/podd.h delete mode 100755 mac/libdes/src/qud_cksm.c delete mode 100755 mac/libdes/src/rand_key.c delete mode 100755 mac/libdes/src/read_pwd.c delete mode 100755 mac/libdes/src/resource.h delete mode 100755 mac/libdes/src/rnd_keys.c delete mode 100755 mac/libdes/src/rpc_des.h delete mode 100755 mac/libdes/src/rpc_enc.c delete mode 100755 mac/libdes/src/rpw.c delete mode 100755 mac/libdes/src/set_key.c delete mode 100755 mac/libdes/src/sha.c delete mode 100755 mac/libdes/src/sha.h delete mode 100755 mac/libdes/src/shifts.pl delete mode 100755 mac/libdes/src/sk.h delete mode 100755 mac/libdes/src/speed.c delete mode 100755 mac/libdes/src/spr.h delete mode 100755 mac/libdes/src/str2key.c delete mode 100755 mac/libdes/src/supp.c delete mode 100755 mac/libdes/src/testdes.pl delete mode 100755 mac/libdes/src/times delete mode 100755 mac/libdes/src/typemap delete mode 100755 mac/libdes/src/version.h delete mode 100755 mac/libdes/src/vms.com delete mode 100755 mac/libdes/src/xcbc_enc.c diff --git a/mac/libdes/libdes_68K/libdes_68K b/mac/libdes/libdes_68K/libdes_68K deleted file mode 100755 index e88ea8730fa530f6174325c57bc1eb5b298da00f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40770 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 k|6?EE`#Jv0J%#q9;h)I&_Hg`TX~bz>% diff --git a/mac/libdes/libdes_ppc/libdes_ppc b/mac/libdes/libdes_ppc/libdes_ppc deleted file mode 100755 index 6dec1440a9ba054c83e2ebf171f3fc1ab80dcb38..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 39680 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 AUH||9 diff --git a/mac/libdes/libdes_ppc/libdes_ppc.Carbon.exp b/mac/libdes/libdes_ppc/libdes_ppc.Carbon.exp deleted file mode 100755 index 5661298f..00000000 --- a/mac/libdes/libdes_ppc/libdes_ppc.Carbon.exp +++ /dev/null @@ -1,33 +0,0 @@ -des_3cbc_encrypt -des_cbc_cksum -des_cbc_encrypt -des_ede3_cfb64_encrypt -des_cfb64_encrypt -des_cfb_encrypt -des_ecb3_encrypt -des_SPtrans -libdes_version -DES_version -des_ecb_encrypt -des_options -des_ede3_cbc_encrypt -des_ncbc_encrypt -des_ede3_ofb64_encrypt -des_ofb64_encrypt -des_ofb_encrypt -des_xcbc_encrypt -des_xwhite_in2out -des_fixup_key_parity -des_decrypt3 -des_encrypt3 -des_encrypt2 -des_encrypt -des_fcrypt -crypt -des_pcbc_encrypt -des_quad_cksum -des_check_key -des_key_sched -des_set_key -des_is_weak_key -des_set_odd_parity diff --git a/mac/libdes/libdes_ppc/libdes_ppc.exp b/mac/libdes/libdes_ppc/libdes_ppc.exp deleted file mode 100755 index 5661298f..00000000 --- a/mac/libdes/libdes_ppc/libdes_ppc.exp +++ /dev/null @@ -1,33 +0,0 @@ -des_3cbc_encrypt -des_cbc_cksum -des_cbc_encrypt -des_ede3_cfb64_encrypt -des_cfb64_encrypt -des_cfb_encrypt -des_ecb3_encrypt -des_SPtrans -libdes_version -DES_version -des_ecb_encrypt -des_options -des_ede3_cbc_encrypt -des_ncbc_encrypt -des_ede3_ofb64_encrypt -des_ofb64_encrypt -des_ofb_encrypt -des_xcbc_encrypt -des_xwhite_in2out -des_fixup_key_parity -des_decrypt3 -des_encrypt3 -des_encrypt2 -des_encrypt -des_fcrypt -crypt -des_pcbc_encrypt -des_quad_cksum -des_check_key -des_key_sched -des_set_key -des_is_weak_key -des_set_odd_parity diff --git a/mac/libdes/public/cfm68k_import_off.h b/mac/libdes/public/cfm68k_import_off.h deleted file mode 100755 index 221f42c5..00000000 --- a/mac/libdes/public/cfm68k_import_off.h +++ /dev/null @@ -1,10 +0,0 @@ -/* - * set a macro for des.h from libdes to not turn all the des functions - * for cfm68k into pragma imports - */ -#define DESLIB_CFM68K_NO_IMPORTS 1 - -/* - * compiler doesnt allow an empty file even for precompiled... go figure - */ -typedef int cfm68_des_enable_braindead; diff --git a/mac/libdes/public/des.h b/mac/libdes/public/des.h deleted file mode 100755 index 82598740..00000000 --- a/mac/libdes/public/des.h +++ /dev/null @@ -1,317 +0,0 @@ -/* crypto/des/des.h */ -/* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@mincom.oz.au). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@mincom.oz.au). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@mincom.oz.au)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - */ - -#ifndef HEADER_DES_H -#define HEADER_DES_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#if (defined(__MWERKS__)&&defined(__MC68K__)&&(!defined(DESLIB_CFM68K_NO_IMPORTS))) -#pragma import on -#define UNDO_CFM68K_IMPORT -#endif - -#ifndef DES_LIB_FUNCTION -#if defined(__BORLANDC__) -#define DES_LIB_FUNCTION /* not-ready-definition-yet */ -#elif defined(_MSC_VER) -#define DES_LIB_FUNCTION /* not-ready-definition-yet2 */ -#else -#define DES_LIB_FUNCTION -#endif -#endif - -/* If this is set to 'unsigned int' on a DEC Alpha, this gives about a - * %20 speed up (longs are 8 bytes, int's are 4). */ -#ifndef DES_LONG -#if defined(__alpha) -#define DES_LONG unsigned int -#else /* Not a 64 bit machine */ -#define DES_LONG unsigned long -#endif -#endif - -typedef unsigned char des_cblock[8]; -typedef struct des_ks_struct - { - union { - des_cblock _; - /* make sure things are correct size on machines with - * 8 byte longs */ - DES_LONG pad[2]; - } ks; -#undef _ -#define _ ks._ - } des_key_schedule[16]; - -#define DES_KEY_SZ (sizeof(des_cblock)) -#define DES_SCHEDULE_SZ (sizeof(des_key_schedule)) - -#define DES_ENCRYPT 1 -#define DES_DECRYPT 0 - -#define DES_CBC_MODE 0 -#define DES_PCBC_MODE 1 - -#define des_ecb2_encrypt(i,o,k1,k2,e) \ - des_ecb3_encrypt((i),(o),(k1),(k2),(k1),(e)) - -#define des_ede2_cbc_encrypt(i,o,l,k1,k2,iv,e) \ - des_ede3_cbc_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(e)) - -#define des_ede2_cfb64_encrypt(i,o,l,k1,k2,iv,n,e) \ - des_ede3_cfb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n),(e)) - -#define des_ede2_ofb64_encrypt(i,o,l,k1,k2,iv,n) \ - des_ede3_ofb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n)) - -#define C_Block des_cblock -#define Key_schedule des_key_schedule -#ifdef KERBEROS -#define ENCRYPT DES_ENCRYPT -#define DECRYPT DES_DECRYPT -#endif -#define KEY_SZ DES_KEY_SZ -#define string_to_key des_string_to_key -#define read_pw_string des_read_pw_string -#define random_key des_random_key -#define pcbc_encrypt des_pcbc_encrypt -#define set_key des_set_key -#define key_sched des_key_sched -#define ecb_encrypt des_ecb_encrypt -#define cbc_encrypt des_cbc_encrypt -#define ncbc_encrypt des_ncbc_encrypt -#define xcbc_encrypt des_xcbc_encrypt -#define cbc_cksum des_cbc_cksum -#define quad_cksum des_quad_cksum - -/* For compatibility with the MIT lib - eay 20/05/92 */ -typedef des_key_schedule bit_64; -#define des_fixup_key_parity des_set_odd_parity -#define des_check_key_parity check_parity - -extern int des_check_key; /* defaults to false */ -extern int des_rw_mode; /* defaults to DES_PCBC_MODE */ - -#ifdef cplusplus -extern "C" { -#endif - -/* The next line is used to disable full ANSI prototypes, if your - * compiler has problems with the prototypes, make sure this line always - * evaluates to true :-) */ -#if defined(MSDOS) || defined(__STDC__) -#undef NOPROTO -#endif -#ifndef NOPROTO -char *DES_LIB_FUNCTION des_options(void); -void DES_LIB_FUNCTION des_ecb3_encrypt(des_cblock *input,des_cblock *output, - des_key_schedule ks1,des_key_schedule ks2, - des_key_schedule ks3, int enc); -DES_LONG DES_LIB_FUNCTION des_cbc_cksum(des_cblock *input,des_cblock *output, - long length,des_key_schedule schedule,des_cblock *ivec); -void DES_LIB_FUNCTION des_cbc_encrypt(des_cblock *input,des_cblock *output,long length, - des_key_schedule schedule,des_cblock *ivec,int enc); -void DES_LIB_FUNCTION des_ncbc_encrypt(des_cblock *input,des_cblock *output,long length, - des_key_schedule schedule,des_cblock *ivec,int enc); -void DES_LIB_FUNCTION des_xcbc_encrypt(des_cblock *input,des_cblock *output,long length, - des_key_schedule schedule,des_cblock *ivec, - des_cblock *inw,des_cblock *outw,int enc); -void DES_LIB_FUNCTION des_3cbc_encrypt(des_cblock *input,des_cblock *output,long length, - des_key_schedule sk1,des_key_schedule sk2, - des_cblock *ivec1,des_cblock *ivec2,int enc); -void DES_LIB_FUNCTION des_cfb_encrypt(unsigned char *in,unsigned char *out,int numbits, - long length,des_key_schedule schedule,des_cblock *ivec,int enc); -void DES_LIB_FUNCTION des_ecb_encrypt(des_cblock *input,des_cblock *output, - des_key_schedule ks,int enc); -void DES_LIB_FUNCTION des_encrypt(DES_LONG *data,des_key_schedule ks, int enc); -void DES_LIB_FUNCTION des_encrypt2(DES_LONG *data,des_key_schedule ks, int enc); -void DES_LIB_FUNCTION des_encrypt3(DES_LONG *data, des_key_schedule ks1, - des_key_schedule ks2, des_key_schedule ks3); -void DES_LIB_FUNCTION des_decrypt3(DES_LONG *data, des_key_schedule ks1, - des_key_schedule ks2, des_key_schedule ks3); -void DES_LIB_FUNCTION des_ede3_cbc_encrypt(des_cblock *input, des_cblock *output, - long length, des_key_schedule ks1, des_key_schedule ks2, - des_key_schedule ks3, des_cblock *ivec, int enc); -void DES_LIB_FUNCTION des_ede3_cfb64_encrypt(unsigned char *in, unsigned char *out, - long length, des_key_schedule ks1, des_key_schedule ks2, - des_key_schedule ks3, des_cblock *ivec, int *num, int encrypt); -void DES_LIB_FUNCTION des_ede3_ofb64_encrypt(unsigned char *in, unsigned char *out, - long length, des_key_schedule ks1, des_key_schedule ks2, - des_key_schedule ks3, des_cblock *ivec, int *num); - -int DES_LIB_FUNCTION des_enc_read(int fd,char *buf,int len,des_key_schedule sched, - des_cblock *iv); -int DES_LIB_FUNCTION des_enc_write(int fd,char *buf,int len,des_key_schedule sched, - des_cblock *iv); -char *DES_LIB_FUNCTION des_fcrypt(const char *buf,const char *salt, char *ret); -#ifdef PERL5 -char *des_crypt(const char *buf,const char *salt); -#else -/* some stupid compilers complain because I have declared char instead - * of const char */ -#ifdef HEADER_DES_LOCL_H -char *DES_LIB_FUNCTION crypt(const char *buf,const char *salt); -#else -char *crypt(); -#endif -#endif -void DES_LIB_FUNCTION des_ofb_encrypt(unsigned char *in,unsigned char *out, - int numbits,long length,des_key_schedule schedule,des_cblock *ivec); -void DES_LIB_FUNCTION des_pcbc_encrypt(des_cblock *input,des_cblock *output,long length, - des_key_schedule schedule,des_cblock *ivec,int enc); -DES_LONG DES_LIB_FUNCTION des_quad_cksum(des_cblock *input,des_cblock *output, - long length,int out_count,des_cblock *seed); -void DES_LIB_FUNCTION des_random_seed(des_cblock key); -void DES_LIB_FUNCTION des_random_key(des_cblock ret); -int DES_LIB_FUNCTION des_read_password(des_cblock *key,char *prompt,int verify); -int DES_LIB_FUNCTION des_read_2passwords(des_cblock *key1,des_cblock *key2, - char *prompt,int verify); -int DES_LIB_FUNCTION des_read_pw_string(char *buf,int length,char *prompt,int verify); -void DES_LIB_FUNCTION des_set_odd_parity(des_cblock *key); -int DES_LIB_FUNCTION des_is_weak_key(des_cblock *key); -int DES_LIB_FUNCTION des_set_key(des_cblock *key,des_key_schedule schedule); -int DES_LIB_FUNCTION des_key_sched(des_cblock *key,des_key_schedule schedule); -void DES_LIB_FUNCTION des_string_to_key(char *str,des_cblock *key); -void DES_LIB_FUNCTION des_string_to_2keys(char *str,des_cblock *key1,des_cblock *key2); -void DES_LIB_FUNCTION des_cfb64_encrypt(unsigned char *in, unsigned char *out, long length, - des_key_schedule schedule, des_cblock *ivec, int *num, int enc); -void DES_LIB_FUNCTION des_ofb64_encrypt(unsigned char *in, unsigned char *out, long length, - des_key_schedule schedule, des_cblock *ivec, int *num); - -/* Extra functions from Mark Murray */ -void DES_LIB_FUNCTION des_cblock_print_file(des_cblock *cb, FILE *fp); -/* The following functions are not in the normal unix build or the - * SSLeay build. When using the SSLeay build, use RAND_seed() - * and RAND_bytes() instead. */ -int DES_LIB_FUNCTION des_new_random_key(des_cblock *key); -void DES_LIB_FUNCTION des_init_random_number_generator(des_cblock *key); -void DES_LIB_FUNCTION des_set_random_generator_seed(des_cblock *key); -void DES_LIB_FUNCTION des_set_sequence_number(des_cblock new_sequence_number); -void DES_LIB_FUNCTION des_generate_random_block(des_cblock *block); -void DES_LIB_FUNCTION des_rand_data(unsigned char *data, int size); - -#else - -char *des_options(); -void des_ecb3_encrypt(); -DES_LONG des_cbc_cksum(); -void des_cbc_encrypt(); -void des_ncbc_encrypt(); -void des_xcbc_encrypt(); -void des_3cbc_encrypt(); -void des_cfb_encrypt(); -void des_ede3_cfb64_encrypt(); -void des_ede3_ofb64_encrypt(); -void des_ecb_encrypt(); -void des_encrypt(); -void des_encrypt2(); -void des_encrypt3(); -void des_decrypt3(); -void des_ede3_cbc_encrypt(); -int des_enc_read(); -int des_enc_write(); -char *des_fcrypt(); -#ifdef PERL5 -char *des_crypt(); -#else -char *crypt(); -#endif -void des_ofb_encrypt(); -void des_pcbc_encrypt(); -DES_LONG des_quad_cksum(); -void des_random_seed(); -void des_random_key(); -int des_read_password(); -int des_read_2passwords(); -int des_read_pw_string(); -void des_set_odd_parity(); -int des_is_weak_key(); -int des_set_key(); -int des_key_sched(); -void des_string_to_key(); -void des_string_to_2keys(); -void des_cfb64_encrypt(); -void des_ofb64_encrypt(); - -/* Extra functions from Mark Murray */ -void des_cblock_print_file(); -/* The following functions are not in the normal unix build or the - * SSLeay build. When using the SSLeay build, use RAND_seed() - * and RAND_bytes() instead. */ -int des_new_random_key(); -void des_init_random_number_generator(); -void des_set_random_generator_seed(); -void des_set_sequence_number(); -void des_generate_random_block(); -void des_rand_data(); - -#endif - -#ifdef UNDO_CFM68K_IMPORT -#pragma import reset -#endif -#ifdef __cplusplus -} -#endif - -#endif diff --git a/mac/libdes/public/destest.c b/mac/libdes/public/destest.c deleted file mode 100755 index 3537a291..00000000 --- a/mac/libdes/public/destest.c +++ /dev/null @@ -1,842 +0,0 @@ -/* crypto/des/destest.c */ -/* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@mincom.oz.au). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@mincom.oz.au). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@mincom.oz.au)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#if defined(WIN32) || defined(WIN16) || defined(WINDOWS) -#ifndef MSDOS -#define MSDOS -#endif -#endif - -#include -#include -#include -#ifdef HAVE_UNISTD_H -#include -#endif -#ifdef HAVE_IO_H -#include -#endif - -#include "des.h" - -/* tisk tisk - the test keys don't all have odd parity :-( */ -/* test data */ -#define NUM_TESTS 34 -static unsigned char key_data[NUM_TESTS][8]={ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, - {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11}, - {0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF}, - {0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0xFE,0xDC,0xBA,0x98,0x76,0x54,0x32,0x10}, - {0x7C,0xA1,0x10,0x45,0x4A,0x1A,0x6E,0x57}, - {0x01,0x31,0xD9,0x61,0x9D,0xC1,0x37,0x6E}, - {0x07,0xA1,0x13,0x3E,0x4A,0x0B,0x26,0x86}, - {0x38,0x49,0x67,0x4C,0x26,0x02,0x31,0x9E}, - {0x04,0xB9,0x15,0xBA,0x43,0xFE,0xB5,0xB6}, - {0x01,0x13,0xB9,0x70,0xFD,0x34,0xF2,0xCE}, - {0x01,0x70,0xF1,0x75,0x46,0x8F,0xB5,0xE6}, - {0x43,0x29,0x7F,0xAD,0x38,0xE3,0x73,0xFE}, - {0x07,0xA7,0x13,0x70,0x45,0xDA,0x2A,0x16}, - {0x04,0x68,0x91,0x04,0xC2,0xFD,0x3B,0x2F}, - {0x37,0xD0,0x6B,0xB5,0x16,0xCB,0x75,0x46}, - {0x1F,0x08,0x26,0x0D,0x1A,0xC2,0x46,0x5E}, - {0x58,0x40,0x23,0x64,0x1A,0xBA,0x61,0x76}, - {0x02,0x58,0x16,0x16,0x46,0x29,0xB0,0x07}, - {0x49,0x79,0x3E,0xBC,0x79,0xB3,0x25,0x8F}, - {0x4F,0xB0,0x5E,0x15,0x15,0xAB,0x73,0xA7}, - {0x49,0xE9,0x5D,0x6D,0x4C,0xA2,0x29,0xBF}, - {0x01,0x83,0x10,0xDC,0x40,0x9B,0x26,0xD6}, - {0x1C,0x58,0x7F,0x1C,0x13,0x92,0x4F,0xEF}, - {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01}, - {0x1F,0x1F,0x1F,0x1F,0x0E,0x0E,0x0E,0x0E}, - {0xE0,0xFE,0xE0,0xFE,0xF1,0xFE,0xF1,0xFE}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, - {0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF}, - {0xFE,0xDC,0xBA,0x98,0x76,0x54,0x32,0x10}}; - -static unsigned char plain_data[NUM_TESTS][8]={ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, - {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, - {0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11}, - {0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11}, - {0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF}, - {0x01,0xA1,0xD6,0xD0,0x39,0x77,0x67,0x42}, - {0x5C,0xD5,0x4C,0xA8,0x3D,0xEF,0x57,0xDA}, - {0x02,0x48,0xD4,0x38,0x06,0xF6,0x71,0x72}, - {0x51,0x45,0x4B,0x58,0x2D,0xDF,0x44,0x0A}, - {0x42,0xFD,0x44,0x30,0x59,0x57,0x7F,0xA2}, - {0x05,0x9B,0x5E,0x08,0x51,0xCF,0x14,0x3A}, - {0x07,0x56,0xD8,0xE0,0x77,0x47,0x61,0xD2}, - {0x76,0x25,0x14,0xB8,0x29,0xBF,0x48,0x6A}, - {0x3B,0xDD,0x11,0x90,0x49,0x37,0x28,0x02}, - {0x26,0x95,0x5F,0x68,0x35,0xAF,0x60,0x9A}, - {0x16,0x4D,0x5E,0x40,0x4F,0x27,0x52,0x32}, - {0x6B,0x05,0x6E,0x18,0x75,0x9F,0x5C,0xCA}, - {0x00,0x4B,0xD6,0xEF,0x09,0x17,0x60,0x62}, - {0x48,0x0D,0x39,0x00,0x6E,0xE7,0x62,0xF2}, - {0x43,0x75,0x40,0xC8,0x69,0x8F,0x3C,0xFA}, - {0x07,0x2D,0x43,0xA0,0x77,0x07,0x52,0x92}, - {0x02,0xFE,0x55,0x77,0x81,0x17,0xF1,0x2A}, - {0x1D,0x9D,0x5C,0x50,0x18,0xF7,0x28,0xC2}, - {0x30,0x55,0x32,0x28,0x6D,0x6F,0x29,0x5A}, - {0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF}, - {0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF}, - {0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF}, - {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}}; - -static unsigned char cipher_data[NUM_TESTS][8]={ - {0x8C,0xA6,0x4D,0xE9,0xC1,0xB1,0x23,0xA7}, - {0x73,0x59,0xB2,0x16,0x3E,0x4E,0xDC,0x58}, - {0x95,0x8E,0x6E,0x62,0x7A,0x05,0x55,0x7B}, - {0xF4,0x03,0x79,0xAB,0x9E,0x0E,0xC5,0x33}, - {0x17,0x66,0x8D,0xFC,0x72,0x92,0x53,0x2D}, - {0x8A,0x5A,0xE1,0xF8,0x1A,0xB8,0xF2,0xDD}, - {0x8C,0xA6,0x4D,0xE9,0xC1,0xB1,0x23,0xA7}, - {0xED,0x39,0xD9,0x50,0xFA,0x74,0xBC,0xC4}, - {0x69,0x0F,0x5B,0x0D,0x9A,0x26,0x93,0x9B}, - {0x7A,0x38,0x9D,0x10,0x35,0x4B,0xD2,0x71}, - {0x86,0x8E,0xBB,0x51,0xCA,0xB4,0x59,0x9A}, - {0x71,0x78,0x87,0x6E,0x01,0xF1,0x9B,0x2A}, - {0xAF,0x37,0xFB,0x42,0x1F,0x8C,0x40,0x95}, - {0x86,0xA5,0x60,0xF1,0x0E,0xC6,0xD8,0x5B}, - {0x0C,0xD3,0xDA,0x02,0x00,0x21,0xDC,0x09}, - {0xEA,0x67,0x6B,0x2C,0xB7,0xDB,0x2B,0x7A}, - {0xDF,0xD6,0x4A,0x81,0x5C,0xAF,0x1A,0x0F}, - {0x5C,0x51,0x3C,0x9C,0x48,0x86,0xC0,0x88}, - {0x0A,0x2A,0xEE,0xAE,0x3F,0xF4,0xAB,0x77}, - {0xEF,0x1B,0xF0,0x3E,0x5D,0xFA,0x57,0x5A}, - {0x88,0xBF,0x0D,0xB6,0xD7,0x0D,0xEE,0x56}, - {0xA1,0xF9,0x91,0x55,0x41,0x02,0x0B,0x56}, - {0x6F,0xBF,0x1C,0xAF,0xCF,0xFD,0x05,0x56}, - {0x2F,0x22,0xE4,0x9B,0xAB,0x7C,0xA1,0xAC}, - {0x5A,0x6B,0x61,0x2C,0xC2,0x6C,0xCE,0x4A}, - {0x5F,0x4C,0x03,0x8E,0xD1,0x2B,0x2E,0x41}, - {0x63,0xFA,0xC0,0xD0,0x34,0xD9,0xF7,0x93}, - {0x61,0x7B,0x3A,0x0C,0xE8,0xF0,0x71,0x00}, - {0xDB,0x95,0x86,0x05,0xF8,0xC8,0xC6,0x06}, - {0xED,0xBF,0xD1,0xC6,0x6C,0x29,0xCC,0xC7}, - {0x35,0x55,0x50,0xB2,0x15,0x0E,0x24,0x51}, - {0xCA,0xAA,0xAF,0x4D,0xEA,0xF1,0xDB,0xAE}, - {0xD5,0xD4,0x4F,0xF7,0x20,0x68,0x3D,0x0D}, - {0x2A,0x2B,0xB0,0x08,0xDF,0x97,0xC2,0xF2}}; - -static unsigned char cipher_ecb2[NUM_TESTS-1][8]={ - {0x92,0x95,0xB5,0x9B,0xB3,0x84,0x73,0x6E}, - {0x19,0x9E,0x9D,0x6D,0xF3,0x9A,0xA8,0x16}, - {0x2A,0x4B,0x4D,0x24,0x52,0x43,0x84,0x27}, - {0x35,0x84,0x3C,0x01,0x9D,0x18,0xC5,0xB6}, - {0x4A,0x5B,0x2F,0x42,0xAA,0x77,0x19,0x25}, - {0xA0,0x6B,0xA9,0xB8,0xCA,0x5B,0x17,0x8A}, - {0xAB,0x9D,0xB7,0xFB,0xED,0x95,0xF2,0x74}, - {0x3D,0x25,0x6C,0x23,0xA7,0x25,0x2F,0xD6}, - {0xB7,0x6F,0xAB,0x4F,0xBD,0xBD,0xB7,0x67}, - {0x8F,0x68,0x27,0xD6,0x9C,0xF4,0x1A,0x10}, - {0x82,0x57,0xA1,0xD6,0x50,0x5E,0x81,0x85}, - {0xA2,0x0F,0x0A,0xCD,0x80,0x89,0x7D,0xFA}, - {0xCD,0x2A,0x53,0x3A,0xDB,0x0D,0x7E,0xF3}, - {0xD2,0xC2,0xBE,0x27,0xE8,0x1B,0x68,0xE3}, - {0xE9,0x24,0xCF,0x4F,0x89,0x3C,0x5B,0x0A}, - {0xA7,0x18,0xC3,0x9F,0xFA,0x9F,0xD7,0x69}, - {0x77,0x2C,0x79,0xB1,0xD2,0x31,0x7E,0xB1}, - {0x49,0xAB,0x92,0x7F,0xD0,0x22,0x00,0xB7}, - {0xCE,0x1C,0x6C,0x7D,0x85,0xE3,0x4A,0x6F}, - {0xBE,0x91,0xD6,0xE1,0x27,0xB2,0xE9,0x87}, - {0x70,0x28,0xAE,0x8F,0xD1,0xF5,0x74,0x1A}, - {0xAA,0x37,0x80,0xBB,0xF3,0x22,0x1D,0xDE}, - {0xA6,0xC4,0xD2,0x5E,0x28,0x93,0xAC,0xB3}, - {0x22,0x07,0x81,0x5A,0xE4,0xB7,0x1A,0xAD}, - {0xDC,0xCE,0x05,0xE7,0x07,0xBD,0xF5,0x84}, - {0x26,0x1D,0x39,0x2C,0xB3,0xBA,0xA5,0x85}, - {0xB4,0xF7,0x0F,0x72,0xFB,0x04,0xF0,0xDC}, - {0x95,0xBA,0xA9,0x4E,0x87,0x36,0xF2,0x89}, - {0xD4,0x07,0x3A,0xF1,0x5A,0x17,0x82,0x0E}, - {0xEF,0x6F,0xAF,0xA7,0x66,0x1A,0x7E,0x89}, - {0xC1,0x97,0xF5,0x58,0x74,0x8A,0x20,0xE7}, - {0x43,0x34,0xCF,0xDA,0x22,0xC4,0x86,0xC8}, - {0x08,0xD7,0xB4,0xFB,0x62,0x9D,0x08,0x85}}; - -static unsigned char cbc_key [8]={0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef}; -static unsigned char cbc2_key[8]={0xf0,0xe1,0xd2,0xc3,0xb4,0xa5,0x96,0x87}; -static unsigned char cbc3_key[8]={0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10}; -static unsigned char cbc_iv [8]={0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10}; -static char cbc_data[40]="7654321 Now is the time for "; - -static unsigned char cbc_ok[32]={ - 0xcc,0xd1,0x73,0xff,0xab,0x20,0x39,0xf4, - 0xac,0xd8,0xae,0xfd,0xdf,0xd8,0xa1,0xeb, - 0x46,0x8e,0x91,0x15,0x78,0x88,0xba,0x68, - 0x1d,0x26,0x93,0x97,0xf7,0xfe,0x62,0xb4}; - -static unsigned char xcbc_ok[32]={ - 0x86,0x74,0x81,0x0D,0x61,0xA4,0xA5,0x48, - 0xB9,0x93,0x03,0xE1,0xB8,0xBB,0xBD,0xBD, - 0x64,0x30,0x0B,0xB9,0x06,0x65,0x81,0x76, - 0x04,0x1D,0x77,0x62,0x17,0xCA,0x2B,0xD2, - }; - -static unsigned char cbc3_ok[32]={ - 0x3F,0xE3,0x01,0xC9,0x62,0xAC,0x01,0xD0, - 0x22,0x13,0x76,0x3C,0x1C,0xBD,0x4C,0xDC, - 0x79,0x96,0x57,0xC0,0x64,0xEC,0xF5,0xD4, - 0x1C,0x67,0x38,0x12,0xCF,0xDE,0x96,0x75}; - -static unsigned char pcbc_ok[32]={ - 0xcc,0xd1,0x73,0xff,0xab,0x20,0x39,0xf4, - 0x6d,0xec,0xb4,0x70,0xa0,0xe5,0x6b,0x15, - 0xae,0xa6,0xbf,0x61,0xed,0x7d,0x9c,0x9f, - 0xf7,0x17,0x46,0x3b,0x8a,0xb3,0xcc,0x88}; - -static unsigned char cfb_key[8]={0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef}; -static unsigned char cfb_iv[8]={0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef}; -static unsigned char cfb_buf1[40],cfb_buf2[40],cfb_tmp[8]; -static unsigned char plain[24]= - { - 0x4e,0x6f,0x77,0x20,0x69,0x73, - 0x20,0x74,0x68,0x65,0x20,0x74, - 0x69,0x6d,0x65,0x20,0x66,0x6f, - 0x72,0x20,0x61,0x6c,0x6c,0x20 - }; -static unsigned char cfb_cipher8[24]= { - 0xf3,0x1f,0xda,0x07,0x01,0x14, 0x62,0xee,0x18,0x7f,0x43,0xd8, - 0x0a,0x7c,0xd9,0xb5,0xb0,0xd2, 0x90,0xda,0x6e,0x5b,0x9a,0x87 }; -static unsigned char cfb_cipher16[24]={ - 0xF3,0x09,0x87,0x87,0x7F,0x57, 0xF7,0x3C,0x36,0xB6,0xDB,0x70, - 0xD8,0xD5,0x34,0x19,0xD3,0x86, 0xB2,0x23,0xB7,0xB2,0xAD,0x1B }; -static unsigned char cfb_cipher32[24]={ - 0xF3,0x09,0x62,0x49,0xA4,0xDF, 0xA4,0x9F,0x33,0xDC,0x7B,0xAD, - 0x4C,0xC8,0x9F,0x64,0xE4,0x53, 0xE5,0xEC,0x67,0x20,0xDA,0xB6 }; -static unsigned char cfb_cipher48[24]={ - 0xF3,0x09,0x62,0x49,0xC7,0xF4, 0x30,0xB5,0x15,0xEC,0xBB,0x85, - 0x97,0x5A,0x13,0x8C,0x68,0x60, 0xE2,0x38,0x34,0x3C,0xDC,0x1F }; -static unsigned char cfb_cipher64[24]={ - 0xF3,0x09,0x62,0x49,0xC7,0xF4, 0x6E,0x51,0xA6,0x9E,0x83,0x9B, - 0x1A,0x92,0xF7,0x84,0x03,0x46, 0x71,0x33,0x89,0x8E,0xA6,0x22 }; - -static unsigned char ofb_key[8]={0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef}; -static unsigned char ofb_iv[8]={0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef}; -static unsigned char ofb_buf1[24],ofb_buf2[24],ofb_tmp[8]; -static unsigned char ofb_cipher[24]= - { - 0xf3,0x09,0x62,0x49,0xc7,0xf4,0x6e,0x51, - 0x35,0xf2,0x4a,0x24,0x2e,0xeb,0x3d,0x3f, - 0x3d,0x6d,0x5b,0xe3,0x25,0x5a,0xf8,0xc3 - }; - -DES_LONG cbc_cksum_ret=0xB462FEF7L; -unsigned char cbc_cksum_data[8]={0x1D,0x26,0x93,0x97,0xf7,0xfe,0x62,0xb4}; - -#ifndef NOPROTO -static char *pt(unsigned char *p); -static int cfb_test(int bits, unsigned char *cfb_cipher); -static int cfb64_test(unsigned char *cfb_cipher); -static int ede_cfb64_test(unsigned char *cfb_cipher); -#else -static char *pt(); -static int cfb_test(); -static int cfb64_test(); -static int ede_cfb64_test(); -#endif - -int main(argc,argv) -int argc; -char *argv[]; - { - int i,j,err=0; - des_cblock in,out,outin,iv3; - des_key_schedule ks,ks2,ks3; - unsigned char cbc_in[40]; - unsigned char cbc_out[40]; - DES_LONG cs; - unsigned char cret[8]; - DES_LONG lqret[4]; - int num; - char *str; - - printf("Doing ecb\n"); - for (i=0; i>4)&0xf]; - ret[i*2+1]=f[p[i]&0xf]; - } - ret[16]='\0'; - return(ret); - } - -#ifndef LIBDES_LIT - -static int cfb_test(bits, cfb_cipher) -int bits; -unsigned char *cfb_cipher; - { - des_key_schedule ks; - int i,err=0; - - des_key_sched((C_Block *)cfb_key,ks); - memcpy(cfb_tmp,cfb_iv,sizeof(cfb_iv)); - des_cfb_encrypt(plain,cfb_buf1,bits,(long)sizeof(plain),ks, - (C_Block *)cfb_tmp,DES_ENCRYPT); - if (memcmp(cfb_cipher,cfb_buf1,sizeof(plain)) != 0) - { - err=1; - printf("cfb_encrypt encrypt error\n"); - for (i=0; i<24; i+=8) - printf("%s\n",pt(&(cfb_buf1[i]))); - } - memcpy(cfb_tmp,cfb_iv,sizeof(cfb_iv)); - des_cfb_encrypt(cfb_buf1,cfb_buf2,bits,(long)sizeof(plain),ks, - (C_Block *)cfb_tmp,DES_DECRYPT); - if (memcmp(plain,cfb_buf2,sizeof(plain)) != 0) - { - err=1; - printf("cfb_encrypt decrypt error\n"); - for (i=0; i<24; i+=8) - printf("%s\n",pt(&(cfb_buf1[i]))); - } - return(err); - } - -static int cfb64_test(cfb_cipher) -unsigned char *cfb_cipher; - { - des_key_schedule ks; - int err=0,i,n; - - des_key_sched((C_Block *)cfb_key,ks); - memcpy(cfb_tmp,cfb_iv,sizeof(cfb_iv)); - n=0; - des_cfb64_encrypt(plain,cfb_buf1,(long)12,ks, - (C_Block *)cfb_tmp,&n,DES_ENCRYPT); - des_cfb64_encrypt(&(plain[12]),&(cfb_buf1[12]), - (long)sizeof(plain)-12,ks, - (C_Block *)cfb_tmp,&n,DES_ENCRYPT); - if (memcmp(cfb_cipher,cfb_buf1,sizeof(plain)) != 0) - { - err=1; - printf("cfb_encrypt encrypt error\n"); - for (i=0; i<24; i+=8) - printf("%s\n",pt(&(cfb_buf1[i]))); - } - memcpy(cfb_tmp,cfb_iv,sizeof(cfb_iv)); - n=0; - des_cfb64_encrypt(cfb_buf1,cfb_buf2,(long)17,ks, - (C_Block *)cfb_tmp,&n,DES_DECRYPT); - des_cfb64_encrypt(&(cfb_buf1[17]),&(cfb_buf2[17]), - (long)sizeof(plain)-17,ks, - (C_Block *)cfb_tmp,&n,DES_DECRYPT); - if (memcmp(plain,cfb_buf2,sizeof(plain)) != 0) - { - err=1; - printf("cfb_encrypt decrypt error\n"); - for (i=0; i<24; i+=8) - printf("%s\n",pt(&(cfb_buf2[i]))); - } - return(err); - } - -static int ede_cfb64_test(cfb_cipher) -unsigned char *cfb_cipher; - { - des_key_schedule ks; - int err=0,i,n; - - des_key_sched((C_Block *)cfb_key,ks); - memcpy(cfb_tmp,cfb_iv,sizeof(cfb_iv)); - n=0; - des_ede3_cfb64_encrypt(plain,cfb_buf1,(long)12,ks,ks,ks, - (C_Block *)cfb_tmp,&n,DES_ENCRYPT); - des_ede3_cfb64_encrypt(&(plain[12]),&(cfb_buf1[12]), - (long)sizeof(plain)-12,ks,ks,ks, - (C_Block *)cfb_tmp,&n,DES_ENCRYPT); - if (memcmp(cfb_cipher,cfb_buf1,sizeof(plain)) != 0) - { - err=1; - printf("ede_cfb_encrypt encrypt error\n"); - for (i=0; i<24; i+=8) - printf("%s\n",pt(&(cfb_buf1[i]))); - } - memcpy(cfb_tmp,cfb_iv,sizeof(cfb_iv)); - n=0; - des_ede3_cfb64_encrypt(cfb_buf1,cfb_buf2,(long)17,ks,ks,ks, - (C_Block *)cfb_tmp,&n,DES_DECRYPT); - des_ede3_cfb64_encrypt(&(cfb_buf1[17]),&(cfb_buf2[17]), - (long)sizeof(plain)-17,ks,ks,ks, - (C_Block *)cfb_tmp,&n,DES_DECRYPT); - if (memcmp(plain,cfb_buf2,sizeof(plain)) != 0) - { - err=1; - printf("ede_cfb_encrypt decrypt error\n"); - for (i=0; i<24; i+=8) - printf("%s\n",pt(&(cfb_buf2[i]))); - } - return(err); - } - -#endif - diff --git a/mac/libdes/src/COPYRIGHT b/mac/libdes/src/COPYRIGHT deleted file mode 100755 index 00800d6f..00000000 --- a/mac/libdes/src/COPYRIGHT +++ /dev/null @@ -1 +0,0 @@ -Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) All rights reserved. This package is an DES implementation written by Eric Young (eay@mincom.oz.au). The implementation was written so as to conform with MIT's libdes. This library is free for commercial and non-commercial use as long as the following conditions are aheared to. The following conditions apply to all code found in this distribution. Copyright remains Eric Young's, and as such any Copyright notices in the code are not to be removed. If this package is used in a product, Eric Young should be given attribution as the author of that the SSL library. This can be in the form of a textual message at program startup or in documentation (online or textual) provided with the package. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by Eric Young (eay@mincom.oz.au) THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The license and distribution terms for any publically available version or derivative of this code cannot be changed. i.e. this code cannot simply be copied and put under another distrubution license [including the GNU Public License.] The reason behind this being stated in this direct manner is past experience in code simply being copied and the attribution removed from it and then being distributed as part of other packages. This implementation was a non-trivial and unpaid effort. \ No newline at end of file diff --git a/mac/libdes/src/ChangeLog b/mac/libdes/src/ChangeLog deleted file mode 100755 index 22e97493..00000000 --- a/mac/libdes/src/ChangeLog +++ /dev/null @@ -1 +0,0 @@ -Mon May 25 05:24:56 1998 Assar Westerlund * Makefile.in (clean): try to remove shared library debris Sun Apr 19 09:50:53 1998 Assar Westerlund * Makefile.in: add symlink magic for linux Sun Nov 9 07:14:45 1997 Assar Westerlund * mdtest.c: print out old and new string \ No newline at end of file diff --git a/mac/libdes/src/DES.pm b/mac/libdes/src/DES.pm deleted file mode 100755 index 6a175b6c..00000000 --- a/mac/libdes/src/DES.pm +++ /dev/null @@ -1,19 +0,0 @@ -package DES; - -require Exporter; -require DynaLoader; -@ISA = qw(Exporter DynaLoader); -# Items to export into callers namespace by default -# (move infrequently used names to @EXPORT_OK below) -@EXPORT = qw( -); -# Other items we are prepared to export if requested -@EXPORT_OK = qw( -crypt -); - -# Preloaded methods go here. Autoload methods go after __END__, and are -# processed by the autosplit program. -bootstrap DES; -1; -__END__ diff --git a/mac/libdes/src/DES.pod b/mac/libdes/src/DES.pod deleted file mode 100755 index 2b89e837..00000000 --- a/mac/libdes/src/DES.pod +++ /dev/null @@ -1 +0,0 @@ -crypt <= crypt(buf,salt) key <= set_odd_parity(key) int <= is_weak_key(key) keysched<= set_key(key) key <= ecb_encrypt(string8,ks,enc) key <= ecb3_encrypt(input,ks1,ks2,enc) string <= cbc_encrypt(input,ks,ivec,enc) => ivec string <= cbc3_encrypt(input,ks1,ks2,ivec1,ivec2,enc) => ivec1&ivec2 ck1,ck2 <= cbc_cksum(input,ks,ivec) => ivec string <= pcbc_encrypt(input,ks,ivec,enc) => ivec string <= ofb_encrypt(input,numbits,ks,ivec) => ivec string <= cfb_encrypt(input,numbits,ks,ivec,enc) => ivec key <= random_key() key <= string_to_key(string) key1,key2<= string_to_2keys(string) \ No newline at end of file diff --git a/mac/libdes/src/DES.xs b/mac/libdes/src/DES.xs deleted file mode 100755 index 51917194..00000000 --- a/mac/libdes/src/DES.xs +++ /dev/null @@ -1 +0,0 @@ -#include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include "des.h" #define deschar char static STRLEN len; static int not_here(s) char *s; { croak("%s not implemented on this architecture", s); return -1; } MODULE = DES PACKAGE = DES PREFIX = des_ char * des_crypt(buf,salt) char * buf char * salt void des_set_odd_parity(key) des_cblock * key PPCODE: { SV *s; s=sv_newmortal(); sv_setpvn(s,(char *)key,8); des_set_odd_parity((des_cblock *)SvPV(s,na)); PUSHs(s); } int des_is_weak_key(key) des_cblock * key des_key_schedule des_set_key(key) des_cblock * key CODE: des_set_key(key,RETVAL); OUTPUT: RETVAL des_cblock des_ecb_encrypt(input,ks,encrypt) des_cblock * input des_key_schedule * ks int encrypt CODE: des_ecb_encrypt(input,&RETVAL,*ks,encrypt); OUTPUT: RETVAL void des_cbc_encrypt(input,ks,ivec,encrypt) char * input des_key_schedule * ks des_cblock * ivec int encrypt PPCODE: { SV *s; STRLEN len,l; char *c; l=SvCUR(ST(0)); len=((((unsigned long)l)+7)/8)*8; s=sv_newmortal(); sv_setpvn(s,"",0); SvGROW(s,len); SvCUR_set(s,len); c=(char *)SvPV(s,na); des_cbc_encrypt((des_cblock *)input,(des_cblock *)c, l,*ks,ivec,encrypt); sv_setpvn(ST(2),(char *)c[len-8],8); PUSHs(s); } void des_cbc3_encrypt(input,ks1,ks2,ivec1,ivec2,encrypt) char * input des_key_schedule * ks1 des_key_schedule * ks2 des_cblock * ivec1 des_cblock * ivec2 int encrypt PPCODE: { SV *s; STRLEN len,l; l=SvCUR(ST(0)); len=((((unsigned long)l)+7)/8)*8; s=sv_newmortal(); sv_setpvn(s,"",0); SvGROW(s,len); SvCUR_set(s,len); des_3cbc_encrypt((des_cblock *)input,(des_cblock *)SvPV(s,na), l,*ks1,*ks2,ivec1,ivec2,encrypt); sv_setpvn(ST(3),(char *)ivec1,8); sv_setpvn(ST(4),(char *)ivec2,8); PUSHs(s); } void des_cbc_cksum(input,ks,ivec) char * input des_key_schedule * ks des_cblock * ivec PPCODE: { SV *s1,*s2; STRLEN len,l; des_cblock c; unsigned long i1,i2; s1=sv_newmortal(); s2=sv_newmortal(); l=SvCUR(ST(0)); des_cbc_cksum((des_cblock *)input,(des_cblock *)c, l,*ks,ivec); i1=c[4]|(c[5]<<8)|(c[6]<<16)|(c[7]<<24); i2=c[0]|(c[1]<<8)|(c[2]<<16)|(c[3]<<24); sv_setiv(s1,i1); sv_setiv(s2,i2); sv_setpvn(ST(2),(char *)c,8); PUSHs(s1); PUSHs(s2); } void des_cfb_encrypt(input,numbits,ks,ivec,encrypt) char * input int numbits des_key_schedule * ks des_cblock * ivec int encrypt PPCODE: { SV *s; STRLEN len; char *c; len=SvCUR(ST(0)); s=sv_newmortal(); sv_setpvn(s,"",0); SvGROW(s,len); SvCUR_set(s,len); c=(char *)SvPV(s,na); des_cfb_encrypt((unsigned char *)input,(unsigned char *)c, (int)numbits,(long)len,*ks,ivec,encrypt); sv_setpvn(ST(3),(char *)ivec,8); PUSHs(s); } des_cblock * des_ecb3_encrypt(input,ks1,ks2,encrypt) des_cblock * input des_key_schedule * ks1 des_key_schedule * ks2 int encrypt CODE: { des_cblock c; des_3ecb_encrypt((des_cblock *)input,(des_cblock *)&c, *ks1,*ks2,encrypt); RETVAL= &c; } OUTPUT: RETVAL void des_ofb_encrypt(input,numbits,ks,ivec) unsigned char * input int numbits des_key_schedule * ks des_cblock * ivec PPCODE: { SV *s; STRLEN len,l; unsigned char *c; len=SvCUR(ST(0)); s=sv_newmortal(); sv_setpvn(s,"",0); SvGROW(s,len); SvCUR_set(s,len); c=(unsigned char *)SvPV(s,na); des_ofb_encrypt((unsigned char *)input,(unsigned char *)c, numbits,len,*ks,ivec); sv_setpvn(ST(3),(char *)ivec,8); PUSHs(s); } void des_pcbc_encrypt(input,ks,ivec,encrypt) char * input des_key_schedule * ks des_cblock * ivec int encrypt PPCODE: { SV *s; STRLEN len,l; char *c; l=SvCUR(ST(0)); len=((((unsigned long)l)+7)/8)*8; s=sv_newmortal(); sv_setpvn(s,"",0); SvGROW(s,len); SvCUR_set(s,len); c=(char *)SvPV(s,na); des_pcbc_encrypt((des_cblock *)input,(des_cblock *)c, l,*ks,ivec,encrypt); sv_setpvn(ST(2),(char *)c[len-8],8); PUSHs(s); } des_cblock * des_random_key() CODE: { des_cblock c; des_random_key(c); RETVAL=&c; } OUTPUT: RETVAL des_cblock * des_string_to_key(str) char * str CODE: { des_cblock c; des_string_to_key(str,&c); RETVAL=&c; } OUTPUT: RETVAL void des_string_to_2keys(str) char * str PPCODE: { des_cblock c1,c2; SV *s1,*s2; des_string_to_2keys(str,&c1,&c2); EXTEND(sp,2); s1=sv_newmortal(); sv_setpvn(s1,(char *)c1,8); s2=sv_newmortal(); sv_setpvn(s2,(char *)c2,8); PUSHs(s1); PUSHs(s2); } \ No newline at end of file diff --git a/mac/libdes/src/FILES b/mac/libdes/src/FILES deleted file mode 100755 index 2fb0071d..00000000 --- a/mac/libdes/src/FILES +++ /dev/null @@ -1 +0,0 @@ -/* General stuff */ COPYRIGHT - Copyright info. MODES.DES - A description of the features of the different modes of DES. FILES - This file. INSTALL - How to make things compile. Imakefile - For use with kerberos. README - What this package is. VERSION - Which version this is and what was changed. KERBEROS - Kerberos version 4 notes. Makefile.PL - An old makefile to build with perl5, not current. Makefile.ssl - The SSLeay makefile Makefile.uni - The normal unix makefile. GNUmakefile - The makefile for use with glibc. makefile.bc - A Borland C makefile times - Some outputs from 'speed' on some machines. vms.com - For use when compiling under VMS /* My SunOS des(1) replacement */ des.c - des(1) source code. des.man - des(1) manual. /* Testing and timing programs. */ destest.c - Source for libdes.a test program. speed.c - Source for libdes.a timing program. rpw.c - Source for libdes.a testing password reading routines. /* libdes.a source code */ des_crypt.man - libdes.a manual page. des.h - Public libdes.a header file. ecb_enc.c - des_ecb_encrypt() source, this contains the basic DES code. ecb3_enc.c - des_ecb3_encrypt() source. cbc_ckm.c - des_cbc_cksum() source. cbc_enc.c - des_cbc_encrypt() source. ncbc_enc.c - des_cbc_encrypt() that is 'normal' in that it copies the new iv values back in the passed iv vector. ede_enc.c - des_ede3_cbc_encrypt() cbc mode des using triple DES. cbc3_enc.c - des_3cbc_encrypt() source, don't use this function. cfb_enc.c - des_cfb_encrypt() source. cfb64enc.c - des_cfb64_encrypt() cfb in 64 bit mode but setup to be used as a stream cipher. cfb64ede.c - des_ede3_cfb64_encrypt() cfb in 64 bit mode but setup to be used as a stream cipher and using triple DES. ofb_enc.c - des_cfb_encrypt() source. ofb64_enc.c - des_ofb_encrypt() ofb in 64 bit mode but setup to be used as a stream cipher. ofb64ede.c - des_ede3_ofb64_encrypt() ofb in 64 bit mode but setup to be used as a stream cipher and using triple DES. enc_read.c - des_enc_read() source. enc_writ.c - des_enc_write() source. pcbc_enc.c - des_pcbc_encrypt() source. qud_cksm.c - quad_cksum() source. rand_key.c - des_random_key() source. read_pwd.c - Source for des_read_password() plus related functions. set_key.c - Source for des_set_key(). str2key.c - Covert a string of any length into a key. fcrypt.c - A small, fast version of crypt(3). des_locl.h - Internal libdes.a header file. podd.h - Odd parity tables - used in des_set_key(). sk.h - Lookup tables used in des_set_key(). spr.h - What is left of the S tables - used in ecb_encrypt(). des_ver.h - header file for the external definition of the version string. des.doc - SSLeay documentation for the library. /* The perl scripts - you can ignore these files they are only * included for the curious */ des.pl - des in perl anyone? des_set_key and des_ecb_encrypt both done in a perl library. testdes.pl - Testing program for des.pl doIP - Perl script used to develop IP xor/shift code. doPC1 - Perl script used to develop PC1 xor/shift code. doPC2 - Generates sk.h. PC1 - Output of doPC1 should be the same as output from PC1. PC2 - used in development of doPC2. shifts.pl - Perl library used by my perl scripts. /* I started making a perl5 dynamic library for libdes * but did not fully finish, these files are part of that effort. */ DES.pm DES.pod DES.xs t typemap /* The following are for use with sun RPC implementaions. */ rpc_des.h rpc_enc.c /* The following are contibuted by Mark Murray . They * are not normally built into libdes due to machine specific routines * contained in them. They are for use in the most recent incarnation of * export kerberos v 4 (eBones). */ supp.c new_rkey.c \ No newline at end of file diff --git a/mac/libdes/src/INSTALL b/mac/libdes/src/INSTALL deleted file mode 100755 index c07b1590..00000000 --- a/mac/libdes/src/INSTALL +++ /dev/null @@ -1 +0,0 @@ -Check the CC and CFLAGS lines in the makefile If your C library does not support the times(3) function, change the #define TIMES to #undef TIMES in speed.c If it does, check the HZ value for the times(3) function. If your system does not define CLK_TCK it will be assumed to be 100.0. If possible use gcc v 2.7.? Turn on the maximum optimising (normally '-O3 -fomit-frame-pointer' for gcc) In recent times, some system compilers give better performace. type 'make' run './destest' to check things are ok. run './rpw' to check the tty code for reading passwords works. run './speed' to see how fast those optimisations make the library run :-) run './des_opts' to determin the best compile time options. The output from des_opts should be put in the makefile options and des_enc.c should be rebuilt. For 64 bit computers, do not use the DES_PTR option. For the DEC Alpha, edit des.h and change DES_LONG to 'unsigned int' and then you can use the 'DES_PTR' option. The file options.txt has the options listed for best speed on quite a few systems. Look and the options (UNROLL, PTR, RISC2 etc) and then turn on the relevent option in the Makefile There are some special Makefile targets that make life easier. make cc - standard cc build make gcc - standard gcc build make x86-elf - x86 assember (elf), linux-elf. make x86-out - x86 assember (a.out), FreeBSD make x86-solaris- x86 assember make x86-bsdi - x86 assember (a.out with primative assember). If at all possible use the assember (for Windows NT/95, use asm/win32.obj to link with). The x86 assember is very very fast. A make install will by default install libdes.a in /usr/local/lib/libdes.a des in /usr/local/bin/des des_crypt.man in /usr/local/man/man3/des_crypt.3 des.man in /usr/local/man/man1/des.1 des.h in /usr/include/des.h des(1) should be compatible with sunOS's but I have been unable to test it. These routines should compile on MSDOS, most 32bit and 64bit version of Unix (BSD and SYSV) and VMS, without modification. The only problems should be #include files that are in the wrong places. These routines can be compiled under MSDOS. I have successfully encrypted files using des(1) under MSDOS and then decrypted the files on a SparcStation. I have been able to compile and test the routines with Microsoft C v 5.1 and Turbo C v 2.0. The code in this library is in no way optimised for the 16bit operation of MSDOS. When building for glibc, ignore all of the above and just unpack into glibc-1.??/des and then gmake as per normal. As a final note on performace. Certain CPUs like sparcs and Alpha often give a %10 speed difference depending on the link order. It is rather anoying when one program reports 'x' DES encrypts a second and another reports 'x*0.9' the speed. \ No newline at end of file diff --git a/mac/libdes/src/Imakefile b/mac/libdes/src/Imakefile deleted file mode 100755 index 9d74a35f..00000000 --- a/mac/libdes/src/Imakefile +++ /dev/null @@ -1 +0,0 @@ -# This Imakefile has not been tested for a while but it should still # work when placed in the correct directory in the kerberos v 4 distribution SRCS= cbc_cksm.c cbc_enc.c ecb_enc.c pcbc_enc.c \ qud_cksm.c rand_key.c read_pwd.c set_key.c str2key.c \ enc_read.c enc_writ.c fcrypt.c cfb_enc.c \ ecb3_enc.c ofb_enc.c ofb64enc.c OBJS= cbc_cksm.o cbc_enc.o ecb_enc.o pcbc_enc.o \ qud_cksm.o rand_key.o read_pwd.o set_key.o str2key.o \ enc_read.o enc_writ.o fcrypt.o cfb_enc.o \ ecb3_enc.o ofb_enc.o ofb64enc.o GENERAL=COPYRIGHT FILES INSTALL Imakefile README VERSION makefile times \ vms.com KERBEROS DES= des.c des.man TESTING=destest.c speed.c rpw.c LIBDES= des_crypt.man des.h des_locl.h podd.h sk.h spr.h PERL= des.pl testdes.pl doIP doPC1 doPC2 PC1 PC2 shifts.pl CODE= $(GENERAL) $(DES) $(TESTING) $(SRCS) $(LIBDES) $(PERL) SRCDIR=$(SRCTOP)/lib/des DBG= -O INCLUDE= -I$(SRCDIR) CC= cc library_obj_rule() install_library_target(des,$(OBJS),$(SRCS),) test(destest,libdes.a,) test(rpw,libdes.a,) \ No newline at end of file diff --git a/mac/libdes/src/KERBEROS b/mac/libdes/src/KERBEROS deleted file mode 100755 index db3bfe4b..00000000 --- a/mac/libdes/src/KERBEROS +++ /dev/null @@ -1 +0,0 @@ - [ This is an old file, I don't know if it is true anymore but I will leave the file here - eay 21/11/95 ] To use this library with Bones (kerberos without DES): 1) Get my modified Bones - eBones. It can be found on gondwana.ecr.mu.oz.au (128.250.1.63) /pub/athena/eBones-p9.tar.Z and nic.funet.fi (128.214.6.100) /pub/unix/security/Kerberos/eBones-p9.tar.Z 2) Unpack this library in src/lib/des, makeing sure it is version 3.00 or greater (libdes.tar.93-10-07.Z). This versions differences from the version in comp.sources.misc volume 29 patchlevel2. The primarily difference is that it should compile under kerberos :-). It can be found at. ftp.psy.uq.oz.au (130.102.32.1) /pub/DES/libdes.tar.93-10-07.Z Now do a normal kerberos build and things should work. One problem I found when I was build on my local sun. --- For sunOS 4.1.1 apply the following patch to src/util/ss/make_commands.c *** make_commands.c.orig Fri Jul 3 04:18:35 1987 --- make_commands.c Wed May 20 08:47:42 1992 *************** *** 98,104 **** if (!rename(o_file, z_file)) { if (!vfork()) { chdir("/tmp"); ! execl("/bin/ld", "ld", "-o", o_file+5, "-s", "-r", "-n", z_file+5, 0); perror("/bin/ld"); _exit(1); --- 98,104 ---- if (!rename(o_file, z_file)) { if (!vfork()) { chdir("/tmp"); ! execl("/bin/ld", "ld", "-o", o_file+5, "-s", "-r", z_file+5, 0); perror("/bin/ld"); _exit(1); \ No newline at end of file diff --git a/mac/libdes/src/MODES.DES b/mac/libdes/src/MODES.DES deleted file mode 100755 index 63b0eb20..00000000 --- a/mac/libdes/src/MODES.DES +++ /dev/null @@ -1 +0,0 @@ -Modes of DES Quite a bit of the following information has been taken from AS 2805.5.2 Australian Standard Electronic funds transfer - Requirements for interfaces, Part 5.2: Modes of operation for an n-bit block cipher algorithm Appendix A There are several different modes in which DES can be used, they are as follows. Electronic Codebook Mode (ECB) (des_ecb_encrypt()) - 64 bits are enciphered at a time. - The order of the blocks can be rearranged without detection. - The same plaintext block always produces the same ciphertext block (for the same key) making it vulnerable to a 'dictionary attack'. - An error will only affect one ciphertext block. Cipher Block Chaining Mode (CBC) (des_cbc_encrypt()) - a multiple of 64 bits are enciphered at a time. - The CBC mode produces the same ciphertext whenever the same plaintext is encrypted using the same key and starting variable. - The chaining operation makes the ciphertext blocks dependent on the current and all preceding plaintext blocks and therefore blocks can not be rearranged. - The use of different starting variables prevents the same plaintext enciphering to the same ciphertext. - An error will affect the current and the following ciphertext blocks. Cipher Feedback Mode (CFB) (des_cfb_encrypt()) - a number of bits (j) <= 64 are enciphered at a time. - The CFB mode produces the same ciphertext whenever the same plaintext is encrypted using the same key and starting variable. - The chaining operation makes the ciphertext variables dependent on the current and all preceding variables and therefore j-bit variables are chained together and con not be rearranged. - The use of different starting variables prevents the same plaintext enciphering to the same ciphertext. - The strength of the CFB mode depends on the size of k (maximal if j == k). In my implementation this is always the case. - Selection of a small value for j will require more cycles through the encipherment algorithm per unit of plaintext and thus cause greater processing overheads. - Only multiples of j bits can be enciphered. - An error will affect the current and the following ciphertext variables. Output Feedback Mode (OFB) (des_ofb_encrypt()) - a number of bits (j) <= 64 are enciphered at a time. - The OFB mode produces the same ciphertext whenever the same plaintext enciphered using the same key and starting variable. More over, in the OFB mode the same key stream is produced when the same key and start variable are used. Consequently, for security reasons a specific start variable should be used only once for a given key. - The absence of chaining makes the OFB more vulnerable to specific attacks. - The use of different start variables values prevents the same plaintext enciphering to the same ciphertext, by producing different key streams. - Selection of a small value for j will require more cycles through the encipherment algorithm per unit of plaintext and thus cause greater processing overheads. - Only multiples of j bits can be enciphered. - OFB mode of operation does not extend ciphertext errors in the resultant plaintext output. Every bit error in the ciphertext causes only one bit to be in error in the deciphered plaintext. - OFB mode is not self-synchronising. If the two operation of encipherment and decipherment get out of synchronism, the system needs to be re-initialised. - Each re-initialisation should use a value of the start variable different from the start variable values used before with the same key. The reason for this is that an identical bit stream would be produced each time from the same parameters. This would be susceptible to a 'known plaintext' attack. Triple ECB Mode (des_3ecb_encrypt()) - Encrypt with key1, decrypt with key2 and encrypt with key1 again. - As for ECB encryption but increases the effective key length to 112 bits. - If both keys are the same it is equivalent to encrypting once with just one key. Triple CBC Mode (des_3cbc_encrypt()) - Encrypt with key1, decrypt with key2 and encrypt with key1 again. - As for CBC encryption but increases the effective key length to 112 bits. - If both keys are the same it is equivalent to encrypting once with just one key. \ No newline at end of file diff --git a/mac/libdes/src/Makefile.PL b/mac/libdes/src/Makefile.PL deleted file mode 100755 index d68b89d3..00000000 --- a/mac/libdes/src/Makefile.PL +++ /dev/null @@ -1 +0,0 @@ -use ExtUtils::MakeMaker; # See lib/ExtUtils/MakeMaker.pm for details of how to influence # the contents of the Makefile being created. &writeMakefile( 'potential_libs' => '', # e.g., '-lm' 'INC' => '', # e.g., '-I/usr/include/other' 'DISTNAME' => 'DES', 'VERSION' => '0.1', 'DEFINE' => '-DPERL5', 'OBJECT' => 'DES.o cbc_cksm.o cbc_enc.o ecb_enc.o pcbc_enc.o \ rand_key.o set_key.o str2key.o \ enc_read.o enc_writ.o fcrypt.o cfb_enc.o \ ecb3_enc.o ofb_enc.o cbc3_enc.o des_enc.o', ); \ No newline at end of file diff --git a/mac/libdes/src/Makefile.am b/mac/libdes/src/Makefile.am deleted file mode 100755 index 82fd07f6..00000000 --- a/mac/libdes/src/Makefile.am +++ /dev/null @@ -1 +0,0 @@ -# $Id: Makefile.am,v 1.2 2001/12/04 02:06:26 rjs3 Exp $ AUTOMAKE_OPTIONS = no-dependencies foreign INCLUDES = -I$(top_builddir)/include #lib_LIBRARIES = libdes.a lib_LTLIBRARIES = libdes.la include_HEADERS = des.h noinst_PROGRAMS = destest mdtest bin_PROGRAMS = des rpw speed LDADD = $(lib_LTLIBRARIES) libdes_la_SOURCES = \ cbc3_enc.c cbc_cksm.c cbc_enc.c \ cfb64ede.c cfb64enc.c cfb_enc.c des_enc.c \ ecb3_enc.c ecb_enc.c ede_enc.c enc_read.c \ enc_writ.c fcrypt.c key_par.c md4.c md5.c \ ncbc_enc.c ofb64ede.c ofb64enc.c ofb_enc.c \ pcbc_enc.c qud_cksm.c read_pwd.c rnd_keys.c \ set_key.c sha.c str2key.c xcbc_enc.c \ No newline at end of file diff --git a/mac/libdes/src/Makefile.in b/mac/libdes/src/Makefile.in deleted file mode 100755 index cf16b251..00000000 --- a/mac/libdes/src/Makefile.in +++ /dev/null @@ -1 +0,0 @@ -# # $Id: Makefile.in,v 1.2 2001/12/04 02:06:26 rjs3 Exp $ # SHELL = /bin/sh srcdir = @srcdir@ VPATH = @srcdir@ CC = @CC@ LINK = @LINK@ AR = ar RANLIB = @RANLIB@ LN_S = @LN_S@ DEFS = @DEFS@ CFLAGS = @CFLAGS@ LD_FLAGS = @LD_FLAGS@ LDSHARED = @LDSHARED@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ MKINSTALLDIRS = @top_srcdir@/mkinstalldirs prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ libdir = @libdir@ transform=@program_transform_name@ EXECSUFFIX=@EXECSUFFIX@ PICFLAGS = @PICFLAGS@ LIB_DEPS = @lib_deps_yes@ -lc build_symlink_command = @build_symlink_command@ install_symlink_command = @install_symlink_command@ PROGS = destest$(EXECSUFFIX) \ mdtest$(EXECSUFFIX) \ des$(EXECSUFFIX) \ rpw$(EXECSUFFIX) \ speed$(EXECSUFFIX) PROGS2INSTALL = des$(EXECSUFFIX) LIBNAME = $(LIBPREFIX)des LIBEXT = @LIBEXT@ LIBPREFIX = @LIBPREFIX@ SHLIBEXT = @SHLIBEXT@ LIB = $(LIBNAME).$(LIBEXT) # Generated with lorder *.o | tsort | xargs echo LIBSRC = xcbc_enc.c sha.c rnd_keys.c read_pwd.c qud_cksm.c pcbc_enc.c \ ofb_enc.c ofb64enc.c ofb64ede.c ncbc_enc.c md4.c key_par.c fcrypt.c \ ede_enc.c ecb3_enc.c cfb_enc.c cfb64enc.c cfb64ede.c cbc3_enc.c \ str2key.c set_key.c md5.c cbc_enc.c cbc_cksm.c ecb_enc.c des_enc.c LIBOBJ = xcbc_enc.o sha.o rnd_keys.o read_pwd.o qud_cksm.o pcbc_enc.o \ ofb_enc.o ofb64enc.o ofb64ede.o ncbc_enc.o md4.o key_par.o fcrypt.o \ ede_enc.o ecb3_enc.o cfb_enc.o cfb64enc.o cfb64ede.o cbc3_enc.o \ str2key.o set_key.o md5.o cbc_enc.o cbc_cksm.o ecb_enc.o des_enc.o all: $(LIB) $(PROGS) Wall: make CFLAGS="-g -Wall -Wno-comment -Wmissing-prototypes -Wmissing-declarations -D__USE_FIXED_PROTOTYPES__" COM = $(CC) -c $(CPPFLAGS) $(DEFS) -I../../include -I$(srcdir) $(PICFLAGS) .c.o: $(COM) $(CFLAGS) $< # Compile this file without debug if using gcc des_enc.o: des_enc.c @if test "$(CC)" = gcc; then\ echo "$(COM) -fomit-frame-pointer -O3 $(srcdir)/des_enc.c"; \ $(COM) -fomit-frame-pointer -O3 $(srcdir)/des_enc.c; \ else \ echo "$(COM) $(CFLAGS) $(srcdir)/des_enc.c"; \ $(COM) $(CFLAGS) $(srcdir)/des_enc.c; \ fi install: all $(MKINSTALLDIRS) $(DESTDIR)$(libdir) $(INSTALL_DATA) -m 0555 $(LIB) $(DESTDIR)$(libdir)/$(LIB) @install_symlink_command@ $(MKINSTALLDIRS) $(DESTDIR)$(bindir) for x in $(PROGS2INSTALL); do \ $(INSTALL_PROGRAM) $$x $(DESTDIR)$(bindir)/`echo $$x | sed '$(transform)'`; \ done uninstall: rm -f $(DESTDIR)$(libdir)/$(LIB) for x in $(PROGS2INSTALL); do \ rm -f $(DESTDIR)$(bindir)/`echo $$x | sed '$(transform)'`; \ done TAGS: $(LIBSRC) etags $(LIBSRC) check: destest$(EXECSUFFIX) mdtest$(EXECSUFFIX) ./destest$(EXECSUFFIX) ./mdtest$(EXECSUFFIX) clean: rm -f $(LIB) *.so *.so.* so_locations *.o *.a $(PROGS) mostlyclean: clean distclean: clean rm -f Makefile *.tab.c *~ realclean: distclean rm -f TAGS $(LIBNAME).a: $(LIBOBJ) rm -f $@ $(AR) cr $@ $(LIBOBJ) -$(RANLIB) $@ $(LIBNAME).$(SHLIBEXT): $(LIBOBJ) rm -f $@ $(LDSHARED) -o $@ $(LIBOBJ) $(LIB_DEPS) @build_symlink_command@ # To make psoriaris make happy we have to mention these files in some # rule, so we might as well put them here. mdtest.o: mdtest.c des_opts.o: des_opts.c destest.o: destest.c des.o: des.c rpw.o: rpw.c speed.o: speed.c mdtest$(EXECSUFFIX): mdtest.o $(LIB) $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ mdtest.o -L. -ldes des_opts$(EXECSUFFIX): des_opts.o set_key.o $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ des_opts.o set_key.o destest$(EXECSUFFIX): destest.o $(LIB) $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ destest.o -L. -ldes des$(EXECSUFFIX): des.o $(LIB) $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ des.o -L. -ldes rpw$(EXECSUFFIX): rpw.o $(LIB) $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ rpw.o -L. -ldes speed$(EXECSUFFIX): speed.o $(LIB) $(LINK) $(LD_FLAGS) $(LDFLAGS) -o $@ speed.o -L. -ldes $(LIBOBJ): ../../include/config.h .PHONY: all Wall install uninstall check clean mostlyclean distclean realclean \ No newline at end of file diff --git a/mac/libdes/src/Makefile.ssl b/mac/libdes/src/Makefile.ssl deleted file mode 100755 index 68e76a6b..00000000 --- a/mac/libdes/src/Makefile.ssl +++ /dev/null @@ -1 +0,0 @@ -# # SSLeay/crypto/des/Makefile # DIR= des TOP= ../.. CC= cc CPP= cc -E INCLUDES= CFLAG=-g INSTALLTOP=/usr/local/ssl MAKE= make -f Makefile.ssl MAKEDEPEND= makedepend -fMakefile.ssl MAKEFILE= Makefile.ssl DES_ENC= des_enc.o CFLAGS= $(INCLUDES) $(CFLAG) GENERAL=Makefile des.org des_locl.org TEST=destest.c APPS= LIB=$(TOP)/libcrypto.a LIBSRC= cbc3_enc.c cbc_cksm.c cbc_enc.c cfb64enc.c cfb_enc.c \ ecb3_enc.c ecb_enc.c ede_enc.c enc_read.c enc_writ.c \ fcrypt.c ncbc_enc.c ofb64enc.c ofb_enc.c pcbc_enc.c \ qud_cksm.c rand_key.c read_pwd.c rpc_enc.c set_key.c \ xcbc_enc.c des_enc.c \ str2key.c cfb64ede.c ofb64ede.c supp.c LIBOBJ= set_key.o ecb_enc.o ede_enc.o cbc_enc.o cbc3_enc.o \ ecb3_enc.o cfb64enc.o cfb64ede.o cfb_enc.o ofb64ede.o \ enc_read.o enc_writ.o fcrypt.o ncbc_enc.o ofb64enc.o \ ofb_enc.o str2key.o pcbc_enc.o qud_cksm.o rand_key.o \ xcbc_enc.o ${DES_ENC} \ read_pwd.o rpc_enc.o cbc_cksm.o supp.o SRC= $(LIBSRC) EXHEADER= des.h HEADER= des_locl.h rpc_des.h podd.h sk.h spr.h des_ver.h $(EXHEADER) ALL= $(GENERAL) $(SRC) $(HEADER) top: (cd ../..; $(MAKE) DIRS=crypto SDIRS=$(DIR) sub_all) all: lib lib: $(LIBOBJ) ar r $(LIB) $(LIBOBJ) sh $(TOP)/util/ranlib.sh $(LIB) @touch lib asm/dx86-elf.o: asm/dx86-cpp.s asm/dx86unix.cpp $(CPP) -DELF asm/dx86unix.cpp | as -o asm/dx86-elf.o asm/dx86-sol.o: asm/dx86-cpp.s asm/dx86unix.cpp $(CPP) -DSOL asm/dx86unix.cpp | as -o asm/dx86-sol.o asm/dx86-out.o: asm/dx86-cpp.s asm/dx86unix.cpp $(CPP) -DOUT asm/dx86unix.cpp | as -o asm/dx86-out.o asm/dx86bsdi.o: asm/dx86-cpp.s asm/dx86unix.cpp $(CPP) -DBSDI asm/dx86unix.cpp | as -o asm/dx86bsdi.o files: perl $(TOP)/util/files.pl Makefile.ssl >> $(TOP)/MINFO links: /bin/rm -f Makefile $(TOP)/util/point.sh Makefile.ssl Makefile ; /bin/rm -f des.doc $(TOP)/util/point.sh ../../doc/des.doc des.doc ; $(TOP)/util/mklink.sh ../../include $(EXHEADER) $(TOP)/util/mklink.sh ../../test $(TEST) $(TOP)/util/mklink.sh ../../apps $(APPS) install: installs installs: @for i in $(EXHEADER) ; \ do \ (cp $$i $(INSTALLTOP)/include/$$i; \ chmod 644 $(INSTALLTOP)/include/$$i ) \ done; tags: ctags $(SRC) tests: lint: lint -DLINT $(INCLUDES) $(SRC)>fluff depend: $(MAKEDEPEND) $(INCLUDES) $(PROGS) $(LIBSRC) dclean: perl -pe 'if (/^# DO NOT DELETE THIS LINE/) {print; exit(0);}' $(MAKEFILE) >Makefile.new mv -f Makefile.new $(MAKEFILE) clean: /bin/rm -f *.o asm/*.o *.obj lib tags core .pure .nfs* *.old *.bak fluff errors: # DO NOT DELETE THIS LINE -- make depend depends on it. \ No newline at end of file diff --git a/mac/libdes/src/Makefile.uni b/mac/libdes/src/Makefile.uni deleted file mode 100755 index 16787a75..00000000 --- a/mac/libdes/src/Makefile.uni +++ /dev/null @@ -1 +0,0 @@ -# You must select the correct terminal control system to be used to # turn character echo off when reading passwords. There a 5 systems # SGTTY - the old BSD system # TERMIO - most system V boxes # TERMIOS - SGI (ala IRIX). # VMS - the DEC operating system # MSDOS - we all know what it is :-) # read_pwd.c makes a reasonable guess at what is correct. # If you are on a DEC Alpha, edit des.h and change the DES_LONG # define to 'unsigned int'. I have seen this give a %20 speedup. OPTS0= -DRAND -DTERMIO #-DNOCONST # Version 1.94 has changed the strings_to_key function so that it is # now compatible with MITs when the string is longer than 8 characters. # If you wish to keep the old version, uncomment the following line. # This will affect the -E/-D options on des(1). #OPTS1= -DOLD_STR_TO_KEY # There are 4 possible performance options # -DDES_PTR # -DDES_RISC1 # -DDES_RISC2 (only one of DES_RISC1 and DES_RISC2) # -DDES_UNROLL # after the initial build, run 'des_opts' to see which options are best # for your platform. There are some listed in options.txt #OPTS2= -DDES_PTR #OPTS3= -DDES_RISC1 # or DES_RISC2 OPTS4= -DDES_UNROLL OPTS= $(OPTS0) $(OPTS1) $(OPTS2) $(OPTS3) $(OPTS4) CC=cc CFLAGS= -D_HPUX_SOURCE -Aa +O2 $(OPTS) $(CFLAG) #CC=gcc #CFLAGS= -O3 -fomit-frame-pointer $(OPTS) $(CFLAG) CPP=$(CC) -E DES_ENC=des_enc.o # normal C version #DES_ENC=asm/dx86-elf.o # elf format x86 #DES_ENC=asm/dx86-out.o # a.out format x86 #DES_ENC=asm/dx86-sol.o # solaris format x86 #DES_ENC=asm/dx86bsdi.o # bsdi format x86 LIBDIR=/usr/local/lib BINDIR=/usr/local/bin INCDIR=/usr/local/include MANDIR=/usr/local/man MAN1=1 MAN3=3 SHELL=/bin/sh OBJS= cbc3_enc.o cbc_cksm.o cbc_enc.o ncbc_enc.o pcbc_enc.o qud_cksm.o \ cfb64ede.o cfb64enc.o cfb_enc.o ecb3_enc.o ecb_enc.o ede_enc.o \ enc_read.o enc_writ.o fcrypt.o ofb64ede.o ofb64enc.o ofb_enc.o \ rand_key.o read_pwd.o set_key.o rpc_enc.o str2key.o supp.o \ $(DES_ENC) xcbc_enc.o GENERAL=$(GENERAL_LIT) FILES Imakefile times vms.com KERBEROS MODES.DES \ GNUmakefile des.man DES.pm DES.pod DES.xs Makefile.PL \ Makefile.uni typemap t Makefile.ssl makefile.bc Makefile.lit \ des.org des_locl.org DES= des.c TESTING=rpw.c $(TESTING_LIT) HEADERS= $(HEADERS_LIT) rpc_des.h LIBDES= cbc_cksm.c pcbc_enc.c qud_cksm.c \ cfb64ede.c cfb64enc.c cfb_enc.c ecb3_enc.c cbc3_enc.c \ enc_read.c enc_writ.c ofb64ede.c ofb64enc.c ofb_enc.c \ rand_key.c rpc_enc.c str2key.c supp.c \ xcbc_enc.c $(LIBDES_LIT) read_pwd.c TESTING_LIT=destest.c speed.c des_opts.c GENERAL_LIT=COPYRIGHT INSTALL README VERSION Makefile des_crypt.man \ des.doc options.txt asm HEADERS_LIT=des_ver.h des.h des_locl.h podd.h sk.h spr.h LIBDES_LIT=ede_enc.c cbc_enc.c ncbc_enc.c ecb_enc.c fcrypt.c set_key.c des_enc.c PERL= des.pl testdes.pl doIP doIP2 doPC1 doPC2 PC1 PC2 shifts.pl ALL= $(GENERAL) $(DES) $(TESTING) $(LIBDES) $(PERL) $(HEADERS) DLIB= libdes.a all: $(DLIB) destest rpw des speed des_opts cc: make CC=cc CFLAGS="-O $(OPTS) $(CFLAG)" all gcc: make CC=gcc CFLAGS="-O3 -fomit-frame-pointer $(OPTS) $(CFLAG)" all x86-elf: make DES_ENC=asm/dx86-elf.o CC=gcc CFLAGS="-DELF -O3 -fomit-frame-pointer $(OPTS) $(CFLAG)" all x86-out: make DES_ENC=asm/dx86-out.o CC=gcc CFLAGS="-DOUT -O3 -fomit-frame-pointer $(OPTS) $(CFLAG)" all x86-solaris: make DES_ENC=asm/dx86-sol.o CFLAGS="-DSOL -O $(OPTS) $(CFLAG)" all x86-bsdi: make DES_ENC=asm/dx86bsdi.o CC=gcc CFLAGS="-DBSDI -O3 -fomit-frame-pointer $(OPTS) $(CFLAG)" all asm/dx86-elf.o: asm/dx86-cpp.s asm/dx86unix.cpp $(CPP) -DELF asm/dx86unix.cpp | as -o asm/dx86-elf.o asm/dx86-sol.o: asm/dx86-cpp.s asm/dx86unix.cpp $(CPP) -DSOL asm/dx86unix.cpp | as -o asm/dx86-sol.o asm/dx86-out.o: asm/dx86-cpp.s asm/dx86unix.cpp $(CPP) -DOUT asm/dx86unix.cpp | as -o asm/dx86-out.o asm/dx86bsdi.o: asm/dx86-cpp.s asm/dx86unix.cpp $(CPP) -DBSDI asm/dx86unix.cpp | as -o asm/dx86bsdi.o test: all ./destest $(DLIB): $(OBJS) /bin/rm -f $(DLIB) ar cr $(DLIB) $(OBJS) -if test -s /bin/ranlib; then /bin/ranlib $(DLIB); \ else if test -s /usr/bin/ranlib; then /usr/bin/ranlib $(DLIB); \ else exit 0; fi; fi des_opts: des_opts.o libdes.a $(CC) $(CFLAGS) -o des_opts des_opts.o libdes.a destest: destest.o libdes.a $(CC) $(CFLAGS) -o destest destest.o libdes.a rpw: rpw.o libdes.a $(CC) $(CFLAGS) -o rpw rpw.o libdes.a speed: speed.o libdes.a $(CC) $(CFLAGS) -o speed speed.o libdes.a des: des.o libdes.a $(CC) $(CFLAGS) -o des des.o libdes.a tags: ctags $(DES) $(TESTING) $(LIBDES) tar_lit: /bin/mv Makefile Makefile.tmp /bin/cp Makefile.lit Makefile tar chf libdes-l.tar $(LIBDES_LIT) $(HEADERS_LIT) \ $(GENERAL_LIT) $(TESTING_LIT) /bin/rm -f Makefile /bin/mv Makefile.tmp Makefile tar: tar chf libdes.tar $(ALL) shar: shar $(ALL) >libdes.shar depend: makedepend $(LIBDES) $(DES) $(TESTING) clean: /bin/rm -f *.o tags core rpw destest des speed $(DLIB) .nfs* *.old \ *.bak destest rpw des_opts asm/*.o dclean: sed -e '/^# DO NOT DELETE THIS LINE/ q' Makefile >Makefile.new mv -f Makefile.new Makefile # Eric is probably going to choke when he next looks at this --tjh install: $(DLIB) des if test $(INSTALLTOP); then \ echo SSL style install; \ cp $(DLIB) $(INSTALLTOP)/lib; \ if test -s /bin/ranlib; then \ /bin/ranlib $(INSTALLTOP)/lib/$(DLIB); \ else \ if test -s /usr/bin/ranlib; then \ /usr/bin/ranlib $(INSTALLTOP)/lib/$(DLIB); \ fi; fi; \ chmod 644 $(INSTALLTOP)/lib/$(DLIB); \ cp des.h $(INSTALLTOP)/include; \ chmod 644 $(INSTALLTOP)/include/des.h; \ cp des $(INSTALLTOP)/bin; \ chmod 755 $(INSTALLTOP)/bin/des; \ else \ echo Standalone install; \ cp $(DLIB) $(LIBDIR)/$(DLIB); \ if test -s /bin/ranlib; then \ /bin/ranlib $(LIBDIR)/$(DLIB); \ else \ if test -s /usr/bin/ranlib; then \ /usr/bin/ranlib $(LIBDIR)/$(DLIB); \ fi; \ fi; \ chmod 644 $(LIBDIR)/$(DLIB); \ cp des $(BINDIR)/des; \ chmod 711 $(BINDIR)/des; \ cp des_crypt.man $(MANDIR)/man$(MAN3)/des_crypt.$(MAN3); \ chmod 644 $(MANDIR)/man$(MAN3)/des_crypt.$(MAN3); \ cp des.man $(MANDIR)/man$(MAN1)/des.$(MAN1); \ chmod 644 $(MANDIR)/man$(MAN1)/des.$(MAN1); \ cp des.h $(INCDIR)/des.h; \ chmod 644 $(INCDIR)/des.h; \ fi # DO NOT DELETE THIS LINE -- make depend depends on it. \ No newline at end of file diff --git a/mac/libdes/src/PC1 b/mac/libdes/src/PC1 deleted file mode 100755 index a6ea13dc..00000000 --- a/mac/libdes/src/PC1 +++ /dev/null @@ -1 +0,0 @@ -#!/usr/local/bin/perl @PC1=( 57,49,41,33,25,17, 9, 1,58,50,42,34,26,18, 10, 2,59,51,43,35,27, 19,11, 3,60,52,44,36, "-","-","-","-", 63,55,47,39,31,23,15, 7,62,54,46,38,30,22, 14, 6,61,53,45,37,29, 21,13, 5,28,20,12, 4, "-","-","-","-", ); foreach (@PC1) { if ($_ ne "-") { $_--; $_=int($_/8)*8+7-($_%8); printf "%2d ",$_; } else { print "-- "; } print "\n" if (((++$i) % 8) == 0); print "\n" if ((($i) % 32) == 0); } \ No newline at end of file diff --git a/mac/libdes/src/PC2 b/mac/libdes/src/PC2 deleted file mode 100755 index 32560417..00000000 --- a/mac/libdes/src/PC2 +++ /dev/null @@ -1 +0,0 @@ -#!/usr/local/bin/perl @PC2_C=(14,17,11,24, 1, 5, 3,28,15, 6,21,10, 23,19,12, 4,26, 8, 16, 7,27,20,13, 2, ); @PC2_D=(41,52,31,37,47,55, 30,40,51,45,33,48, 44,49,39,56,34,53, 46,42,50,36,29,32, ); foreach (@PC2_C) { if ($_ ne "-") { $_--; printf "%2d ",$_; } else { print "-- "; } $C{$_}=1; print "\n" if (((++$i) % 8) == 0); } $i=0; print "\n"; foreach (@PC2_D) { if ($_ ne "-") { $_-=29; printf "%2d ",$_; } else { print "-- "; } $D{$_}=1; print "\n" if (((++$i) % 8) == 0); } print "\n"; foreach $i (0 .. 27) { $_=$C{$i}; if ($_ ne "-") {printf "%2d ",$_;} else { print "-- "; } print "\n" if (((++$i) % 8) == 0); } print "\n"; print "\n"; foreach $i (0 .. 27) { $_=$D{$i}; if ($_ ne "-") {printf "%2d ",$_;} else { print "-- "; } print "\n" if (((++$i) % 8) == 0); } print "\n"; sub numsort { $a-$b; } \ No newline at end of file diff --git a/mac/libdes/src/README b/mac/libdes/src/README deleted file mode 100755 index a72b0d09..00000000 --- a/mac/libdes/src/README +++ /dev/null @@ -1 +0,0 @@ - libdes, Version 4.01 13-Jan-97 Copyright (c) 1997, Eric Young All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms specified in COPYRIGHT. -- The primary ftp site for this library is ftp://ftp.psy.uq.oz.au/pub/Crypto/DES/libdes-x.xx.tar.gz libdes is now also shipped with SSLeay. Primary ftp site of ftp://ftp.psy.uq.oz.au/pub/Crypto/SSL/SSLeay-x.x.x.tar.gz The best way to build this library is to build it as part of SSLeay. This kit builds a DES encryption library and a DES encryption program. It supports ecb, cbc, ofb, cfb, triple ecb, triple cbc, triple ofb, triple cfb, desx, and MIT's pcbc encryption modes and also has a fast implementation of crypt(3). It contains support routines to read keys from a terminal, generate a random key, generate a key from an arbitrary length string, read/write encrypted data from/to a file descriptor. The implementation was written so as to conform with the manual entry for the des_crypt(3) library routines from MIT's project Athena. destest should be run after compilation to test the des routines. rpw should be run after compilation to test the read password routines. The des program is a replacement for the sun des command. I believe it conforms to the sun version. The Imakefile is setup for use in the kerberos distribution. These routines are best compiled with gcc or any other good optimising compiler. Just turn you optimiser up to the highest settings and run destest after the build to make sure everything works. I believe these routines are close to the fastest and most portable DES routines that use small lookup tables (4.5k) that are publicly available. The fcrypt routine is faster than ufc's fcrypt (when compiling with gcc2 -O2) on the sparc 2 (1410 vs 1270) but is not so good on other machines (on a sun3/260 168 vs 336). It is a function of CPU on chip cache size. [ 10-Jan-97 and a function of an incorrect speed testing program in ufc which gave much better test figures that reality ]. It is worth noting that on sparc and Alpha CPUs, performance of the DES library can vary by upto %10 due to the positioning of files after application linkage. Eric Young (eay@mincom.oz.au) \ No newline at end of file diff --git a/mac/libdes/src/VERSION b/mac/libdes/src/VERSION deleted file mode 100755 index 110bb619..00000000 --- a/mac/libdes/src/VERSION +++ /dev/null @@ -1 +0,0 @@ -Version 4.01 14/01/97 Even faster inner loop in the DES assember for x86 and a modification for IP/FP which is faster on x86. Both of these changes are from Svend Olaf Mikkelsen . His changes make the assember run %40 faster on a pentium. This is just a case of getting the instruction sequence 'just right'. All credit to 'Svend' :-) Quite a few special x86 'make' targets. A libdes-l (lite) distribution. Version 4.00 After a bit of a pause, I'll up the major version number since this is mostly a performace release. I've added x86 assember and added more options for performance. A %28 speedup for gcc on a pentium and the assember is a %50 speedup. MIPS CPU's, sparc and Alpha are the main CPU's with speedups. Run des_opts to work out which options should be used. DES_RISC1/DES_RISC2 use alternative inner loops which use more registers but should give speedups on any CPU that does dual issue (pentium). DES_UNROLL unrolls the inner loop, which costs in code size. Version 3.26 I've finally removed one of the shifts in D_ENCRYPT. This meant I've changed the des_SPtrans table (spr.h), the set_key() function and some things in des_enc.c. This has definitly made things faster :-). I've known about this one for some time but I've been too lazy to follow it up :-). Noticed that in the D_ENCRYPT() macro, we can just do L^=(..)^(..)^.. instead of L^=((..)|(..)|(..).. This should save a register at least. Assember for x86. The file to replace is des_enc.c, which is replaced by one of the assember files found in asm. Look at des/asm/readme for more info. /* Modification to fcrypt so it can be compiled to support HPUX 10.x's long password format, define -DLONGCRYPT to use this. Thanks to Jens Kupferschmidt . */ SIGWINCH case put in des_read_passwd() so the function does not 'exit' if this function is recieved. Version 3.25 17/07/96 Modified read_pwd.c so that stdin can be read if not a tty. Thanks to Jeff Barber for the patches. des_init_random_number_generator() shortened due to VMS linker limits. Added RSA's DESX cbc mode. It is a form of cbc encryption, with 2 8 byte quantites xored before and after encryption. des_xcbc_encryption() - the name is funny to preserve the des_ prefix on all functions. Version 3.24 20/04/96 The DES_PTR macro option checked and used by SSLeay configuration Version 3.23 11/04/96 Added DES_LONG. If defined to 'unsigned int' on the DEC Alpha, it gives a %20 speedup :-) Fixed the problem with des.pl under perl5. The patches were sent by Ed Kubaitis (ejk@uiuc.edu). if fcrypt.c, changed values to handle illegal salt values the way normal crypt() implementations do. Some programs apparently use them :-(. The patch was sent by Bjorn Gronvall Version 3.22 29/11/95 Bug in des(1), an error with the uuencoding stuff when the 'data' is small, thanks to Geoff Keating for the patch. Version 3.21 22/11/95 After some emailing back and forth with Colin Plumb , I've tweaked a few things and in a future version I will probably put in some of the optimisation he suggested for use with the DES_USE_PTR option. Extra routines from Mark Murray for use in freeBSD. They mostly involve random number generation for use with kerberos. They involve evil machine specific system calls etc so I would normally suggest pushing this stuff into the application and/or using RAND_seed()/RAND_bytes() if you are using this DES library as part of SSLeay. Redone the read_pw() function so that it is cleaner and supports termios, thanks to Sameer Parekh for the initial patches for this. Renamed 3ecb_encrypt() to ecb3_encrypt(). This has been done just to make things more consistent. I have also now added triple DES versions of cfb and ofb. Version 3.20 Damn, Damn, Damn, as pointed out by Mike_Spreitzer.PARC@xerox.com, my des_random_seed() function was only copying 4 bytes of the passed seed into the init structure. It is now fixed to copy 8. My own suggestion is to used something like MD5 :-) Version 3.19 While looking at my code one day, I though, why do I keep on calling des_encrypt(in,out,ks,enc) when every function that calls it has in and out the same. So I dropped the 'out' parameter, people should not be using this function. Version 3.18 30/08/95 Fixed a few bit with the distribution and the filenames. 3.17 had been munged via a move to DOS and back again. NO CODE CHANGES Version 3.17 14/07/95 Fixed ede3 cbc which I had broken in 3.16. I have also removed some unneeded variables in 7-8 of the routines. Version 3.16 26/06/95 Added des_encrypt2() which does not use IP/FP, used by triple des routines. Tweaked things a bit elsewhere. %13 speedup on sparc and %6 on a R4400 for ede3 cbc mode. Version 3.15 06/06/95 Added des_ncbc_encrypt(), it is des_cbc mode except that it is 'normal' and copies the new iv value back over the top of the passed parameter. CHANGED des_ede3_cbc_encrypt() so that it too now overwrites the iv. THIS WILL BREAK EXISTING CODE, but since this function only new, I feel I can change it, not so with des_cbc_encrypt :-(. I need to update the documentation. Version 3.14 31/05/95 New release upon the world, as part of my SSL implementation. New copyright and usage stuff. Basically free for all to use as long as you say it came from me :-) Version 3.13 31/05/95 A fix in speed.c, if HZ is not defined, I set it to 100.0 which is reasonable for most unixes except SunOS 4.x. I now have a #ifdef sun but timing for SunOS 4.x looked very good :-(. At my last job where I used SunOS 4.x, it was defined to be 60.0 (look at the old INSTALL documentation), at the last release had it changed to 100.0 since I now work with Solaris2 and SVR4 boxes. Thanks to Rory Chisholm for pointing this one out. Version 3.12 08/05/95 As pointed out by The Crypt Keeper , my D_ENCRYPT macro in crypt() had an un-necessary variable. It has been removed. Version 3.11 03/05/95 Added des_ede3_cbc_encrypt() which is cbc mode des with 3 keys and one iv. It is a standard and I needed it for my SSL code. It makes more sense to use this for triple DES than 3cbc_encrypt(). I have also added (or should I say tested :-) cfb64_encrypt() which is cfb64 but it will encrypt a partial number of bytes - 3 bytes in 3 bytes out. Again this is for my SSL library, as a form of encryption to use with SSL telnet. Version 3.10 22/03/95 Fixed a bug in 3cbc_encrypt() :-(. When making repeated calls to cbc3_encrypt, the 2 iv values that were being returned to be used in the next call were reversed :-(. Many thanks to Bill Wade for pointing out this error. Version 3.09 01/02/95 Fixed des_random_key to far more random, it was rather feeble with regards to picking the initial seed. The problem was pointed out by Olaf Kirch . Version 3.08 14/12/94 Added Makefile.PL so libdes can be built into perl5. Changed des_locl.h so RAND is always defined. Version 3.07 05/12/94 Added GNUmake and stuff so the library can be build with glibc. Version 3.06 30/08/94 Added rpc_enc.c which contains _des_crypt. This is for use in secure_rpc v 4.0 Finally fixed the cfb_enc problems. Fixed a few parameter parsing bugs in des (-3 and -b), thanks to Rob McMillan Version 3.05 21/04/94 for unsigned long l; gcc does not produce ((l>>34) == 0) This causes bugs in cfb_enc. Thanks to Hadmut Danisch Version 3.04 20/04/94 Added a version number to des.c and libdes.a Version 3.03 12/01/94 Fixed a bug in non zero iv in 3cbc_enc. Version 3.02 29/10/93 I now work in a place where there are 6+ architectures and 14+ OS versions :-). Fixed TERMIO definition so the most sys V boxes will work :-) Release upon comp.sources.misc Version 3.01 08/10/93 Added des_3cbc_encrypt() Version 3.00 07/10/93 Fixed up documentation. quad_cksum definitely compatible with MIT's now. Version 2.30 24/08/93 Triple DES now defaults to triple cbc but can do triple ecb with the -b flag. Fixed some MSDOS uuen/uudecoding problems, thanks to Added prototypes. Version 2.22 29/06/93 Fixed a bug in des_is_weak_key() which stopped it working :-( thanks to engineering@MorningStar.Com. Version 2.21 03/06/93 des(1) with no arguments gives quite a bit of help. Added -c (generate ckecksum) flag to des(1). Added -3 (triple DES) flag to des(1). Added cfb and ofb routines to the library. Version 2.20 11/03/93 Added -u (uuencode) flag to des(1). I have been playing with byte order in quad_cksum to make it compatible with MIT's version. All I can say is avid this function if possible since MIT's output is endian dependent. Version 2.12 14/10/92 Added MSDOS specific macro in ecb_encrypt which gives a %70 speed up when the code is compiled with turbo C. Version 2.11 12/10/92 Speedup in set_key (recoding of PC-1) I now do it in 47 simple operations, down from 60. Thanks to John Fletcher (john_fletcher@lccmail.ocf.llnl.gov) for motivating me to look for a faster system :-) The speedup is probably less that 1% but it is still 13 instructions less :-). Version 2.10 06/10/92 The code now works on the 64bit ETA10 and CRAY without modifications or #defines. I believe the code should work on any machine that defines long, int or short to be 8 bytes long. Thanks to Shabbir J. Safdar (shabby@mentor.cc.purdue.edu) for helping me fix the code to run on 64bit machines (he had access to an ETA10). Thanks also to John Fletcher for testing the routines on a CRAY. read_password.c has been renamed to read_passwd.c string_to_key.c has been renamed to string2key.c Version 2.00 14/09/92 Made mods so that the library should work on 64bit CPU's. Removed all my uchar and ulong defs. To many different versions of unix define them in their header files in too many different combinations :-) IRIX - Sillicon Graphics mods (mostly in read_password.c). Thanks to Andrew Daviel (advax@erich.triumf.ca) Version 1.99 26/08/92 Fixed a bug or 2 in enc_read.c Fixed a bug in enc_write.c Fixed a pseudo bug in fcrypt.c (very obscure). Version 1.98 31/07/92 Support for the ETA10. This is a strange machine that defines longs and ints as 8 bytes and shorts as 4 bytes. Since I do evil things with long * that assume that they are 4 bytes. Look in the Makefile for the option to compile for this machine. quad_cksum appears to have problems but I will don't have the time to fix it right now, and this is not a function that uses DES and so will not effect the main uses of the library. Version 1.97 20/05/92 eay Fixed the Imakefile and made some changes to des.h to fix some problems when building this package with Kerberos v 4. Version 1.96 18/05/92 eay Fixed a small bug in string_to_key() where problems could occur if des_check_key was set to true and the string generated a weak key. Patch2 posted to comp.sources.misc Version 1.95 13/05/92 eay Added an alternative version of the D_ENCRYPT macro in ecb_encrypt and fcrypt. Depending on the compiler, one version or the other will be faster. This was inspired by Dana How , and her pointers about doing the *(ulong *)((uchar *)ptr+(value&0xfc)) vs ptr[value&0x3f] to stop the C compiler doing a <<2 to convert the long array index. Version 1.94 05/05/92 eay Fixed an incompatibility between my string_to_key and the MIT version. When the key is longer than 8 chars, I was wrapping with a different method. To use the old version, define OLD_STR_TO_KEY in the makefile. Thanks to viktor@newsu.shearson.com (Viktor Dukhovni). Version 1.93 28/04/92 eay Fixed the VMS mods so that echo is now turned off in read_password. Thanks again to brennan@coco.cchs.su.oz.AU. MSDOS support added. The routines can be compiled with Turbo C (v2.0) and MSC (v5.1). Make sure MSDOS is defined. Patch1 posted to comp.sources.misc Version 1.92 13/04/92 eay Changed D_ENCRYPT so that the rotation of R occurs outside of the loop. This required rotating all the longs in sp.h (now called spr.h). Thanks to Richard Outerbridge <71755.204@CompuServe.COM> speed.c has been changed so it will work without SIGALRM. If times(3) is not present it will try to use ftime() instead. Version 1.91 08/04/92 eay Added -E/-D options to des(1) so it can use string_to_key. Added SVR4 mods suggested by witr@rwwa.COM Added VMS mods suggested by brennan@coco.cchs.su.oz.AU. If anyone knows how to turn of tty echo in VMS please tell me or implement it yourself :-). Changed FILE *IN/*OUT to *DES_IN/*DES_OUT since it appears VMS does not like IN/OUT being used. Libdes posted to comp.sources.misc Version 1.9 24/03/92 eay Now contains a fast small crypt replacement. Added des(1) command. Added des_rw_mode so people can use cbc encryption with enc_read and enc_write. Version 1.8 15/10/91 eay Bug in cbc_cksum. Many thanks to Keith Reynolds (keithr@sco.COM) for pointing this one out. Version 1.7 24/09/91 eay Fixed set_key :-) set_key is 4 times faster and takes less space. There are a few minor changes that could be made. Version 1.6 19/09/1991 eay Finally go IP and FP finished. Now I need to fix set_key. This version is quite a bit faster that 1.51 Version 1.52 15/06/1991 eay 20% speedup in ecb_encrypt by changing the E bit selection to use 2 32bit words. This also required modification of the sp table. There is still a way to speedup the IP and IP-1 (hints from outer@sq.com) still working on this one :-(. Version 1.51 07/06/1991 eay Faster des_encrypt by loop unrolling Fixed bug in quad_cksum.c (thanks to hughes@logos.ucs.indiana.edu) Version 1.50 28/05/1991 eay Optimised the code a bit more for the sparc. I have improved the speed of the inner des_encrypt by speeding up the initial and final permutations. Version 1.40 23/10/1990 eay Fixed des_random_key, it did not produce a random key :-( Version 1.30 2/10/1990 eay Have made des_quad_cksum the same as MIT's, the full package should be compatible with MIT's Have tested on a DECstation 3100 Still need to fix des_set_key (make it faster). Does des_cbc_encrypts at 70.5k/sec on a 3100. Version 1.20 18/09/1990 eay Fixed byte order dependencies. Fixed (I hope) all the word alignment problems. Speedup in des_ecb_encrypt. Version 1.10 11/09/1990 eay Added des_enc_read and des_enc_write. Still need to fix des_quad_cksum. Still need to document des_enc_read and des_enc_write. Version 1.00 27/08/1990 eay \ No newline at end of file diff --git a/mac/libdes/src/cbc3_enc.c b/mac/libdes/src/cbc3_enc.c deleted file mode 100755 index 1f5b2351..00000000 --- a/mac/libdes/src/cbc3_enc.c +++ /dev/null @@ -1 +0,0 @@ -/* crypto/des/cbc3_enc.c */ /* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@mincom.oz.au). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@mincom.oz.au). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@mincom.oz.au)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ #include "des_locl.h" /* HAS BUGS? DON'T USE */ void des_3cbc_encrypt(input, output, length, ks1, ks2, iv1, iv2, encrypt) des_cblock (*input); des_cblock (*output); long length; des_key_schedule ks1; des_key_schedule ks2; des_cblock (*iv1); des_cblock (*iv2); int encrypt; { int off=((int)length-1)/8; long l8=((length+7)/8)*8; des_cblock niv1,niv2; if (encrypt == DES_ENCRYPT) { des_cbc_encrypt(input,output,length,ks1,iv1,encrypt); if (length >= sizeof(des_cblock)) memcpy(niv1,output[off],sizeof(des_cblock)); des_cbc_encrypt(output,output,l8,ks2,iv1,!encrypt); des_cbc_encrypt(output,output,l8,ks1,iv2, encrypt); if (length >= sizeof(des_cblock)) memcpy(niv2,output[off],sizeof(des_cblock)); } else { if (length >= sizeof(des_cblock)) memcpy(niv2,input[off],sizeof(des_cblock)); des_cbc_encrypt(input,output,l8,ks1,iv2,encrypt); des_cbc_encrypt(output,output,l8,ks2,iv1,!encrypt); if (length >= sizeof(des_cblock)) memcpy(niv1,output[off],sizeof(des_cblock)); des_cbc_encrypt(output,output,length,ks1,iv1, encrypt); } memcpy(*iv1,niv1,sizeof(des_cblock)); memcpy(*iv2,niv2,sizeof(des_cblock)); } \ No newline at end of file diff --git a/mac/libdes/src/cbc_cksm.c b/mac/libdes/src/cbc_cksm.c deleted file mode 100755 index bed308b7..00000000 --- a/mac/libdes/src/cbc_cksm.c +++ /dev/null @@ -1 +0,0 @@ -/* crypto/des/cbc_cksm.c */ /* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@mincom.oz.au). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@mincom.oz.au). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@mincom.oz.au)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ #include "des_locl.h" DES_LONG des_cbc_cksum(input, output, length, schedule, ivec) des_cblock (*input); des_cblock (*output); long length; des_key_schedule schedule; des_cblock (*ivec); { register DES_LONG tout0,tout1,tin0,tin1; register long l=length; DES_LONG tin[2]; unsigned char *in,*out,*iv; in=(unsigned char *)input; out=(unsigned char *)output; iv=(unsigned char *)ivec; c2l(iv,tout0); c2l(iv,tout1); for (; l>0; l-=8) { if (l >= 8) { c2l(in,tin0); c2l(in,tin1); } else c2ln(in,tin0,tin1,l); tin0^=tout0; tin[0]=tin0; tin1^=tout1; tin[1]=tin1; des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); /* fix 15/10/91 eay - thanks to keithr@sco.COM */ tout0=tin[0]; tout1=tin[1]; } if (out != NULL) { l2c(tout0,out); l2c(tout1,out); } tout0=tin0=tin1=tin[0]=tin[1]=0; return(tout1); } \ No newline at end of file diff --git a/mac/libdes/src/cbc_enc.c b/mac/libdes/src/cbc_enc.c deleted file mode 100755 index dd799115..00000000 --- a/mac/libdes/src/cbc_enc.c +++ /dev/null @@ -1 +0,0 @@ -/* crypto/des/cbc_enc.c */ /* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@mincom.oz.au). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@mincom.oz.au). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@mincom.oz.au)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ #include "des_locl.h" void des_cbc_encrypt(input, output, length, schedule, ivec, encrypt) des_cblock (*input); des_cblock (*output); long length; des_key_schedule schedule; des_cblock (*ivec); int encrypt; { register DES_LONG tin0,tin1; register DES_LONG tout0,tout1,xor0,xor1; register unsigned char *in,*out; register long l=length; DES_LONG tin[2]; unsigned char *iv; in=(unsigned char *)input; out=(unsigned char *)output; iv=(unsigned char *)ivec; if (encrypt) { c2l(iv,tout0); c2l(iv,tout1); for (l-=8; l>=0; l-=8) { c2l(in,tin0); c2l(in,tin1); tin0^=tout0; tin[0]=tin0; tin1^=tout1; tin[1]=tin1; des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); tout0=tin[0]; l2c(tout0,out); tout1=tin[1]; l2c(tout1,out); } if (l != -8) { c2ln(in,tin0,tin1,l+8); tin0^=tout0; tin[0]=tin0; tin1^=tout1; tin[1]=tin1; des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); tout0=tin[0]; l2c(tout0,out); tout1=tin[1]; l2c(tout1,out); } } else { c2l(iv,xor0); c2l(iv,xor1); for (l-=8; l>=0; l-=8) { c2l(in,tin0); tin[0]=tin0; c2l(in,tin1); tin[1]=tin1; des_encrypt((DES_LONG *)tin,schedule,DES_DECRYPT); tout0=tin[0]^xor0; tout1=tin[1]^xor1; l2c(tout0,out); l2c(tout1,out); xor0=tin0; xor1=tin1; } if (l != -8) { c2l(in,tin0); tin[0]=tin0; c2l(in,tin1); tin[1]=tin1; des_encrypt((DES_LONG *)tin,schedule,DES_DECRYPT); tout0=tin[0]^xor0; tout1=tin[1]^xor1; l2cn(tout0,tout1,out,l+8); /* xor0=tin0; xor1=tin1; */ } } tin0=tin1=tout0=tout1=xor0=xor1=0; tin[0]=tin[1]=0; } \ No newline at end of file diff --git a/mac/libdes/src/cfb64ede.c b/mac/libdes/src/cfb64ede.c deleted file mode 100755 index 4ece7657..00000000 --- a/mac/libdes/src/cfb64ede.c +++ /dev/null @@ -1 +0,0 @@ -/* crypto/des/cfb64ede.c */ /* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@mincom.oz.au). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@mincom.oz.au). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@mincom.oz.au)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ #include "des_locl.h" /* The input and output encrypted as though 64bit cfb mode is being * used. The extra state information to record how much of the * 64bit block we have used is contained in *num; */ void des_ede3_cfb64_encrypt(in, out, length, ks1,ks2,ks3, ivec, num, encrypt) unsigned char *in; unsigned char *out; long length; des_key_schedule ks1,ks2,ks3; des_cblock (*ivec); int *num; int encrypt; { register DES_LONG v0,v1; register long l=length; register int n= *num; DES_LONG ti[2]; unsigned char *iv,c,cc; iv=(unsigned char *)ivec; if (encrypt) { while (l--) { if (n == 0) { c2l(iv,v0); c2l(iv,v1); ti[0]=v0; ti[1]=v1; des_encrypt3((DES_LONG *)ti,ks1,ks2,ks3); v0=ti[0]; v1=ti[1]; iv=(unsigned char *)ivec; l2c(v0,iv); l2c(v1,iv); iv=(unsigned char *)ivec; } c= *(in++)^iv[n]; *(out++)=c; iv[n]=c; n=(n+1)&0x07; } } else { while (l--) { if (n == 0) { c2l(iv,v0); c2l(iv,v1); ti[0]=v0; ti[1]=v1; des_encrypt3((DES_LONG *)ti,ks1,ks2,ks3); v0=ti[0]; v1=ti[1]; iv=(unsigned char *)ivec; l2c(v0,iv); l2c(v1,iv); iv=(unsigned char *)ivec; } cc= *(in++); c=iv[n]; iv[n]=cc; *(out++)=c^cc; n=(n+1)&0x07; } } v0=v1=ti[0]=ti[1]=c=cc=0; *num=n; } #ifdef undef /* MACRO */ void des_ede2_cfb64_encrypt(in, out, length, ks1,ks2, ivec, num, encrypt) unsigned char *in; unsigned char *out; long length; des_key_schedule ks1,ks2; des_cblock (*ivec); int *num; int encrypt; { des_ede3_cfb64_encrypt(in,out,length,ks1,ks2,ks1,ivec,num,encrypt); } #endif \ No newline at end of file diff --git a/mac/libdes/src/cfb64enc.c b/mac/libdes/src/cfb64enc.c deleted file mode 100755 index 20caaf2a..00000000 --- a/mac/libdes/src/cfb64enc.c +++ /dev/null @@ -1 +0,0 @@ -/* crypto/des/cfb64enc.c */ /* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@mincom.oz.au). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@mincom.oz.au). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@mincom.oz.au)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ #include "des_locl.h" /* The input and output encrypted as though 64bit cfb mode is being * used. The extra state information to record how much of the * 64bit block we have used is contained in *num; */ void des_cfb64_encrypt(in, out, length, schedule, ivec, num, encrypt) unsigned char *in; unsigned char *out; long length; des_key_schedule schedule; des_cblock (*ivec); int *num; int encrypt; { register DES_LONG v0,v1; register long l=length; register int n= *num; DES_LONG ti[2]; unsigned char *iv,c,cc; iv=(unsigned char *)ivec; if (encrypt) { while (l--) { if (n == 0) { c2l(iv,v0); ti[0]=v0; c2l(iv,v1); ti[1]=v1; des_encrypt((DES_LONG *)ti, schedule,DES_ENCRYPT); iv=(unsigned char *)ivec; v0=ti[0]; l2c(v0,iv); v0=ti[1]; l2c(v0,iv); iv=(unsigned char *)ivec; } c= *(in++)^iv[n]; *(out++)=c; iv[n]=c; n=(n+1)&0x07; } } else { while (l--) { if (n == 0) { c2l(iv,v0); ti[0]=v0; c2l(iv,v1); ti[1]=v1; des_encrypt((DES_LONG *)ti, schedule,DES_ENCRYPT); iv=(unsigned char *)ivec; v0=ti[0]; l2c(v0,iv); v0=ti[1]; l2c(v0,iv); iv=(unsigned char *)ivec; } cc= *(in++); c=iv[n]; iv[n]=cc; *(out++)=c^cc; n=(n+1)&0x07; } } v0=v1=ti[0]=ti[1]=c=cc=0; *num=n; } \ No newline at end of file diff --git a/mac/libdes/src/cfb_enc.c b/mac/libdes/src/cfb_enc.c deleted file mode 100755 index 32172e33..00000000 --- a/mac/libdes/src/cfb_enc.c +++ /dev/null @@ -1 +0,0 @@ -/* crypto/des/cfb_enc.c */ /* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@mincom.oz.au). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@mincom.oz.au). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@mincom.oz.au)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ #include "des_locl.h" /* The input and output are loaded in multiples of 8 bits. * What this means is that if you hame numbits=12 and length=2 * the first 12 bits will be retrieved from the first byte and half * the second. The second 12 bits will come from the 3rd and half the 4th * byte. */ void des_cfb_encrypt(in, out, numbits, length, schedule, ivec, encrypt) unsigned char *in; unsigned char *out; int numbits; long length; des_key_schedule schedule; des_cblock (*ivec); int encrypt; { register DES_LONG d0,d1,v0,v1,n=(numbits+7)/8; register DES_LONG mask0,mask1; register unsigned long l=length; register int num=numbits; DES_LONG ti[2]; unsigned char *iv; if (num > 64) return; if (num > 32) { mask0=0xffffffffL; if (num == 64) mask1=mask0; else mask1=(1L<<(num-32))-1; } else { if (num == 32) mask0=0xffffffffL; else mask0=(1L<= n) { l-=n; ti[0]=v0; ti[1]=v1; des_encrypt((DES_LONG *)ti,schedule,DES_ENCRYPT); c2ln(in,d0,d1,n); in+=n; d0=(d0^ti[0])&mask0; d1=(d1^ti[1])&mask1; l2cn(d0,d1,out,n); out+=n; /* 30-08-94 - eay - changed because l>>32 and * l<<32 are bad under gcc :-( */ if (num == 32) { v0=v1; v1=d0; } else if (num == 64) { v0=d0; v1=d1; } else if (num > 32) /* && num != 64 */ { v0=((v1>>(num-32))|(d0<<(64-num)))&0xffffffffL; v1=((d0>>(num-32))|(d1<<(64-num)))&0xffffffffL; } else /* num < 32 */ { v0=((v0>>num)|(v1<<(32-num)))&0xffffffffL; v1=((v1>>num)|(d0<<(32-num)))&0xffffffffL; } } } else { while (l >= n) { l-=n; ti[0]=v0; ti[1]=v1; des_encrypt((DES_LONG *)ti,schedule,DES_ENCRYPT); c2ln(in,d0,d1,n); in+=n; /* 30-08-94 - eay - changed because l>>32 and * l<<32 are bad under gcc :-( */ if (num == 32) { v0=v1; v1=d0; } else if (num == 64) { v0=d0; v1=d1; } else if (num > 32) /* && num != 64 */ { v0=((v1>>(num-32))|(d0<<(64-num)))&0xffffffffL; v1=((d0>>(num-32))|(d1<<(64-num)))&0xffffffffL; } else /* num < 32 */ { v0=((v0>>num)|(v1<<(32-num)))&0xffffffffL; v1=((v1>>num)|(d0<<(32-num)))&0xffffffffL; } d0=(d0^ti[0])&mask0; d1=(d1^ti[1])&mask1; l2cn(d0,d1,out,n); out+=n; } } iv=(unsigned char *)ivec; l2c(v0,iv); l2c(v1,iv); v0=v1=d0=d1=ti[0]=ti[1]=0; } \ No newline at end of file diff --git a/mac/libdes/src/des.c b/mac/libdes/src/des.c deleted file mode 100755 index 12284c5c..00000000 --- a/mac/libdes/src/des.c +++ /dev/null @@ -1 +0,0 @@ -/* crypto/des/des.c */ /* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@mincom.oz.au). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@mincom.oz.au). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@mincom.oz.au)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_IO_H #include #endif #include #include "des_ver.h" #ifdef VMS #include #include #endif #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_SYS_STAT_H #include #endif #include "des.h" #ifndef HAVE_RANDOM #define random rand #define srandom(s) srand(s) #endif #ifndef NOPROTO void usage(void); void doencryption(void); int uufwrite(unsigned char *data, int size, unsigned int num, FILE *fp); void uufwriteEnd(FILE *fp); int uufread(unsigned char *out,int size,unsigned int num,FILE *fp); int uuencode(unsigned char *in,int num,unsigned char *out); int uudecode(unsigned char *in,int num,unsigned char *out); #else void usage(); void doencryption(); int uufwrite(); void uufwriteEnd(); int uufread(); int uuencode(); int uudecode(); #endif #ifdef VMS #define EXIT(a) exit(a&0x10000000) #else #define EXIT(a) exit(a) #endif #define BUFSIZE (8*1024) #define VERIFY 1 #define KEYSIZ 8 #define KEYSIZB 1024 /* should hit tty line limit first :-) */ char key[KEYSIZB+1]; int do_encrypt,longk=0; FILE *DES_IN,*DES_OUT,*CKSUM_OUT; char uuname[200]; unsigned char uubuf[50]; int uubufnum=0; #define INUUBUFN (45*100) #define OUTUUBUF (65*100) unsigned char b[OUTUUBUF]; unsigned char bb[300]; des_cblock cksum={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; char cksumname[200]=""; int vflag,cflag,eflag,dflag,kflag,bflag,fflag,sflag,uflag,flag3,hflag,error; int main(argc, argv) int argc; char **argv; { int i; struct stat ins,outs; char *p; char *in=NULL,*out=NULL; vflag=cflag=eflag=dflag=kflag=hflag=bflag=fflag=sflag=uflag=flag3=0; error=0; memset(key,0,sizeof(key)); for (i=1; i=0; j--) argv[i][j]='\0'; } break; default: fprintf(stderr,"'%c' unknown flag\n",p[-1]); error=1; break; } } } else { if (in == NULL) in=argv[i]; else if (out == NULL) out=argv[i]; else error=1; } } if (error) usage(); /* We either * do checksum or * do encrypt or * do decrypt or * do decrypt then ckecksum or * do checksum then encrypt */ if (((eflag+dflag) == 1) || cflag) { if (eflag) do_encrypt=DES_ENCRYPT; if (dflag) do_encrypt=DES_DECRYPT; } else { if (vflag) { #ifndef _Windows fprintf(stderr,"des(1) built with %s\n",libdes_version); #endif EXIT(1); } else usage(); } #ifndef _Windows if (vflag) fprintf(stderr,"des(1) built with %s\n",libdes_version); #endif if ( (in != NULL) && (out != NULL) && #ifndef MSDOS (stat(in,&ins) != -1) && (stat(out,&outs) != -1) && (ins.st_dev == outs.st_dev) && (ins.st_ino == outs.st_ino)) #else /* MSDOS */ (strcmp(in,out) == 0)) #endif { fputs("input and output file are the same\n",stderr); EXIT(3); } if (!kflag) if (des_read_pw_string(key,KEYSIZB+1,"Enter key:",eflag?VERIFY:0)) { fputs("password error\n",stderr); EXIT(2); } if (in == NULL) DES_IN=stdin; else if ((DES_IN=fopen(in,"r")) == NULL) { perror("opening input file"); EXIT(4); } CKSUM_OUT=stdout; if (out == NULL) { DES_OUT=stdout; CKSUM_OUT=stderr; } else if ((DES_OUT=fopen(out,"w")) == NULL) { perror("opening output file"); EXIT(5); } #ifdef MSDOS /* This should set the file to binary mode. */ { #include if (!(uflag && dflag)) setmode(fileno(DES_IN),O_BINARY); if (!(uflag && eflag)) setmode(fileno(DES_OUT),O_BINARY); } #endif doencryption(); fclose(DES_IN); fclose(DES_OUT); EXIT(0); } void usage() { char **u; static const char *Usage[]={ "des [input-file [output-file]]", "options:", "-v : des(1) version number", "-e : encrypt using sunOS compatible user key to DES key conversion.", "-E : encrypt ", "-d : decrypt using sunOS compatible user key to DES key conversion.", "-D : decrypt ", "-c[ckname] : generate a cbc_cksum using sunOS compatible user key to", " DES key conversion and output to ckname (stdout default,", " stderr if data being output on stdout). The checksum is", " generated before encryption and after decryption if used", " in conjunction with -[eEdD].", "-C[ckname] : generate a cbc_cksum as for -c but compatible with -[ED].", "-k key : use key 'key'", "-h : the key that is entered will be a hexidecimal number", " that is used directly as the des key", "-u[uuname] : input file is uudecoded if -[dD] or output uuencoded data if -[eE]", " (uuname is the filename to put in the uuencode header).", "-b : encrypt using DES in ecb encryption mode, the defaut is cbc mode.", "-3 : encrypt using tripple DES encryption. This uses 2 keys", " generated from the input key. If the input key is less", " than 8 characters long, this is equivelent to normal", " encryption. Default is tripple cbc, -b makes it tripple ecb.", NULL }; for (u=(char **)Usage; *u; u++) { fputs(*u,stderr); fputc('\n',stderr); } EXIT(1); } void doencryption() { #ifdef _LIBC extern int srandom(); extern int random(); extern unsigned long time(); #endif register int i; des_key_schedule ks,ks2; unsigned char iv[8],iv2[8]; char *p; int num=0,j,k,l,rem,ll,len,last,ex=0; des_cblock kk,k2; FILE *O; int Exit=0; #ifndef MSDOS static unsigned char buf[BUFSIZE+8],obuf[BUFSIZE+8]; #else static unsigned char *buf=NULL,*obuf=NULL; if (buf == NULL) { if ( (( buf=(unsigned char *)Malloc(BUFSIZE+8)) == NULL) || ((obuf=(unsigned char *)Malloc(BUFSIZE+8)) == NULL)) { fputs("Not enough memory\n",stderr); Exit=10; goto problems; } } #endif if (hflag) { j=(flag3?16:8); p=key; for (i=0; i= '0')) k=(*p-'0')<<4; else if ((*p <= 'f') && (*p >= 'a')) k=(*p-'a'+10)<<4; else if ((*p <= 'F') && (*p >= 'A')) k=(*p-'A'+10)<<4; else { fputs("Bad hex key\n",stderr); Exit=9; goto problems; } p++; if ((*p <= '9') && (*p >= '0')) k|=(*p-'0'); else if ((*p <= 'f') && (*p >= 'a')) k|=(*p-'a'+10); else if ((*p <= 'F') && (*p >= 'A')) k|=(*p-'A'+10); else { fputs("Bad hex key\n",stderr); Exit=9; goto problems; } p++; if (i < 8) kk[i]=k; else k2[i-8]=k; } des_set_key((C_Block *)k2,ks2); memset(k2,0,sizeof(k2)); } else if (longk || flag3) { if (flag3) { des_string_to_2keys(key,(C_Block *)kk,(C_Block *)k2); des_set_key((C_Block *)k2,ks2); memset(k2,0,sizeof(k2)); } else des_string_to_key(key,(C_Block *)kk); } else for (i=0; i>=1; } if (l & 1) kk[i]=key[i]&0x7f; else kk[i]=key[i]|0x80; } des_set_key((C_Block *)kk,ks); memset(key,0,sizeof(key)); memset(kk,0,sizeof(kk)); /* woops - A bug that does not showup under unix :-( */ memset(iv,0,sizeof(iv)); memset(iv2,0,sizeof(iv2)); l=1; rem=0; /* first read */ if (eflag || (!dflag && cflag)) { for (;;) { num=l=fread(&(buf[rem]),1,BUFSIZE,DES_IN); l+=rem; num+=rem; if (l < 0) { perror("read error"); Exit=6; goto problems; } rem=l%8; len=l-rem; if (feof(DES_IN)) { srandom((unsigned int)time(NULL)); for (i=7-rem; i>0; i--) buf[l++]=random()&0xff; buf[l++]=rem; ex=1; len+=rem; } else l-=rem; if (cflag) { des_cbc_cksum((C_Block *)buf,(C_Block *)cksum, (long)len,ks,(C_Block *)cksum); if (!eflag) { if (feof(DES_IN)) break; else continue; } } if (bflag && !flag3) for (i=0; i= 8) memcpy(iv,&(obuf[l-8]),8); } if (rem) memcpy(buf,&(buf[l]),(unsigned int)rem); i=0; while (i < l) { if (uflag) j=uufwrite(obuf,1,(unsigned int)l-i, DES_OUT); else j=fwrite(obuf,1,(unsigned int)l-i, DES_OUT); if (j == -1) { perror("Write error"); Exit=7; goto problems; } i+=j; } if (feof(DES_IN)) { if (uflag) uufwriteEnd(DES_OUT); break; } } } else /* decrypt */ { ex=1; for (;;) { if (ex) { if (uflag) l=uufread(buf,1,BUFSIZE,DES_IN); else l=fread(buf,1,BUFSIZE,DES_IN); ex=0; rem=l%8; l-=rem; } if (l < 0) { perror("read error"); Exit=6; goto problems; } if (bflag && !flag3) for (i=0; i= 8) memcpy(iv,&(buf[l-8]),8); } if (uflag) ll=uufread(&(buf[rem]),1,BUFSIZE,DES_IN); else ll=fread(&(buf[rem]),1,BUFSIZE,DES_IN); ll+=rem; rem=ll%8; ll-=rem; if (feof(DES_IN) && (ll == 0)) { last=obuf[l-1]; if ((last > 7) || (last < 0)) { fputs("The file was not decrypted correctly.\n", stderr); Exit=8; last=0; } l=l-8+last; } i=0; if (cflag) des_cbc_cksum((C_Block *)obuf, (C_Block *)cksum,(long)l/8*8,ks, (C_Block *)cksum); while (i != l) { j=fwrite(obuf,1,(unsigned int)l-i,DES_OUT); if (j == -1) { perror("Write error"); Exit=7; goto problems; } i+=j; } l=ll; if ((l == 0) && feof(DES_IN)) break; } } if (cflag) { l=0; if (cksumname[0] != '\0') { if ((O=fopen(cksumname,"w")) != NULL) { CKSUM_OUT=O; l=1; } } for (i=0; i<8; i++) fprintf(CKSUM_OUT,"%02X",cksum[i]); fprintf(CKSUM_OUT,"\n"); if (l) fclose(CKSUM_OUT); } problems: memset(buf,0,sizeof(buf)); memset(obuf,0,sizeof(obuf)); memset(ks,0,sizeof(ks)); memset(ks2,0,sizeof(ks2)); memset(iv,0,sizeof(iv)); memset(iv2,0,sizeof(iv2)); memset(kk,0,sizeof(kk)); memset(k2,0,sizeof(k2)); memset(uubuf,0,sizeof(uubuf)); memset(b,0,sizeof(b)); memset(bb,0,sizeof(bb)); memset(cksum,0,sizeof(cksum)); if (Exit) EXIT(Exit); } int uufwrite(data, size, num, fp) unsigned char *data; int size; unsigned int num; FILE *fp; /* We ignore this parameter but it should be > ~50 I believe */ { int i,j,left,rem,ret=num; static int start=1; if (start) { fprintf(fp,"begin 600 %s\n", (uuname[0] == '\0')?"text.d":uuname); start=0; } if (uubufnum) { if (uubufnum+num < 45) { memcpy(&(uubuf[uubufnum]),data,(unsigned int)num); uubufnum+=num; return(num); } else { i=45-uubufnum; memcpy(&(uubuf[uubufnum]),data,(unsigned int)i); j=uuencode((unsigned char *)uubuf,45,b); fwrite(b,1,(unsigned int)j,fp); uubufnum=0; data+=i; num-=i; } } for (i=0; i<(((int)num)-INUUBUFN); i+=INUUBUFN) { j=uuencode(&(data[i]),INUUBUFN,b); fwrite(b,1,(unsigned int)j,fp); } rem=(num-i)%45; left=(num-i-rem); if (left) { j=uuencode(&(data[i]),left,b); fwrite(b,1,(unsigned int)j,fp); i+=left; } if (i != num) { memcpy(uubuf,&(data[i]),(unsigned int)rem); uubufnum=rem; } return(ret); } void uufwriteEnd(fp) FILE *fp; { int j; static const char *end=" \nend\n"; if (uubufnum != 0) { uubuf[uubufnum]='\0'; uubuf[uubufnum+1]='\0'; uubuf[uubufnum+2]='\0'; j=uuencode(uubuf,uubufnum,b); fwrite(b,1,(unsigned int)j,fp); } fwrite(end,1,strlen(end),fp); } int uufread(out, size, num, fp) unsigned char *out; int size; /* should always be > ~ 60; I actually ignore this parameter :-) */ unsigned int num; FILE *fp; { int i,j,tot; static int done=0; static int valid=0; static int start=1; if (start) { for (;;) { b[0]='\0'; fgets((char *)b,300,fp); if (b[0] == '\0') { fprintf(stderr,"no 'begin' found in uuencoded input\n"); return(-1); } if (strncmp((char *)b,"begin ",6) == 0) break; } start=0; } if (done) return(0); tot=0; if (valid) { memcpy(out,bb,(unsigned int)valid); tot=valid; valid=0; } for (;;) { b[0]='\0'; fgets((char *)b,300,fp); if (b[0] == '\0') break; i=strlen((char *)b); if ((b[0] == 'e') && (b[1] == 'n') && (b[2] == 'd')) { done=1; while (!feof(fp)) { fgets((char *)b,300,fp); } break; } i=uudecode(b,i,bb); if (i < 0) break; if ((i+tot+8) > num) { /* num to copy to make it a multiple of 8 */ j=(num/8*8)-tot-8; memcpy(&(out[tot]),bb,(unsigned int)j); tot+=j; memcpy(bb,&(bb[j]),(unsigned int)i-j); valid=i-j; break; } memcpy(&(out[tot]),bb,(unsigned int)i); tot+=i; } return(tot); } #define ccc2l(c,l) (l =((DES_LONG)(*((c)++)))<<16, \ l|=((DES_LONG)(*((c)++)))<< 8, \ l|=((DES_LONG)(*((c)++)))) #define l2ccc(l,c) (*((c)++)=(unsigned char)(((l)>>16)&0xff), \ *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ *((c)++)=(unsigned char)(((l) )&0xff)) int uuencode(in, num, out) unsigned char *in; int num; unsigned char *out; { int j,i,n,tot=0; DES_LONG l; register unsigned char *p; p=out; for (j=0; j num) i=(num-j); else i=45; *(p++)=i+' '; for (n=0; n>18)&0x3f)+' '; *(p++)=((l>>12)&0x3f)+' '; *(p++)=((l>> 6)&0x3f)+' '; *(p++)=((l )&0x3f)+' '; tot+=4; } *(p++)='\n'; tot+=2; } *p='\0'; l=0; return(tot); } int uudecode(in, num, out) unsigned char *in; int num; unsigned char *out; { int j,i,k; unsigned int n=0,space=0; DES_LONG l; DES_LONG w,x,y,z; unsigned int blank=(unsigned int)'\n'-' '; for (j=0; j 60) { fprintf(stderr,"uuencoded line length too long\n"); return(-1); } j++; for (i=0; i 63) || (x > 63) || (y > 63) || (z > 63)) { k=0; if (w == blank) k=1; if (x == blank) k=2; if (y == blank) k=3; if (z == blank) k=4; space=1; switch (k) { case 1: w=0; in--; case 2: x=0; in--; case 3: y=0; in--; case 4: z=0; in--; break; case 0: space=0; fprintf(stderr,"bad uuencoded data values\n"); w=x=y=z=0; return(-1); break; } } l=(w<<18)|(x<<12)|(y<< 6)|(z ); l2ccc(l,out); } if (*(in++) != '\n') { fprintf(stderr,"missing nl in uuencoded line\n"); w=x=y=z=0; return(-1); } j++; } *out='\0'; w=x=y=z=0; return(n); } \ No newline at end of file diff --git a/mac/libdes/src/des.def b/mac/libdes/src/des.def deleted file mode 100755 index f056ecfd..00000000 --- a/mac/libdes/src/des.def +++ /dev/null @@ -1 +0,0 @@ -LIBRARY des BASE=0x06000000 EXPORTS des_ecb3_encrypt des_cbc_cksum des_cbc_encrypt des_ncbc_encrypt des_3cbc_encrypt des_cfb_encrypt des_ede3_cfb64_encrypt des_ede3_ofb64_encrypt des_ecb_encrypt des_encrypt des_encrypt2 des_ede3_cbc_encrypt des_enc_read des_enc_write crypt des_ofb_encrypt des_pcbc_encrypt des_quad_cksum des_read_password des_read_2passwords des_read_pw_string des_set_odd_parity des_is_weak_key des_set_key des_key_sched des_string_to_key des_string_to_2keys des_cfb64_encrypt des_ofb64_encrypt des_cblock_print_file des_new_random_key des_init_random_number_generator des_set_random_generator_seed des_set_sequence_number des_generate_random_block \ No newline at end of file diff --git a/mac/libdes/src/des.doc b/mac/libdes/src/des.doc deleted file mode 100755 index 1e301581..00000000 --- a/mac/libdes/src/des.doc +++ /dev/null @@ -1,505 +0,0 @@ -The DES library. - -Please note that this library was originally written to operate with -eBones, a version of Kerberos that had had encryption removed when it left -the USA and then put back in. As such there are some routines that I will -advise not using but they are still in the library for historical reasons. -For all calls that have an 'input' and 'output' variables, they can be the -same. - -This library requires the inclusion of 'des.h'. - -All of the encryption functions take what is called a des_key_schedule as an -argument. A des_key_schedule is an expanded form of the des key. -A des_key is 8 bytes of odd parity, the type used to hold the key is a -des_cblock. A des_cblock is an array of 8 bytes, often in this library -description I will refer to input bytes when the function specifies -des_cblock's as input or output, this just means that the variable should -be a multiple of 8 bytes. - -The define DES_ENCRYPT is passed to specify encryption, DES_DECRYPT to -specify decryption. The functions and global variable are as follows: - -int des_check_key; - DES keys are supposed to be odd parity. If this variable is set to - a non-zero value, des_set_key() will check that the key has odd - parity and is not one of the known weak DES keys. By default this - variable is turned off; - -void des_set_odd_parity( -des_cblock *key ); - This function takes a DES key (8 bytes) and sets the parity to odd. - -int des_is_weak_key( -des_cblock *key ); - This function returns a non-zero value if the DES key passed is a - weak, DES key. If it is a weak key, don't use it, try a different - one. If you are using 'random' keys, the chances of hitting a weak - key are 1/2^52 so it is probably not worth checking for them. - -int des_set_key( -des_cblock *key, -des_key_schedule schedule); - Des_set_key converts an 8 byte DES key into a des_key_schedule. - A des_key_schedule is an expanded form of the key which is used to - perform actual encryption. It can be regenerated from the DES key - so it only needs to be kept when encryption or decryption is about - to occur. Don't save or pass around des_key_schedule's since they - are CPU architecture dependent, DES keys are not. If des_check_key - is non zero, zero is returned if the key has the wrong parity or - the key is a weak key, else 1 is returned. - -int des_key_sched( -des_cblock *key, -des_key_schedule schedule); - An alternative name for des_set_key(). - -int des_rw_mode; /* defaults to DES_PCBC_MODE */ - This flag holds either DES_CBC_MODE or DES_PCBC_MODE (default). - This specifies the function to use in the enc_read() and enc_write() - functions. - -void des_encrypt( -unsigned long *data, -des_key_schedule ks, -int enc); - This is the DES encryption function that gets called by just about - every other DES routine in the library. You should not use this - function except to implement 'modes' of DES. I say this because the - functions that call this routine do the conversion from 'char *' to - long, and this needs to be done to make sure 'non-aligned' memory - access do not occur. The characters are loaded 'little endian', - have a look at my source code for more details on how I use this - function. - Data is a pointer to 2 unsigned long's and ks is the - des_key_schedule to use. enc, is non zero specifies encryption, - zero if decryption. - -void des_encrypt2( -unsigned long *data, -des_key_schedule ks, -int enc); - This functions is the same as des_encrypt() except that the DES - initial permutation (IP) and final permutation (FP) have been left - out. As for des_encrypt(), you should not use this function. - It is used by the routines in my library that implement triple DES. - IP() des_encrypt2() des_encrypt2() des_encrypt2() FP() is the same - as des_encrypt() des_encrypt() des_encrypt() except faster :-). - -void des_ecb_encrypt( -des_cblock *input, -des_cblock *output, -des_key_schedule ks, -int enc); - This is the basic Electronic Code Book form of DES, the most basic - form. Input is encrypted into output using the key represented by - ks. If enc is non zero (DES_ENCRYPT), encryption occurs, otherwise - decryption occurs. Input is 8 bytes long and output is 8 bytes. - (the des_cblock structure is 8 chars). - -void des_ecb3_encrypt( -des_cblock *input, -des_cblock *output, -des_key_schedule ks1, -des_key_schedule ks2, -des_key_schedule ks3, -int enc); - This is the 3 key EDE mode of ECB DES. What this means is that - the 8 bytes of input is encrypted with ks1, decrypted with ks2 and - then encrypted again with ks3, before being put into output; - C=E(ks3,D(ks2,E(ks1,M))). There is a macro, des_ecb2_encrypt() - that only takes 2 des_key_schedules that implements, - C=E(ks1,D(ks2,E(ks1,M))) in that the final encrypt is done with ks1. - -void des_cbc_encrypt( -des_cblock *input, -des_cblock *output, -long length, -des_key_schedule ks, -des_cblock *ivec, -int enc); - This routine implements DES in Cipher Block Chaining mode. - Input, which should be a multiple of 8 bytes is encrypted - (or decrypted) to output which will also be a multiple of 8 bytes. - The number of bytes is in length (and from what I've said above, - should be a multiple of 8). If length is not a multiple of 8, I'm - not being held responsible :-). ivec is the initialisation vector. - This function does not modify this variable. To correctly implement - cbc mode, you need to do one of 2 things; copy the last 8 bytes of - cipher text for use as the next ivec in your application, - or use des_ncbc_encrypt(). - Only this routine has this problem with updating the ivec, all - other routines that are implementing cbc mode update ivec. - -void des_ncbc_encrypt( -des_cblock *input, -des_cblock *output, -long length, -des_key_schedule sk, -des_cblock *ivec, -int enc); - For historical reasons, des_cbc_encrypt() did not update the - ivec with the value requires so that subsequent calls to - des_cbc_encrypt() would 'chain'. This was needed so that the same - 'length' values would not need to be used when decrypting. - des_ncbc_encrypt() does the right thing. It is the same as - des_cbc_encrypt accept that ivec is updates with the correct value - to pass in subsequent calls to des_ncbc_encrypt(). I advise using - des_ncbc_encrypt() instead of des_cbc_encrypt(); - -void des_xcbc_encrypt( -des_cblock *input, -des_cblock *output, -long length, -des_key_schedule sk, -des_cblock *ivec, -des_cblock *inw, -des_cblock *outw, -int enc); - This is RSA's DESX mode of DES. It uses inw and outw to - 'whiten' the encryption. inw and outw are secret (unlike the iv) - and are as such, part of the key. So the key is sort of 24 bytes. - This is much better than cbc des. - -void des_3cbc_encrypt( -des_cblock *input, -des_cblock *output, -long length, -des_key_schedule sk1, -des_key_schedule sk2, -des_cblock *ivec1, -des_cblock *ivec2, -int enc); - This function is flawed, do not use it. I have left it in the - library because it is used in my des(1) program and will function - correctly when used by des(1). If I removed the function, people - could end up unable to decrypt files. - This routine implements outer triple cbc encryption using 2 ks and - 2 ivec's. Use des_ede2_cbc_encrypt() instead. - -void des_ede3_cbc_encrypt( -des_cblock *input, -des_cblock *output, -long length, -des_key_schedule ks1, -des_key_schedule ks2, -des_key_schedule ks3, -des_cblock *ivec, -int enc); - This function implements inner triple CBC DES encryption with 3 - keys. What this means is that each 'DES' operation - inside the cbc mode is really an C=E(ks3,D(ks2,E(ks1,M))). - Again, this is cbc mode so an ivec is requires. - This mode is used by SSL. - There is also a des_ede2_cbc_encrypt() that only uses 2 - des_key_schedule's, the first being reused for the final - encryption. C=E(ks1,D(ks2,E(ks1,M))). This form of triple DES - is used by the RSAref library. - -void des_pcbc_encrypt( -des_cblock *input, -des_cblock *output, -long length, -des_key_schedule ks, -des_cblock *ivec, -int enc); - This is Propagating Cipher Block Chaining mode of DES. It is used - by Kerberos v4. It's parameters are the same as des_ncbc_encrypt(). - -void des_cfb_encrypt( -unsigned char *in, -unsigned char *out, -int numbits, -long length, -des_key_schedule ks, -des_cblock *ivec, -int enc); - Cipher Feedback Back mode of DES. This implementation 'feeds back' - in numbit blocks. The input (and output) is in multiples of numbits - bits. numbits should to be a multiple of 8 bits. Length is the - number of bytes input. If numbits is not a multiple of 8 bits, - the extra bits in the bytes will be considered padding. So if - numbits is 12, for each 2 input bytes, the 4 high bits of the - second byte will be ignored. So to encode 72 bits when using - a numbits of 12 take 12 bytes. To encode 72 bits when using - numbits of 9 will take 16 bytes. To encode 80 bits when using - numbits of 16 will take 10 bytes. etc, etc. This padding will - apply to both input and output. - - -void des_cfb64_encrypt( -unsigned char *in, -unsigned char *out, -long length, -des_key_schedule ks, -des_cblock *ivec, -int *num, -int enc); - This is one of the more useful functions in this DES library, it - implements CFB mode of DES with 64bit feedback. Why is this - useful you ask? Because this routine will allow you to encrypt an - arbitrary number of bytes, no 8 byte padding. Each call to this - routine will encrypt the input bytes to output and then update ivec - and num. num contains 'how far' we are though ivec. If this does - not make much sense, read more about cfb mode of DES :-). - -void des_ede3_cfb64_encrypt( -unsigned char *in, -unsigned char *out, -long length, -des_key_schedule ks1, -des_key_schedule ks2, -des_key_schedule ks3, -des_cblock *ivec, -int *num, -int enc); - Same as des_cfb64_encrypt() accept that the DES operation is - triple DES. As usual, there is a macro for - des_ede2_cfb64_encrypt() which reuses ks1. - -void des_ofb_encrypt( -unsigned char *in, -unsigned char *out, -int numbits, -long length, -des_key_schedule ks, -des_cblock *ivec); - This is a implementation of Output Feed Back mode of DES. It is - the same as des_cfb_encrypt() in that numbits is the size of the - units dealt with during input and output (in bits). - -void des_ofb64_encrypt( -unsigned char *in, -unsigned char *out, -long length, -des_key_schedule ks, -des_cblock *ivec, -int *num); - The same as des_cfb64_encrypt() except that it is Output Feed Back - mode. - -void des_ede3_ofb64_encrypt( -unsigned char *in, -unsigned char *out, -long length, -des_key_schedule ks1, -des_key_schedule ks2, -des_key_schedule ks3, -des_cblock *ivec, -int *num); - Same as des_ofb64_encrypt() accept that the DES operation is - triple DES. As usual, there is a macro for - des_ede2_ofb64_encrypt() which reuses ks1. - -int des_read_pw_string( -char *buf, -int length, -char *prompt, -int verify); - This routine is used to get a password from the terminal with echo - turned off. Buf is where the string will end up and length is the - size of buf. Prompt is a string presented to the 'user' and if - verify is set, the key is asked for twice and unless the 2 copies - match, an error is returned. A return code of -1 indicates a - system error, 1 failure due to use interaction, and 0 is success. - -unsigned long des_cbc_cksum( -des_cblock *input, -des_cblock *output, -long length, -des_key_schedule ks, -des_cblock *ivec); - This function produces an 8 byte checksum from input that it puts in - output and returns the last 4 bytes as a long. The checksum is - generated via cbc mode of DES in which only the last 8 byes are - kept. I would recommend not using this function but instead using - the EVP_Digest routines, or at least using MD5 or SHA. This - function is used by Kerberos v4 so that is why it stays in the - library. - -char *des_fcrypt( -const char *buf, -const char *salt -char *ret); - This is my fast version of the unix crypt(3) function. This version - takes only a small amount of space relative to other fast - crypt() implementations. This is different to the normal crypt - in that the third parameter is the buffer that the return value - is written into. It needs to be at least 14 bytes long. This - function is thread safe, unlike the normal crypt. - -char *crypt( -const char *buf, -const char *salt); - This function calls des_fcrypt() with a static array passed as the - third parameter. This emulates the normal non-thread safe semantics - of crypt(3). - -void des_string_to_key( -char *str, -des_cblock *key); - This function takes str and converts it into a DES key. I would - recommend using MD5 instead and use the first 8 bytes of output. - When I wrote the first version of these routines back in 1990, MD5 - did not exist but I feel these routines are still sound. This - routines is compatible with the one in MIT's libdes. - -void des_string_to_2keys( -char *str, -des_cblock *key1, -des_cblock *key2); - This function takes str and converts it into 2 DES keys. - I would recommend using MD5 and using the 16 bytes as the 2 keys. - I have nothing against these 2 'string_to_key' routines, it's just - that if you say that your encryption key is generated by using the - 16 bytes of an MD5 hash, every-one knows how you generated your - keys. - -int des_read_password( -des_cblock *key, -char *prompt, -int verify); - This routine combines des_read_pw_string() with des_string_to_key(). - -int des_read_2passwords( -des_cblock *key1, -des_cblock *key2, -char *prompt, -int verify); - This routine combines des_read_pw_string() with des_string_to_2key(). - -void des_random_seed( -des_cblock key); - This routine sets a starting point for des_random_key(). - -void des_random_key( -des_cblock ret); - This function return a random key. Make sure to 'seed' the random - number generator (with des_random_seed()) before using this function. - I personally now use a MD5 based random number system. - -int des_enc_read( -int fd, -char *buf, -int len, -des_key_schedule ks, -des_cblock *iv); - This function will write to a file descriptor the encrypted data - from buf. This data will be preceded by a 4 byte 'byte count' and - will be padded out to 8 bytes. The encryption is either CBC of - PCBC depending on the value of des_rw_mode. If it is DES_PCBC_MODE, - pcbc is used, if DES_CBC_MODE, cbc is used. The default is to use - DES_PCBC_MODE. - -int des_enc_write( -int fd, -char *buf, -int len, -des_key_schedule ks, -des_cblock *iv); - This routines read stuff written by des_enc_read() and decrypts it. - I have used these routines quite a lot but I don't believe they are - suitable for non-blocking io. If you are after a full - authentication/encryption over networks, have a look at SSL instead. - -unsigned long des_quad_cksum( -des_cblock *input, -des_cblock *output, -long length, -int out_count, -des_cblock *seed); - This is a function from Kerberos v4 that is not anything to do with - DES but was needed. It is a cksum that is quicker to generate than - des_cbc_cksum(); I personally would use MD5 routines now. -===== -Modes of DES -Quite a bit of the following information has been taken from - AS 2805.5.2 - Australian Standard - Electronic funds transfer - Requirements for interfaces, - Part 5.2: Modes of operation for an n-bit block cipher algorithm - Appendix A - -There are several different modes in which DES can be used, they are -as follows. - -Electronic Codebook Mode (ECB) (des_ecb_encrypt()) -- 64 bits are enciphered at a time. -- The order of the blocks can be rearranged without detection. -- The same plaintext block always produces the same ciphertext block - (for the same key) making it vulnerable to a 'dictionary attack'. -- An error will only affect one ciphertext block. - -Cipher Block Chaining Mode (CBC) (des_cbc_encrypt()) -- a multiple of 64 bits are enciphered at a time. -- The CBC mode produces the same ciphertext whenever the same - plaintext is encrypted using the same key and starting variable. -- The chaining operation makes the ciphertext blocks dependent on the - current and all preceding plaintext blocks and therefore blocks can not - be rearranged. -- The use of different starting variables prevents the same plaintext - enciphering to the same ciphertext. -- An error will affect the current and the following ciphertext blocks. - -Cipher Feedback Mode (CFB) (des_cfb_encrypt()) -- a number of bits (j) <= 64 are enciphered at a time. -- The CFB mode produces the same ciphertext whenever the same - plaintext is encrypted using the same key and starting variable. -- The chaining operation makes the ciphertext variables dependent on the - current and all preceding variables and therefore j-bit variables are - chained together and can not be rearranged. -- The use of different starting variables prevents the same plaintext - enciphering to the same ciphertext. -- The strength of the CFB mode depends on the size of k (maximal if - j == k). In my implementation this is always the case. -- Selection of a small value for j will require more cycles through - the encipherment algorithm per unit of plaintext and thus cause - greater processing overheads. -- Only multiples of j bits can be enciphered. -- An error will affect the current and the following ciphertext variables. - -Output Feedback Mode (OFB) (des_ofb_encrypt()) -- a number of bits (j) <= 64 are enciphered at a time. -- The OFB mode produces the same ciphertext whenever the same - plaintext enciphered using the same key and starting variable. More - over, in the OFB mode the same key stream is produced when the same - key and start variable are used. Consequently, for security reasons - a specific start variable should be used only once for a given key. -- The absence of chaining makes the OFB more vulnerable to specific attacks. -- The use of different start variables values prevents the same - plaintext enciphering to the same ciphertext, by producing different - key streams. -- Selection of a small value for j will require more cycles through - the encipherment algorithm per unit of plaintext and thus cause - greater processing overheads. -- Only multiples of j bits can be enciphered. -- OFB mode of operation does not extend ciphertext errors in the - resultant plaintext output. Every bit error in the ciphertext causes - only one bit to be in error in the deciphered plaintext. -- OFB mode is not self-synchronising. If the two operation of - encipherment and decipherment get out of synchronism, the system needs - to be re-initialised. -- Each re-initialisation should use a value of the start variable - different from the start variable values used before with the same - key. The reason for this is that an identical bit stream would be - produced each time from the same parameters. This would be - susceptible to a ' known plaintext' attack. - -Triple ECB Mode (des_ecb3_encrypt()) -- Encrypt with key1, decrypt with key2 and encrypt with key3 again. -- As for ECB encryption but increases the key length to 168 bits. - There are theoretic attacks that can be used that make the effective - key length 112 bits, but this attack also requires 2^56 blocks of - memory, not very likely, even for the NSA. -- If both keys are the same it is equivalent to encrypting once with - just one key. -- If the first and last key are the same, the key length is 112 bits. - There are attacks that could reduce the key space to 55 bit's but it - requires 2^56 blocks of memory. -- If all 3 keys are the same, this is effectively the same as normal - ecb mode. - -Triple CBC Mode (des_ede3_cbc_encrypt()) -- Encrypt with key1, decrypt with key2 and then encrypt with key3. -- As for CBC encryption but increases the key length to 168 bits with - the same restrictions as for triple ecb mode. diff --git a/mac/libdes/src/des.dsp b/mac/libdes/src/des.dsp deleted file mode 100755 index f669b4fe..00000000 --- a/mac/libdes/src/des.dsp +++ /dev/null @@ -1 +0,0 @@ -# Microsoft Developer Studio Project File - Name="des" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 5.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 CFG=des - Win32 Release !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "des.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "des.mak" CFG="des - Win32 Release" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "des - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE "des - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE # Begin Project # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe MTL=midl.exe RSC=rc.exe !IF "$(CFG)" == "des - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir ".\Release" # PROP BASE Intermediate_Dir ".\Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir ".\Release" # PROP Intermediate_Dir ".\Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c # ADD CPP /nologo /MT /W3 /GX /O2 /I "..\roken" /I "." /I "..\..\include" /I "..\..\include\win32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "HAVE_CONFIG_H" /YX /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 # ADD LINK32 ..\roken\Release\roken.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /machine:I386 !ELSEIF "$(CFG)" == "des - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir ".\Debug" # PROP BASE Intermediate_Dir ".\Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir ".\Debug" # PROP Intermediate_Dir ".\Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c # ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\roken" /I "." /I "..\..\include" /I "..\..\include\win32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "HAVE_CONFIG_H" /YX /FD /c # ADD BASE MTL /nologo /D "_DEBUG" /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 # ADD LINK32 ..\roken\Debug\roken.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /debug /machine:I386 !ENDIF # Begin Target # Name "des - Win32 Release" # Name "des - Win32 Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90" # Begin Source File SOURCE=.\cbc3_enc.c # End Source File # Begin Source File SOURCE=.\cbc_cksm.c # End Source File # Begin Source File SOURCE=.\cbc_enc.c # End Source File # Begin Source File SOURCE=.\cfb64ede.c # End Source File # Begin Source File SOURCE=.\cfb64enc.c # End Source File # Begin Source File SOURCE=.\cfb_enc.c # End Source File # Begin Source File SOURCE=.\des.def # End Source File # Begin Source File SOURCE=.\des_enc.c # End Source File # Begin Source File SOURCE=.\dllmain.c # End Source File # Begin Source File SOURCE=.\ecb3_enc.c # End Source File # Begin Source File SOURCE=.\ecb_enc.c # End Source File # Begin Source File SOURCE=.\ede_enc.c # End Source File # Begin Source File SOURCE=.\enc_read.c # End Source File # Begin Source File SOURCE=.\enc_writ.c # End Source File # Begin Source File SOURCE=.\fcrypt.c # End Source File # Begin Source File SOURCE=.\key_par.c # End Source File # Begin Source File SOURCE=.\ncbc_enc.c # End Source File # Begin Source File SOURCE=.\ofb64ede.c # End Source File # Begin Source File SOURCE=.\ofb64enc.c # End Source File # Begin Source File SOURCE=.\ofb_enc.c # End Source File # Begin Source File SOURCE=.\passwd_dlg.c # End Source File # Begin Source File SOURCE=.\pcbc_enc.c # End Source File # Begin Source File SOURCE=.\qud_cksm.c # End Source File # Begin Source File SOURCE=.\read_pwd.c # End Source File # Begin Source File SOURCE=.\rnd_keys.c # End Source File # Begin Source File SOURCE=.\rpc_enc.c # End Source File # Begin Source File SOURCE=.\set_key.c # End Source File # Begin Source File SOURCE=.\str2key.c # End Source File # Begin Source File SOURCE=.\supp.c # End Source File # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" # Begin Source File SOURCE=.\des.h # End Source File # Begin Source File SOURCE=.\des_locl.h # End Source File # Begin Source File SOURCE=.\des_ver.h # End Source File # Begin Source File SOURCE=.\md5.h # End Source File # Begin Source File SOURCE=.\passwd_dlg.h # End Source File # Begin Source File SOURCE=.\podd.h # End Source File # Begin Source File SOURCE=.\rpc_des.h # End Source File # Begin Source File SOURCE=.\sk.h # End Source File # Begin Source File SOURCE=.\spr.h # End Source File # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe" # Begin Source File SOURCE=.\passwd_dialog.rc # End Source File # End Group # End Target # End Project \ No newline at end of file diff --git a/mac/libdes/src/des.mak b/mac/libdes/src/des.mak deleted file mode 100755 index 05525073..00000000 --- a/mac/libdes/src/des.mak +++ /dev/null @@ -1 +0,0 @@ -# Microsoft Developer Studio Generated NMAKE File, Based on des.dsp !IF "$(CFG)" == "" CFG=des - Win32 Release !MESSAGE No configuration specified. Defaulting to des - Win32 Release. !ENDIF !IF "$(CFG)" != "des - Win32 Release" && "$(CFG)" != "des - Win32 Debug" !MESSAGE Invalid configuration "$(CFG)" specified. !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "des.mak" CFG="des - Win32 Release" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "des - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE "des - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE !ERROR An invalid configuration is specified. !ENDIF !IF "$(OS)" == "Windows_NT" NULL= !ELSE NULL=nul !ENDIF !IF "$(CFG)" == "des - Win32 Release" OUTDIR=.\Release INTDIR=.\Release # Begin Custom Macros OutDir=.\.\Release # End Custom Macros !IF "$(RECURSE)" == "0" ALL : "$(OUTDIR)\des.dll" !ELSE ALL : "roken - Win32 Release" "$(OUTDIR)\des.dll" !ENDIF !IF "$(RECURSE)" == "1" CLEAN :"roken - Win32 ReleaseCLEAN" !ELSE CLEAN : !ENDIF -@erase "$(INTDIR)\cbc3_enc.obj" -@erase "$(INTDIR)\cbc_cksm.obj" -@erase "$(INTDIR)\cbc_enc.obj" -@erase "$(INTDIR)\cfb64ede.obj" -@erase "$(INTDIR)\cfb64enc.obj" -@erase "$(INTDIR)\cfb_enc.obj" -@erase "$(INTDIR)\des_enc.obj" -@erase "$(INTDIR)\dllmain.obj" -@erase "$(INTDIR)\ecb3_enc.obj" -@erase "$(INTDIR)\ecb_enc.obj" -@erase "$(INTDIR)\ede_enc.obj" -@erase "$(INTDIR)\enc_read.obj" -@erase "$(INTDIR)\enc_writ.obj" -@erase "$(INTDIR)\fcrypt.obj" -@erase "$(INTDIR)\key_par.obj" -@erase "$(INTDIR)\ncbc_enc.obj" -@erase "$(INTDIR)\ofb64ede.obj" -@erase "$(INTDIR)\ofb64enc.obj" -@erase "$(INTDIR)\ofb_enc.obj" -@erase "$(INTDIR)\passwd_dialog.res" -@erase "$(INTDIR)\passwd_dlg.obj" -@erase "$(INTDIR)\pcbc_enc.obj" -@erase "$(INTDIR)\qud_cksm.obj" -@erase "$(INTDIR)\read_pwd.obj" -@erase "$(INTDIR)\rnd_keys.obj" -@erase "$(INTDIR)\rpc_enc.obj" -@erase "$(INTDIR)\set_key.obj" -@erase "$(INTDIR)\str2key.obj" -@erase "$(INTDIR)\supp.obj" -@erase "$(INTDIR)\vc50.idb" -@erase "$(OUTDIR)\des.dll" -@erase "$(OUTDIR)\des.exp" -@erase "$(OUTDIR)\des.lib" "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP=cl.exe CPP_PROJ=/nologo /MT /W3 /GX /O2 /I "..\roken" /I "." /I "..\..\include" /I\ "..\..\include\win32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "HAVE_CONFIG_H"\ /Fp"$(INTDIR)\des.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c CPP_OBJS=.\Release/ CPP_SBRS=. .c{$(CPP_OBJS)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(CPP_OBJS)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(CPP_OBJS)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(CPP_SBRS)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(CPP_SBRS)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(CPP_SBRS)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << MTL=midl.exe MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 RSC=rc.exe RSC_PROJ=/l 0x409 /fo"$(INTDIR)\passwd_dialog.res" /d "NDEBUG" BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\des.bsc" BSC32_SBRS= \ LINK32=link.exe LINK32_FLAGS=..\roken\Release\roken.lib kernel32.lib user32.lib gdi32.lib\ winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib\ uuid.lib /nologo /subsystem:windows /dll /incremental:no\ /pdb:"$(OUTDIR)\des.pdb" /machine:I386 /def:".\des.def"\ /out:"$(OUTDIR)\des.dll" /implib:"$(OUTDIR)\des.lib" DEF_FILE= \ ".\des.def" LINK32_OBJS= \ "$(INTDIR)\cbc3_enc.obj" \ "$(INTDIR)\cbc_cksm.obj" \ "$(INTDIR)\cbc_enc.obj" \ "$(INTDIR)\cfb64ede.obj" \ "$(INTDIR)\cfb64enc.obj" \ "$(INTDIR)\cfb_enc.obj" \ "$(INTDIR)\des_enc.obj" \ "$(INTDIR)\dllmain.obj" \ "$(INTDIR)\ecb3_enc.obj" \ "$(INTDIR)\ecb_enc.obj" \ "$(INTDIR)\ede_enc.obj" \ "$(INTDIR)\enc_read.obj" \ "$(INTDIR)\enc_writ.obj" \ "$(INTDIR)\fcrypt.obj" \ "$(INTDIR)\key_par.obj" \ "$(INTDIR)\ncbc_enc.obj" \ "$(INTDIR)\ofb64ede.obj" \ "$(INTDIR)\ofb64enc.obj" \ "$(INTDIR)\ofb_enc.obj" \ "$(INTDIR)\passwd_dialog.res" \ "$(INTDIR)\passwd_dlg.obj" \ "$(INTDIR)\pcbc_enc.obj" \ "$(INTDIR)\qud_cksm.obj" \ "$(INTDIR)\read_pwd.obj" \ "$(INTDIR)\rnd_keys.obj" \ "$(INTDIR)\rpc_enc.obj" \ "$(INTDIR)\set_key.obj" \ "$(INTDIR)\str2key.obj" \ "$(INTDIR)\supp.obj" \ "..\roken\Release\roken.lib" "$(OUTDIR)\des.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << !ELSEIF "$(CFG)" == "des - Win32 Debug" OUTDIR=.\Debug INTDIR=.\Debug # Begin Custom Macros OutDir=.\.\Debug # End Custom Macros !IF "$(RECURSE)" == "0" ALL : "$(OUTDIR)\des.dll" !ELSE ALL : "roken - Win32 Debug" "$(OUTDIR)\des.dll" !ENDIF !IF "$(RECURSE)" == "1" CLEAN :"roken - Win32 DebugCLEAN" !ELSE CLEAN : !ENDIF -@erase "$(INTDIR)\cbc3_enc.obj" -@erase "$(INTDIR)\cbc_cksm.obj" -@erase "$(INTDIR)\cbc_enc.obj" -@erase "$(INTDIR)\cfb64ede.obj" -@erase "$(INTDIR)\cfb64enc.obj" -@erase "$(INTDIR)\cfb_enc.obj" -@erase "$(INTDIR)\des_enc.obj" -@erase "$(INTDIR)\dllmain.obj" -@erase "$(INTDIR)\ecb3_enc.obj" -@erase "$(INTDIR)\ecb_enc.obj" -@erase "$(INTDIR)\ede_enc.obj" -@erase "$(INTDIR)\enc_read.obj" -@erase "$(INTDIR)\enc_writ.obj" -@erase "$(INTDIR)\fcrypt.obj" -@erase "$(INTDIR)\key_par.obj" -@erase "$(INTDIR)\ncbc_enc.obj" -@erase "$(INTDIR)\ofb64ede.obj" -@erase "$(INTDIR)\ofb64enc.obj" -@erase "$(INTDIR)\ofb_enc.obj" -@erase "$(INTDIR)\passwd_dialog.res" -@erase "$(INTDIR)\passwd_dlg.obj" -@erase "$(INTDIR)\pcbc_enc.obj" -@erase "$(INTDIR)\qud_cksm.obj" -@erase "$(INTDIR)\read_pwd.obj" -@erase "$(INTDIR)\rnd_keys.obj" -@erase "$(INTDIR)\rpc_enc.obj" -@erase "$(INTDIR)\set_key.obj" -@erase "$(INTDIR)\str2key.obj" -@erase "$(INTDIR)\supp.obj" -@erase "$(INTDIR)\vc50.idb" -@erase "$(INTDIR)\vc50.pdb" -@erase "$(OUTDIR)\des.dll" -@erase "$(OUTDIR)\des.exp" -@erase "$(OUTDIR)\des.ilk" -@erase "$(OUTDIR)\des.lib" -@erase "$(OUTDIR)\des.pdb" "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP=cl.exe CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\roken" /I "." /I\ "..\..\include" /I "..\..\include\win32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS"\ /D "HAVE_CONFIG_H" /Fp"$(INTDIR)\des.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\"\ /FD /c CPP_OBJS=.\Debug/ CPP_SBRS=. .c{$(CPP_OBJS)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(CPP_OBJS)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(CPP_OBJS)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(CPP_SBRS)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(CPP_SBRS)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(CPP_SBRS)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << MTL=midl.exe MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 RSC=rc.exe RSC_PROJ=/l 0x409 /fo"$(INTDIR)\passwd_dialog.res" /d "_DEBUG" BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\des.bsc" BSC32_SBRS= \ LINK32=link.exe LINK32_FLAGS=..\roken\Debug\roken.lib kernel32.lib user32.lib gdi32.lib\ winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib\ uuid.lib /nologo /subsystem:windows /dll /incremental:yes\ /pdb:"$(OUTDIR)\des.pdb" /debug /machine:I386 /def:".\des.def"\ /out:"$(OUTDIR)\des.dll" /implib:"$(OUTDIR)\des.lib" DEF_FILE= \ ".\des.def" LINK32_OBJS= \ "$(INTDIR)\cbc3_enc.obj" \ "$(INTDIR)\cbc_cksm.obj" \ "$(INTDIR)\cbc_enc.obj" \ "$(INTDIR)\cfb64ede.obj" \ "$(INTDIR)\cfb64enc.obj" \ "$(INTDIR)\cfb_enc.obj" \ "$(INTDIR)\des_enc.obj" \ "$(INTDIR)\dllmain.obj" \ "$(INTDIR)\ecb3_enc.obj" \ "$(INTDIR)\ecb_enc.obj" \ "$(INTDIR)\ede_enc.obj" \ "$(INTDIR)\enc_read.obj" \ "$(INTDIR)\enc_writ.obj" \ "$(INTDIR)\fcrypt.obj" \ "$(INTDIR)\key_par.obj" \ "$(INTDIR)\ncbc_enc.obj" \ "$(INTDIR)\ofb64ede.obj" \ "$(INTDIR)\ofb64enc.obj" \ "$(INTDIR)\ofb_enc.obj" \ "$(INTDIR)\passwd_dialog.res" \ "$(INTDIR)\passwd_dlg.obj" \ "$(INTDIR)\pcbc_enc.obj" \ "$(INTDIR)\qud_cksm.obj" \ "$(INTDIR)\read_pwd.obj" \ "$(INTDIR)\rnd_keys.obj" \ "$(INTDIR)\rpc_enc.obj" \ "$(INTDIR)\set_key.obj" \ "$(INTDIR)\str2key.obj" \ "$(INTDIR)\supp.obj" \ "..\roken\Debug\roken.lib" "$(OUTDIR)\des.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << !ENDIF !IF "$(CFG)" == "des - Win32 Release" || "$(CFG)" == "des - Win32 Debug" SOURCE=.\cbc3_enc.c DEP_CPP_CBC3_=\ "..\..\include\win32\config.h"\ ".\des.h"\ ".\des_locl.h"\ "$(INTDIR)\cbc3_enc.obj" : $(SOURCE) $(DEP_CPP_CBC3_) "$(INTDIR)" SOURCE=.\cbc_cksm.c DEP_CPP_CBC_C=\ "..\..\include\win32\config.h"\ ".\des.h"\ ".\des_locl.h"\ "$(INTDIR)\cbc_cksm.obj" : $(SOURCE) $(DEP_CPP_CBC_C) "$(INTDIR)" SOURCE=.\cbc_enc.c DEP_CPP_CBC_E=\ "..\..\include\win32\config.h"\ ".\des.h"\ ".\des_locl.h"\ "$(INTDIR)\cbc_enc.obj" : $(SOURCE) $(DEP_CPP_CBC_E) "$(INTDIR)" SOURCE=.\cfb64ede.c DEP_CPP_CFB64=\ "..\..\include\win32\config.h"\ ".\des.h"\ ".\des_locl.h"\ "$(INTDIR)\cfb64ede.obj" : $(SOURCE) $(DEP_CPP_CFB64) "$(INTDIR)" SOURCE=.\cfb64enc.c DEP_CPP_CFB64E=\ "..\..\include\win32\config.h"\ ".\des.h"\ ".\des_locl.h"\ "$(INTDIR)\cfb64enc.obj" : $(SOURCE) $(DEP_CPP_CFB64E) "$(INTDIR)" SOURCE=.\cfb_enc.c DEP_CPP_CFB_E=\ "..\..\include\win32\config.h"\ ".\des.h"\ ".\des_locl.h"\ "$(INTDIR)\cfb_enc.obj" : $(SOURCE) $(DEP_CPP_CFB_E) "$(INTDIR)" SOURCE=.\des_enc.c DEP_CPP_DES_E=\ "..\..\include\win32\config.h"\ ".\des.h"\ ".\des_locl.h"\ "$(INTDIR)\des_enc.obj" : $(SOURCE) $(DEP_CPP_DES_E) "$(INTDIR)" SOURCE=.\dllmain.c DEP_CPP_DLLMA=\ "..\..\include\win32\config.h"\ "$(INTDIR)\dllmain.obj" : $(SOURCE) $(DEP_CPP_DLLMA) "$(INTDIR)" SOURCE=.\ecb3_enc.c DEP_CPP_ECB3_=\ "..\..\include\win32\config.h"\ ".\des.h"\ ".\des_locl.h"\ "$(INTDIR)\ecb3_enc.obj" : $(SOURCE) $(DEP_CPP_ECB3_) "$(INTDIR)" SOURCE=.\ecb_enc.c DEP_CPP_ECB_E=\ "..\..\include\win32\config.h"\ ".\des.h"\ ".\des_locl.h"\ ".\spr.h"\ "$(INTDIR)\ecb_enc.obj" : $(SOURCE) $(DEP_CPP_ECB_E) "$(INTDIR)" SOURCE=.\ede_enc.c DEP_CPP_EDE_E=\ "..\..\include\win32\config.h"\ ".\des.h"\ ".\des_locl.h"\ "$(INTDIR)\ede_enc.obj" : $(SOURCE) $(DEP_CPP_EDE_E) "$(INTDIR)" SOURCE=.\enc_read.c DEP_CPP_ENC_R=\ "..\..\include\win32\config.h"\ ".\des.h"\ ".\des_locl.h"\ "$(INTDIR)\enc_read.obj" : $(SOURCE) $(DEP_CPP_ENC_R) "$(INTDIR)" SOURCE=.\enc_writ.c DEP_CPP_ENC_W=\ "..\..\include\win32\config.h"\ ".\des.h"\ ".\des_locl.h"\ "$(INTDIR)\enc_writ.obj" : $(SOURCE) $(DEP_CPP_ENC_W) "$(INTDIR)" SOURCE=.\fcrypt.c DEP_CPP_FCRYP=\ "..\..\include\win32\config.h"\ "..\..\include\win32\ktypes.h"\ ".\des.h"\ ".\des_locl.h"\ ".\md5.h"\ {$(INCLUDE)}"sys\types.h"\ "$(INTDIR)\fcrypt.obj" : $(SOURCE) $(DEP_CPP_FCRYP) "$(INTDIR)" SOURCE=.\key_par.c DEP_CPP_KEY_P=\ "..\..\include\win32\config.h"\ ".\des.h"\ ".\des_locl.h"\ "$(INTDIR)\key_par.obj" : $(SOURCE) $(DEP_CPP_KEY_P) "$(INTDIR)" SOURCE=.\ncbc_enc.c DEP_CPP_NCBC_=\ "..\..\include\win32\config.h"\ ".\des.h"\ ".\des_locl.h"\ "$(INTDIR)\ncbc_enc.obj" : $(SOURCE) $(DEP_CPP_NCBC_) "$(INTDIR)" SOURCE=.\ofb64ede.c DEP_CPP_OFB64=\ "..\..\include\win32\config.h"\ ".\des.h"\ ".\des_locl.h"\ "$(INTDIR)\ofb64ede.obj" : $(SOURCE) $(DEP_CPP_OFB64) "$(INTDIR)" SOURCE=.\ofb64enc.c DEP_CPP_OFB64E=\ "..\..\include\win32\config.h"\ ".\des.h"\ ".\des_locl.h"\ "$(INTDIR)\ofb64enc.obj" : $(SOURCE) $(DEP_CPP_OFB64E) "$(INTDIR)" SOURCE=.\ofb_enc.c DEP_CPP_OFB_E=\ "..\..\include\win32\config.h"\ ".\des.h"\ ".\des_locl.h"\ "$(INTDIR)\ofb_enc.obj" : $(SOURCE) $(DEP_CPP_OFB_E) "$(INTDIR)" SOURCE=.\passwd_dlg.c DEP_CPP_PASSW=\ "..\..\include\win32\config.h"\ ".\passwd_dlg.h"\ "$(INTDIR)\passwd_dlg.obj" : $(SOURCE) $(DEP_CPP_PASSW) "$(INTDIR)" SOURCE=.\pcbc_enc.c DEP_CPP_PCBC_=\ "..\..\include\win32\config.h"\ ".\des.h"\ ".\des_locl.h"\ "$(INTDIR)\pcbc_enc.obj" : $(SOURCE) $(DEP_CPP_PCBC_) "$(INTDIR)" SOURCE=.\qud_cksm.c DEP_CPP_QUD_C=\ "..\..\include\win32\config.h"\ ".\des.h"\ ".\des_locl.h"\ "$(INTDIR)\qud_cksm.obj" : $(SOURCE) $(DEP_CPP_QUD_C) "$(INTDIR)" SOURCE=.\read_pwd.c DEP_CPP_READ_=\ "..\..\include\win32\config.h"\ ".\des.h"\ ".\des_locl.h"\ "$(INTDIR)\read_pwd.obj" : $(SOURCE) $(DEP_CPP_READ_) "$(INTDIR)" SOURCE=.\rnd_keys.c DEP_CPP_RND_K=\ "..\..\include\win32\config.h"\ "..\..\include\win32\ktypes.h"\ ".\des.h"\ ".\des_locl.h"\ {$(INCLUDE)}"sys\types.h"\ "$(INTDIR)\rnd_keys.obj" : $(SOURCE) $(DEP_CPP_RND_K) "$(INTDIR)" SOURCE=.\rpc_enc.c DEP_CPP_RPC_E=\ "..\..\include\win32\config.h"\ ".\des.h"\ ".\des_locl.h"\ ".\des_ver.h"\ ".\rpc_des.h"\ "$(INTDIR)\rpc_enc.obj" : $(SOURCE) $(DEP_CPP_RPC_E) "$(INTDIR)" SOURCE=.\set_key.c DEP_CPP_SET_K=\ "..\..\include\win32\config.h"\ ".\des.h"\ ".\des_locl.h"\ ".\podd.h"\ ".\sk.h"\ "$(INTDIR)\set_key.obj" : $(SOURCE) $(DEP_CPP_SET_K) "$(INTDIR)" SOURCE=.\str2key.c DEP_CPP_STR2K=\ "..\..\include\win32\config.h"\ ".\des.h"\ ".\des_locl.h"\ "$(INTDIR)\str2key.obj" : $(SOURCE) $(DEP_CPP_STR2K) "$(INTDIR)" SOURCE=.\supp.c DEP_CPP_SUPP_=\ "..\..\include\win32\config.h"\ ".\des.h"\ ".\des_locl.h"\ "$(INTDIR)\supp.obj" : $(SOURCE) $(DEP_CPP_SUPP_) "$(INTDIR)" SOURCE=.\passwd_dialog.rc "$(INTDIR)\passwd_dialog.res" : $(SOURCE) "$(INTDIR)" $(RSC) $(RSC_PROJ) $(SOURCE) !IF "$(CFG)" == "des - Win32 Release" "roken - Win32 Release" : cd "\tmp\wirus-krb\krb4-pre-0.9.9\lib\roken" $(MAKE) /$(MAKEFLAGS) /F ".\roken.mak" CFG="roken - Win32 Release" cd "..\des" "roken - Win32 ReleaseCLEAN" : cd "\tmp\wirus-krb\krb4-pre-0.9.9\lib\roken" $(MAKE) /$(MAKEFLAGS) CLEAN /F ".\roken.mak" CFG="roken - Win32 Release"\ RECURSE=1 cd "..\des" !ELSEIF "$(CFG)" == "des - Win32 Debug" "roken - Win32 Debug" : cd "\tmp\wirus-krb\krb4-pre-0.9.9\lib\roken" $(MAKE) /$(MAKEFLAGS) /F ".\roken.mak" CFG="roken - Win32 Debug" cd "..\des" "roken - Win32 DebugCLEAN" : cd "\tmp\wirus-krb\krb4-pre-0.9.9\lib\roken" $(MAKE) /$(MAKEFLAGS) CLEAN /F ".\roken.mak" CFG="roken - Win32 Debug"\ RECURSE=1 cd "..\des" !ENDIF !ENDIF \ No newline at end of file diff --git a/mac/libdes/src/des.man b/mac/libdes/src/des.man deleted file mode 100755 index 658bf924..00000000 --- a/mac/libdes/src/des.man +++ /dev/null @@ -1 +0,0 @@ -.TH DES 1 .SH NAME des - encrypt or decrypt data using Data Encryption Standard .SH SYNOPSIS .B des ( .B \-e | .B \-E ) | ( .B \-d | .B \-D ) | ( .B \-\fR[\fPcC\fR][\fPckname\fR]\fP ) | [ .B \-b3hfs ] [ .B \-k .I key ] ] [ .B \-u\fR[\fIuuname\fR] [ .I input-file [ .I output-file ] ] .SH DESCRIPTION .B des encrypts and decrypts data using the Data Encryption Standard algorithm. One of .B \-e, \-E (for encrypt) or .B \-d, \-D (for decrypt) must be specified. It is also possible to use .B \-c or .B \-C in conjunction or instead of the a encrypt/decrypt option to generate a 16 character hexadecimal checksum, generated via the .I des_cbc_cksum. .LP Two standard encryption modes are supported by the .B des program, Cipher Block Chaining (the default) and Electronic Code Book (specified with .B \-b ). .LP The key used for the DES algorithm is obtained by prompting the user unless the .B `\-k .I key' option is given. If the key is an argument to the .B des command, it is potentially visible to users executing .BR ps (1) or a derivative. To minimise this possibility, .B des takes care to destroy the key argument immediately upon entry. If your shell keeps a history file be careful to make sure it is not world readable. .LP Since this program attempts to maintain compatability with sunOS's des(1) command, there are 2 different methods used to convert the user supplied key to a des key. Whenever and one or more of .B \-E, \-D, \-C or .B \-3 options are used, the key conversion procedure will not be compatible with the sunOS des(1) version but will use all the user supplied character to generate the des key. .B des command reads from standard input unless .I input-file is specified and writes to standard output unless .I output-file is given. .SH OPTIONS .TP .B \-b Select ECB (eight bytes at a time) encryption mode. .TP .B \-3 Encrypt using triple encryption. By default triple cbc encryption is used but if the .B \-b option is used then triple ecb encryption is performed. If the key is less than 8 characters long, the flag has no effect. .TP .B \-e Encrypt data using an 8 byte key in a manner compatible with sunOS des(1). .TP .B \-E Encrypt data using a key of nearly unlimited length (1024 bytes). This will product a more secure encryption. .TP .B \-d Decrypt data that was encrypted with the \-e option. .TP .B \-D Decrypt data that was encrypted with the \-E option. .TP .B \-c Generate a 16 character hexadecimal cbc checksum and output this to stderr. If a filename was specified after the .B \-c option, the checksum is output to that file. The checksum is generated using a key generated in a sunOS compatible manner. .TP .B \-C A cbc checksum is generated in the same manner as described for the .B \-c option but the DES key is generated in the same manner as used for the .B \-E and .B \-D options .TP .B \-f Does nothing - allowed for compatibility with sunOS des(1) command. .TP .B \-s Does nothing - allowed for compatibility with sunOS des(1) command. .TP .B "\-k \fIkey\fP" Use the encryption .I key specified. .TP .B "\-h" The .I key is assumed to be a 16 character hexadecimal number. If the .B "\-3" option is used the key is assumed to be a 32 character hexadecimal number. .TP .B \-u This flag is used to read and write uuencoded files. If decrypting, the input file is assumed to contain uuencoded, DES encrypted data. If encrypting, the characters following the -u are used as the name of the uuencoded file to embed in the begin line of the uuencoded output. If there is no name specified after the -u, the name text.des will be embedded in the header. .SH SEE ALSO .B ps (1) .B des_crypt(3) .SH BUGS .LP The problem with using the .B -e option is the short key length. It would be better to use a real 56-bit key rather than an ASCII-based 56-bit pattern. Knowing that the key was derived from ASCII radically reduces the time necessary for a brute-force cryptographic attack. My attempt to remove this problem is to add an alternative text-key to DES-key function. This alternative function (accessed via .B -E, -D, -S and .B -3 ) uses DES to help generate the key. .LP Be carefully when using the -u option. Doing des -ud will not decrypt filename (the -u option will gobble the d option). .LP The VMS operating system operates in a world where files are always a multiple of 512 bytes. This causes problems when encrypted data is send from unix to VMS since a 88 byte file will suddenly be padded with 424 null bytes. To get around this problem, use the -u option to uuencode the data before it is send to the VMS system. .SH AUTHOR .LP Eric Young (eay@mincom.oz.au or eay@psych.psy.uq.oz.au) \ No newline at end of file diff --git a/mac/libdes/src/des.org b/mac/libdes/src/des.org deleted file mode 100755 index dcf79a5f..00000000 --- a/mac/libdes/src/des.org +++ /dev/null @@ -1 +0,0 @@ -/* crypto/des/des.h */ /* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@mincom.oz.au). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@mincom.oz.au). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@mincom.oz.au)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ #ifndef HEADER_DES_H #define HEADER_DES_H #ifdef __cplusplus extern "C" { #endif #include /* If this is set to 'unsigned int' on a DEC Alpha, this gives about a * %20 speed up (longs are 8 bytes, int's are 4). */ #ifndef DES_LONG #define DES_LONG unsigned long #endif typedef unsigned char des_cblock[8]; typedef struct des_ks_struct { union { des_cblock _; /* make sure things are correct size on machines with * 8 byte longs */ DES_LONG pad[2]; } ks; #undef _ #define _ ks._ } des_key_schedule[16]; #define DES_KEY_SZ (sizeof(des_cblock)) #define DES_SCHEDULE_SZ (sizeof(des_key_schedule)) #define DES_ENCRYPT 1 #define DES_DECRYPT 0 #define DES_CBC_MODE 0 #define DES_PCBC_MODE 1 #define des_ecb2_encrypt(i,o,k1,k2,e) \ des_ecb3_encrypt((i),(o),(k1),(k2),(k1),(e)) #define des_ede2_cbc_encrypt(i,o,l,k1,k2,iv,e) \ des_ede3_cbc_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(e)) #define des_ede2_cfb64_encrypt(i,o,l,k1,k2,iv,n,e) \ des_ede3_cfb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n),(e)) #define des_ede2_ofb64_encrypt(i,o,l,k1,k2,iv,n) \ des_ede3_ofb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n)) #define C_Block des_cblock #define Key_schedule des_key_schedule #ifdef KERBEROS #define ENCRYPT DES_ENCRYPT #define DECRYPT DES_DECRYPT #endif #define KEY_SZ DES_KEY_SZ #define string_to_key des_string_to_key #define read_pw_string des_read_pw_string #define random_key des_random_key #define pcbc_encrypt des_pcbc_encrypt #define set_key des_set_key #define key_sched des_key_sched #define ecb_encrypt des_ecb_encrypt #define cbc_encrypt des_cbc_encrypt #define ncbc_encrypt des_ncbc_encrypt #define xcbc_encrypt des_xcbc_encrypt #define cbc_cksum des_cbc_cksum #define quad_cksum des_quad_cksum /* For compatibility with the MIT lib - eay 20/05/92 */ typedef des_key_schedule bit_64; #define des_fixup_key_parity des_set_odd_parity #define des_check_key_parity check_parity extern int des_check_key; /* defaults to false */ extern int des_rw_mode; /* defaults to DES_PCBC_MODE */ /* The next line is used to disable full ANSI prototypes, if your * compiler has problems with the prototypes, make sure this line always * evaluates to true :-) */ #if defined(MSDOS) || defined(__STDC__) #undef NOPROTO #endif #ifndef NOPROTO char *des_options(void); void des_ecb3_encrypt(des_cblock *input,des_cblock *output, des_key_schedule ks1,des_key_schedule ks2, des_key_schedule ks3, int enc); DES_LONG des_cbc_cksum(des_cblock *input,des_cblock *output, long length,des_key_schedule schedule,des_cblock *ivec); void des_cbc_encrypt(des_cblock *input,des_cblock *output,long length, des_key_schedule schedule,des_cblock *ivec,int enc); void des_ncbc_encrypt(des_cblock *input,des_cblock *output,long length, des_key_schedule schedule,des_cblock *ivec,int enc); void des_xcbc_encrypt(des_cblock *input,des_cblock *output,long length, des_key_schedule schedule,des_cblock *ivec, des_cblock *inw,des_cblock *outw,int enc); void des_3cbc_encrypt(des_cblock *input,des_cblock *output,long length, des_key_schedule sk1,des_key_schedule sk2, des_cblock *ivec1,des_cblock *ivec2,int enc); void des_cfb_encrypt(unsigned char *in,unsigned char *out,int numbits, long length,des_key_schedule schedule,des_cblock *ivec,int enc); void des_ecb_encrypt(des_cblock *input,des_cblock *output, des_key_schedule ks,int enc); void des_encrypt(DES_LONG *data,des_key_schedule ks, int enc); void des_encrypt2(DES_LONG *data,des_key_schedule ks, int enc); void des_encrypt3(DES_LONG *data, des_key_schedule ks1, des_key_schedule ks2, des_key_schedule ks3); void des_decrypt3(DES_LONG *data, des_key_schedule ks1, des_key_schedule ks2, des_key_schedule ks3); void des_ede3_cbc_encrypt(des_cblock *input, des_cblock *output, long length, des_key_schedule ks1, des_key_schedule ks2, des_key_schedule ks3, des_cblock *ivec, int enc); void des_ede3_cfb64_encrypt(unsigned char *in, unsigned char *out, long length, des_key_schedule ks1, des_key_schedule ks2, des_key_schedule ks3, des_cblock *ivec, int *num, int encrypt); void des_ede3_ofb64_encrypt(unsigned char *in, unsigned char *out, long length, des_key_schedule ks1, des_key_schedule ks2, des_key_schedule ks3, des_cblock *ivec, int *num); int des_enc_read(int fd,char *buf,int len,des_key_schedule sched, des_cblock *iv); int des_enc_write(int fd,char *buf,int len,des_key_schedule sched, des_cblock *iv); char *des_fcrypt(const char *buf,const char *salt, char *ret); #ifdef PERL5 char *des_crypt(const char *buf,const char *salt); #else /* some stupid compilers complain because I have declared char instead * of const char */ #ifdef HEADER_DES_LOCL_H char *crypt(const char *buf,const char *salt); #else char *crypt(); #endif #endif void des_ofb_encrypt(unsigned char *in,unsigned char *out, int numbits,long length,des_key_schedule schedule,des_cblock *ivec); void des_pcbc_encrypt(des_cblock *input,des_cblock *output,long length, des_key_schedule schedule,des_cblock *ivec,int enc); DES_LONG des_quad_cksum(des_cblock *input,des_cblock *output, long length,int out_count,des_cblock *seed); void des_random_seed(des_cblock key); void des_random_key(des_cblock ret); int des_read_password(des_cblock *key,char *prompt,int verify); int des_read_2passwords(des_cblock *key1,des_cblock *key2, char *prompt,int verify); int des_read_pw_string(char *buf,int length,char *prompt,int verify); void des_set_odd_parity(des_cblock *key); int des_is_weak_key(des_cblock *key); int des_set_key(des_cblock *key,des_key_schedule schedule); int des_key_sched(des_cblock *key,des_key_schedule schedule); void des_string_to_key(char *str,des_cblock *key); void des_string_to_2keys(char *str,des_cblock *key1,des_cblock *key2); void des_cfb64_encrypt(unsigned char *in, unsigned char *out, long length, des_key_schedule schedule, des_cblock *ivec, int *num, int enc); void des_ofb64_encrypt(unsigned char *in, unsigned char *out, long length, des_key_schedule schedule, des_cblock *ivec, int *num); /* Extra functions from Mark Murray */ void des_cblock_print_file(des_cblock *cb, FILE *fp); /* The following functions are not in the normal unix build or the * SSLeay build. When using the SSLeay build, use RAND_seed() * and RAND_bytes() instead. */ int des_new_random_key(des_cblock *key); void des_init_random_number_generator(des_cblock *key); void des_set_random_generator_seed(des_cblock *key); void des_set_sequence_number(des_cblock new_sequence_number); void des_generate_random_block(des_cblock *block); #else char *des_options(); void des_ecb3_encrypt(); DES_LONG des_cbc_cksum(); void des_cbc_encrypt(); void des_ncbc_encrypt(); void des_xcbc_encrypt(); void des_3cbc_encrypt(); void des_cfb_encrypt(); void des_ede3_cfb64_encrypt(); void des_ede3_ofb64_encrypt(); void des_ecb_encrypt(); void des_encrypt(); void des_encrypt2(); void des_encrypt3(); void des_decrypt3(); void des_ede3_cbc_encrypt(); int des_enc_read(); int des_enc_write(); char *des_fcrypt(); #ifdef PERL5 char *des_crypt(); #else char *crypt(); #endif void des_ofb_encrypt(); void des_pcbc_encrypt(); DES_LONG des_quad_cksum(); void des_random_seed(); void des_random_key(); int des_read_password(); int des_read_2passwords(); int des_read_pw_string(); void des_set_odd_parity(); int des_is_weak_key(); int des_set_key(); int des_key_sched(); void des_string_to_key(); void des_string_to_2keys(); void des_cfb64_encrypt(); void des_ofb64_encrypt(); /* Extra functions from Mark Murray */ void des_cblock_print_file(); /* The following functions are not in the normal unix build or the * SSLeay build. When using the SSLeay build, use RAND_seed() * and RAND_bytes() instead. */ #ifdef FreeBSD int des_new_random_key(); void des_init_random_number_generator(); void des_set_random_generator_seed(); void des_set_sequence_number(); void des_generate_random_block(); #endif #endif #ifdef __cplusplus } #endif #endif \ No newline at end of file diff --git a/mac/libdes/src/des.pl b/mac/libdes/src/des.pl deleted file mode 100755 index fbc808a3..00000000 --- a/mac/libdes/src/des.pl +++ /dev/null @@ -1 +0,0 @@ -#!/usr/local/bin/perl # des.pl - eric young 22/11/1991 eay@mincom.oz.au or eay@psych.psy.uq.oz.au # # Copyright (C) 1993 Eric Young # # 11 April 1996 - patched to circumvent Perl 5 (through 5.002) problem # with sign-extension on right shift operations. # Ed Kubaitis - ejk@uiuc.edu # # eay - 92/08/31 - I think I have fixed all problems for 64bit # versions of perl but I could be wrong since I have not tested it yet :-). # # This is an implementation of DES in perl. # The two routines (des_set_key and des_ecb_encrypt) # take 8 byte objects as arguments. # # des_set_key takes an 8 byte string as a key and returns a key schedule # for use in calls to des_ecb_encrypt. # des_ecb_encrypt takes three arguments, the first is a key schedule # (make sure to pass it by reference with the *), the second is 1 # to encrypt, 0 to decrypt. The third argument is an 8 byte object # to encrypt. The function returns an 8 byte object that has been # DES encrypted. # # example: # require 'des.pl' # # $key =pack("C8",0x12,0x23,0x45,0x67,0x89,0xab,0xcd,0xef); # @ks= &des_set_key($key); # # $outbytes= &des_ecb_encrypt(*ks,1,$data); # @enc =unpack("C8",$outbytes); # package des; eval("usr integer;") if (int($]) > 4); # The following 8 arrays are used in des_set_key @skb0=( # for C bits (numbered as per FIPS 46) 1 2 3 4 5 6 0x00000000,0x00000010,0x20000000,0x20000010, 0x00010000,0x00010010,0x20010000,0x20010010, 0x00000800,0x00000810,0x20000800,0x20000810, 0x00010800,0x00010810,0x20010800,0x20010810, 0x00000020,0x00000030,0x20000020,0x20000030, 0x00010020,0x00010030,0x20010020,0x20010030, 0x00000820,0x00000830,0x20000820,0x20000830, 0x00010820,0x00010830,0x20010820,0x20010830, 0x00080000,0x00080010,0x20080000,0x20080010, 0x00090000,0x00090010,0x20090000,0x20090010, 0x00080800,0x00080810,0x20080800,0x20080810, 0x00090800,0x00090810,0x20090800,0x20090810, 0x00080020,0x00080030,0x20080020,0x20080030, 0x00090020,0x00090030,0x20090020,0x20090030, 0x00080820,0x00080830,0x20080820,0x20080830, 0x00090820,0x00090830,0x20090820,0x20090830, ); @skb1=( # for C bits (numbered as per FIPS 46) 7 8 10 11 12 13 0x00000000,0x02000000,0x00002000,0x02002000, 0x00200000,0x02200000,0x00202000,0x02202000, 0x00000004,0x02000004,0x00002004,0x02002004, 0x00200004,0x02200004,0x00202004,0x02202004, 0x00000400,0x02000400,0x00002400,0x02002400, 0x00200400,0x02200400,0x00202400,0x02202400, 0x00000404,0x02000404,0x00002404,0x02002404, 0x00200404,0x02200404,0x00202404,0x02202404, 0x10000000,0x12000000,0x10002000,0x12002000, 0x10200000,0x12200000,0x10202000,0x12202000, 0x10000004,0x12000004,0x10002004,0x12002004, 0x10200004,0x12200004,0x10202004,0x12202004, 0x10000400,0x12000400,0x10002400,0x12002400, 0x10200400,0x12200400,0x10202400,0x12202400, 0x10000404,0x12000404,0x10002404,0x12002404, 0x10200404,0x12200404,0x10202404,0x12202404, ); @skb2=( # for C bits (numbered as per FIPS 46) 14 15 16 17 19 20 0x00000000,0x00000001,0x00040000,0x00040001, 0x01000000,0x01000001,0x01040000,0x01040001, 0x00000002,0x00000003,0x00040002,0x00040003, 0x01000002,0x01000003,0x01040002,0x01040003, 0x00000200,0x00000201,0x00040200,0x00040201, 0x01000200,0x01000201,0x01040200,0x01040201, 0x00000202,0x00000203,0x00040202,0x00040203, 0x01000202,0x01000203,0x01040202,0x01040203, 0x08000000,0x08000001,0x08040000,0x08040001, 0x09000000,0x09000001,0x09040000,0x09040001, 0x08000002,0x08000003,0x08040002,0x08040003, 0x09000002,0x09000003,0x09040002,0x09040003, 0x08000200,0x08000201,0x08040200,0x08040201, 0x09000200,0x09000201,0x09040200,0x09040201, 0x08000202,0x08000203,0x08040202,0x08040203, 0x09000202,0x09000203,0x09040202,0x09040203, ); @skb3=( # for C bits (numbered as per FIPS 46) 21 23 24 26 27 28 0x00000000,0x00100000,0x00000100,0x00100100, 0x00000008,0x00100008,0x00000108,0x00100108, 0x00001000,0x00101000,0x00001100,0x00101100, 0x00001008,0x00101008,0x00001108,0x00101108, 0x04000000,0x04100000,0x04000100,0x04100100, 0x04000008,0x04100008,0x04000108,0x04100108, 0x04001000,0x04101000,0x04001100,0x04101100, 0x04001008,0x04101008,0x04001108,0x04101108, 0x00020000,0x00120000,0x00020100,0x00120100, 0x00020008,0x00120008,0x00020108,0x00120108, 0x00021000,0x00121000,0x00021100,0x00121100, 0x00021008,0x00121008,0x00021108,0x00121108, 0x04020000,0x04120000,0x04020100,0x04120100, 0x04020008,0x04120008,0x04020108,0x04120108, 0x04021000,0x04121000,0x04021100,0x04121100, 0x04021008,0x04121008,0x04021108,0x04121108, ); @skb4=( # for D bits (numbered as per FIPS 46) 1 2 3 4 5 6 0x00000000,0x10000000,0x00010000,0x10010000, 0x00000004,0x10000004,0x00010004,0x10010004, 0x20000000,0x30000000,0x20010000,0x30010000, 0x20000004,0x30000004,0x20010004,0x30010004, 0x00100000,0x10100000,0x00110000,0x10110000, 0x00100004,0x10100004,0x00110004,0x10110004, 0x20100000,0x30100000,0x20110000,0x30110000, 0x20100004,0x30100004,0x20110004,0x30110004, 0x00001000,0x10001000,0x00011000,0x10011000, 0x00001004,0x10001004,0x00011004,0x10011004, 0x20001000,0x30001000,0x20011000,0x30011000, 0x20001004,0x30001004,0x20011004,0x30011004, 0x00101000,0x10101000,0x00111000,0x10111000, 0x00101004,0x10101004,0x00111004,0x10111004, 0x20101000,0x30101000,0x20111000,0x30111000, 0x20101004,0x30101004,0x20111004,0x30111004, ); @skb5=( # for D bits (numbered as per FIPS 46) 8 9 11 12 13 14 0x00000000,0x08000000,0x00000008,0x08000008, 0x00000400,0x08000400,0x00000408,0x08000408, 0x00020000,0x08020000,0x00020008,0x08020008, 0x00020400,0x08020400,0x00020408,0x08020408, 0x00000001,0x08000001,0x00000009,0x08000009, 0x00000401,0x08000401,0x00000409,0x08000409, 0x00020001,0x08020001,0x00020009,0x08020009, 0x00020401,0x08020401,0x00020409,0x08020409, 0x02000000,0x0A000000,0x02000008,0x0A000008, 0x02000400,0x0A000400,0x02000408,0x0A000408, 0x02020000,0x0A020000,0x02020008,0x0A020008, 0x02020400,0x0A020400,0x02020408,0x0A020408, 0x02000001,0x0A000001,0x02000009,0x0A000009, 0x02000401,0x0A000401,0x02000409,0x0A000409, 0x02020001,0x0A020001,0x02020009,0x0A020009, 0x02020401,0x0A020401,0x02020409,0x0A020409, ); @skb6=( # for D bits (numbered as per FIPS 46) 16 17 18 19 20 21 0x00000000,0x00000100,0x00080000,0x00080100, 0x01000000,0x01000100,0x01080000,0x01080100, 0x00000010,0x00000110,0x00080010,0x00080110, 0x01000010,0x01000110,0x01080010,0x01080110, 0x00200000,0x00200100,0x00280000,0x00280100, 0x01200000,0x01200100,0x01280000,0x01280100, 0x00200010,0x00200110,0x00280010,0x00280110, 0x01200010,0x01200110,0x01280010,0x01280110, 0x00000200,0x00000300,0x00080200,0x00080300, 0x01000200,0x01000300,0x01080200,0x01080300, 0x00000210,0x00000310,0x00080210,0x00080310, 0x01000210,0x01000310,0x01080210,0x01080310, 0x00200200,0x00200300,0x00280200,0x00280300, 0x01200200,0x01200300,0x01280200,0x01280300, 0x00200210,0x00200310,0x00280210,0x00280310, 0x01200210,0x01200310,0x01280210,0x01280310, ); @skb7=( # for D bits (numbered as per FIPS 46) 22 23 24 25 27 28 0x00000000,0x04000000,0x00040000,0x04040000, 0x00000002,0x04000002,0x00040002,0x04040002, 0x00002000,0x04002000,0x00042000,0x04042000, 0x00002002,0x04002002,0x00042002,0x04042002, 0x00000020,0x04000020,0x00040020,0x04040020, 0x00000022,0x04000022,0x00040022,0x04040022, 0x00002020,0x04002020,0x00042020,0x04042020, 0x00002022,0x04002022,0x00042022,0x04042022, 0x00000800,0x04000800,0x00040800,0x04040800, 0x00000802,0x04000802,0x00040802,0x04040802, 0x00002800,0x04002800,0x00042800,0x04042800, 0x00002802,0x04002802,0x00042802,0x04042802, 0x00000820,0x04000820,0x00040820,0x04040820, 0x00000822,0x04000822,0x00040822,0x04040822, 0x00002820,0x04002820,0x00042820,0x04042820, 0x00002822,0x04002822,0x00042822,0x04042822, ); @shifts2=(0,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0); # used in ecb_encrypt @SP0=( 0x00410100, 0x00010000, 0x40400000, 0x40410100, 0x00400000, 0x40010100, 0x40010000, 0x40400000, 0x40010100, 0x00410100, 0x00410000, 0x40000100, 0x40400100, 0x00400000, 0x00000000, 0x40010000, 0x00010000, 0x40000000, 0x00400100, 0x00010100, 0x40410100, 0x00410000, 0x40000100, 0x00400100, 0x40000000, 0x00000100, 0x00010100, 0x40410000, 0x00000100, 0x40400100, 0x40410000, 0x00000000, 0x00000000, 0x40410100, 0x00400100, 0x40010000, 0x00410100, 0x00010000, 0x40000100, 0x00400100, 0x40410000, 0x00000100, 0x00010100, 0x40400000, 0x40010100, 0x40000000, 0x40400000, 0x00410000, 0x40410100, 0x00010100, 0x00410000, 0x40400100, 0x00400000, 0x40000100, 0x40010000, 0x00000000, 0x00010000, 0x00400000, 0x40400100, 0x00410100, 0x40000000, 0x40410000, 0x00000100, 0x40010100, ); @SP1=( 0x08021002, 0x00000000, 0x00021000, 0x08020000, 0x08000002, 0x00001002, 0x08001000, 0x00021000, 0x00001000, 0x08020002, 0x00000002, 0x08001000, 0x00020002, 0x08021000, 0x08020000, 0x00000002, 0x00020000, 0x08001002, 0x08020002, 0x00001000, 0x00021002, 0x08000000, 0x00000000, 0x00020002, 0x08001002, 0x00021002, 0x08021000, 0x08000002, 0x08000000, 0x00020000, 0x00001002, 0x08021002, 0x00020002, 0x08021000, 0x08001000, 0x00021002, 0x08021002, 0x00020002, 0x08000002, 0x00000000, 0x08000000, 0x00001002, 0x00020000, 0x08020002, 0x00001000, 0x08000000, 0x00021002, 0x08001002, 0x08021000, 0x00001000, 0x00000000, 0x08000002, 0x00000002, 0x08021002, 0x00021000, 0x08020000, 0x08020002, 0x00020000, 0x00001002, 0x08001000, 0x08001002, 0x00000002, 0x08020000, 0x00021000, ); @SP2=( 0x20800000, 0x00808020, 0x00000020, 0x20800020, 0x20008000, 0x00800000, 0x20800020, 0x00008020, 0x00800020, 0x00008000, 0x00808000, 0x20000000, 0x20808020, 0x20000020, 0x20000000, 0x20808000, 0x00000000, 0x20008000, 0x00808020, 0x00000020, 0x20000020, 0x20808020, 0x00008000, 0x20800000, 0x20808000, 0x00800020, 0x20008020, 0x00808000, 0x00008020, 0x00000000, 0x00800000, 0x20008020, 0x00808020, 0x00000020, 0x20000000, 0x00008000, 0x20000020, 0x20008000, 0x00808000, 0x20800020, 0x00000000, 0x00808020, 0x00008020, 0x20808000, 0x20008000, 0x00800000, 0x20808020, 0x20000000, 0x20008020, 0x20800000, 0x00800000, 0x20808020, 0x00008000, 0x00800020, 0x20800020, 0x00008020, 0x00800020, 0x00000000, 0x20808000, 0x20000020, 0x20800000, 0x20008020, 0x00000020, 0x00808000, ); @SP3=( 0x00080201, 0x02000200, 0x00000001, 0x02080201, 0x00000000, 0x02080000, 0x02000201, 0x00080001, 0x02080200, 0x02000001, 0x02000000, 0x00000201, 0x02000001, 0x00080201, 0x00080000, 0x02000000, 0x02080001, 0x00080200, 0x00000200, 0x00000001, 0x00080200, 0x02000201, 0x02080000, 0x00000200, 0x00000201, 0x00000000, 0x00080001, 0x02080200, 0x02000200, 0x02080001, 0x02080201, 0x00080000, 0x02080001, 0x00000201, 0x00080000, 0x02000001, 0x00080200, 0x02000200, 0x00000001, 0x02080000, 0x02000201, 0x00000000, 0x00000200, 0x00080001, 0x00000000, 0x02080001, 0x02080200, 0x00000200, 0x02000000, 0x02080201, 0x00080201, 0x00080000, 0x02080201, 0x00000001, 0x02000200, 0x00080201, 0x00080001, 0x00080200, 0x02080000, 0x02000201, 0x00000201, 0x02000000, 0x02000001, 0x02080200, ); @SP4=( 0x01000000, 0x00002000, 0x00000080, 0x01002084, 0x01002004, 0x01000080, 0x00002084, 0x01002000, 0x00002000, 0x00000004, 0x01000004, 0x00002080, 0x01000084, 0x01002004, 0x01002080, 0x00000000, 0x00002080, 0x01000000, 0x00002004, 0x00000084, 0x01000080, 0x00002084, 0x00000000, 0x01000004, 0x00000004, 0x01000084, 0x01002084, 0x00002004, 0x01002000, 0x00000080, 0x00000084, 0x01002080, 0x01002080, 0x01000084, 0x00002004, 0x01002000, 0x00002000, 0x00000004, 0x01000004, 0x01000080, 0x01000000, 0x00002080, 0x01002084, 0x00000000, 0x00002084, 0x01000000, 0x00000080, 0x00002004, 0x01000084, 0x00000080, 0x00000000, 0x01002084, 0x01002004, 0x01002080, 0x00000084, 0x00002000, 0x00002080, 0x01002004, 0x01000080, 0x00000084, 0x00000004, 0x00002084, 0x01002000, 0x01000004, ); @SP5=( 0x10000008, 0x00040008, 0x00000000, 0x10040400, 0x00040008, 0x00000400, 0x10000408, 0x00040000, 0x00000408, 0x10040408, 0x00040400, 0x10000000, 0x10000400, 0x10000008, 0x10040000, 0x00040408, 0x00040000, 0x10000408, 0x10040008, 0x00000000, 0x00000400, 0x00000008, 0x10040400, 0x10040008, 0x10040408, 0x10040000, 0x10000000, 0x00000408, 0x00000008, 0x00040400, 0x00040408, 0x10000400, 0x00000408, 0x10000000, 0x10000400, 0x00040408, 0x10040400, 0x00040008, 0x00000000, 0x10000400, 0x10000000, 0x00000400, 0x10040008, 0x00040000, 0x00040008, 0x10040408, 0x00040400, 0x00000008, 0x10040408, 0x00040400, 0x00040000, 0x10000408, 0x10000008, 0x10040000, 0x00040408, 0x00000000, 0x00000400, 0x10000008, 0x10000408, 0x10040400, 0x10040000, 0x00000408, 0x00000008, 0x10040008, ); @SP6=( 0x00000800, 0x00000040, 0x00200040, 0x80200000, 0x80200840, 0x80000800, 0x00000840, 0x00000000, 0x00200000, 0x80200040, 0x80000040, 0x00200800, 0x80000000, 0x00200840, 0x00200800, 0x80000040, 0x80200040, 0x00000800, 0x80000800, 0x80200840, 0x00000000, 0x00200040, 0x80200000, 0x00000840, 0x80200800, 0x80000840, 0x00200840, 0x80000000, 0x80000840, 0x80200800, 0x00000040, 0x00200000, 0x80000840, 0x00200800, 0x80200800, 0x80000040, 0x00000800, 0x00000040, 0x00200000, 0x80200800, 0x80200040, 0x80000840, 0x00000840, 0x00000000, 0x00000040, 0x80200000, 0x80000000, 0x00200040, 0x00000000, 0x80200040, 0x00200040, 0x00000840, 0x80000040, 0x00000800, 0x80200840, 0x00200000, 0x00200840, 0x80000000, 0x80000800, 0x80200840, 0x80200000, 0x00200840, 0x00200800, 0x80000800, ); @SP7=( 0x04100010, 0x04104000, 0x00004010, 0x00000000, 0x04004000, 0x00100010, 0x04100000, 0x04104010, 0x00000010, 0x04000000, 0x00104000, 0x00004010, 0x00104010, 0x04004010, 0x04000010, 0x04100000, 0x00004000, 0x00104010, 0x00100010, 0x04004000, 0x04104010, 0x04000010, 0x00000000, 0x00104000, 0x04000000, 0x00100000, 0x04004010, 0x04100010, 0x00100000, 0x00004000, 0x04104000, 0x00000010, 0x00100000, 0x00004000, 0x04000010, 0x04104010, 0x00004010, 0x04000000, 0x00000000, 0x00104000, 0x04100010, 0x04004010, 0x04004000, 0x00100010, 0x04104000, 0x00000010, 0x00100010, 0x04004000, 0x04104010, 0x00100000, 0x04100000, 0x04000010, 0x00104000, 0x00004010, 0x04004010, 0x04100000, 0x00000010, 0x04104000, 0x00104010, 0x00000000, 0x04000000, 0x04100010, 0x00004000, 0x00104010, ); sub main'des_set_key { local($param)=@_; local(@key); local($c,$d,$i,$s,$t); local(@ks)=(); # Get the bytes in the order we want. @key=unpack("C8",$param); $c= ($key[0] )| ($key[1]<< 8)| ($key[2]<<16)| ($key[3]<<24); $d= ($key[4] )| ($key[5]<< 8)| ($key[6]<<16)| ($key[7]<<24); &doPC1(*c,*d); for $i (@shifts2) { if ($i) { $c=($c>>2)|($c<<26); $d=($d>>2)|($d<<26); } else { $c=($c>>1)|($c<<27); $d=($d>>1)|($d<<27); } $c&=0x0fffffff; $d&=0x0fffffff; $s= $skb0[ ($c )&0x3f ]| $skb1[(($c>> 6)&0x03)|(($c>> 7)&0x3c)]| $skb2[(($c>>13)&0x0f)|(($c>>14)&0x30)]| $skb3[(($c>>20)&0x01)|(($c>>21)&0x06) | (($c>>22)&0x38)]; $t= $skb4[ ($d )&0x3f ]| $skb5[(($d>> 7)&0x03)|(($d>> 8)&0x3c)]| $skb6[ ($d>>15)&0x3f ]| $skb7[(($d>>21)&0x0f)|(($d>>22)&0x30)]; push(@ks,(($t<<16)|($s&0x0000ffff))&0xffffffff); $s= (($s>>16)&0x0000ffff)|($t&0xffff0000) ; push(@ks,(($s<<4)|(($s>>28)&0xf))&0xffffffff); } @ks; } sub doPC1 { local(*a,*b)=@_; local($t); $t=(($b>>4)^$a)&0x0f0f0f0f; $b^=($t<<4); $a^=$t; # do $a first $t=(($a<<18)^$a)&0xcccc0000; $a=$a^$t^(($t>>18)&0x00003fff); $t=(($a<<17)^$a)&0xaaaa0000; $a=$a^$t^(($t>>17)&0x00007fff); $t=(($a<< 8)^$a)&0x00ff0000; $a=$a^$t^(($t>> 8)&0x00ffffff); $t=(($a<<17)^$a)&0xaaaa0000; $a=$a^$t^(($t>>17)&0x00007fff); # now do $b $t=(($b<<24)^$b)&0xff000000; $b=$b^$t^(($t>>24)&0x000000ff); $t=(($b<< 8)^$b)&0x00ff0000; $b=$b^$t^(($t>> 8)&0x00ffffff); $t=(($b<<14)^$b)&0x33330000; $b=$b^$t^(($t>>14)&0x0003ffff); $b=(($b&0x00aa00aa)<<7)|(($b&0x55005500)>>7)|($b&0xaa55aa55); $b=(($b>>8)&0x00ffffff)|((($a&0xf0000000)>>4)&0x0fffffff); $a&=0x0fffffff; } sub doIP { local(*a,*b)=@_; local($t); $t=(($b>> 4)^$a)&0x0f0f0f0f; $b^=($t<< 4); $a^=$t; $t=(($a>>16)^$b)&0x0000ffff; $a^=($t<<16); $b^=$t; $t=(($b>> 2)^$a)&0x33333333; $b^=($t<< 2); $a^=$t; $t=(($a>> 8)^$b)&0x00ff00ff; $a^=($t<< 8); $b^=$t; $t=(($b>> 1)^$a)&0x55555555; $b^=($t<< 1); $a^=$t; $t=$a; $a=$b&0xffffffff; $b=$t&0xffffffff; } sub doFP { local(*a,*b)=@_; local($t); $t=(($b>> 1)^$a)&0x55555555; $b^=($t<< 1); $a^=$t; $t=(($a>> 8)^$b)&0x00ff00ff; $a^=($t<< 8); $b^=$t; $t=(($b>> 2)^$a)&0x33333333; $b^=($t<< 2); $a^=$t; $t=(($a>>16)^$b)&0x0000ffff; $a^=($t<<16); $b^=$t; $t=(($b>> 4)^$a)&0x0f0f0f0f; $b^=($t<< 4); $a^=$t; $a&=0xffffffff; $b&=0xffffffff; } sub main'des_ecb_encrypt { local(*ks,$encrypt,$in)=@_; local($l,$r,$i,$t,$u,@input); @input=unpack("C8",$in); # Get the bytes in the order we want. $l= ($input[0] )| ($input[1]<< 8)| ($input[2]<<16)| ($input[3]<<24); $r= ($input[4] )| ($input[5]<< 8)| ($input[6]<<16)| ($input[7]<<24); $l&=0xffffffff; $r&=0xffffffff; &doIP(*l,*r); if ($encrypt) { for ($i=0; $i<32; $i+=4) { $t=((($r&0x7fffffff)<<1)|(($r>>31)&0x00000001)); $u=$t^$ks[$i ]; $t=$t^$ks[$i+1]; $t2=(($t&0x0000000f)<<28); $t=((($t>>4)&0x0fffffff)|(($t&0x0000000f)<<28)); $l^= $SP1[ $t &0x3f]| $SP3[($t>> 8)&0x3f]| $SP5[($t>>16)&0x3f]| $SP7[($t>>24)&0x3f]| $SP0[ $u &0x3f]| $SP2[($u>> 8)&0x3f]| $SP4[($u>>16)&0x3f]| $SP6[($u>>24)&0x3f]; $t=(($l<<1)|(($l>>31)&0x1))&0xffffffff; $u=$t^$ks[$i+2]; $t=$t^$ks[$i+3]; $t=((($t>>4)&0x0fffffff)|($t<<28))&0xffffffff; $r^= $SP1[ $t &0x3f]| $SP3[($t>> 8)&0x3f]| $SP5[($t>>16)&0x3f]| $SP7[($t>>24)&0x3f]| $SP0[ $u &0x3f]| $SP2[($u>> 8)&0x3f]| $SP4[($u>>16)&0x3f]| $SP6[($u>>24)&0x3f]; } } else { for ($i=30; $i>0; $i-=4) { $t=(($r<<1)|(($r>>31)&0x1))&0xffffffff; $u=$t^$ks[$i ]; $t=$t^$ks[$i+1]; $t=((($t>>4)&0x0fffffff)|($t<<28))&0xffffffff; $l^= $SP1[ $t &0x3f]| $SP3[($t>> 8)&0x3f]| $SP5[($t>>16)&0x3f]| $SP7[($t>>24)&0x3f]| $SP0[ $u &0x3f]| $SP2[($u>> 8)&0x3f]| $SP4[($u>>16)&0x3f]| $SP6[($u>>24)&0x3f]; $t=(($l<<1)|(($l>>31)&0x1))&0xffffffff; $u=$t^$ks[$i-2]; $t=$t^$ks[$i-1]; $t=((($t>>4)&0x0fffffff)|($t<<28))&0xffffffff; $r^= $SP1[ $t &0x3f]| $SP3[($t>> 8)&0x3f]| $SP5[($t>>16)&0x3f]| $SP7[($t>>24)&0x3f]| $SP0[ $u &0x3f]| $SP2[($u>> 8)&0x3f]| $SP4[($u>>16)&0x3f]| $SP6[($u>>24)&0x3f]; } } &doFP(*l,*r); pack("C8",$l&0xff, ($l>> 8)&0x00ffffff, ($l>>16)&0x0000ffff, ($l>>24)&0x000000ff, $r&0xff, ($r>> 8)&0x00ffffff, ($r>>16)&0x0000ffff, ($r>>24)&0x000000ff); } \ No newline at end of file diff --git a/mac/libdes/src/des_crypt.man b/mac/libdes/src/des_crypt.man deleted file mode 100755 index 8c33e5f0..00000000 --- a/mac/libdes/src/des_crypt.man +++ /dev/null @@ -1 +0,0 @@ -.TH DES_CRYPT 3 .SH NAME des_read_password, des_read_2password, des_string_to_key, des_string_to_2key, des_read_pw_string, des_random_key, des_set_key, des_key_sched, des_ecb_encrypt, des_3ecb_encrypt, des_cbc_encrypt, des_3cbc_encrypt, des_pcbc_encrypt, des_cfb_encrypt, des_ofb_encrypt, des_cbc_cksum, des_quad_cksum, des_enc_read, des_enc_write, des_set_odd_parity, des_is_weak_key, crypt \- (non USA) DES encryption .SH SYNOPSIS .nf .nj .ft B #include .PP .B int des_read_password(key,prompt,verify) des_cblock *key; char *prompt; int verify; .PP .B int des_read_2password(key1,key2,prompt,verify) des_cblock *key1,*key2; char *prompt; int verify; .PP .B int des_string_to_key(str,key) char *str; des_cblock *key; .PP .B int des_string_to_2keys(str,key1,key2) char *str; des_cblock *key1,*key2; .PP .B int des_read_pw_string(buf,length,prompt,verify) char *buf; int length; char *prompt; int verify; .PP .B int des_random_key(key) des_cblock *key; .PP .B int des_set_key(key,schedule) des_cblock *key; des_key_schedule schedule; .PP .B int des_key_sched(key,schedule) des_cblock *key; des_key_schedule schedule; .PP .B int des_ecb_encrypt(input,output,schedule,encrypt) des_cblock *input; des_cblock *output; des_key_schedule schedule; int encrypt; .PP .B int des_3ecb_encrypt(input,output,ks1,ks2,encrypt) des_cblock *input; des_cblock *output; des_key_schedule ks1,ks2; int encrypt; .PP .B int des_cbc_encrypt(input,output,length,schedule,ivec,encrypt) des_cblock *input; des_cblock *output; long length; des_key_schedule schedule; des_cblock *ivec; int encrypt; .PP .B int des_3cbc_encrypt(input,output,length,sk1,sk2,ivec1,ivec2,encrypt) des_cblock *input; des_cblock *output; long length; des_key_schedule sk1; des_key_schedule sk2; des_cblock *ivec1; des_cblock *ivec2; int encrypt; .PP .B int des_pcbc_encrypt(input,output,length,schedule,ivec,encrypt) des_cblock *input; des_cblock *output; long length; des_key_schedule schedule; des_cblock *ivec; int encrypt; .PP .B int des_cfb_encrypt(input,output,numbits,length,schedule,ivec,encrypt) unsigned char *input; unsigned char *output; int numbits; long length; des_key_schedule schedule; des_cblock *ivec; int encrypt; .PP .B int des_ofb_encrypt(input,output,numbits,length,schedule,ivec) unsigned char *input,*output; int numbits; long length; des_key_schedule schedule; des_cblock *ivec; .PP .B unsigned long des_cbc_cksum(input,output,length,schedule,ivec) des_cblock *input; des_cblock *output; long length; des_key_schedule schedule; des_cblock *ivec; .PP .B unsigned long des_quad_cksum(input,output,length,out_count,seed) des_cblock *input; des_cblock *output; long length; int out_count; des_cblock *seed; .PP .B int des_check_key; .PP .B int des_enc_read(fd,buf,len,sched,iv) int fd; char *buf; int len; des_key_schedule sched; des_cblock *iv; .PP .B int des_enc_write(fd,buf,len,sched,iv) int fd; char *buf; int len; des_key_schedule sched; des_cblock *iv; .PP .B extern int des_rw_mode; .PP .B void des_set_odd_parity(key) des_cblock *key; .PP .B int des_is_weak_key(key) des_cblock *key; .PP .B char *crypt(passwd,salt) char *passwd; char *salt; .PP .fi .SH DESCRIPTION This library contains a fast implementation of the DES encryption algorithm. .PP There are two phases to the use of DES encryption. The first is the generation of a .I des_key_schedule from a key, the second is the actual encryption. A des key is of type .I des_cblock. This type is made from 8 characters with odd parity. The least significant bit in the character is the parity bit. The key schedule is an expanded form of the key; it is used to speed the encryption process. .PP .I des_read_password writes the string specified by prompt to the standard output, turns off echo and reads an input string from standard input until terminated with a newline. If verify is non-zero, it prompts and reads the input again and verifies that both entered passwords are the same. The entered string is converted into a des key by using the .I des_string_to_key routine. The new key is placed in the .I des_cblock that was passed (by reference) to the routine. If there were no errors, .I des_read_password returns 0, -1 is returned if there was a terminal error and 1 is returned for any other error. .PP .I des_read_2password operates in the same way as .I des_read_password except that it generates 2 keys by using the .I des_string_to_2key function. .PP .I des_read_pw_string is called by .I des_read_password to read and verify a string from a terminal device. The string is returned in .I buf. The size of .I buf is passed to the routine via the .I length parameter. .PP .I des_string_to_key converts a string into a valid des key. .PP .I des_string_to_2key converts a string into 2 valid des keys. This routine is best suited for used to generate keys for use with .I des_3ecb_encrypt. .PP .I des_random_key returns a random key that is made of a combination of process id, time and an increasing counter. .PP Before a des key can be used it is converted into a .I des_key_schedule via the .I des_set_key routine. If the .I des_check_key flag is non-zero, .I des_set_key will check that the key passed is of odd parity and is not a week or semi-weak key. If the parity is wrong, then -1 is returned. If the key is a weak key, then -2 is returned. If an error is returned, the key schedule is not generated. .PP .I des_key_sched is another name for the .I des_set_key function. .PP The following routines mostly operate on an input and output stream of .I des_cblock's. .PP .I des_ecb_encrypt is the basic DES encryption routine that encrypts or decrypts a single 8-byte .I des_cblock in .I electronic code book mode. It always transforms the input data, pointed to by .I input, into the output data, pointed to by the .I output argument. If the .I encrypt argument is non-zero (DES_ENCRYPT), the .I input (cleartext) is encrypted in to the .I output (ciphertext) using the key_schedule specified by the .I schedule argument, previously set via .I des_set_key. If .I encrypt is zero (DES_DECRYPT), the .I input (now ciphertext) is decrypted into the .I output (now cleartext). Input and output may overlap. No meaningful value is returned. .PP .I des_3ecb_encrypt encrypts/decrypts the .I input block by using triple ecb DES encryption. This involves encrypting the input with .I ks1, decryption with the key schedule .I ks2, and then encryption with the first again. This routine greatly reduces the chances of brute force breaking of DES and has the advantage of if .I ks1 and .I ks2 are the same, it is equivalent to just encryption using ecb mode and .I ks1 as the key. .PP .I des_cbc_encrypt encrypts/decrypts using the .I cipher-block-chaining mode of DES. If the .I encrypt argument is non-zero, the routine cipher-block-chain encrypts the cleartext data pointed to by the .I input argument into the ciphertext pointed to by the .I output argument, using the key schedule provided by the .I schedule argument, and initialisation vector provided by the .I ivec argument. If the .I length argument is not an integral multiple of eight bytes, the last block is copied to a temporary area and zero filled. The output is always an integral multiple of eight bytes. To make multiple cbc encrypt calls on a large amount of data appear to be one .I des_cbc_encrypt call, the .I ivec of subsequent calls should be the last 8 bytes of the output. .PP .I des_3cbc_encrypt encrypts/decrypts the .I input block by using triple cbc DES encryption. This involves encrypting the input with key schedule .I ks1, decryption with the key schedule .I ks2, and then encryption with the first again. 2 initialisation vectors are required, .I ivec1 and .I ivec2. Unlike .I des_cbc_encrypt, these initialisation vectors are modified by the subroutine. This routine greatly reduces the chances of brute force breaking of DES and has the advantage of if .I ks1 and .I ks2 are the same, it is equivalent to just encryption using cbc mode and .I ks1 as the key. .PP .I des_pcbc_encrypt encrypt/decrypts using a modified block chaining mode. It provides better error propagation characteristics than cbc encryption. .PP .I des_cfb_encrypt encrypt/decrypts using cipher feedback mode. This method takes an array of characters as input and outputs and array of characters. It does not require any padding to 8 character groups. Note: the ivec variable is changed and the new changed value needs to be passed to the next call to this function. Since this function runs a complete DES ecb encryption per numbits, this function is only suggested for use when sending small numbers of characters. .PP .I des_ofb_encrypt encrypt using output feedback mode. This method takes an array of characters as input and outputs and array of characters. It does not require any padding to 8 character groups. Note: the ivec variable is changed and the new changed value needs to be passed to the next call to this function. Since this function runs a complete DES ecb encryption per numbits, this function is only suggested for use when sending small numbers of characters. .PP .I des_cbc_cksum produces an 8 byte checksum based on the input stream (via cbc encryption). The last 4 bytes of the checksum is returned and the complete 8 bytes is placed in .I output. .PP .I des_quad_cksum returns a 4 byte checksum from the input bytes. The algorithm can be iterated over the input, depending on .I out_count, 1, 2, 3 or 4 times. If .I output is non-NULL, the 8 bytes generated by each pass are written into .I output. .PP .I des_enc_write is used to write .I len bytes to file descriptor .I fd from buffer .I buf. The data is encrypted via .I pcbc_encrypt (default) using .I sched for the key and .I iv as a starting vector. The actual data send down .I fd consists of 4 bytes (in network byte order) containing the length of the following encrypted data. The encrypted data then follows, padded with random data out to a multiple of 8 bytes. .PP .I des_enc_read is used to read .I len bytes from file descriptor .I fd into buffer .I buf. The data being read from .I fd is assumed to have come from .I des_enc_write and is decrypted using .I sched for the key schedule and .I iv for the initial vector. The .I des_enc_read/des_enc_write pair can be used to read/write to files, pipes and sockets. I have used them in implementing a version of rlogin in which all data is encrypted. .PP .I des_rw_mode is used to specify the encryption mode to use with .I des_enc_read and .I des_end_write. If set to .I DES_PCBC_MODE (the default), des_pcbc_encrypt is used. If set to .I DES_CBC_MODE des_cbc_encrypt is used. These two routines and the variable are not part of the normal MIT library. .PP .I des_set_odd_parity sets the parity of the passed .I key to odd. This routine is not part of the standard MIT library. .PP .I des_is_weak_key returns 1 is the passed key is a weak key (pick again :-), 0 if it is ok. This routine is not part of the standard MIT library. .PP .I crypt is a replacement for the normal system crypt. It is much faster than the system crypt. .PP .SH FILES /usr/include/des.h .br /usr/lib/libdes.a .PP The encryption routines have been tested on 16bit, 32bit and 64bit machines of various endian and even works under VMS. .PP .SH BUGS .PP If you think this manual is sparse, read the des_crypt(3) manual from the MIT kerberos (or bones outside of the USA) distribution. .PP .I des_cfb_encrypt and .I des_ofb_encrypt operates on input of 8 bits. What this means is that if you set numbits to 12, and length to 2, the first 12 bits will come from the 1st input byte and the low half of the second input byte. The second 12 bits will have the low 8 bits taken from the 3rd input byte and the top 4 bits taken from the 4th input byte. The same holds for output. This function has been implemented this way because most people will be using a multiple of 8 and because once you get into pulling bytes input bytes apart things get ugly! .PP .I des_read_pw_string is the most machine/OS dependent function and normally generates the most problems when porting this code. .PP .I des_string_to_key is probably different from the MIT version since there are lots of fun ways to implement one-way encryption of a text string. .PP The routines are optimised for 32 bit machines and so are not efficient on IBM PCs. .PP NOTE: extensive work has been done on this library since this document was origionally written. Please try to read des.doc from the libdes distribution since it is far more upto date and documents more of the functions. Libdes is now also being shipped as part of SSLeay, a general cryptographic library that amonst other things implements netscapes SSL protocoll. The most recent version can be found in SSLeay distributions. .SH AUTHOR Eric Young (eay@mincom.oz.au or eay@psych.psy.uq.oz.au) \ No newline at end of file diff --git a/mac/libdes/src/des_enc.c b/mac/libdes/src/des_enc.c deleted file mode 100755 index 2a839a68..00000000 --- a/mac/libdes/src/des_enc.c +++ /dev/null @@ -1 +0,0 @@ -/* crypto/des/des_enc.c */ /* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@mincom.oz.au). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@mincom.oz.au). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@mincom.oz.au)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ #include "des_locl.h" void des_encrypt(data, ks, encrypt) DES_LONG *data; des_key_schedule ks; int encrypt; { register DES_LONG l,r,t,u; #ifdef DES_PTR register unsigned char *des_SP=(unsigned char *)des_SPtrans; #endif #ifndef DES_UNROLL register int i; #endif register DES_LONG *s; r=data[0]; l=data[1]; IP(r,l); /* Things have been modified so that the initial rotate is * done outside the loop. This required the * des_SPtrans values in sp.h to be rotated 1 bit to the right. * One perl script later and things have a 5% speed up on a sparc2. * Thanks to Richard Outerbridge <71755.204@CompuServe.COM> * for pointing this out. */ /* clear the top bits on machines with 8byte longs */ /* shift left by 2 */ r=ROTATE(r,29)&0xffffffffL; l=ROTATE(l,29)&0xffffffffL; s=(DES_LONG *)ks; /* I don't know if it is worth the effort of loop unrolling the * inner loop */ if (encrypt) { #ifdef DES_UNROLL D_ENCRYPT(l,r, 0); /* 1 */ D_ENCRYPT(r,l, 2); /* 2 */ D_ENCRYPT(l,r, 4); /* 3 */ D_ENCRYPT(r,l, 6); /* 4 */ D_ENCRYPT(l,r, 8); /* 5 */ D_ENCRYPT(r,l,10); /* 6 */ D_ENCRYPT(l,r,12); /* 7 */ D_ENCRYPT(r,l,14); /* 8 */ D_ENCRYPT(l,r,16); /* 9 */ D_ENCRYPT(r,l,18); /* 10 */ D_ENCRYPT(l,r,20); /* 11 */ D_ENCRYPT(r,l,22); /* 12 */ D_ENCRYPT(l,r,24); /* 13 */ D_ENCRYPT(r,l,26); /* 14 */ D_ENCRYPT(l,r,28); /* 15 */ D_ENCRYPT(r,l,30); /* 16 */ #else for (i=0; i<32; i+=8) { D_ENCRYPT(l,r,i+0); /* 1 */ D_ENCRYPT(r,l,i+2); /* 2 */ D_ENCRYPT(l,r,i+4); /* 3 */ D_ENCRYPT(r,l,i+6); /* 4 */ } #endif } else { #ifdef DES_UNROLL D_ENCRYPT(l,r,30); /* 16 */ D_ENCRYPT(r,l,28); /* 15 */ D_ENCRYPT(l,r,26); /* 14 */ D_ENCRYPT(r,l,24); /* 13 */ D_ENCRYPT(l,r,22); /* 12 */ D_ENCRYPT(r,l,20); /* 11 */ D_ENCRYPT(l,r,18); /* 10 */ D_ENCRYPT(r,l,16); /* 9 */ D_ENCRYPT(l,r,14); /* 8 */ D_ENCRYPT(r,l,12); /* 7 */ D_ENCRYPT(l,r,10); /* 6 */ D_ENCRYPT(r,l, 8); /* 5 */ D_ENCRYPT(l,r, 6); /* 4 */ D_ENCRYPT(r,l, 4); /* 3 */ D_ENCRYPT(l,r, 2); /* 2 */ D_ENCRYPT(r,l, 0); /* 1 */ #else for (i=30; i>0; i-=8) { D_ENCRYPT(l,r,i-0); /* 16 */ D_ENCRYPT(r,l,i-2); /* 15 */ D_ENCRYPT(l,r,i-4); /* 14 */ D_ENCRYPT(r,l,i-6); /* 13 */ } #endif } /* rotate and clear the top bits on machines with 8byte longs */ l=ROTATE(l,3)&0xffffffffL; r=ROTATE(r,3)&0xffffffffL; FP(r,l); data[0]=l; data[1]=r; l=r=t=u=0; } void des_encrypt2(data, ks, encrypt) DES_LONG *data; des_key_schedule ks; int encrypt; { register DES_LONG l,r,t,u; #ifdef DES_PTR register unsigned char *des_SP=(unsigned char *)des_SPtrans; #endif #ifndef DES_UNROLL register int i; #endif register DES_LONG *s; r=data[0]; l=data[1]; /* Things have been modified so that the initial rotate is * done outside the loop. This required the * des_SPtrans values in sp.h to be rotated 1 bit to the right. * One perl script later and things have a 5% speed up on a sparc2. * Thanks to Richard Outerbridge <71755.204@CompuServe.COM> * for pointing this out. */ /* clear the top bits on machines with 8byte longs */ r=ROTATE(r,29)&0xffffffff; l=ROTATE(l,29)&0xffffffff; s=(DES_LONG *)ks; /* I don't know if it is worth the effort of loop unrolling the * inner loop */ if (encrypt) { #ifdef DES_UNROLL D_ENCRYPT(l,r, 0); /* 1 */ D_ENCRYPT(r,l, 2); /* 2 */ D_ENCRYPT(l,r, 4); /* 3 */ D_ENCRYPT(r,l, 6); /* 4 */ D_ENCRYPT(l,r, 8); /* 5 */ D_ENCRYPT(r,l,10); /* 6 */ D_ENCRYPT(l,r,12); /* 7 */ D_ENCRYPT(r,l,14); /* 8 */ D_ENCRYPT(l,r,16); /* 9 */ D_ENCRYPT(r,l,18); /* 10 */ D_ENCRYPT(l,r,20); /* 11 */ D_ENCRYPT(r,l,22); /* 12 */ D_ENCRYPT(l,r,24); /* 13 */ D_ENCRYPT(r,l,26); /* 14 */ D_ENCRYPT(l,r,28); /* 15 */ D_ENCRYPT(r,l,30); /* 16 */ #else for (i=0; i<32; i+=8) { D_ENCRYPT(l,r,i+0); /* 1 */ D_ENCRYPT(r,l,i+2); /* 2 */ D_ENCRYPT(l,r,i+4); /* 3 */ D_ENCRYPT(r,l,i+6); /* 4 */ } #endif } else { #ifdef DES_UNROLL D_ENCRYPT(l,r,30); /* 16 */ D_ENCRYPT(r,l,28); /* 15 */ D_ENCRYPT(l,r,26); /* 14 */ D_ENCRYPT(r,l,24); /* 13 */ D_ENCRYPT(l,r,22); /* 12 */ D_ENCRYPT(r,l,20); /* 11 */ D_ENCRYPT(l,r,18); /* 10 */ D_ENCRYPT(r,l,16); /* 9 */ D_ENCRYPT(l,r,14); /* 8 */ D_ENCRYPT(r,l,12); /* 7 */ D_ENCRYPT(l,r,10); /* 6 */ D_ENCRYPT(r,l, 8); /* 5 */ D_ENCRYPT(l,r, 6); /* 4 */ D_ENCRYPT(r,l, 4); /* 3 */ D_ENCRYPT(l,r, 2); /* 2 */ D_ENCRYPT(r,l, 0); /* 1 */ #else for (i=30; i>0; i-=8) { D_ENCRYPT(l,r,i-0); /* 16 */ D_ENCRYPT(r,l,i-2); /* 15 */ D_ENCRYPT(l,r,i-4); /* 14 */ D_ENCRYPT(r,l,i-6); /* 13 */ } #endif } /* rotate and clear the top bits on machines with 8byte longs */ data[0]=ROTATE(l,3)&0xffffffff; data[1]=ROTATE(r,3)&0xffffffff; l=r=t=u=0; } void des_encrypt3(data,ks1,ks2,ks3) DES_LONG *data; des_key_schedule ks1; des_key_schedule ks2; des_key_schedule ks3; { register DES_LONG l,r; l=data[0]; r=data[1]; IP(l,r); data[0]=l; data[1]=r; des_encrypt2((DES_LONG *)data,ks1,DES_ENCRYPT); des_encrypt2((DES_LONG *)data,ks2,DES_DECRYPT); des_encrypt2((DES_LONG *)data,ks3,DES_ENCRYPT); l=data[0]; r=data[1]; FP(r,l); data[0]=l; data[1]=r; } void des_decrypt3(data,ks1,ks2,ks3) DES_LONG *data; des_key_schedule ks1; des_key_schedule ks2; des_key_schedule ks3; { register DES_LONG l,r; l=data[0]; r=data[1]; IP(l,r); data[0]=l; data[1]=r; des_encrypt2((DES_LONG *)data,ks3,DES_DECRYPT); des_encrypt2((DES_LONG *)data,ks2,DES_ENCRYPT); des_encrypt2((DES_LONG *)data,ks1,DES_DECRYPT); l=data[0]; r=data[1]; FP(r,l); data[0]=l; data[1]=r; } \ No newline at end of file diff --git a/mac/libdes/src/des_locl.h b/mac/libdes/src/des_locl.h deleted file mode 100755 index 24bf6ae9..00000000 --- a/mac/libdes/src/des_locl.h +++ /dev/null @@ -1 +0,0 @@ -#ifdef HAVE_CONFIG_H #include "config.h" /* if (we have termios.h) define TERMIOS else if (we have termio.h) define TERMIO */ #ifdef HAVE_TERMIOS_H #define TERMIOS #else /* !HAVE_TERMIOS_H */ #ifdef HAVE_TERMIO_H #define TERMIO #endif #endif /* !HAVE_TERMIOS_H */ #endif /* HAVE_CONFIG_H */ /* crypto/des/des_locl.h */ /* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@mincom.oz.au). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@mincom.oz.au). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@mincom.oz.au)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ /* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING * * Always modify des_locl.org since des_locl.h is automatically generated from * it during SSLeay configuration. * * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING */ #ifndef HEADER_DES_LOCL_H #define HEADER_DES_LOCL_H #if defined(WIN32) || defined(WIN16) #ifndef MSDOS #define MSDOS #endif #endif #include #include #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_IO_H #include #endif #include "des.h" #ifndef DES_DEFAULT_OPTIONS /* the following is tweaked from a config script, that is why it is a * protected undef/define */ #ifndef DES_PTR #undef DES_PTR #endif /* This helps C compiler generate the correct code for multiple functional * units. It reduces register dependancies at the expense of 2 more * registers */ #ifndef DES_RISC1 #undef DES_RISC1 #endif #ifndef DES_RISC2 #undef DES_RISC2 #endif #if defined(DES_RISC1) && defined(DES_RISC2) YOU SHOULD NOT HAVE BOTH DES_RISC1 AND DES_RISC2 DEFINED!!!!! #endif /* Unroll the inner loop, this sometimes helps, sometimes hinders. * Very mucy CPU dependant */ #ifndef DES_UNROLL #undef DES_UNROLL #endif /* These default values were supplied by * Peter Gutman * They are only used if nothing else has been defined */ #if !defined(DES_PTR) && !defined(DES_RISC1) && !defined(DES_RISC2) && !defined(DES_UNROLL) /* Special defines which change the way the code is built depending on the CPU and OS. For SGI machines you can use _MIPS_SZLONG (32 or 64) to find even newer MIPS CPU's, but at the moment one size fits all for optimization options. Older Sparc's work better with only UNROLL, but there's no way to tell at compile time what it is you're running on */ #if defined( sun ) /* Newer Sparc's */ #define DES_PTR #define DES_RISC1 #define DES_UNROLL #elif defined( __ultrix ) /* Older MIPS */ #define DES_PTR #define DES_RISC2 #define DES_UNROLL #elif defined( __osf1__ ) /* Alpha */ #define DES_PTR #define DES_RISC2 #elif defined ( _AIX ) /* RS6000 */ /* Unknown */ #elif defined( __hpux ) /* HP-PA */ #define DES_UNROLL #elif defined( __aux ) /* 68K */ /* Unknown */ #elif defined( __dgux ) /* 88K (but P6 in latest boxes) */ #define DES_UNROLL #elif defined( __sgi ) /* Newer MIPS */ #define DES_PTR #define DES_RISC2 #define DES_UNROLL #elif defined( i386 ) /* x86 boxes, should be gcc */ #define DES_PTR #define DES_RISC1 #define DES_UNROLL #endif /* Systems-specific speed defines */ #endif #endif /* DES_DEFAULT_OPTIONS */ #ifdef MSDOS /* Visual C++ 2.1 (Windows NT/95) */ #include #include #include #include #ifndef RAND #define RAND #endif #undef NOPROTO #endif #if defined(__STDC__) || defined(VMS) || defined(M_XENIX) || defined(MSDOS) || defined(WIN32) #include #endif #ifndef RAND #define RAND #endif #ifdef linux #undef RAND #endif #ifdef MSDOS #define getpid() 2 #define RAND #undef NOPROTO #endif #if defined(NOCONST) #define const #endif #ifdef __STDC__ #undef NOPROTO #endif #ifdef RAND #define srandom(s) srand(s) #define random rand #endif #define ITERATIONS 16 #define HALF_ITERATIONS 8 /* used in des_read and des_write */ #define MAXWRITE (1024*16) #define BSIZE (MAXWRITE+4) #define c2l(c,l) (l =((DES_LONG)(*((c)++))) , \ l|=((DES_LONG)(*((c)++)))<< 8L, \ l|=((DES_LONG)(*((c)++)))<<16L, \ l|=((DES_LONG)(*((c)++)))<<24L) /* NOTE - c is not incremented as per c2l */ #define c2ln(c,l1,l2,n) { \ c+=n; \ l1=l2=0; \ switch (n) { \ case 8: l2 =((DES_LONG)(*(--(c))))<<24L; \ case 7: l2|=((DES_LONG)(*(--(c))))<<16L; \ case 6: l2|=((DES_LONG)(*(--(c))))<< 8L; \ case 5: l2|=((DES_LONG)(*(--(c)))); \ case 4: l1 =((DES_LONG)(*(--(c))))<<24L; \ case 3: l1|=((DES_LONG)(*(--(c))))<<16L; \ case 2: l1|=((DES_LONG)(*(--(c))))<< 8L; \ case 1: l1|=((DES_LONG)(*(--(c)))); \ } \ } #define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ *((c)++)=(unsigned char)(((l)>>24L)&0xff)) /* replacements for htonl and ntohl since I have no idea what to do * when faced with machines with 8 byte longs. */ #define HDRSIZE 4 #define n2l(c,l) (l =((DES_LONG)(*((c)++)))<<24L, \ l|=((DES_LONG)(*((c)++)))<<16L, \ l|=((DES_LONG)(*((c)++)))<< 8L, \ l|=((DES_LONG)(*((c)++)))) #define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24L)&0xff), \ *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ *((c)++)=(unsigned char)(((l) )&0xff)) /* NOTE - c is not incremented as per l2c */ #define l2cn(l1,l2,c,n) { \ c+=n; \ switch (n) { \ case 8: *(--(c))=(unsigned char)(((l2)>>24L)&0xff); \ case 7: *(--(c))=(unsigned char)(((l2)>>16L)&0xff); \ case 6: *(--(c))=(unsigned char)(((l2)>> 8L)&0xff); \ case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \ case 4: *(--(c))=(unsigned char)(((l1)>>24L)&0xff); \ case 3: *(--(c))=(unsigned char)(((l1)>>16L)&0xff); \ case 2: *(--(c))=(unsigned char)(((l1)>> 8L)&0xff); \ case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \ } \ } #if defined(WIN32) #define ROTATE(a,n) (_lrotr(a,n)) #else #define ROTATE(a,n) (((a)>>(n))+((a)<<(32-(n)))) #endif /* Don't worry about the LOAD_DATA() stuff, that is used by * fcrypt() to add it's little bit to the front */ #ifdef DES_FCRYPT #define LOAD_DATA_tmp(R,S,u,t,E0,E1) \ { DES_LONG tmp; LOAD_DATA(R,S,u,t,E0,E1,tmp); } #define LOAD_DATA(R,S,u,t,E0,E1,tmp) \ t=R^(R>>16L); \ u=t&E0; t&=E1; \ tmp=(u<<16); u^=R^s[S ]; u^=tmp; \ tmp=(t<<16); t^=R^s[S+1]; t^=tmp #else #define LOAD_DATA_tmp(a,b,c,d,e,f) LOAD_DATA(a,b,c,d,e,f,g) #define LOAD_DATA(R,S,u,t,E0,E1,tmp) \ u=R^s[S ]; \ t=R^s[S+1] #endif /* The changes to this macro may help or hinder, depending on the * compiler and the achitecture. gcc2 always seems to do well :-). * Inspired by Dana How * DO NOT use the alternative version on machines with 8 byte longs. * It does not seem to work on the Alpha, even when DES_LONG is 4 * bytes, probably an issue of accessing non-word aligned objects :-( */ #ifdef DES_PTR /* It recently occured to me that 0^0^0^0^0^0^0 == 0, so there * is no reason to not xor all the sub items together. This potentially * saves a register since things can be xored directly into L */ #if defined(DES_RISC1) || defined(DES_RISC2) #ifdef DES_RISC1 #define D_ENCRYPT(LL,R,S) { \ unsigned int u1,u2,u3; \ LOAD_DATA(R,S,u,t,E0,E1,u1); \ u2=(int)u>>8L; \ u1=(int)u&0xfc; \ u2&=0xfc; \ t=ROTATE(t,4); \ u>>=16L; \ LL^= *(DES_LONG *)((unsigned char *)des_SP +u1); \ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x200+u2); \ u3=(int)(u>>8L); \ u1=(int)u&0xfc; \ u3&=0xfc; \ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x400+u1); \ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x600+u3); \ u2=(int)t>>8L; \ u1=(int)t&0xfc; \ u2&=0xfc; \ t>>=16L; \ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x100+u1); \ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x300+u2); \ u3=(int)t>>8L; \ u1=(int)t&0xfc; \ u3&=0xfc; \ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x500+u1); \ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x700+u3); } #endif #ifdef DES_RISC2 #define D_ENCRYPT(LL,R,S) { \ unsigned int u1,u2,s1,s2; \ LOAD_DATA(R,S,u,t,E0,E1,u1); \ u2=(int)u>>8L; \ u1=(int)u&0xfc; \ u2&=0xfc; \ t=ROTATE(t,4); \ LL^= *(DES_LONG *)((unsigned char *)des_SP +u1); \ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x200+u2); \ s1=(int)(u>>16L); \ s2=(int)(u>>24L); \ s1&=0xfc; \ s2&=0xfc; \ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x400+s1); \ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x600+s2); \ u2=(int)t>>8L; \ u1=(int)t&0xfc; \ u2&=0xfc; \ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x100+u1); \ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x300+u2); \ s1=(int)(t>>16L); \ s2=(int)(t>>24L); \ s1&=0xfc; \ s2&=0xfc; \ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x500+s1); \ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x700+s2); } #endif #else #define D_ENCRYPT(LL,R,S) { \ LOAD_DATA_tmp(R,S,u,t,E0,E1); \ t=ROTATE(t,4); \ LL^= \ *(DES_LONG *)((unsigned char *)des_SP +((u )&0xfc))^ \ *(DES_LONG *)((unsigned char *)des_SP+0x200+((u>> 8L)&0xfc))^ \ *(DES_LONG *)((unsigned char *)des_SP+0x400+((u>>16L)&0xfc))^ \ *(DES_LONG *)((unsigned char *)des_SP+0x600+((u>>24L)&0xfc))^ \ *(DES_LONG *)((unsigned char *)des_SP+0x100+((t )&0xfc))^ \ *(DES_LONG *)((unsigned char *)des_SP+0x300+((t>> 8L)&0xfc))^ \ *(DES_LONG *)((unsigned char *)des_SP+0x500+((t>>16L)&0xfc))^ \ *(DES_LONG *)((unsigned char *)des_SP+0x700+((t>>24L)&0xfc)); } #endif #else /* original version */ #if defined(DES_RISC1) || defined(DES_RISC2) #ifdef DES_RISC1 #define D_ENCRYPT(LL,R,S) {\ unsigned int u1,u2,u3; \ LOAD_DATA(R,S,u,t,E0,E1,u1); \ u>>=2L; \ t=ROTATE(t,6); \ u2=(int)u>>8L; \ u1=(int)u&0x3f; \ u2&=0x3f; \ u>>=16L; \ LL^=des_SPtrans[0][u1]; \ LL^=des_SPtrans[2][u2]; \ u3=(int)u>>8L; \ u1=(int)u&0x3f; \ u3&=0x3f; \ LL^=des_SPtrans[4][u1]; \ LL^=des_SPtrans[6][u3]; \ u2=(int)t>>8L; \ u1=(int)t&0x3f; \ u2&=0x3f; \ t>>=16L; \ LL^=des_SPtrans[1][u1]; \ LL^=des_SPtrans[3][u2]; \ u3=(int)t>>8L; \ u1=(int)t&0x3f; \ u3&=0x3f; \ LL^=des_SPtrans[5][u1]; \ LL^=des_SPtrans[7][u3]; } #endif #ifdef DES_RISC2 #define D_ENCRYPT(LL,R,S) {\ unsigned int u1,u2,s1,s2; \ LOAD_DATA(R,S,u,t,E0,E1,u1); \ u>>=2L; \ t=ROTATE(t,6); \ u2=(int)u>>8L; \ u1=(int)u&0x3f; \ u2&=0x3f; \ LL^=des_SPtrans[0][u1]; \ LL^=des_SPtrans[2][u2]; \ s1=(int)u>>16L; \ s2=(int)u>>24L; \ s1&=0x3f; \ s2&=0x3f; \ LL^=des_SPtrans[4][s1]; \ LL^=des_SPtrans[6][s2]; \ u2=(int)t>>8L; \ u1=(int)t&0x3f; \ u2&=0x3f; \ LL^=des_SPtrans[1][u1]; \ LL^=des_SPtrans[3][u2]; \ s1=(int)t>>16; \ s2=(int)t>>24L; \ s1&=0x3f; \ s2&=0x3f; \ LL^=des_SPtrans[5][s1]; \ LL^=des_SPtrans[7][s2]; } #endif #else #define D_ENCRYPT(LL,R,S) {\ LOAD_DATA_tmp(R,S,u,t,E0,E1); \ t=ROTATE(t,4); \ LL^=\ des_SPtrans[0][(u>> 2L)&0x3f]^ \ des_SPtrans[2][(u>>10L)&0x3f]^ \ des_SPtrans[4][(u>>18L)&0x3f]^ \ des_SPtrans[6][(u>>26L)&0x3f]^ \ des_SPtrans[1][(t>> 2L)&0x3f]^ \ des_SPtrans[3][(t>>10L)&0x3f]^ \ des_SPtrans[5][(t>>18L)&0x3f]^ \ des_SPtrans[7][(t>>26L)&0x3f]; } #endif #endif /* IP and FP * The problem is more of a geometric problem that random bit fiddling. 0 1 2 3 4 5 6 7 62 54 46 38 30 22 14 6 8 9 10 11 12 13 14 15 60 52 44 36 28 20 12 4 16 17 18 19 20 21 22 23 58 50 42 34 26 18 10 2 24 25 26 27 28 29 30 31 to 56 48 40 32 24 16 8 0 32 33 34 35 36 37 38 39 63 55 47 39 31 23 15 7 40 41 42 43 44 45 46 47 61 53 45 37 29 21 13 5 48 49 50 51 52 53 54 55 59 51 43 35 27 19 11 3 56 57 58 59 60 61 62 63 57 49 41 33 25 17 9 1 The output has been subject to swaps of the form 0 1 -> 3 1 but the odd and even bits have been put into 2 3 2 0 different words. The main trick is to remember that t=((l>>size)^r)&(mask); r^=t; l^=(t<>(n))^(b))&(m)),\ (b)^=(t),\ (a)^=((t)<<(n))) #define IP(l,r) \ { \ register DES_LONG tt; \ PERM_OP(r,l,tt, 4,0x0f0f0f0fL); \ PERM_OP(l,r,tt,16,0x0000ffffL); \ PERM_OP(r,l,tt, 2,0x33333333L); \ PERM_OP(l,r,tt, 8,0x00ff00ffL); \ PERM_OP(r,l,tt, 1,0x55555555L); \ } #define FP(l,r) \ { \ register DES_LONG tt; \ PERM_OP(l,r,tt, 1,0x55555555L); \ PERM_OP(r,l,tt, 8,0x00ff00ffL); \ PERM_OP(l,r,tt, 2,0x33333333L); \ PERM_OP(r,l,tt,16,0x0000ffffL); \ PERM_OP(l,r,tt, 4,0x0f0f0f0fL); \ } extern const DES_LONG des_SPtrans[8][64]; #endif \ No newline at end of file diff --git a/mac/libdes/src/des_locl.org b/mac/libdes/src/des_locl.org deleted file mode 100755 index d7af95be..00000000 --- a/mac/libdes/src/des_locl.org +++ /dev/null @@ -1 +0,0 @@ -/* crypto/des/des_locl.h */ /* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@mincom.oz.au). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@mincom.oz.au). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@mincom.oz.au)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ /* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING * * Always modify des_locl.org since des_locl.h is automatically generated from * it during SSLeay configuration. * * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING */ #ifndef HEADER_DES_LOCL_H #define HEADER_DES_LOCL_H #if defined(WIN32) || defined(WIN16) #ifndef MSDOS #define MSDOS #endif #endif #include #include #ifndef MSDOS #include #endif #include "des.h" #ifndef DES_DEFAULT_OPTIONS /* the following is tweaked from a config script, that is why it is a * protected undef/define */ #ifndef DES_PTR #undef DES_PTR #endif /* This helps C compiler generate the correct code for multiple functional * units. It reduces register dependancies at the expense of 2 more * registers */ #ifndef DES_RISC1 #undef DES_RISC1 #endif #ifndef DES_RISC2 #undef DES_RISC2 #endif #if defined(DES_RISC1) && defined(DES_RISC2) YOU SHOULD NOT HAVE BOTH DES_RISC1 AND DES_RISC2 DEFINED!!!!! #endif /* Unroll the inner loop, this sometimes helps, sometimes hinders. * Very mucy CPU dependant */ #ifndef DES_UNROLL #undef DES_UNROLL #endif /* These default values were supplied by * Peter Gutman * They are only used if nothing else has been defined */ #if !defined(DES_PTR) && !defined(DES_RISC1) && !defined(DES_RISC2) && !defined(DES_UNROLL) /* Special defines which change the way the code is built depending on the CPU and OS. For SGI machines you can use _MIPS_SZLONG (32 or 64) to find even newer MIPS CPU's, but at the moment one size fits all for optimization options. Older Sparc's work better with only UNROLL, but there's no way to tell at compile time what it is you're running on */ #if defined( sun ) /* Newer Sparc's */ #define DES_PTR #define DES_RISC1 #define DES_UNROLL #elif defined( __ultrix ) /* Older MIPS */ #define DES_PTR #define DES_RISC2 #define DES_UNROLL #elif defined( __osf1__ ) /* Alpha */ #define DES_PTR #define DES_RISC2 #elif defined ( _AIX ) /* RS6000 */ /* Unknown */ #elif defined( __hpux ) /* HP-PA */ /* Unknown */ #elif defined( __aux ) /* 68K */ /* Unknown */ #elif defined( __dgux ) /* 88K (but P6 in latest boxes) */ #define DES_UNROLL #elif defined( __sgi ) /* Newer MIPS */ #define DES_PTR #define DES_RISC2 #define DES_UNROLL #elif defined( i386 ) /* x86 boxes, should be gcc */ #define DES_PTR #define DES_RISC1 #define DES_UNROLL #endif /* Systems-specific speed defines */ #endif #endif /* DES_DEFAULT_OPTIONS */ #ifdef MSDOS /* Visual C++ 2.1 (Windows NT/95) */ #include #include #include #include #ifndef RAND #define RAND #endif #undef NOPROTO #endif #if defined(__STDC__) || defined(VMS) || defined(M_XENIX) || defined(MSDOS) #include #endif #ifndef RAND #define RAND #endif #ifdef linux #undef RAND #endif #ifdef MSDOS #define getpid() 2 #define RAND #undef NOPROTO #endif #if defined(NOCONST) #define const #endif #ifdef __STDC__ #undef NOPROTO #endif #ifdef RAND #define srandom(s) srand(s) #define random rand #endif #define ITERATIONS 16 #define HALF_ITERATIONS 8 /* used in des_read and des_write */ #define MAXWRITE (1024*16) #define BSIZE (MAXWRITE+4) #define c2l(c,l) (l =((DES_LONG)(*((c)++))) , \ l|=((DES_LONG)(*((c)++)))<< 8L, \ l|=((DES_LONG)(*((c)++)))<<16L, \ l|=((DES_LONG)(*((c)++)))<<24L) /* NOTE - c is not incremented as per c2l */ #define c2ln(c,l1,l2,n) { \ c+=n; \ l1=l2=0; \ switch (n) { \ case 8: l2 =((DES_LONG)(*(--(c))))<<24L; \ case 7: l2|=((DES_LONG)(*(--(c))))<<16L; \ case 6: l2|=((DES_LONG)(*(--(c))))<< 8L; \ case 5: l2|=((DES_LONG)(*(--(c)))); \ case 4: l1 =((DES_LONG)(*(--(c))))<<24L; \ case 3: l1|=((DES_LONG)(*(--(c))))<<16L; \ case 2: l1|=((DES_LONG)(*(--(c))))<< 8L; \ case 1: l1|=((DES_LONG)(*(--(c)))); \ } \ } #define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ *((c)++)=(unsigned char)(((l)>>24L)&0xff)) /* replacements for htonl and ntohl since I have no idea what to do * when faced with machines with 8 byte longs. */ #define HDRSIZE 4 #define n2l(c,l) (l =((DES_LONG)(*((c)++)))<<24L, \ l|=((DES_LONG)(*((c)++)))<<16L, \ l|=((DES_LONG)(*((c)++)))<< 8L, \ l|=((DES_LONG)(*((c)++)))) #define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24L)&0xff), \ *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ *((c)++)=(unsigned char)(((l) )&0xff)) /* NOTE - c is not incremented as per l2c */ #define l2cn(l1,l2,c,n) { \ c+=n; \ switch (n) { \ case 8: *(--(c))=(unsigned char)(((l2)>>24L)&0xff); \ case 7: *(--(c))=(unsigned char)(((l2)>>16L)&0xff); \ case 6: *(--(c))=(unsigned char)(((l2)>> 8L)&0xff); \ case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \ case 4: *(--(c))=(unsigned char)(((l1)>>24L)&0xff); \ case 3: *(--(c))=(unsigned char)(((l1)>>16L)&0xff); \ case 2: *(--(c))=(unsigned char)(((l1)>> 8L)&0xff); \ case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \ } \ } #if defined(WIN32) #define ROTATE(a,n) (_lrotr(a,n)) #else #define ROTATE(a,n) (((a)>>(n))+((a)<<(32-(n)))) #endif /* Don't worry about the LOAD_DATA() stuff, that is used by * fcrypt() to add it's little bit to the front */ #ifdef DES_FCRYPT #define LOAD_DATA_tmp(R,S,u,t,E0,E1) \ { DES_LONG tmp; LOAD_DATA(R,S,u,t,E0,E1,tmp); } #define LOAD_DATA(R,S,u,t,E0,E1,tmp) \ t=R^(R>>16L); \ u=t&E0; t&=E1; \ tmp=(u<<16); u^=R^s[S ]; u^=tmp; \ tmp=(t<<16); t^=R^s[S+1]; t^=tmp #else #define LOAD_DATA_tmp(a,b,c,d,e,f) LOAD_DATA(a,b,c,d,e,f,g) #define LOAD_DATA(R,S,u,t,E0,E1,tmp) \ u=R^s[S ]; \ t=R^s[S+1] #endif /* The changes to this macro may help or hinder, depending on the * compiler and the achitecture. gcc2 always seems to do well :-). * Inspired by Dana How * DO NOT use the alternative version on machines with 8 byte longs. * It does not seem to work on the Alpha, even when DES_LONG is 4 * bytes, probably an issue of accessing non-word aligned objects :-( */ #ifdef DES_PTR /* It recently occured to me that 0^0^0^0^0^0^0 == 0, so there * is no reason to not xor all the sub items together. This potentially * saves a register since things can be xored directly into L */ #if defined(DES_RISC1) || defined(DES_RISC2) #ifdef DES_RISC1 #define D_ENCRYPT(LL,R,S) { \ unsigned int u1,u2,u3; \ LOAD_DATA(R,S,u,t,E0,E1,u1); \ u2=(int)u>>8L; \ u1=(int)u&0xfc; \ u2&=0xfc; \ t=ROTATE(t,4); \ u>>=16L; \ LL^= *(DES_LONG *)((unsigned char *)des_SP +u1); \ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x200+u2); \ u3=(int)(u>>8L); \ u1=(int)u&0xfc; \ u3&=0xfc; \ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x400+u1); \ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x600+u3); \ u2=(int)t>>8L; \ u1=(int)t&0xfc; \ u2&=0xfc; \ t>>=16L; \ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x100+u1); \ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x300+u2); \ u3=(int)t>>8L; \ u1=(int)t&0xfc; \ u3&=0xfc; \ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x500+u1); \ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x700+u3); } #endif #ifdef DES_RISC2 #define D_ENCRYPT(LL,R,S) { \ unsigned int u1,u2,s1,s2; \ LOAD_DATA(R,S,u,t,E0,E1,u1); \ u2=(int)u>>8L; \ u1=(int)u&0xfc; \ u2&=0xfc; \ t=ROTATE(t,4); \ LL^= *(DES_LONG *)((unsigned char *)des_SP +u1); \ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x200+u2); \ s1=(int)(u>>16L); \ s2=(int)(u>>24L); \ s1&=0xfc; \ s2&=0xfc; \ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x400+s1); \ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x600+s2); \ u2=(int)t>>8L; \ u1=(int)t&0xfc; \ u2&=0xfc; \ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x100+u1); \ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x300+u2); \ s1=(int)(t>>16L); \ s2=(int)(t>>24L); \ s1&=0xfc; \ s2&=0xfc; \ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x500+s1); \ LL^= *(DES_LONG *)((unsigned char *)des_SP+0x700+s2); } #endif #else #define D_ENCRYPT(LL,R,S) { \ LOAD_DATA_tmp(R,S,u,t,E0,E1); \ t=ROTATE(t,4); \ LL^= \ *(DES_LONG *)((unsigned char *)des_SP +((u )&0xfc))^ \ *(DES_LONG *)((unsigned char *)des_SP+0x200+((u>> 8L)&0xfc))^ \ *(DES_LONG *)((unsigned char *)des_SP+0x400+((u>>16L)&0xfc))^ \ *(DES_LONG *)((unsigned char *)des_SP+0x600+((u>>24L)&0xfc))^ \ *(DES_LONG *)((unsigned char *)des_SP+0x100+((t )&0xfc))^ \ *(DES_LONG *)((unsigned char *)des_SP+0x300+((t>> 8L)&0xfc))^ \ *(DES_LONG *)((unsigned char *)des_SP+0x500+((t>>16L)&0xfc))^ \ *(DES_LONG *)((unsigned char *)des_SP+0x700+((t>>24L)&0xfc)); } #endif #else /* original version */ #if defined(DES_RISC1) || defined(DES_RISC2) #ifdef DES_RISC1 #define D_ENCRYPT(LL,R,S) {\ unsigned int u1,u2,u3; \ LOAD_DATA(R,S,u,t,E0,E1,u1); \ u>>=2L; \ t=ROTATE(t,6); \ u2=(int)u>>8L; \ u1=(int)u&0x3f; \ u2&=0x3f; \ u>>=16L; \ LL^=des_SPtrans[0][u1]; \ LL^=des_SPtrans[2][u2]; \ u3=(int)u>>8L; \ u1=(int)u&0x3f; \ u3&=0x3f; \ LL^=des_SPtrans[4][u1]; \ LL^=des_SPtrans[6][u3]; \ u2=(int)t>>8L; \ u1=(int)t&0x3f; \ u2&=0x3f; \ t>>=16L; \ LL^=des_SPtrans[1][u1]; \ LL^=des_SPtrans[3][u2]; \ u3=(int)t>>8L; \ u1=(int)t&0x3f; \ u3&=0x3f; \ LL^=des_SPtrans[5][u1]; \ LL^=des_SPtrans[7][u3]; } #endif #ifdef DES_RISC2 #define D_ENCRYPT(LL,R,S) {\ unsigned int u1,u2,s1,s2; \ LOAD_DATA(R,S,u,t,E0,E1,u1); \ u>>=2L; \ t=ROTATE(t,6); \ u2=(int)u>>8L; \ u1=(int)u&0x3f; \ u2&=0x3f; \ LL^=des_SPtrans[0][u1]; \ LL^=des_SPtrans[2][u2]; \ s1=(int)u>>16L; \ s2=(int)u>>24L; \ s1&=0x3f; \ s2&=0x3f; \ LL^=des_SPtrans[4][s1]; \ LL^=des_SPtrans[6][s2]; \ u2=(int)t>>8L; \ u1=(int)t&0x3f; \ u2&=0x3f; \ LL^=des_SPtrans[1][u1]; \ LL^=des_SPtrans[3][u2]; \ s1=(int)t>>16; \ s2=(int)t>>24L; \ s1&=0x3f; \ s2&=0x3f; \ LL^=des_SPtrans[5][s1]; \ LL^=des_SPtrans[7][s2]; } #endif #else #define D_ENCRYPT(LL,R,S) {\ LOAD_DATA_tmp(R,S,u,t,E0,E1); \ t=ROTATE(t,4); \ LL^=\ des_SPtrans[0][(u>> 2L)&0x3f]^ \ des_SPtrans[2][(u>>10L)&0x3f]^ \ des_SPtrans[4][(u>>18L)&0x3f]^ \ des_SPtrans[6][(u>>26L)&0x3f]^ \ des_SPtrans[1][(t>> 2L)&0x3f]^ \ des_SPtrans[3][(t>>10L)&0x3f]^ \ des_SPtrans[5][(t>>18L)&0x3f]^ \ des_SPtrans[7][(t>>26L)&0x3f]; } #endif #endif /* IP and FP * The problem is more of a geometric problem that random bit fiddling. 0 1 2 3 4 5 6 7 62 54 46 38 30 22 14 6 8 9 10 11 12 13 14 15 60 52 44 36 28 20 12 4 16 17 18 19 20 21 22 23 58 50 42 34 26 18 10 2 24 25 26 27 28 29 30 31 to 56 48 40 32 24 16 8 0 32 33 34 35 36 37 38 39 63 55 47 39 31 23 15 7 40 41 42 43 44 45 46 47 61 53 45 37 29 21 13 5 48 49 50 51 52 53 54 55 59 51 43 35 27 19 11 3 56 57 58 59 60 61 62 63 57 49 41 33 25 17 9 1 The output has been subject to swaps of the form 0 1 -> 3 1 but the odd and even bits have been put into 2 3 2 0 different words. The main trick is to remember that t=((l>>size)^r)&(mask); r^=t; l^=(t<>(n))^(b))&(m)),\ (b)^=(t),\ (a)^=((t)<<(n))) #define IP(l,r) \ { \ register DES_LONG tt; \ PERM_OP(r,l,tt, 4,0x0f0f0f0fL); \ PERM_OP(l,r,tt,16,0x0000ffffL); \ PERM_OP(r,l,tt, 2,0x33333333L); \ PERM_OP(l,r,tt, 8,0x00ff00ffL); \ PERM_OP(r,l,tt, 1,0x55555555L); \ } #define FP(l,r) \ { \ register DES_LONG tt; \ PERM_OP(l,r,tt, 1,0x55555555L); \ PERM_OP(r,l,tt, 8,0x00ff00ffL); \ PERM_OP(l,r,tt, 2,0x33333333L); \ PERM_OP(r,l,tt,16,0x0000ffffL); \ PERM_OP(l,r,tt, 4,0x0f0f0f0fL); \ } extern const DES_LONG des_SPtrans[8][64]; #endif \ No newline at end of file diff --git a/mac/libdes/src/des_opts.c b/mac/libdes/src/des_opts.c deleted file mode 100755 index 6a719810..00000000 --- a/mac/libdes/src/des_opts.c +++ /dev/null @@ -1 +0,0 @@ -/* crypto/des/des_opts.c */ /* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@mincom.oz.au). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@mincom.oz.au). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@mincom.oz.au)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ /* define PART1, PART2, PART3 or PART4 to build only with a few of the options. * This is for machines with 64k code segment size restrictions. */ #ifndef MSDOS #define TIMES #endif #include #ifndef MSDOS #include #else #include extern void exit(); #endif #include #ifndef VMS #ifndef _IRIX #include #endif #ifdef TIMES #include #include #endif #else /* VMS */ #include struct tms { time_t tms_utime; time_t tms_stime; time_t tms_uchild; /* I dunno... */ time_t tms_uchildsys; /* so these names are a guess :-) */ } #endif #ifndef TIMES #include #endif #ifdef sun #include #include #endif #include "des.h" #include "spr.h" #define DES_DEFAULT_OPTIONS #if !defined(PART1) && !defined(PART2) && !defined(PART3) && !defined(PART4) #define PART1 #define PART2 #define PART3 #define PART4 #endif #ifdef PART1 #undef DES_UNROLL #undef DES_RISC1 #undef DES_RISC2 #undef DES_PTR #undef D_ENCRYPT #define des_encrypt des_encrypt_u4_cisc_idx #define des_encrypt2 des_encrypt2_u4_cisc_idx #define des_encrypt3 des_encrypt3_u4_cisc_idx #define des_decrypt3 des_decrypt3_u4_cisc_idx #undef HEADER_DES_LOCL_H #include "des_enc.c" #define DES_UNROLL #undef DES_RISC1 #undef DES_RISC2 #undef DES_PTR #undef D_ENCRYPT #undef des_encrypt #undef des_encrypt2 #undef des_encrypt3 #undef des_decrypt3 #define des_encrypt des_encrypt_u16_cisc_idx #define des_encrypt2 des_encrypt2_u16_cisc_idx #define des_encrypt3 des_encrypt3_u16_cisc_idx #define des_decrypt3 des_decrypt3_u16_cisc_idx #undef HEADER_DES_LOCL_H #include "des_enc.c" #undef DES_UNROLL #define DES_RISC1 #undef DES_RISC2 #undef DES_PTR #undef D_ENCRYPT #undef des_encrypt #undef des_encrypt2 #undef des_encrypt3 #undef des_decrypt3 #define des_encrypt des_encrypt_u4_risc1_idx #define des_encrypt2 des_encrypt2_u4_risc1_idx #define des_encrypt3 des_encrypt3_u4_risc1_idx #define des_decrypt3 des_decrypt3_u4_risc1_idx #undef HEADER_DES_LOCL_H #include "des_enc.c" #endif #ifdef PART2 #undef DES_UNROLL #undef DES_RISC1 #define DES_RISC2 #undef DES_PTR #undef D_ENCRYPT #undef des_encrypt #undef des_encrypt2 #undef des_encrypt3 #undef des_decrypt3 #define des_encrypt des_encrypt_u4_risc2_idx #define des_encrypt2 des_encrypt2_u4_risc2_idx #define des_encrypt3 des_encrypt3_u4_risc2_idx #define des_decrypt3 des_decrypt3_u4_risc2_idx #undef HEADER_DES_LOCL_H #include "des_enc.c" #define DES_UNROLL #define DES_RISC1 #undef DES_RISC2 #undef DES_PTR #undef D_ENCRYPT #undef des_encrypt #undef des_encrypt2 #undef des_encrypt3 #undef des_decrypt3 #define des_encrypt des_encrypt_u16_risc1_idx #define des_encrypt2 des_encrypt2_u16_risc1_idx #define des_encrypt3 des_encrypt3_u16_risc1_idx #define des_decrypt3 des_decrypt3_u16_risc1_idx #undef HEADER_DES_LOCL_H #include "des_enc.c" #define DES_UNROLL #undef DES_RISC1 #define DES_RISC2 #undef DES_PTR #undef D_ENCRYPT #undef des_encrypt #undef des_encrypt2 #undef des_encrypt3 #undef des_decrypt3 #define des_encrypt des_encrypt_u16_risc2_idx #define des_encrypt2 des_encrypt2_u16_risc2_idx #define des_encrypt3 des_encrypt3_u16_risc2_idx #define des_decrypt3 des_decrypt3_u16_risc2_idx #undef HEADER_DES_LOCL_H #include "des_enc.c" #endif #ifdef PART3 #undef DES_UNROLL #undef DES_RISC1 #undef DES_RISC2 #define DES_PTR #undef D_ENCRYPT #undef des_encrypt #undef des_encrypt2 #undef des_encrypt3 #undef des_decrypt3 #define des_encrypt des_encrypt_u4_cisc_ptr #define des_encrypt2 des_encrypt2_u4_cisc_ptr #define des_encrypt3 des_encrypt3_u4_cisc_ptr #define des_decrypt3 des_decrypt3_u4_cisc_ptr #undef HEADER_DES_LOCL_H #include "des_enc.c" #define DES_UNROLL #undef DES_RISC1 #undef DES_RISC2 #define DES_PTR #undef D_ENCRYPT #undef des_encrypt #undef des_encrypt2 #undef des_encrypt3 #undef des_decrypt3 #define des_encrypt des_encrypt_u16_cisc_ptr #define des_encrypt2 des_encrypt2_u16_cisc_ptr #define des_encrypt3 des_encrypt3_u16_cisc_ptr #define des_decrypt3 des_decrypt3_u16_cisc_ptr #undef HEADER_DES_LOCL_H #include "des_enc.c" #undef DES_UNROLL #define DES_RISC1 #undef DES_RISC2 #define DES_PTR #undef D_ENCRYPT #undef des_encrypt #undef des_encrypt2 #undef des_encrypt3 #undef des_decrypt3 #define des_encrypt des_encrypt_u4_risc1_ptr #define des_encrypt2 des_encrypt2_u4_risc1_ptr #define des_encrypt3 des_encrypt3_u4_risc1_ptr #define des_decrypt3 des_decrypt3_u4_risc1_ptr #undef HEADER_DES_LOCL_H #include "des_enc.c" #endif #ifdef PART4 #undef DES_UNROLL #undef DES_RISC1 #define DES_RISC2 #define DES_PTR #undef D_ENCRYPT #undef des_encrypt #undef des_encrypt2 #undef des_encrypt3 #undef des_decrypt3 #define des_encrypt des_encrypt_u4_risc2_ptr #define des_encrypt2 des_encrypt2_u4_risc2_ptr #define des_encrypt3 des_encrypt3_u4_risc2_ptr #define des_decrypt3 des_decrypt3_u4_risc2_ptr #undef HEADER_DES_LOCL_H #include "des_enc.c" #define DES_UNROLL #define DES_RISC1 #undef DES_RISC2 #define DES_PTR #undef D_ENCRYPT #undef des_encrypt #undef des_encrypt2 #undef des_encrypt3 #undef des_decrypt3 #define des_encrypt des_encrypt_u16_risc1_ptr #define des_encrypt2 des_encrypt2_u16_risc1_ptr #define des_encrypt3 des_encrypt3_u16_risc1_ptr #define des_decrypt3 des_decrypt3_u16_risc1_ptr #undef HEADER_DES_LOCL_H #include "des_enc.c" #define DES_UNROLL #undef DES_RISC1 #define DES_RISC2 #define DES_PTR #undef D_ENCRYPT #undef des_encrypt #undef des_encrypt2 #undef des_encrypt3 #undef des_decrypt3 #define des_encrypt des_encrypt_u16_risc2_ptr #define des_encrypt2 des_encrypt2_u16_risc2_ptr #define des_encrypt3 des_encrypt3_u16_risc2_ptr #define des_decrypt3 des_decrypt3_u16_risc2_ptr #undef HEADER_DES_LOCL_H #include "des_enc.c" #endif /* The following if from times(3) man page. It may need to be changed */ #ifndef HZ #ifndef CLK_TCK #ifndef VMS #define HZ 100.0 #else /* VMS */ #define HZ 100.0 #endif #else /* CLK_TCK */ #define HZ ((double)CLK_TCK) #endif #endif #define BUFSIZE ((long)1024) long run=0; #ifndef NOPROTO double Time_F(int s); #else double Time_F(); #endif #ifdef SIGALRM #if defined(__STDC__) || defined(sgi) #define SIGRETTYPE void #else #define SIGRETTYPE int #endif #ifndef NOPROTO SIGRETTYPE sig_done(int sig); #else SIGRETTYPE sig_done(); #endif SIGRETTYPE sig_done(sig) int sig; { signal(SIGALRM,sig_done); run=0; #ifdef LINT sig=sig; #endif } #endif #define START 0 #define STOP 1 double Time_F(s) int s; { double ret; #ifdef TIMES static struct tms tstart,tend; if (s == START) { times(&tstart); return(0); } else { times(&tend); ret=((double)(tend.tms_utime-tstart.tms_utime))/HZ; return((ret == 0.0)?1e-6:ret); } #else /* !times() */ static struct timeb tstart,tend; long i; if (s == START) { ftime(&tstart); return(0); } else { ftime(&tend); i=(long)tend.millitm-(long)tstart.millitm; ret=((double)(tend.time-tstart.time))+((double)i)/1000.0; return((ret == 0.0)?1e-6:ret); } #endif } #ifdef SIGALRM #define print_name(name) fprintf(stderr,"Doing %s's for 10 seconds\n",name); alarm(10); #else #define print_name(name) fprintf(stderr,"Doing %s %ld times\n",name,cb); #endif #define time_it(func,name,index) \ print_name(name); \ Time_F(START); \ for (count=0,run=1; COND(cb); count++) \ { \ unsigned long d[2]; \ func(d,&(sch[0]),DES_ENCRYPT); \ } \ tm[index]=Time_F(STOP); \ fprintf(stderr,"%ld %s's in %.2f second\n",count,name,tm[index]); \ tm[index]=((double)COUNT(cb))/tm[index]; #define print_it(name,index) \ fprintf(stderr,"%s bytes per sec = %12.2f (%5.1fuS)\n",name, \ tm[index]*8,1.0e6/tm[index]); int main(argc,argv) int argc; char **argv; { long count; static unsigned char buf[BUFSIZE]; static des_cblock key ={0x12,0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0}; static des_cblock key2={0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12}; static des_cblock key3={0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12,0x34}; des_key_schedule sch,sch2,sch3; double d,tm[16],max=0; int rank[16]; char *str[16]; int max_idx=0,i,num=0,j; #ifndef SIGALARM long ca,cb,cc,cd,ce; #endif for (i=0; i<12; i++) { tm[i]=0.0; rank[i]=0; } #ifndef TIMES fprintf(stderr,"To get the most acurate results, try to run this\n"); fprintf(stderr,"program when this computer is idle.\n"); #endif des_set_key((C_Block *)key,sch); des_set_key((C_Block *)key2,sch2); des_set_key((C_Block *)key3,sch3); #ifndef SIGALRM fprintf(stderr,"First we calculate the approximate speed ...\n"); des_set_key((C_Block *)key,sch); count=10; do { long i; unsigned long data[2]; count*=2; Time_F(START); for (i=count; i; i--) des_encrypt(data,&(sch[0]),DES_ENCRYPT); d=Time_F(STOP); } while (d < 3.0); ca=count; cb=count*3; cc=count*3*8/BUFSIZE+1; cd=count*8/BUFSIZE+1; ce=count/20+1; #define COND(d) (count != (d)) #define COUNT(d) (d) #else #define COND(c) (run) #define COUNT(d) (count) signal(SIGALRM,sig_done); alarm(10); #endif #ifdef PART1 time_it(des_encrypt_u4_cisc_idx, "des_encrypt_u4_cisc_idx ", 0); time_it(des_encrypt_u16_cisc_idx, "des_encrypt_u16_cisc_idx ", 1); time_it(des_encrypt_u4_risc1_idx, "des_encrypt_u4_risc1_idx ", 2); num+=3; #endif #ifdef PART2 time_it(des_encrypt_u16_risc1_idx,"des_encrypt_u16_risc1_idx", 3); time_it(des_encrypt_u4_risc2_idx, "des_encrypt_u4_risc2_idx ", 4); time_it(des_encrypt_u16_risc2_idx,"des_encrypt_u16_risc2_idx", 5); num+=3; #endif #ifdef PART3 time_it(des_encrypt_u4_cisc_ptr, "des_encrypt_u4_cisc_ptr ", 6); time_it(des_encrypt_u16_cisc_ptr, "des_encrypt_u16_cisc_ptr ", 7); time_it(des_encrypt_u4_risc1_ptr, "des_encrypt_u4_risc1_ptr ", 8); num+=3; #endif #ifdef PART4 time_it(des_encrypt_u16_risc1_ptr,"des_encrypt_u16_risc1_ptr", 9); time_it(des_encrypt_u4_risc2_ptr, "des_encrypt_u4_risc2_ptr ",10); time_it(des_encrypt_u16_risc2_ptr,"des_encrypt_u16_risc2_ptr",11); num+=3; #endif #ifdef PART1 str[0]=" 4 c i"; print_it("des_encrypt_u4_cisc_idx ",0); max=tm[0]; max_idx=0; str[1]="16 c i"; print_it("des_encrypt_u16_cisc_idx ",1); if (max < tm[1]) { max=tm[1]; max_idx=1; } str[2]=" 4 r1 i"; print_it("des_encrypt_u4_risc1_idx ",2); if (max < tm[2]) { max=tm[2]; max_idx=2; } #endif #ifdef PART2 str[3]="16 r1 i"; print_it("des_encrypt_u16_risc1_idx",3); if (max < tm[3]) { max=tm[3]; max_idx=3; } str[4]=" 4 r2 i"; print_it("des_encrypt_u4_risc2_idx ",4); if (max < tm[4]) { max=tm[4]; max_idx=4; } str[5]="16 r2 i"; print_it("des_encrypt_u16_risc2_idx",5); if (max < tm[5]) { max=tm[5]; max_idx=5; } #endif #ifdef PART3 str[6]=" 4 c p"; print_it("des_encrypt_u4_cisc_ptr ",6); if (max < tm[6]) { max=tm[6]; max_idx=6; } str[7]="16 c p"; print_it("des_encrypt_u16_cisc_ptr ",7); if (max < tm[7]) { max=tm[7]; max_idx=7; } str[8]=" 4 r1 p"; print_it("des_encrypt_u4_risc1_ptr ",8); if (max < tm[8]) { max=tm[8]; max_idx=8; } #endif #ifdef PART4 str[9]="16 r1 p"; print_it("des_encrypt_u16_risc1_ptr",9); if (max < tm[9]) { max=tm[9]; max_idx=9; } str[10]=" 4 r2 p"; print_it("des_encrypt_u4_risc2_ptr ",10); if (max < tm[10]) { max=tm[10]; max_idx=10; } str[11]="16 r2 p"; print_it("des_encrypt_u16_risc2_ptr",11); if (max < tm[11]) { max=tm[11]; max_idx=11; } #endif printf("options des ecb/s\n"); printf("%s %12.2f 100.0%%\n",str[max_idx],tm[max_idx]); d=tm[max_idx]; tm[max_idx]= -2.0; max= -1.0; for (;;) { for (i=0; i<12; i++) { if (max < tm[i]) { max=tm[i]; j=i; } } if (max < 0.0) break; printf("%s %12.2f %4.1f%%\n",str[j],tm[j],tm[j]/d*100.0); tm[j]= -2.0; max= -1.0; } switch (max_idx) { case 0: printf("-DDES_DEFAULT_OPTIONS\n"); break; case 1: printf("-DDES_UNROLL\n"); break; case 2: printf("-DDES_RISC1\n"); break; case 3: printf("-DDES_UNROLL -DDES_RISC1\n"); break; case 4: printf("-DDES_RISC2\n"); break; case 5: printf("-DDES_UNROLL -DDES_RISC2\n"); break; case 6: printf("-DDES_PTR\n"); break; case 7: printf("-DDES_UNROLL -DDES_PTR\n"); break; case 8: printf("-DDES_RISC1 -DDES_PTR\n"); break; case 9: printf("-DDES_UNROLL -DDES_RISC1 -DDES_PTR\n"); break; case 10: printf("-DDES_RISC2 -DDES_PTR\n"); break; case 11: printf("-DDES_UNROLL -DDES_RISC2 -DDES_PTR\n"); break; } exit(0); #if defined(LINT) || defined(MSDOS) return(0); #endif } \ No newline at end of file diff --git a/mac/libdes/src/des_ver.h b/mac/libdes/src/des_ver.h deleted file mode 100755 index 746c01d9..00000000 --- a/mac/libdes/src/des_ver.h +++ /dev/null @@ -1 +0,0 @@ -/* crypto/des/des_ver.h */ /* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@mincom.oz.au). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@mincom.oz.au). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@mincom.oz.au)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ extern char *DES_version; /* SSLeay version string */ extern char *libdes_version; /* old libdes version string */ \ No newline at end of file diff --git a/mac/libdes/src/dllmain.c b/mac/libdes/src/dllmain.c deleted file mode 100755 index a8986362..00000000 --- a/mac/libdes/src/dllmain.c +++ /dev/null @@ -1 +0,0 @@ -/* * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Hgskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the Kungliga Tekniska * Hgskolan and its contributors. * * 4. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #include RCSID("$Id: dllmain.c,v 1.2 2001/12/04 02:06:29 rjs3 Exp $"); #endif #include BOOL WINAPI DllMain (HANDLE hInst, ULONG reason, LPVOID lpReserved) { switch(reason) { case DLL_PROCESS_ATTACH: case DLL_PROCESS_DETACH: default: return TRUE; } } \ No newline at end of file diff --git a/mac/libdes/src/doIP b/mac/libdes/src/doIP deleted file mode 100755 index b0a4dbe8..00000000 --- a/mac/libdes/src/doIP +++ /dev/null @@ -1 +0,0 @@ -#!/usr/local/bin/perl @l=( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, 16,17,18,19,20,21,22,23, 24,25,26,27,28,29,30,31 ); @r=( 32,33,34,35,36,37,38,39, 40,41,42,43,44,45,46,47, 48,49,50,51,52,53,54,55, 56,57,58,59,60,61,62,63 ); require 'shifts.pl'; sub PERM_OP { local(*a,*b,*t,$n,$m)=@_; @z=&shift(*a,-$n); @z=&xor(*b,*z); @z=&and(*z,$m); @b=&xor(*b,*z); @z=&shift(*z,$n); @a=&xor(*a,*z); } @L=@l; @R=@r; &PERM_OP(*R,*L,*T,4,0x0f0f0f0f); &PERM_OP(*L,*R,*T,16,0x0000ffff); &PERM_OP(*R,*L,*T,2,0x33333333); &PERM_OP(*L,*R,*T,8,0x00ff00ff); &PERM_OP(*R,*L,*T,1,0x55555555); &printit(@L); &printit(@R); &PERM_OP(*R,*L,*T,1,0x55555555); &PERM_OP(*L,*R,*T,8,0x00ff00ff); &PERM_OP(*R,*L,*T,2,0x33333333); &PERM_OP(*L,*R,*T,16,0x0000ffff); &PERM_OP(*R,*L,*T,4,0x0f0f0f0f); &printit(@L); &printit(@R); \ No newline at end of file diff --git a/mac/libdes/src/doPC1 b/mac/libdes/src/doPC1 deleted file mode 100755 index f4827e6d..00000000 --- a/mac/libdes/src/doPC1 +++ /dev/null @@ -1 +0,0 @@ -#!/usr/local/bin/perl @l=( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, 16,17,18,19,20,21,22,23, 24,25,26,27,28,29,30,31 ); @r=( 32,33,34,35,36,37,38,39, 40,41,42,43,44,45,46,47, 48,49,50,51,52,53,54,55, 56,57,58,59,60,61,62,63 ); require 'shifts.pl'; sub PERM_OP { local(*a,*b,*t,$n,$m)=@_; @z=&shift(*a,-$n); @z=&xor(*b,*z); @z=&and(*z,$m); @b=&xor(*b,*z); @z=&shift(*z,$n); @a=&xor(*a,*z); } sub HPERM_OP2 { local(*a,*t,$n,$m)=@_; local(@x,@y,$i); @z=&shift(*a,16-$n); @z=&xor(*a,*z); @z=&and(*z,$m); @a=&xor(*a,*z); @z=&shift(*z,$n-16); @a=&xor(*a,*z); } sub HPERM_OP { local(*a,*t,$n,$m)=@_; local(@x,@y,$i); for ($i=0; $i<16; $i++) { $x[$i]=$a[$i]; $y[$i]=$a[16+$i]; } @z=&shift(*x,-$n); @z=&xor(*y,*z); @z=&and(*z,$m); @y=&xor(*y,*z); @z=&shift(*z,$n); @x=&xor(*x,*z); for ($i=0; $i<16; $i++) { $a[$i]=$x[$i]; $a[16+$i]=$y[$i]; } } @L=@l; @R=@r; print "---\n"; &printit(@R); &PERM_OP(*R,*L,*T,4,0x0f0f0f0f); print "---\n"; &printit(@R); &HPERM_OP2(*L,*T,-2,0xcccc0000); &HPERM_OP2(*R,*T,-2,0xcccc0000); print "---\n"; &printit(@R); &PERM_OP(*R,*L,*T,1,0x55555555); print "---\n"; &printit(@R); &PERM_OP(*L,*R,*T,8,0x00ff00ff); print "---\n"; &printit(@R); &PERM_OP(*R,*L,*T,1,0x55555555); print "---\n"; &printit(@R); # &printit(@L); &printit(@R); print <<"EOF"; ============================== 63 55 47 39 31 23 15 7 62 54 46 38 30 22 14 6 61 53 45 37 29 21 13 5 60 52 44 36 -- -- -- -- 57 49 41 33 25 17 9 1 58 50 42 34 26 18 10 2 59 51 43 35 27 19 11 3 28 20 12 4 -- -- -- -- EOF exit(1); @A=&and(*R,0x000000ff); @A=&shift(*A,16); @B=&and(*R,0x0000ff00); @C=&and(*R,0x00ff0000); @C=&shift(*C,-16); @D=&and(*L,0xf0000000); @D=&shift(*D,-4); @A=&or(*A,*B); @B=&or(*D,*C); @R=&or(*A,*B); @L=&and(*L,0x0fffffff); &printit(@L); &printit(@R); \ No newline at end of file diff --git a/mac/libdes/src/doPC2 b/mac/libdes/src/doPC2 deleted file mode 100755 index d2c111fd..00000000 --- a/mac/libdes/src/doPC2 +++ /dev/null @@ -1 +0,0 @@ -#!/usr/local/bin/perl @PC2_C=(14,17,11,24, 1, 5, 3,28,15, 6,21,10, 23,19,12, 4,26, 8, 16, 7,27,20,13, 2, ); @PC2_D=(41,52,31,37,47,55, 30,40,51,45,33,48, 44,49,39,56,34,53, 46,42,50,36,29,32, ); $i=0; foreach (@PC2_C) { $_--; # printf "%2d,",$_; $C{$_}=$i; ++$i; # print "\n" if ((($i) % 8) == 0); } $i=0; #print "\n"; foreach (@PC2_D) { $_-=28; $_--; # printf "%2d,",$_; $D{$_}=$i; $i++; # print "\n" if ((($i) % 8) == 0); } #print "\n"; foreach $i (0 .. 27) { $_=$C{$i}; # printf "%2d,",$_; $i++; # print "\n" if ((($i) % 8) == 0); } #print "\n"; #print "\n"; foreach $i (0 .. 27) { $_=$D{$i}; # printf "%2d,",$_; $i++; # print "\n" if ((($i) % 8) == 0); } #print "\n"; print "static ulong skb[8][64]={\n"; &doit("C",*C, 0, 1, 2, 3, 4, 5); &doit("C",*C, 6, 7, 9,10,11,12); &doit("C",*C,13,14,15,16,18,19); &doit("C",*C,20,22,23,25,26,27); &doit("D",*D, 0, 1, 2, 3, 4, 5); &doit("D",*D, 7, 8,10,11,12,13); &doit("D",*D,15,16,17,18,19,20); &doit("D",*D,21,22,23,24,26,27); print "};\n"; sub doit { local($l,*A,@b)=@_; local(@out); printf("/* for $l bits (numbered as per FIPS 46) %d %d %d %d %d %d */\n", $b[0]+1, $b[1]+1, $b[2]+1, $b[3]+1, $b[4]+1, $b[5]+1); for ($i=0; $i<64; $i++) { $out[$i]=0; $j=1; #print "\n"; for ($k=0; $k<6; $k++) { $l=$A{$b[$k]}; #print"$l - "; if ((1<<$k) & $i) { $ll=int($l/6)*8+($l%6); $out[$i]|=1<<($ll); } } $pp=$out[$i]; $pp=($pp&0xff0000ff)| (($pp&0x00ff0000)>>8)| (($pp&0x0000ff00)<<8); printf("0x%08X,",$pp); print "\n" if (($i+1) % 4 == 0); } } \ No newline at end of file diff --git a/mac/libdes/src/ecb3_enc.c b/mac/libdes/src/ecb3_enc.c deleted file mode 100755 index eeb0e623..00000000 --- a/mac/libdes/src/ecb3_enc.c +++ /dev/null @@ -1 +0,0 @@ -/* crypto/des/ecb3_enc.c */ /* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@mincom.oz.au). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@mincom.oz.au). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@mincom.oz.au)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ #include "des_locl.h" void des_ecb3_encrypt(input, output, ks1, ks2, ks3, encrypt) des_cblock (*input); des_cblock (*output); des_key_schedule ks1; des_key_schedule ks2; des_key_schedule ks3; int encrypt; { register DES_LONG l0,l1; register unsigned char *in,*out; DES_LONG ll[2]; in=(unsigned char *)input; out=(unsigned char *)output; c2l(in,l0); c2l(in,l1); ll[0]=l0; ll[1]=l1; if (encrypt) des_encrypt3(ll,ks1,ks2,ks3); else des_decrypt3(ll,ks1,ks2,ks3); l0=ll[0]; l1=ll[1]; l2c(l0,out); l2c(l1,out); } \ No newline at end of file diff --git a/mac/libdes/src/ecb_enc.c b/mac/libdes/src/ecb_enc.c deleted file mode 100755 index d2a5e896..00000000 --- a/mac/libdes/src/ecb_enc.c +++ /dev/null @@ -1 +0,0 @@ -/* crypto/des/ecb_enc.c */ /* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@mincom.oz.au). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@mincom.oz.au). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@mincom.oz.au)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ #include "des_locl.h" #include "spr.h" char *libdes_version="libdes v 4.01 - 13-Jan-1997 - eay"; char *DES_version="DES part of SSLeay 0.6.6 14-Jan-1997"; char *des_options() { static int init=1; static char buf[32]; if (init) { char *ptr,*unroll,*risc,*size; init=0; #ifdef DES_PTR ptr="ptr"; #else ptr="idx"; #endif #if defined(DES_RISC1) || defined(DES_RISC2) #ifdef DES_RISC1 risc="risc1"; #endif #ifdef DES_RISC2 risc="risc2"; #endif #else risc="cisc"; #endif #ifdef DES_UNROLL unroll="16"; #else unroll="4"; #endif if (sizeof(DES_LONG) != sizeof(long)) size="int"; else size="long"; sprintf(buf,"des(%s,%s,%s,%s)",ptr,risc,unroll,size); } return(buf); } void des_ecb_encrypt(input, output, ks, encrypt) des_cblock (*input); des_cblock (*output); des_key_schedule ks; int encrypt; { register DES_LONG l; register unsigned char *in,*out; DES_LONG ll[2]; in=(unsigned char *)input; out=(unsigned char *)output; c2l(in,l); ll[0]=l; c2l(in,l); ll[1]=l; des_encrypt(ll,ks,encrypt); l=ll[0]; l2c(l,out); l=ll[1]; l2c(l,out); l=ll[0]=ll[1]=0; } \ No newline at end of file diff --git a/mac/libdes/src/ede_enc.c b/mac/libdes/src/ede_enc.c deleted file mode 100755 index dae701b3..00000000 --- a/mac/libdes/src/ede_enc.c +++ /dev/null @@ -1 +0,0 @@ -/* crypto/des/ede_enc.c */ /* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@mincom.oz.au). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@mincom.oz.au). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@mincom.oz.au)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ #include "des_locl.h" void des_ede3_cbc_encrypt(input, output, length, ks1, ks2, ks3, ivec, encrypt) des_cblock (*input); des_cblock (*output); long length; des_key_schedule ks1; des_key_schedule ks2; des_key_schedule ks3; des_cblock (*ivec); int encrypt; { register DES_LONG tin0,tin1; register DES_LONG tout0,tout1,xor0,xor1; register unsigned char *in,*out; register long l=length; DES_LONG tin[2]; unsigned char *iv; in=(unsigned char *)input; out=(unsigned char *)output; iv=(unsigned char *)ivec; if (encrypt) { c2l(iv,tout0); c2l(iv,tout1); for (l-=8; l>=0; l-=8) { c2l(in,tin0); c2l(in,tin1); tin0^=tout0; tin1^=tout1; tin[0]=tin0; tin[1]=tin1; des_encrypt3((DES_LONG *)tin,ks1,ks2,ks3); tout0=tin[0]; tout1=tin[1]; l2c(tout0,out); l2c(tout1,out); } if (l != -8) { c2ln(in,tin0,tin1,l+8); tin0^=tout0; tin1^=tout1; tin[0]=tin0; tin[1]=tin1; des_encrypt3((DES_LONG *)tin,ks1,ks2,ks3); tout0=tin[0]; tout1=tin[1]; l2c(tout0,out); l2c(tout1,out); } iv=(unsigned char *)ivec; l2c(tout0,iv); l2c(tout1,iv); } else { register DES_LONG t0,t1; c2l(iv,xor0); c2l(iv,xor1); for (l-=8; l>=0; l-=8) { c2l(in,tin0); c2l(in,tin1); t0=tin0; t1=tin1; tin[0]=tin0; tin[1]=tin1; des_decrypt3((DES_LONG *)tin,ks1,ks2,ks3); tout0=tin[0]; tout1=tin[1]; tout0^=xor0; tout1^=xor1; l2c(tout0,out); l2c(tout1,out); xor0=t0; xor1=t1; } if (l != -8) { c2l(in,tin0); c2l(in,tin1); t0=tin0; t1=tin1; tin[0]=tin0; tin[1]=tin1; des_decrypt3((DES_LONG *)tin,ks1,ks2,ks3); tout0=tin[0]; tout1=tin[1]; tout0^=xor0; tout1^=xor1; l2cn(tout0,tout1,out,l+8); xor0=t0; xor1=t1; } iv=(unsigned char *)ivec; l2c(xor0,iv); l2c(xor1,iv); } tin0=tin1=tout0=tout1=xor0=xor1=0; tin[0]=tin[1]=0; } #ifdef undef /* MACRO */ void des_ede2_cbc_encrypt(input, output, length, ks1, ks2, ivec, enc) des_cblock (*input); des_cblock (*output); long length; des_key_schedule ks1; des_key_schedule ks2; des_cblock (*ivec); int enc; { des_ede3_cbc_encrypt(input,output,length,ks1,ks2,ks1,ivec,enc); } #endif \ No newline at end of file diff --git a/mac/libdes/src/enc_read.c b/mac/libdes/src/enc_read.c deleted file mode 100755 index 80268d29..00000000 --- a/mac/libdes/src/enc_read.c +++ /dev/null @@ -1 +0,0 @@ -/* crypto/des/enc_read.c */ /* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@mincom.oz.au). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@mincom.oz.au). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@mincom.oz.au)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ #include #include #include "des_locl.h" /* This has some uglies in it but it works - even over sockets. */ /*extern int errno;*/ int des_rw_mode=DES_PCBC_MODE; int des_enc_read(fd, buf, len, sched, iv) int fd; char *buf; int len; des_key_schedule sched; des_cblock (*iv); { /* data to be unencrypted */ int net_num=0; static unsigned char *net=NULL; /* extra unencrypted data * for when a block of 100 comes in but is des_read one byte at * a time. */ static char *unnet=NULL; static int unnet_start=0; static int unnet_left=0; static char *tmpbuf=NULL; int i; long num=0,rnum; unsigned char *p; if (tmpbuf == NULL) { tmpbuf=(char *)malloc(BSIZE); if (tmpbuf == NULL) return(-1); } if (net == NULL) { net=(unsigned char *)malloc(BSIZE); if (net == NULL) return(-1); } if (unnet == NULL) { unnet=(char *)malloc(BSIZE); if (unnet == NULL) return(-1); } /* left over data from last decrypt */ if (unnet_left != 0) { if (unnet_left < len) { /* we still still need more data but will return * with the number of bytes we have - should always * check the return value */ memcpy(buf,&(unnet[unnet_start]), (unsigned int)unnet_left); /* eay 26/08/92 I had the next 2 lines * reversed :-( */ i=unnet_left; unnet_start=unnet_left=0; } else { memcpy(buf,&(unnet[unnet_start]),(unsigned int)len); unnet_start+=len; unnet_left-=len; i=len; } return(i); } /* We need to get more data. */ if (len > MAXWRITE) len=MAXWRITE; /* first - get the length */ while (net_num < HDRSIZE) { i=read(fd,&(net[net_num]),(unsigned int)HDRSIZE-net_num); if ((i == -1) && (errno == EINTR)) continue; if (i <= 0) return(0); net_num+=i; } /* we now have at net_num bytes in net */ p=net; /* num=0; */ n2l(p,num); /* num should be rounded up to the next group of eight * we make sure that we have read a multiple of 8 bytes from the net. */ if ((num > MAXWRITE) || (num < 0)) /* error */ return(-1); rnum=(num < 8)?8:((num+7)/8*8); net_num=0; while (net_num < rnum) { i=read(fd,&(net[net_num]),(unsigned int)rnum-net_num); if ((i == -1) && (errno == EINTR)) continue; if (i <= 0) return(0); net_num+=i; } /* Check if there will be data left over. */ if (len < num) { if (des_rw_mode & DES_PCBC_MODE) des_pcbc_encrypt((des_cblock *)net,(des_cblock *)unnet, num,sched,iv,DES_DECRYPT); else des_cbc_encrypt((des_cblock *)net,(des_cblock *)unnet, num,sched,iv,DES_DECRYPT); memcpy(buf,unnet,(unsigned int)len); unnet_start=len; unnet_left=(int)num-len; /* The following line is done because we return num * as the number of bytes read. */ num=len; } else { /* >output is a multiple of 8 byes, if len < rnum * >we must be careful. The user must be aware that this * >routine will write more bytes than he asked for. * >The length of the buffer must be correct. * FIXED - Should be ok now 18-9-90 - eay */ if (len < rnum) { if (des_rw_mode & DES_PCBC_MODE) des_pcbc_encrypt((des_cblock *)net, (des_cblock *)tmpbuf, num,sched,iv,DES_DECRYPT); else des_cbc_encrypt((des_cblock *)net, (des_cblock *)tmpbuf, num,sched,iv,DES_DECRYPT); /* eay 26/08/92 fix a bug that returned more * bytes than you asked for (returned len bytes :-( */ memcpy(buf,tmpbuf,(unsigned int)num); } else { if (des_rw_mode & DES_PCBC_MODE) des_pcbc_encrypt((des_cblock *)net, (des_cblock *)buf,num,sched,iv, DES_DECRYPT); else des_cbc_encrypt((des_cblock *)net, (des_cblock *)buf,num,sched,iv, DES_DECRYPT); } } return((int)num); } \ No newline at end of file diff --git a/mac/libdes/src/enc_writ.c b/mac/libdes/src/enc_writ.c deleted file mode 100755 index 98e97d33..00000000 --- a/mac/libdes/src/enc_writ.c +++ /dev/null @@ -1 +0,0 @@ -/* crypto/des/enc_writ.c */ /* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@mincom.oz.au). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@mincom.oz.au). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@mincom.oz.au)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ #include #include #include "des_locl.h" int des_enc_write(fd, buf, len, sched, iv) int fd; char *buf; int len; des_key_schedule sched; des_cblock (*iv); { #ifdef _LIBC extern int srandom(); extern unsigned long time(); extern int random(); extern int write(); #endif long rnum; int i,j,k,outnum; char *outbuf=NULL; char shortbuf[8]; char *p; static int start=1; if (outbuf == NULL) { outbuf=(char *)malloc(BSIZE+HDRSIZE); if (outbuf == NULL) return(-1); } /* If we are sending less than 8 bytes, the same char will look * the same if we don't pad it out with random bytes */ if (start) { start=0; srandom((unsigned int)time(NULL)); } /* lets recurse if we want to send the data in small chunks */ if (len > MAXWRITE) { j=0; for (i=0; i MAXWRITE)?MAXWRITE:(len-i),sched,iv); if (k < 0) return(k); else j+=k; } return(j); } /* write length first */ p=outbuf; l2n(len,p); /* pad short strings */ if (len < 8) { p=shortbuf; memcpy(shortbuf,buf,(unsigned int)len); for (i=len; i<8; i++) shortbuf[i]=random(); rnum=8; } else { p=buf; rnum=((len+7)/8*8); /* round up to nearest eight */ } if (des_rw_mode & DES_PCBC_MODE) des_pcbc_encrypt((des_cblock *)p, (des_cblock *)&(outbuf[HDRSIZE]), (long)((len<8)?8:len),sched,iv,DES_ENCRYPT); else des_cbc_encrypt((des_cblock *)p, (des_cblock *)&(outbuf[HDRSIZE]), (long)((len<8)?8:len),sched,iv,DES_ENCRYPT); /* output */ outnum=(int)rnum+HDRSIZE; for (j=0; j /* Eric Young. * This version of crypt has been developed from my MIT compatable * DES library. * The library is available at pub/Crypto/DES at ftp.psy.uq.oz.au * eay@mincom.oz.au or eay@psych.psy.uq.oz.au */ /* Modification by Jens Kupferschmidt (Cu) * I have included directive PARA for shared memory computers. * I have included a directive LONGCRYPT to using this routine to cipher * passwords with more then 8 bytes like HP-UX 10.x it used. The MAXPLEN * definition is the maximum of lenght of password and can changed. I have * defined 24. */ #define FCRYPT_MOD(R,u,t,E0,E1,tmp) \ u=R>>16; \ t=R^u; \ u=t&E0; t=t&E1; \ tmp=(u<<16); u^=R^s[S ]; u^=tmp; \ tmp=(t<<16); t^=R^s[S+1]; t^=tmp #define DES_FCRYPT #include "des_locl.h" #undef DES_FCRYPT #undef PERM_OP #define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\ (b)^=(t),\ (a)^=((t)<<(n))) #undef HPERM_OP #define HPERM_OP(a,t,n,m) ((t)=((((a)<<(16-(n)))^(a))&(m)),\ (a)=(a)^(t)^(t>>(16-(n))))\ #ifdef PARA #define STATIC #else #define STATIC static #endif /* It is really only FreeBSD that still suffers from MD5 based crypts */ #ifdef __FreeBSD__ #define MD5_CRYPT_SUPPORT 1 #endif #if MD5_CRYPT_SUPPORT /* * ---------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42): * wrote this file. As long as you retain this notice you * can do whatever you want with this stuff. If we meet some day, and you think * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp * ---------------------------------------------------------------------------- */ #ifdef HAVE_CONFIG_H #include #endif #include static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; static void to64(s, v, n) char *s; unsigned long v; int n; { while (--n >= 0) { *s++ = itoa64[v&0x3f]; v >>= 6; } } /* * UNIX password * * Use MD5 for what it is best at... */ static char * crypt_md5(pw, salt) register const char *pw; register const char *salt; { static char *magic = "$1$"; /* * This string is magic for * this algorithm. Having * it this way, we can get * get better later on */ static char passwd[120], *p; static const char *sp,*ep; unsigned char final[16]; int sl,pl,i,j; MD5_CTX ctx,ctx1; unsigned long l; /* Refine the Salt first */ sp = salt; /* If it starts with the magic string, then skip that */ if(!strncmp(sp,magic,strlen(magic))) sp += strlen(magic); /* It stops at the first '$', max 8 chars */ for(ep=sp;*ep && *ep != '$' && ep < (sp+8);ep++) continue; /* get the length of the true salt */ sl = ep - sp; MD5Init(&ctx); /* The password first, since that is what is most unknown */ MD5Update(&ctx,pw,strlen(pw)); /* Then our magic string */ MD5Update(&ctx,magic,strlen(magic)); /* Then the raw salt */ MD5Update(&ctx,sp,sl); /* Then just as many characters of the MD5(pw,salt,pw) */ MD5Init(&ctx1); MD5Update(&ctx1,pw,strlen(pw)); MD5Update(&ctx1,sp,sl); MD5Update(&ctx1,pw,strlen(pw)); MD5Final(final,&ctx1); for(pl = strlen(pw); pl > 0; pl -= 16) MD5Update(&ctx,final,pl>16 ? 16 : pl); /* Don't leave anything around in vm they could use. */ memset(final,0,sizeof final); /* Then something really weird... */ for (j=0,i = strlen(pw); i ; i >>= 1) if(i&1) MD5Update(&ctx, final+j, 1); else MD5Update(&ctx, pw+j, 1); /* Now make the output string */ snprintf (passwd, sizeof(passwd), "%s%.*s$", magic, sl, sp); MD5Final(final,&ctx); /* * and now, just to make sure things don't run too fast * On a 60 Mhz Pentium this takes 34 msec, so you would * need 30 seconds to build a 1000 entry dictionary... */ for(i=0;i<1000;i++) { MD5Init(&ctx1); if(i & 1) MD5Update(&ctx1,pw,strlen(pw)); else MD5Update(&ctx1,final,16); if(i % 3) MD5Update(&ctx1,sp,sl); if(i % 7) MD5Update(&ctx1,pw,strlen(pw)); if(i & 1) MD5Update(&ctx1,final,16); else MD5Update(&ctx1,pw,strlen(pw)); MD5Final(final,&ctx1); } p = passwd + strlen(passwd); l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(p,l,4); p += 4; l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(p,l,4); p += 4; l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(p,l,4); p += 4; l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(p,l,4); p += 4; l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(p,l,4); p += 4; l = final[11] ; to64(p,l,2); p += 2; *p = '\0'; /* Don't leave anything around in vm they could use. */ memset(final,0,sizeof final); return passwd; } #endif /* MD5_CRYPT_SUPPORT */ #ifndef NOPROTO STATIC int fcrypt_body(DES_LONG *out0, DES_LONG *out1, des_key_schedule ks, DES_LONG Eswap0, DES_LONG Eswap1); #else STATIC int fcrypt_body(); #endif /* Added more values to handle illegal salt values the way normal * crypt() implementations do. The patch was sent by * Bjorn Gronvall */ static unsigned const char con_salt[128]={ 0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9, 0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,0xE0,0xE1, 0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9, 0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1, 0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9, 0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,0x00,0x01, 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09, 0x0A,0x0B,0x05,0x06,0x07,0x08,0x09,0x0A, 0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12, 0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A, 0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x22, 0x23,0x24,0x25,0x20,0x21,0x22,0x23,0x24, 0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C, 0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,0x34, 0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C, 0x3D,0x3E,0x3F,0x40,0x41,0x42,0x43,0x44, }; static unsigned const char cov_2char[64]={ 0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35, 0x36,0x37,0x38,0x39,0x41,0x42,0x43,0x44, 0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C, 0x4D,0x4E,0x4F,0x50,0x51,0x52,0x53,0x54, 0x55,0x56,0x57,0x58,0x59,0x5A,0x61,0x62, 0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A, 0x6B,0x6C,0x6D,0x6E,0x6F,0x70,0x71,0x72, 0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A }; #ifndef NOPROTO #ifdef PERL5 char *des_crypt(const char *buf,const char *salt); #else char *crypt(const char *buf,const char *salt); #endif #else #ifdef PERL5 char *des_crypt(); #else char *crypt(); #endif #endif #ifdef PERL5 char *des_crypt(buf,salt) #else char *crypt(buf,salt) #endif const char *buf; const char *salt; { static char buff[14]; #if MD5_CRYPT_SUPPORT if (!strncmp(salt, "$1$", 3)) return crypt_md5(buf, salt); #endif return(des_fcrypt(buf,salt,buff)); } char *des_fcrypt(buf,salt,ret) const char *buf; const char *salt; char *ret; { unsigned int i,j,x,y; DES_LONG Eswap0,Eswap1; DES_LONG out[2],ll; des_cblock key; des_key_schedule ks; unsigned char bb[9]; unsigned char *b=bb; unsigned char c,u; /* eay 25/08/92 * If you call crypt("pwd","*") as often happens when you * have * as the pwd field in /etc/passwd, the function * returns *\0XXXXXXXXX * The \0 makes the string look like * so the pwd "*" would * crypt to "*". This was found when replacing the crypt in * our shared libraries. People found that the disbled * accounts effectivly had no passwd :-(. */ x=ret[0]=((salt[0] == '\0')?'A':salt[0]); Eswap0=con_salt[x]<<2; x=ret[1]=((salt[1] == '\0')?'A':salt[1]); Eswap1=con_salt[x]<<6; /* EAY r=strlen(buf); r=(r+7)/8; */ for (i=0; i<8; i++) { c= *(buf++); if (!c) break; key[i]=(c<<1); } for (; i<8; i++) key[i]=0; des_set_key((des_cblock *)(key),ks); fcrypt_body(&(out[0]),&(out[1]),ks,Eswap0,Eswap1); ll=out[0]; l2c(ll,b); ll=out[1]; l2c(ll,b); y=0; u=0x80; bb[8]=0; for (i=2; i<13; i++) { c=0; for (j=0; j<6; j++) { c<<=1; if (bb[y] & u) c|=1; u>>=1; if (!u) { y++; u=0x80; } } ret[i]=cov_2char[c]; } ret[13]='\0'; return(ret); } STATIC int fcrypt_body(out0, out1, ks, Eswap0, Eswap1) DES_LONG *out0; DES_LONG *out1; des_key_schedule ks; DES_LONG Eswap0; DES_LONG Eswap1; { register DES_LONG l,r,t,u; #ifdef DES_PTR register unsigned char *des_SP=(unsigned char *)des_SPtrans; #endif register DES_LONG *s; register int j; register DES_LONG E0,E1; l=0; r=0; s=(DES_LONG *)ks; E0=Eswap0; E1=Eswap1; for (j=0; j<25; j++) { #ifdef DES_UNROLL register int i; for (i=0; i<32; i+=8) { D_ENCRYPT(l,r,i+0); /* 1 */ D_ENCRYPT(r,l,i+2); /* 2 */ D_ENCRYPT(l,r,i+4); /* 3 */ D_ENCRYPT(r,l,i+6); /* 4 */ } #else D_ENCRYPT(l,r, 0); /* 1 */ D_ENCRYPT(r,l, 2); /* 2 */ D_ENCRYPT(l,r, 4); /* 3 */ D_ENCRYPT(r,l, 6); /* 4 */ D_ENCRYPT(l,r, 8); /* 5 */ D_ENCRYPT(r,l,10); /* 6 */ D_ENCRYPT(l,r,12); /* 7 */ D_ENCRYPT(r,l,14); /* 8 */ D_ENCRYPT(l,r,16); /* 9 */ D_ENCRYPT(r,l,18); /* 10 */ D_ENCRYPT(l,r,20); /* 11 */ D_ENCRYPT(r,l,22); /* 12 */ D_ENCRYPT(l,r,24); /* 13 */ D_ENCRYPT(r,l,26); /* 14 */ D_ENCRYPT(l,r,28); /* 15 */ D_ENCRYPT(r,l,30); /* 16 */ #endif t=l; l=r; r=t; } l=ROTATE(l,3)&0xffffffffL; r=ROTATE(r,3)&0xffffffffL; PERM_OP(l,r,t, 1,0x55555555L); PERM_OP(r,l,t, 8,0x00ff00ffL); PERM_OP(l,r,t, 2,0x33333333L); PERM_OP(r,l,t,16,0x0000ffffL); PERM_OP(l,r,t, 4,0x0f0f0f0fL); *out0=r; *out1=l; return(0); } \ No newline at end of file diff --git a/mac/libdes/src/key_par.c b/mac/libdes/src/key_par.c deleted file mode 100755 index 284f2d25..00000000 --- a/mac/libdes/src/key_par.c +++ /dev/null @@ -1 +0,0 @@ -/* * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Hgskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the Kungliga Tekniska * Hgskolan and its contributors. * * 4. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "des_locl.h" /* MIT Link and source compatibility */ #ifdef des_fixup_key_parity #undef des_fixup_key_parity #endif /* des_fixup_key_parity */ void des_fixup_key_parity(des_cblock *key); void des_fixup_key_parity(des_cblock *key) { des_set_odd_parity(key); } \ No newline at end of file diff --git a/mac/libdes/src/makefile.bc b/mac/libdes/src/makefile.bc deleted file mode 100755 index c1e78b34..00000000 --- a/mac/libdes/src/makefile.bc +++ /dev/null @@ -1 +0,0 @@ -# # Origional BC Makefile from Teun # # CC = bcc TLIB = tlib /0 /C # note: the -3 flag produces code for 386, 486, Pentium etc; omit it for 286s OPTIMIZE= -3 -O2 #WINDOWS= -W CFLAGS = -c -ml -d $(OPTIMIZE) $(WINDOWS) -DMSDOS LFLAGS = -ml $(WINDOWS) .c.obj: $(CC) $(CFLAGS) $*.c .obj.exe: $(CC) $(LFLAGS) -e$*.exe $*.obj libdes.lib all: $(LIB) destest.exe rpw.exe des.exe speed.exe # "make clean": use a directory containing only libdes .exe and .obj files... clean: del *.exe del *.obj del libdes.lib del libdes.rsp OBJS= cbc_cksm.obj cbc_enc.obj ecb_enc.obj pcbc_enc.obj \ qud_cksm.obj rand_key.obj set_key.obj str2key.obj \ enc_read.obj enc_writ.obj fcrypt.obj cfb_enc.obj \ ecb3_enc.obj ofb_enc.obj cbc3_enc.obj read_pwd.obj\ cfb64enc.obj ofb64enc.obj ede_enc.obj cfb64ede.obj\ ofb64ede.obj supp.obj LIB= libdes.lib $(LIB): $(OBJS) del $(LIB) makersp "+%s &\n" &&| $(OBJS) | >libdes.rsp $(TLIB) libdes.lib @libdes.rsp,nul del libdes.rsp destest.exe: destest.obj libdes.lib rpw.exe: rpw.obj libdes.lib speed.exe: speed.obj libdes.lib des.exe: des.obj libdes.lib \ No newline at end of file diff --git a/mac/libdes/src/md4.c b/mac/libdes/src/md4.c deleted file mode 100755 index f0954498..00000000 --- a/mac/libdes/src/md4.c +++ /dev/null @@ -1 +0,0 @@ -/* * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Hgskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the Kungliga Tekniska * Hgskolan and its contributors. * * 4. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #include "config.h" RCSID("$Id: md4.c,v 1.2 2001/12/04 02:06:29 rjs3 Exp $"); #endif #include #include #include "md4.h" #ifndef min #define min(a,b) (((a)>(b))?(b):(a)) #endif #define A m->counter[0] #define B m->counter[1] #define C m->counter[2] #define D m->counter[3] #define X data void md4_init (struct md4 *m) { m->offset = 0; m->sz = 0; D = 0x10325476; C = 0x98badcfe; B = 0xefcdab89; A = 0x67452301; } static inline u_int32_t cshift (u_int32_t x, unsigned int n) { return (x << n) | (x >> (32 - n)); } #define F(x,y,z) ((x & y) | (~x & z)) #define G(x,y,z) ((x & y) | (x & z) | (y & z)) #define H(x,y,z) (x ^ y ^ z) #define DOIT(a,b,c,d,k,s,i,OP) \ a = cshift(a + OP(b,c,d) + X[k] + i, s) #define DO1(a,b,c,d,k,s,i) DOIT(a,b,c,d,k,s,i,F) #define DO2(a,b,c,d,k,s,i) DOIT(a,b,c,d,k,s,i,G) #define DO3(a,b,c,d,k,s,i) DOIT(a,b,c,d,k,s,i,H) static inline void calc (struct md4 *m, u_int32_t *data) { u_int32_t AA, BB, CC, DD; AA = A; BB = B; CC = C; DD = D; /* Round 1 */ DO1(A,B,C,D,0,3,0); DO1(D,A,B,C,1,7,0); DO1(C,D,A,B,2,11,0); DO1(B,C,D,A,3,19,0); DO1(A,B,C,D,4,3,0); DO1(D,A,B,C,5,7,0); DO1(C,D,A,B,6,11,0); DO1(B,C,D,A,7,19,0); DO1(A,B,C,D,8,3,0); DO1(D,A,B,C,9,7,0); DO1(C,D,A,B,10,11,0); DO1(B,C,D,A,11,19,0); DO1(A,B,C,D,12,3,0); DO1(D,A,B,C,13,7,0); DO1(C,D,A,B,14,11,0); DO1(B,C,D,A,15,19,0); /* Round 2 */ DO2(A,B,C,D,0,3,0x5A827999); DO2(D,A,B,C,4,5,0x5A827999); DO2(C,D,A,B,8,9,0x5A827999); DO2(B,C,D,A,12,13,0x5A827999); DO2(A,B,C,D,1,3,0x5A827999); DO2(D,A,B,C,5,5,0x5A827999); DO2(C,D,A,B,9,9,0x5A827999); DO2(B,C,D,A,13,13,0x5A827999); DO2(A,B,C,D,2,3,0x5A827999); DO2(D,A,B,C,6,5,0x5A827999); DO2(C,D,A,B,10,9,0x5A827999); DO2(B,C,D,A,14,13,0x5A827999); DO2(A,B,C,D,3,3,0x5A827999); DO2(D,A,B,C,7,5,0x5A827999); DO2(C,D,A,B,11,9,0x5A827999); DO2(B,C,D,A,15,13,0x5A827999); /* Round 3 */ DO3(A,B,C,D,0,3,0x6ED9EBA1); DO3(D,A,B,C,8,9,0x6ED9EBA1); DO3(C,D,A,B,4,11,0x6ED9EBA1); DO3(B,C,D,A,12,15,0x6ED9EBA1); DO3(A,B,C,D,2,3,0x6ED9EBA1); DO3(D,A,B,C,10,9,0x6ED9EBA1); DO3(C,D,A,B,6,11,0x6ED9EBA1); DO3(B,C,D,A,14,15,0x6ED9EBA1); DO3(A,B,C,D,1,3,0x6ED9EBA1); DO3(D,A,B,C,9,9,0x6ED9EBA1); DO3(C,D,A,B,5,11,0x6ED9EBA1); DO3(B,C,D,A,13,15,0x6ED9EBA1); DO3(A,B,C,D,3,3,0x6ED9EBA1); DO3(D,A,B,C,11,9,0x6ED9EBA1); DO3(C,D,A,B,7,11,0x6ED9EBA1); DO3(B,C,D,A,15,15,0x6ED9EBA1); A += AA; B += BB; C += CC; D += DD; } /* * From `Performance analysis of MD5' by Joseph D. Touch */ static inline u_int32_t swap_u_int32_t (u_int32_t t) { #if defined(WORDS_BIGENDIAN) #define ROL(x,n) ((x)<<(n))|((x)>>(32-(n))) u_int32_t temp1, temp2; temp1 = ROL(t,16); temp2 = temp1 >> 8; temp1 &= 0x00ff00ff; temp2 &= 0x00ff00ff; temp1 <<= 8; return temp1 | temp2; #else return t; #endif } struct x32{ unsigned int a:32; unsigned int b:32; }; void md4_update (struct md4 *m, const void *v, size_t len) { const unsigned char *p = v; m->sz += len; while(len > 0){ size_t l = min(len, 64 - m->offset); memcpy(m->save + m->offset, p, l); m->offset += l; p += l; len -= l; if(m->offset == 64){ #if defined(WORDS_BIGENDIAN) int i; u_int32_t current[16]; struct x32 *u = (struct x32*)m->save; for(i = 0; i < 8; i++){ current[2*i+0] = swap_u_int32_t(u[i].a); current[2*i+1] = swap_u_int32_t(u[i].b); } calc(m, current); #else calc(m, (u_int32_t*)m->save); #endif m->offset = 0; } } } void md4_finito (struct md4 *m, void *res) { static unsigned char zeros[72]; u_int32_t len; unsigned int dstart = (120 - m->offset - 1) % 64 + 1; *zeros = 0x80; memset (zeros + 1, 0, sizeof(zeros) - 1); len = 8 * m->sz; zeros[dstart+0] = (len >> 0) & 0xff; zeros[dstart+1] = (len >> 8) & 0xff; zeros[dstart+2] = (len >> 16) & 0xff; zeros[dstart+3] = (len >> 24) & 0xff; md4_update (m, zeros, dstart + 8); { int i; unsigned char *r = (unsigned char *)res; for (i = 0; i < 4; ++i) { r[4*i] = m->counter[i] & 0xFF; r[4*i+1] = (m->counter[i] >> 8) & 0xFF; r[4*i+2] = (m->counter[i] >> 16) & 0xFF; r[4*i+3] = (m->counter[i] >> 24) & 0xFF; } } #if 0 { int i; u_int32_t *r = (u_int32_t *)res; for (i = 0; i < 4; ++i) r[i] = swap_u_int32_t (m->counter[i]); } #endif } \ No newline at end of file diff --git a/mac/libdes/src/md4.h b/mac/libdes/src/md4.h deleted file mode 100755 index faf6d465..00000000 --- a/mac/libdes/src/md4.h +++ /dev/null @@ -1 +0,0 @@ -/* * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Hgskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the Kungliga Tekniska * Hgskolan and its contributors. * * 4. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* $Id: md4.h,v 1.2 2001/12/04 02:06:30 rjs3 Exp $ */ #include #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_SYS_BITYPES_H #include #endif #ifdef KRB5 #include #elif defined(KRB4) #include #endif struct md4 { unsigned int offset; unsigned int sz; u_int32_t counter[4]; unsigned char save[64]; }; void md4_init (struct md4 *m); void md4_update (struct md4 *m, const void *p, size_t len); void md4_finito (struct md4 *m, void *res); \ No newline at end of file diff --git a/mac/libdes/src/md5.c b/mac/libdes/src/md5.c deleted file mode 100755 index f8b1c28d..00000000 --- a/mac/libdes/src/md5.c +++ /dev/null @@ -1 +0,0 @@ -/* * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Hgskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the Kungliga Tekniska * Hgskolan and its contributors. * * 4. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #include "config.h" RCSID("$Id: md5.c,v 1.2 2001/12/04 02:06:30 rjs3 Exp $"); #endif #include #include #include "md5.h" #ifndef min #define min(a,b) (((a)>(b))?(b):(a)) #endif #define A m->counter[0] #define B m->counter[1] #define C m->counter[2] #define D m->counter[3] #define X data void md5_init (struct md5 *m) { m->offset = 0; m->sz = 0; D = 0x10325476; C = 0x98badcfe; B = 0xefcdab89; A = 0x67452301; } static inline u_int32_t cshift (u_int32_t x, unsigned int n) { return (x << n) | (x >> (32 - n)); } #define F(x,y,z) ((x & y) | (~x & z)) #define G(x,y,z) ((x & z) | (y & ~z)) #define H(x,y,z) (x ^ y ^ z) #define I(x,y,z) (y ^ (x | ~z)) #define DOIT(a,b,c,d,k,s,i,OP) \ a = b + cshift(a + OP(b,c,d) + X[k] + (i), s) #define DO1(a,b,c,d,k,s,i) DOIT(a,b,c,d,k,s,i,F) #define DO2(a,b,c,d,k,s,i) DOIT(a,b,c,d,k,s,i,G) #define DO3(a,b,c,d,k,s,i) DOIT(a,b,c,d,k,s,i,H) #define DO4(a,b,c,d,k,s,i) DOIT(a,b,c,d,k,s,i,I) static inline void calc (struct md5 *m, u_int32_t *data) { u_int32_t AA, BB, CC, DD; AA = A; BB = B; CC = C; DD = D; /* Round 1 */ DO1(A,B,C,D,0,7,0xd76aa478); DO1(D,A,B,C,1,12,0xe8c7b756); DO1(C,D,A,B,2,17,0x242070db); DO1(B,C,D,A,3,22,0xc1bdceee); DO1(A,B,C,D,4,7,0xf57c0faf); DO1(D,A,B,C,5,12,0x4787c62a); DO1(C,D,A,B,6,17,0xa8304613); DO1(B,C,D,A,7,22,0xfd469501); DO1(A,B,C,D,8,7,0x698098d8); DO1(D,A,B,C,9,12,0x8b44f7af); DO1(C,D,A,B,10,17,0xffff5bb1); DO1(B,C,D,A,11,22,0x895cd7be); DO1(A,B,C,D,12,7,0x6b901122); DO1(D,A,B,C,13,12,0xfd987193); DO1(C,D,A,B,14,17,0xa679438e); DO1(B,C,D,A,15,22,0x49b40821); /* Round 2 */ DO2(A,B,C,D,1,5,0xf61e2562); DO2(D,A,B,C,6,9,0xc040b340); DO2(C,D,A,B,11,14,0x265e5a51); DO2(B,C,D,A,0,20,0xe9b6c7aa); DO2(A,B,C,D,5,5,0xd62f105d); DO2(D,A,B,C,10,9,0x2441453); DO2(C,D,A,B,15,14,0xd8a1e681); DO2(B,C,D,A,4,20,0xe7d3fbc8); DO2(A,B,C,D,9,5,0x21e1cde6); DO2(D,A,B,C,14,9,0xc33707d6); DO2(C,D,A,B,3,14,0xf4d50d87); DO2(B,C,D,A,8,20,0x455a14ed); DO2(A,B,C,D,13,5,0xa9e3e905); DO2(D,A,B,C,2,9,0xfcefa3f8); DO2(C,D,A,B,7,14,0x676f02d9); DO2(B,C,D,A,12,20,0x8d2a4c8a); /* Round 3 */ DO3(A,B,C,D,5,4,0xfffa3942); DO3(D,A,B,C,8,11,0x8771f681); DO3(C,D,A,B,11,16,0x6d9d6122); DO3(B,C,D,A,14,23,0xfde5380c); DO3(A,B,C,D,1,4,0xa4beea44); DO3(D,A,B,C,4,11,0x4bdecfa9); DO3(C,D,A,B,7,16,0xf6bb4b60); DO3(B,C,D,A,10,23,0xbebfbc70); DO3(A,B,C,D,13,4,0x289b7ec6); DO3(D,A,B,C,0,11,0xeaa127fa); DO3(C,D,A,B,3,16,0xd4ef3085); DO3(B,C,D,A,6,23,0x4881d05); DO3(A,B,C,D,9,4,0xd9d4d039); DO3(D,A,B,C,12,11,0xe6db99e5); DO3(C,D,A,B,15,16,0x1fa27cf8); DO3(B,C,D,A,2,23,0xc4ac5665); /* Round 4 */ DO4(A,B,C,D,0,6,0xf4292244); DO4(D,A,B,C,7,10,0x432aff97); DO4(C,D,A,B,14,15,0xab9423a7); DO4(B,C,D,A,5,21,0xfc93a039); DO4(A,B,C,D,12,6,0x655b59c3); DO4(D,A,B,C,3,10,0x8f0ccc92); DO4(C,D,A,B,10,15,0xffeff47d); DO4(B,C,D,A,1,21,0x85845dd1); DO4(A,B,C,D,8,6,0x6fa87e4f); DO4(D,A,B,C,15,10,0xfe2ce6e0); DO4(C,D,A,B,6,15,0xa3014314); DO4(B,C,D,A,13,21,0x4e0811a1); DO4(A,B,C,D,4,6,0xf7537e82); DO4(D,A,B,C,11,10,0xbd3af235); DO4(C,D,A,B,2,15,0x2ad7d2bb); DO4(B,C,D,A,9,21,0xeb86d391); A += AA; B += BB; C += CC; D += DD; } /* * From `Performance analysis of MD5' by Joseph D. Touch */ static inline u_int32_t swap_u_int32_t (u_int32_t t) { #if defined(WORDS_BIGENDIAN) #define ROL(x,n) ((x)<<(n))|((x)>>(32-(n))) u_int32_t temp1, temp2; temp1 = ROL(t,16); temp2 = temp1 >> 8; temp1 &= 0x00ff00ff; temp2 &= 0x00ff00ff; temp1 <<= 8; return temp1 | temp2; #else return t; #endif } struct x32{ unsigned int a:32; unsigned int b:32; }; void md5_update (struct md5 *m, const void *v, size_t len) { const unsigned char *p = v; m->sz += len; while(len > 0){ size_t l = min(len, 64 - m->offset); memcpy(m->save + m->offset, p, l); m->offset += l; p += l; len -= l; if(m->offset == 64){ #if defined(WORDS_BIGENDIAN) int i; u_int32_t current[16]; struct x32 *u = (struct x32*)m->save; for(i = 0; i < 8; i++){ current[2*i+0] = swap_u_int32_t(u[i].a); current[2*i+1] = swap_u_int32_t(u[i].b); } calc(m, current); #else calc(m, (u_int32_t*)m->save); #endif m->offset = 0; } } } void md5_finito (struct md5 *m, void *res) { static unsigned char zeros[72]; u_int32_t len; unsigned int dstart = (120 - m->offset - 1) % 64 + 1; *zeros = 0x80; memset (zeros + 1, 0, sizeof(zeros) - 1); len = 8 * m->sz; zeros[dstart+0] = (len >> 0) & 0xff; zeros[dstart+1] = (len >> 8) & 0xff; zeros[dstart+2] = (len >> 16) & 0xff; zeros[dstart+3] = (len >> 24) & 0xff; md5_update (m, zeros, dstart + 8); { int i; unsigned char *r = (unsigned char *)res; for (i = 0; i < 4; ++i) { r[4*i] = m->counter[i] & 0xFF; r[4*i+1] = (m->counter[i] >> 8) & 0xFF; r[4*i+2] = (m->counter[i] >> 16) & 0xFF; r[4*i+3] = (m->counter[i] >> 24) & 0xFF; } } #if 0 { int i; u_int32_t *r = (u_int32_t *)res; for (i = 0; i < 4; ++i) r[i] = swap_u_int32_t (m->counter[i]); } #endif } /* * This is only for linkage compatibility! */ #undef MD5Init #undef MD5Update #undef MD5Final void MD5Init (MD5_CTX *mdContext) { md5_init(&mdContext->m.d5); } void MD5Update (MD5_CTX *mdContext, const unsigned char *inBuf, unsigned int inLen) { md5_update(&mdContext->m.d5, (unsigned char *)inBuf, inLen); } void MD5Final (unsigned char digest[16], MD5_CTX *mdContext) { md5_finito(&mdContext->m.d5, digest); } \ No newline at end of file diff --git a/mac/libdes/src/md5.h b/mac/libdes/src/md5.h deleted file mode 100755 index e38a8424..00000000 --- a/mac/libdes/src/md5.h +++ /dev/null @@ -1 +0,0 @@ -/* * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Hgskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the Kungliga Tekniska * Hgskolan and its contributors. * * 4. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* $Id: md5.h,v 1.2 2001/12/04 02:06:30 rjs3 Exp $ */ #include #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_SYS_BITYPES_H #include #endif #ifdef KRB5 #include #elif defined(KRB4) #include #endif struct md5 { unsigned int offset; unsigned int sz; u_int32_t counter[4]; unsigned char save[64]; }; void md5_init (struct md5 *m); void md5_update (struct md5 *m, const void *p, size_t len); void md5_finito (struct md5 *m, void *res); /* u_int32_t res[4] */ /* * Functions for compatibility that have never been tested. */ typedef struct { u_int32_t i[2]; /* number of _bits_ handled mod 2^64 */ u_int32_t buf[4]; /* scratch buffer */ unsigned char in[64]; /* input buffer */ } MD5_CTX_PREAMBLE; typedef struct { union { MD5_CTX_PREAMBLE preamble_; struct md5 d5; } m; } MD5_CTX; void MD5Init (MD5_CTX *mdContext); void MD5Update (MD5_CTX *mdContext, const unsigned char *inBuf, unsigned int inLen); void MD5Final (unsigned char digest[16], MD5_CTX *mdContext); #ifndef NO_MD5_MACROS #define MD5Init(mdContext) md5_init(&(mdContext)->m.d5) #define MD5Update(mdCtx, inBuf, inLen) md5_update(&(mdCtx)->m.d5, inBuf, inLen) #define MD5Final(digest, mdCtx) md5_finito(&(mdCtx)->m.d5, (digest)) #endif \ No newline at end of file diff --git a/mac/libdes/src/mdtest.c b/mac/libdes/src/mdtest.c deleted file mode 100755 index babd72d4..00000000 --- a/mac/libdes/src/mdtest.c +++ /dev/null @@ -1 +0,0 @@ -/* * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Hgskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the Kungliga Tekniska * Hgskolan and its contributors. * * 4. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #include RCSID("$Id: mdtest.c,v 1.2 2001/12/04 02:06:30 rjs3 Exp $"); #endif #include #include #include #include #include static int md4_tests (void) { struct test { char *str; unsigned char hash[16]; } tests[] = { {"", {0x31, 0xd6, 0xcf, 0xe0, 0xd1, 0x6a, 0xe9, 0x31, 0xb7, 0x3c, 0x59, 0xd7, 0xe0, 0xc0, 0x89, 0xc0}}, {"a", {0xbd, 0xe5, 0x2c, 0xb3, 0x1d, 0xe3, 0x3e, 0x46, 0x24, 0x5e, 0x05, 0xfb, 0xdb, 0xd6, 0xfb, 0x24}}, {"abc", {0xa4, 0x48, 0x01, 0x7a, 0xaf, 0x21, 0xd8, 0x52, 0x5f, 0xc1, 0x0a, 0xe8, 0x7a, 0xa6, 0x72, 0x9d}}, {"message digest", {0xd9, 0x13, 0x0a, 0x81, 0x64, 0x54, 0x9f, 0xe8, 0x18, 0x87, 0x48, 0x06, 0xe1, 0xc7, 0x01, 0x4b}}, {"abcdefghijklmnopqrstuvwxyz", {0xd7, 0x9e, 0x1c, 0x30, 0x8a, 0xa5, 0xbb, 0xcd, 0xee, 0xa8, 0xed, 0x63, 0xdf, 0x41, 0x2d, 0xa9, }}, {"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", {0x04, 0x3f, 0x85, 0x82, 0xf2, 0x41, 0xdb, 0x35, 0x1c, 0xe6, 0x27, 0xe1, 0x53, 0xe7, 0xf0, 0xe4}}, {"12345678901234567890123456789012345678901234567890123456789012345678901234567890", {0xe3, 0x3b, 0x4d, 0xdc, 0x9c, 0x38, 0xf2, 0x19, 0x9c, 0x3e, 0x7b, 0x16, 0x4f, 0xcc, 0x05, 0x36, }}, {NULL, { 0x0 }}}; struct test *t; printf ("md4... "); for (t = tests; t->str; ++t) { struct md4 md4; char res[16]; int i; md4_init (&md4); md4_update (&md4, (unsigned char *)t->str, strlen(t->str)); md4_finito (&md4, res); if (memcmp (res, t->hash, 16) != 0) { printf ("MD4(\"%s\") failed\n", t->str); printf("should be: "); for(i = 0; i < 16; ++i) printf("%02x ", t->hash[i]); printf("\nresult was: "); for(i = 0; i < 16; ++i) printf("%02x ", res[i]); printf("\n"); return 1; } } printf ("success\n"); return 0; } static int md5_tests (void) { struct test { char *str; unsigned char hash[16]; } tests[] = { {"", {0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e}}, {"a", {0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8, 0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61}}, {"abc", {0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, 0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72}}, {"message digest", {0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d, 0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0}}, {"abcdefghijklmnopqrstuvwxyz", {0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00, 0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b}}, {"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", {0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5, 0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f}}, {"12345678901234567890123456789012345678901234567890123456789012345678901234567890", {0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55, 0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a}}, {NULL, { 0x0 }}}; struct test *t; printf ("md5... "); for (t = tests; t->str; ++t) { struct md5 md5; char res[16]; md5_init (&md5); md5_update (&md5, (unsigned char *)t->str, strlen(t->str)); md5_finito (&md5, res); if (memcmp (res, t->hash, 16) != 0) { int i; printf ("MD5(\"%s\") failed\n", t->str); printf("should be: "); for(i = 0; i < 16; ++i) printf("%02x ", t->hash[i]); printf("\nresult was: "); for(i = 0; i < 16; ++i) printf("%02x ", res[i]); printf("\n"); return 1; } } printf ("success\n"); return 0; } static int sha_tests (void) { struct test { char *str; unsigned char hash[20]; } tests[] = { {"abc", {0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E, 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D}}, {"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", {0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE, 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1}}, {NULL, { 0x0 }}}; struct test *t; printf ("sha... "); for (t = tests; t->str; ++t) { struct sha sha; char res[20]; sha_init (&sha); sha_update (&sha, (unsigned char *)t->str, strlen(t->str)); sha_finito (&sha, res); if (memcmp (res, t->hash, 20) != 0) { int i; printf ("SHA(\"%s\") failed\n", t->str); printf("should be: "); for(i = 0; i < 20; ++i) printf("%02x ", t->hash[i]); printf("\nresult was: "); for(i = 0; i < 20; ++i) printf("%02x ", res[i]); printf("\n"); return 1; } } printf ("success\n"); return 0; } int main (void) { return md4_tests() + md5_tests() + sha_tests(); } \ No newline at end of file diff --git a/mac/libdes/src/ncbc_enc.c b/mac/libdes/src/ncbc_enc.c deleted file mode 100755 index 69cca823..00000000 --- a/mac/libdes/src/ncbc_enc.c +++ /dev/null @@ -1 +0,0 @@ -/* crypto/des/ncbc_enc.c */ /* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@mincom.oz.au). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@mincom.oz.au). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@mincom.oz.au)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ #include "des_locl.h" void des_ncbc_encrypt(input, output, length, schedule, ivec, encrypt) des_cblock (*input); des_cblock (*output); long length; des_key_schedule schedule; des_cblock (*ivec); int encrypt; { register DES_LONG tin0,tin1; register DES_LONG tout0,tout1,xor0,xor1; register unsigned char *in,*out; register long l=length; DES_LONG tin[2]; unsigned char *iv; in=(unsigned char *)input; out=(unsigned char *)output; iv=(unsigned char *)ivec; if (encrypt) { c2l(iv,tout0); c2l(iv,tout1); for (l-=8; l>=0; l-=8) { c2l(in,tin0); c2l(in,tin1); tin0^=tout0; tin[0]=tin0; tin1^=tout1; tin[1]=tin1; des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); tout0=tin[0]; l2c(tout0,out); tout1=tin[1]; l2c(tout1,out); } if (l != -8) { c2ln(in,tin0,tin1,l+8); tin0^=tout0; tin[0]=tin0; tin1^=tout1; tin[1]=tin1; des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); tout0=tin[0]; l2c(tout0,out); tout1=tin[1]; l2c(tout1,out); } iv=(unsigned char *)ivec; l2c(tout0,iv); l2c(tout1,iv); } else { c2l(iv,xor0); c2l(iv,xor1); for (l-=8; l>=0; l-=8) { c2l(in,tin0); tin[0]=tin0; c2l(in,tin1); tin[1]=tin1; des_encrypt((DES_LONG *)tin,schedule,DES_DECRYPT); tout0=tin[0]^xor0; tout1=tin[1]^xor1; l2c(tout0,out); l2c(tout1,out); xor0=tin0; xor1=tin1; } if (l != -8) { c2l(in,tin0); tin[0]=tin0; c2l(in,tin1); tin[1]=tin1; des_encrypt((DES_LONG *)tin,schedule,DES_DECRYPT); tout0=tin[0]^xor0; tout1=tin[1]^xor1; l2cn(tout0,tout1,out,l+8); xor0=tin0; xor1=tin1; } iv=(unsigned char *)ivec; l2c(xor0,iv); l2c(xor1,iv); } tin0=tin1=tout0=tout1=xor0=xor1=0; tin[0]=tin[1]=0; } \ No newline at end of file diff --git a/mac/libdes/src/ofb64ede.c b/mac/libdes/src/ofb64ede.c deleted file mode 100755 index cfd75efe..00000000 --- a/mac/libdes/src/ofb64ede.c +++ /dev/null @@ -1 +0,0 @@ -/* crypto/des/ofb64ede.c */ /* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@mincom.oz.au). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@mincom.oz.au). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@mincom.oz.au)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ #include "des_locl.h" /* The input and output encrypted as though 64bit ofb mode is being * used. The extra state information to record how much of the * 64bit block we have used is contained in *num; */ void des_ede3_ofb64_encrypt(in, out, length, k1,k2,k3, ivec, num) register unsigned char *in; register unsigned char *out; long length; des_key_schedule k1,k2,k3; des_cblock (*ivec); int *num; { register DES_LONG v0,v1; register int n= *num; register long l=length; des_cblock d; register char *dp; DES_LONG ti[2]; unsigned char *iv; int save=0; iv=(unsigned char *)ivec; c2l(iv,v0); c2l(iv,v1); ti[0]=v0; ti[1]=v1; dp=(char *)d; l2c(v0,dp); l2c(v1,dp); while (l--) { if (n == 0) { ti[0]=v0; ti[1]=v1; des_encrypt3((DES_LONG *)ti,k1,k2,k3); v0=ti[0]; v1=ti[1]; dp=(char *)d; l2c(v0,dp); l2c(v1,dp); save++; } *(out++)= *(in++)^d[n]; n=(n+1)&0x07; } if (save) { /* v0=ti[0]; v1=ti[1];*/ iv=(unsigned char *)ivec; l2c(v0,iv); l2c(v1,iv); } v0=v1=ti[0]=ti[1]=0; *num=n; } #ifdef undef /* MACRO */ void des_ede2_ofb64_encrypt(in, out, length, k1,k2, ivec, num) register unsigned char *in; register unsigned char *out; long length; des_key_schedule k1,k2; des_cblock (*ivec); int *num; { des_ede3_ofb64_encrypt(in, out, length, k1,k2,k1, ivec, num); } #endif \ No newline at end of file diff --git a/mac/libdes/src/ofb64enc.c b/mac/libdes/src/ofb64enc.c deleted file mode 100755 index 3ac12201..00000000 --- a/mac/libdes/src/ofb64enc.c +++ /dev/null @@ -1 +0,0 @@ -/* crypto/des/ofb64enc.c */ /* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@mincom.oz.au). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@mincom.oz.au). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@mincom.oz.au)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ #include "des_locl.h" /* The input and output encrypted as though 64bit ofb mode is being * used. The extra state information to record how much of the * 64bit block we have used is contained in *num; */ void des_ofb64_encrypt(in, out, length, schedule, ivec, num) register unsigned char *in; register unsigned char *out; long length; des_key_schedule schedule; des_cblock (*ivec); int *num; { register DES_LONG v0,v1,t; register int n= *num; register long l=length; des_cblock d; register char *dp; DES_LONG ti[2]; unsigned char *iv; int save=0; iv=(unsigned char *)ivec; c2l(iv,v0); c2l(iv,v1); ti[0]=v0; ti[1]=v1; dp=(char *)d; l2c(v0,dp); l2c(v1,dp); while (l--) { if (n == 0) { des_encrypt((DES_LONG *)ti,schedule,DES_ENCRYPT); dp=(char *)d; t=ti[0]; l2c(t,dp); t=ti[1]; l2c(t,dp); save++; } *(out++)= *(in++)^d[n]; n=(n+1)&0x07; } if (save) { v0=ti[0]; v1=ti[1]; iv=(unsigned char *)ivec; l2c(v0,iv); l2c(v1,iv); } t=v0=v1=ti[0]=ti[1]=0; *num=n; } \ No newline at end of file diff --git a/mac/libdes/src/ofb_enc.c b/mac/libdes/src/ofb_enc.c deleted file mode 100755 index ea719907..00000000 --- a/mac/libdes/src/ofb_enc.c +++ /dev/null @@ -1 +0,0 @@ -/* crypto/des/ofb_enc.c */ /* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@mincom.oz.au). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@mincom.oz.au). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@mincom.oz.au)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ #include "des_locl.h" /* The input and output are loaded in multiples of 8 bits. * What this means is that if you hame numbits=12 and length=2 * the first 12 bits will be retrieved from the first byte and half * the second. The second 12 bits will come from the 3rd and half the 4th * byte. */ void des_ofb_encrypt(in, out, numbits, length, schedule, ivec) unsigned char *in; unsigned char *out; int numbits; long length; des_key_schedule schedule; des_cblock (*ivec); { register DES_LONG d0,d1,v0,v1,n=(numbits+7)/8; register DES_LONG mask0,mask1; register long l=length; register int num=numbits; DES_LONG ti[2]; unsigned char *iv; if (num > 64) return; if (num > 32) { mask0=0xffffffffL; if (num >= 64) mask1=mask0; else mask1=(1L<<(num-32))-1; } else { if (num == 32) mask0=0xffffffffL; else mask0=(1L< 0) { des_encrypt((DES_LONG *)ti,schedule,DES_ENCRYPT); c2ln(in,d0,d1,n); in+=n; d0=(d0^ti[0])&mask0; d1=(d1^ti[1])&mask1; l2cn(d0,d1,out,n); out+=n; } v0=ti[0]; v1=ti[1]; iv=(unsigned char *)ivec; l2c(v0,iv); l2c(v1,iv); v0=v1=d0=d1=ti[0]=ti[1]=0; } \ No newline at end of file diff --git a/mac/libdes/src/passwd_dialog.aps b/mac/libdes/src/passwd_dialog.aps deleted file mode 100755 index e8cc0a41a3707e5de074e95364ef7bee264ba8b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30428 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 diff --git a/mac/libdes/src/passwd_dialog.clw b/mac/libdes/src/passwd_dialog.clw deleted file mode 100755 index 04cc504d..00000000 --- a/mac/libdes/src/passwd_dialog.clw +++ /dev/null @@ -1 +0,0 @@ -; CLW file contains information for the MFC ClassWizard [General Info] Version=1 LastClass= LastTemplate=CDialog NewFileInclude1=#include "stdafx.h" NewFileInclude2=#include "passwd_dialog.h" LastPage=0 ClassCount=0 ResourceCount=2 Resource1=IDD_DIALOG1 Resource2=IDD_PASSWD_DIALOG [DLG:IDD_DIALOG1] Type=1 ControlCount=6 Control1=IDOK,button,1342242817 Control2=IDCANCEL,button,1342242816 Control3=IDC_STATIC,static,1342308352 Control4=IDC_STATIC,static,1342308352 Control5=IDC_EDIT1,edit,1350631552 Control6=IDC_EDIT2,edit,1350631584 [DLG:IDD_PASSWD_DIALOG] Type=1 ControlCount=4 Control1=IDC_PASSWD_EDIT,edit,1350631456 Control2=IDOK,button,1342242817 Control3=IDCANCEL,button,1342242816 Control4=IDC_STATIC,static,1342177280 \ No newline at end of file diff --git a/mac/libdes/src/passwd_dialog.rc b/mac/libdes/src/passwd_dialog.rc deleted file mode 100755 index 555e23d6..00000000 --- a/mac/libdes/src/passwd_dialog.rc +++ /dev/null @@ -1 +0,0 @@ -//Microsoft Developer Studio generated resource script. // #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 2 resource. // #include "afxres.h" ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // Swedish resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_SVE) #ifdef _WIN32 LANGUAGE LANG_SWEDISH, SUBLANG_DEFAULT #pragma code_page(1252) #endif //_WIN32 ///////////////////////////////////////////////////////////////////////////// // // Dialog // IDD_PASSWD_DIALOG DIALOG DISCARDABLE 0, 0, 186, 66 STYLE DS_ABSALIGN | DS_MODALFRAME | DS_SETFOREGROUND | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION CAPTION "Password query" FONT 8, "MS Sans Serif" BEGIN EDITTEXT IDC_PASSWD_EDIT,30,22,125,14,ES_PASSWORD DEFPUSHBUTTON "OK",IDOK,30,45,50,14 PUSHBUTTON "Cancel",IDCANCEL,105,45,50,14 LTEXT "Please insert password:",IDC_STATIC,30,13,87,8,NOT WS_GROUP END ///////////////////////////////////////////////////////////////////////////// // // DESIGNINFO // #ifdef APSTUDIO_INVOKED GUIDELINES DESIGNINFO DISCARDABLE BEGIN IDD_PASSWD_DIALOG, DIALOG BEGIN LEFTMARGIN, 7 RIGHTMARGIN, 179 TOPMARGIN, 7 BOTTOMMARGIN, 59 END END #endif // APSTUDIO_INVOKED #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // TEXTINCLUDE // 1 TEXTINCLUDE DISCARDABLE BEGIN "resource.h\0" END 2 TEXTINCLUDE DISCARDABLE BEGIN "#include ""afxres.h""\r\n" "\0" END 3 TEXTINCLUDE DISCARDABLE BEGIN "\r\n" "\0" END #endif // APSTUDIO_INVOKED #ifndef _MAC ///////////////////////////////////////////////////////////////////////////// // // Version // VS_VERSION_INFO VERSIONINFO FILEVERSION 1,0,0,1 PRODUCTVERSION 1,0,0,1 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L #else FILEFLAGS 0x0L #endif FILEOS 0x40004L FILETYPE 0x2L FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904b0" BEGIN VALUE "CompanyName", "Royal Institute of Technology (KTH)\0" VALUE "FileDescription", "des\0" VALUE "FileVersion", "4, 0, 9, 9\0" VALUE "InternalName", "des\0" VALUE "LegalCopyright", "Copyright 1996 - 1998 Royal Institute of Technology (KTH)\0" VALUE "OriginalFilename", "des.dll\0" VALUE "ProductName", "KTH Kerberos\0" VALUE "ProductVersion", "4,0,9,9\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END #endif // !_MAC #endif // Swedish resources ///////////////////////////////////////////////////////////////////////////// #ifndef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 3 resource. // ///////////////////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED \ No newline at end of file diff --git a/mac/libdes/src/passwd_dialog.res b/mac/libdes/src/passwd_dialog.res deleted file mode 100755 index 162f20af7c5e069ba015d6b3ea0979b21b5eaec1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 320 zcmZ9HI|>3p5Jcbl0Tac@Oz{GO7#eCQqF`Vwy28TZU&O#GcncH38yK5-fw_U#u%>qv zbcTVNel^`S0CgSbk|X)Mf)CHj6B=ultGSQqReV0YP6~HA28K-7Y9Cm#VWtUd_Jq<$ z@dABDs*U7Y$mNx15p#Q8=Q{MFMuih4&ROTKMj#+aS%a2Xpi~zI^inQ|@rZ RCSID("$Id: passwd_dlg.c,v 1.2 2001/12/04 02:06:30 rjs3 Exp $"); #endif #ifdef WIN32 /* Visual C++ 4.0 (Windows95/NT) */ #include #include "passwd_dlg.h" #include "Resource.h" #define passwdBufSZ 64 char passwd[passwdBufSZ]; BOOL CALLBACK pwd_dialog_proc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { case WM_COMMAND: switch(wParam) { case IDOK: if(!GetDlgItemText(hwndDlg,IDC_PASSWD_EDIT, passwd, passwdBufSZ)) EndDialog(hwndDlg, IDCANCEL); case IDCANCEL: EndDialog(hwndDlg, wParam); return TRUE; } } return FALSE; } /* return 0 if ok, 1 otherwise */ int pwd_dialog(char *buf, int size) { int i; HWND wnd = GetActiveWindow(); HANDLE hInst = GetModuleHandle("des"); switch(DialogBox(hInst,MAKEINTRESOURCE(IDD_PASSWD_DIALOG),wnd,pwd_dialog_proc)) { case IDOK: strcpy_truncate(buf, passwd, size); memset (passwd, 0, sizeof(passwd)); return 0; case IDCANCEL: default: memset (passwd, 0, sizeof(passwd)); return 1; } } #endif /* WIN32 */ \ No newline at end of file diff --git a/mac/libdes/src/passwd_dlg.h b/mac/libdes/src/passwd_dlg.h deleted file mode 100755 index 93d43850..00000000 --- a/mac/libdes/src/passwd_dlg.h +++ /dev/null @@ -1 +0,0 @@ -/* * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Hgskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the Kungliga Tekniska * Hgskolan and its contributors. * * 4. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* passwd_dlg.h - Dialog boxes for Windows95/NT * Author: Jrgen Karlsson - d93-jka@nada.kth.se * Date: June 1996 */ /* $Id: passwd_dlg.h,v 1.2 2001/12/04 02:06:30 rjs3 Exp $ */ #ifndef PASSWD_DLG_H #define PASSWD_DLG_H int pwd_dialog(char *buf, int size); #endif /* PASSWD_DLG_H */ \ No newline at end of file diff --git a/mac/libdes/src/pcbc_enc.c b/mac/libdes/src/pcbc_enc.c deleted file mode 100755 index 2c1be89d..00000000 --- a/mac/libdes/src/pcbc_enc.c +++ /dev/null @@ -1 +0,0 @@ -/* crypto/des/pcbc_enc.c */ /* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@mincom.oz.au). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@mincom.oz.au). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@mincom.oz.au)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ #include "des_locl.h" void des_pcbc_encrypt(input, output, length, schedule, ivec, encrypt) des_cblock (*input); des_cblock (*output); long length; des_key_schedule schedule; des_cblock (*ivec); int encrypt; { register DES_LONG sin0,sin1,xor0,xor1,tout0,tout1; DES_LONG tin[2]; unsigned char *in,*out,*iv; in=(unsigned char *)input; out=(unsigned char *)output; iv=(unsigned char *)ivec; if (encrypt) { c2l(iv,xor0); c2l(iv,xor1); for (; length>0; length-=8) { if (length >= 8) { c2l(in,sin0); c2l(in,sin1); } else c2ln(in,sin0,sin1,length); tin[0]=sin0^xor0; tin[1]=sin1^xor1; des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); tout0=tin[0]; tout1=tin[1]; xor0=sin0^tout0; xor1=sin1^tout1; l2c(tout0,out); l2c(tout1,out); } } else { c2l(iv,xor0); c2l(iv,xor1); for (; length>0; length-=8) { c2l(in,sin0); c2l(in,sin1); tin[0]=sin0; tin[1]=sin1; des_encrypt((DES_LONG *)tin,schedule,DES_DECRYPT); tout0=tin[0]^xor0; tout1=tin[1]^xor1; if (length >= 8) { l2c(tout0,out); l2c(tout1,out); } else l2cn(tout0,tout1,out,length); xor0=tout0^sin0; xor1=tout1^sin1; } } tin[0]=tin[1]=0; sin0=sin1=xor0=xor1=tout0=tout1=0; } \ No newline at end of file diff --git a/mac/libdes/src/podd.h b/mac/libdes/src/podd.h deleted file mode 100755 index 18e27ac6..00000000 --- a/mac/libdes/src/podd.h +++ /dev/null @@ -1 +0,0 @@ -/* crypto/des/podd.h */ /* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@mincom.oz.au). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@mincom.oz.au). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@mincom.oz.au)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ static const unsigned char odd_parity[256]={ 1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14, 16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31, 32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47, 49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62, 64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79, 81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94, 97, 97, 98, 98,100,100,103,103,104,104,107,107,109,109,110,110, 112,112,115,115,117,117,118,118,121,121,122,122,124,124,127,127, 128,128,131,131,133,133,134,134,137,137,138,138,140,140,143,143, 145,145,146,146,148,148,151,151,152,152,155,155,157,157,158,158, 161,161,162,162,164,164,167,167,168,168,171,171,173,173,174,174, 176,176,179,179,181,181,182,182,185,185,186,186,188,188,191,191, 193,193,194,194,196,196,199,199,200,200,203,203,205,205,206,206, 208,208,211,211,213,213,214,214,217,217,218,218,220,220,223,223, 224,224,227,227,229,229,230,230,233,233,234,234,236,236,239,239, 241,241,242,242,244,244,247,247,248,248,251,251,253,253,254,254}; \ No newline at end of file diff --git a/mac/libdes/src/qud_cksm.c b/mac/libdes/src/qud_cksm.c deleted file mode 100755 index e3b23f2e..00000000 --- a/mac/libdes/src/qud_cksm.c +++ /dev/null @@ -1 +0,0 @@ -/* crypto/des/qud_cksm.c */ /* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@mincom.oz.au). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@mincom.oz.au). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@mincom.oz.au)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ /* From "Message Authentication" R.R. Jueneman, S.M. Matyas, C.H. Meyer * IEEE Communications Magazine Sept 1985 Vol. 23 No. 9 p 29-40 * This module in only based on the code in this paper and is * almost definitely not the same as the MIT implementation. */ #include "des_locl.h" /* bug fix for dos - 7/6/91 - Larry hughes@logos.ucs.indiana.edu */ #define Q_B0(a) (((DES_LONG)(a))) #define Q_B1(a) (((DES_LONG)(a))<<8) #define Q_B2(a) (((DES_LONG)(a))<<16) #define Q_B3(a) (((DES_LONG)(a))<<24) /* used to scramble things a bit */ /* Got the value MIT uses via brute force :-) 2/10/90 eay */ #define NOISE ((DES_LONG)83653421L) DES_LONG des_quad_cksum(input, output, length, out_count, seed) des_cblock (*input); des_cblock (*output); long length; int out_count; des_cblock (*seed); { DES_LONG z0,z1,t0,t1; int i; long l; #ifdef _CRAY typedef struct { unsigned int a:32; unsigned int b:32; } XXX; #else typedef DES_LONG XXX; #endif unsigned char *cp; XXX *lp; if (out_count < 1) out_count=1; lp=(XXX*)output; z0=Q_B0((*seed)[0])|Q_B1((*seed)[1])|Q_B2((*seed)[2])|Q_B3((*seed)[3]); z1=Q_B0((*seed)[4])|Q_B1((*seed)[5])|Q_B2((*seed)[6])|Q_B3((*seed)[7]); for (i=0; ((i<4)&&(i 0) { if (l > 1) { t0= (DES_LONG)(*(cp++)); t0|=(DES_LONG)Q_B1(*(cp++)); l--; } else t0= (DES_LONG)(*(cp++)); l--; /* add */ t0+=z0; t0&=0xffffffffL; t1=z1; /* square, well sort of square */ z0=((((t0*t0)&0xffffffffL)+((t1*t1)&0xffffffffL)) &0xffffffffL)%0x7fffffffL; z1=((t0*((t1+NOISE)&0xffffffffL))&0xffffffffL)%0x7fffffffL; } if (lp != NULL) { /* The MIT library assumes that the checksum is * composed of 2*out_count 32 bit ints */ #ifdef _CRAY lp->a = z0; lp->b = z1; lp++; #else *lp++ = (XXX)z0; *lp++ = (XXX)z1; #endif } } return(z0); } \ No newline at end of file diff --git a/mac/libdes/src/rand_key.c b/mac/libdes/src/rand_key.c deleted file mode 100755 index 6b9728da..00000000 --- a/mac/libdes/src/rand_key.c +++ /dev/null @@ -1 +0,0 @@ -/* crypto/des/rand_key.c */ /* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@mincom.oz.au). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@mincom.oz.au). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@mincom.oz.au)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ #include "des_locl.h" #include static int seed=0; static des_cblock init; void des_random_seed(key) des_cblock key; { memcpy(init,key,sizeof(des_cblock)); seed=1; } /* Old source */ /* void des_random_key(ret) unsigned char *ret; { des_key_schedule ks; static DES_LONG c=0; static unsigned short pid=0; static des_cblock data={0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef}; des_cblock key; unsigned char *p; DES_LONG t; int i; #if defined(MSDOS) || defined(WIN32) pid=1; #else if (!pid) pid=getpid(); #endif p=key; if (seed) { for (i=0; i<8; i++) { data[i] ^= init[i]; init[i]=0; } seed=0; } t=(DES_LONG)time(NULL); l2c(t,p); t=(DES_LONG)((pid)|((c++)<<16)); l2c(t,p); des_set_odd_parity((des_cblock *)data); des_set_key((des_cblock *)data,ks); des_cbc_cksum((des_cblock *)key,(des_cblock *)key, (long)sizeof(key),ks,(des_cblock *)data); des_set_odd_parity((des_cblock *)key); des_set_key((des_cblock *)key,ks); des_cbc_cksum((des_cblock *)key,(des_cblock *)data, (long)sizeof(key),ks,(des_cblock *)key); memcpy(ret,data,sizeof(key)); memset(key,0,sizeof(key)); memset(ks,0,sizeof(ks)); t=0; } */ \ No newline at end of file diff --git a/mac/libdes/src/read_pwd.c b/mac/libdes/src/read_pwd.c deleted file mode 100755 index d0dbcb23..00000000 --- a/mac/libdes/src/read_pwd.c +++ /dev/null @@ -1 +0,0 @@ -/* crypto/des/read_pwd.c */ /* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@mincom.oz.au). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@mincom.oz.au). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@mincom.oz.au)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ #ifdef WIN16TTY #undef WIN16 #undef _WINDOWS #include #endif /* 06-Apr-92 Luke Brennan Support for VMS */ #include "des_locl.h" #include #include #include #include /* There are 5 types of terminal interface supported, * TERMIO, TERMIOS, VMS, MSDOS and SGTTY */ #if defined(__sgi) && !defined(TERMIOS) #define TERMIOS #undef TERMIO #undef SGTTY #endif #if defined(linux) && !defined(TERMIO) #undef TERMIOS #define TERMIO #undef SGTTY #endif #ifdef _LIBC #define TERMIO #endif #if !defined(TERMIO) && !defined(TERMIOS) && !defined(VMS) && !defined(MSDOS) #define SGTTY #endif #ifdef TERMIOS #include #define TTY_STRUCT struct termios #define TTY_FLAGS c_lflag #define TTY_get(tty,data) tcgetattr(tty,data) #define TTY_set(tty,data) tcsetattr(tty,TCSANOW,data) #endif #ifdef TERMIO #include #define TTY_STRUCT struct termio #define TTY_FLAGS c_lflag #define TTY_get(tty,data) ioctl(tty,TCGETA,data) #define TTY_set(tty,data) ioctl(tty,TCSETA,data) #endif #ifdef SGTTY #include #define TTY_STRUCT struct sgttyb #define TTY_FLAGS sg_flags #define TTY_get(tty,data) ioctl(tty,TIOCGETP,data) #define TTY_set(tty,data) ioctl(tty,TIOCSETP,data) #endif #if !defined(_LIBC) && !defined(MSDOS) && !defined(VMS) #include #endif #ifdef MSDOS #include #define fgets(a,b,c) noecho_fgets(a,b,c) #endif #ifdef VMS #include #include #include #include struct IOSB { short iosb$w_value; short iosb$w_count; long iosb$l_info; }; #endif #ifndef NX509_SIG #define NX509_SIG 32 #endif #ifndef NOPROTO static void read_till_nl(FILE *); static int read_pw(char *buf, char *buff, int size, char *prompt, int verify); static void recsig(int); static void pushsig(void); static void popsig(void); #if defined(MSDOS) && !defined(WIN16) static int noecho_fgets(char *buf, int size, FILE *tty); #endif #else static void read_till_nl(); static int read_pw(); static void recsig(); static void pushsig(); static void popsig(); #if defined(MSDOS) && !defined(WIN16) static int noecho_fgets(); #endif #endif #ifndef NOPROTO static void (*savsig[NX509_SIG])(int ); #else static void (*savsig[NX509_SIG])(); #endif static jmp_buf save; int des_read_password(key, prompt, verify) des_cblock (*key); char *prompt; int verify; { int ok; char buf[BUFSIZ],buff[BUFSIZ]; if ((ok=read_pw(buf,buff,BUFSIZ,prompt,verify)) == 0) des_string_to_key(buf,key); memset(buf,0,BUFSIZ); memset(buff,0,BUFSIZ); return(ok); } int des_read_2passwords(key1, key2, prompt, verify) des_cblock (*key1); des_cblock (*key2); char *prompt; int verify; { int ok; char buf[BUFSIZ],buff[BUFSIZ]; if ((ok=read_pw(buf,buff,BUFSIZ,prompt,verify)) == 0) des_string_to_2keys(buf,key1,key2); memset(buf,0,BUFSIZ); memset(buff,0,BUFSIZ); return(ok); } int des_read_pw_string(buf, length, prompt, verify) char *buf; int length; char *prompt; int verify; { char buff[BUFSIZ]; int ret; ret=read_pw(buf,buff,(length>BUFSIZ)?BUFSIZ:length,prompt,verify); memset(buff,0,BUFSIZ); return(ret); } #ifndef WIN16 static void read_till_nl(in) FILE *in; { #define SIZE 4 char buf[SIZE+1]; do { fgets(buf,SIZE,in); } while (strchr(buf,'\n') == NULL); } /* return 0 if ok, 1 (or -1) otherwise */ static int read_pw(buf, buff, size, prompt, verify) char *buf; char *buff; int size; char *prompt; int verify; { #ifdef VMS struct IOSB iosb; $DESCRIPTOR(terminal,"TT"); long tty_orig[3], tty_new[3]; long status; unsigned short channel = 0; #else #ifndef MSDOS TTY_STRUCT tty_orig,tty_new; #endif #endif int number=5; int ok=0; int ps=0; int is_a_tty=1; FILE *tty=NULL; char *p; #ifdef __CYGWIN32__ tty = stdin; #elif !defined(MSDOS) if ((tty=fopen("/dev/tty","r")) == NULL) tty=stdin; #else /* MSDOS */ if ((tty=fopen("con","r")) == NULL) tty=stdin; #endif /* MSDOS */ #if defined(TTY_get) && !defined(VMS) if (TTY_get(fileno(tty),&tty_orig) == -1) { #ifdef ENOTTY if (errno == ENOTTY) is_a_tty=0; else #endif return(-1); } memcpy(&(tty_new),&(tty_orig),sizeof(tty_orig)); #endif #ifdef VMS status = SYS$ASSIGN(&terminal,&channel,0,0); if (status != SS$_NORMAL) return(-1); status=SYS$QIOW(0,channel,IO$_SENSEMODE,&iosb,0,0,tty_orig,12,0,0,0,0); if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL)) return(-1); #endif if (setjmp(save)) { ok=0; goto error; } pushsig(); ps=1; #ifdef TTY_FLAGS tty_new.TTY_FLAGS &= ~ECHO; #endif #if defined(TTY_set) && !defined(VMS) if (is_a_tty && (TTY_set(fileno(tty),&tty_new) == -1)) return(-1); #endif #ifdef VMS tty_new[0] = tty_orig[0]; tty_new[1] = tty_orig[1] | TT$M_NOECHO; tty_new[2] = tty_orig[2]; status = SYS$QIOW(0,channel,IO$_SETMODE,&iosb,0,0,tty_new,12,0,0,0,0); if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL)) return(-1); #endif ps=2; while ((!ok) && (number--)) { fputs(prompt,stderr); fflush(stderr); buf[0]='\0'; fgets(buf,size,tty); if (feof(tty)) goto error; if (ferror(tty)) goto error; if ((p=(char *)strchr(buf,'\n')) != NULL) *p='\0'; else read_till_nl(tty); if (verify) { fprintf(stderr,"\nVerifying password - %s",prompt); fflush(stderr); buff[0]='\0'; fgets(buff,size,tty); if (feof(tty)) goto error; if ((p=(char *)strchr(buff,'\n')) != NULL) *p='\0'; else read_till_nl(tty); if (strcmp(buf,buff) != 0) { fprintf(stderr,"\nVerify failure"); fflush(stderr); break; /* continue; */ } } ok=1; } error: fprintf(stderr,"\n"); #ifdef DEBUG perror("fgets(tty)"); #endif /* What can we do if there is an error? */ #if defined(TTY_set) && !defined(VMS) if (ps >= 2) TTY_set(fileno(tty),&tty_orig); #endif #ifdef VMS if (ps >= 2) status = SYS$QIOW(0,channel,IO$_SETMODE,&iosb,0,0 ,tty_orig,12,0,0,0,0); #endif if (ps >= 1) popsig(); if (stdin != tty) fclose(tty); #ifdef VMS status = SYS$DASSGN(channel); #endif return(!ok); } #else /* WIN16 */ static int read_pw(buf, buff, size, prompt, verify) char *buf; char *buff; int size; char *prompt; int verify; { memset(buf,0,size); memset(buff,0,size); return(0); } #endif static void pushsig() { int i; for (i=1; i #include #ifdef KRB5 #include #elif defined(KRB4) #include #endif #include #ifdef TIME_WITH_SYS_TIME #include #include #elif defined(HAVE_SYS_TIME_H) #include #else #include #endif #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_IO_H #include #endif #ifdef HAVE_SIGNAL_H #include #endif #ifdef HAVE_FCNTL_H #include #endif #ifdef HAVE_WINSOCK_H #include #endif /* * Generate "random" data by checksumming a file. * * Returns -1 if there were any problems with permissions or I/O * errors. */ static int sumFile (const char *name, int len, void *res) { u_int32_t sum[2]; u_int32_t buf[1024*2]; int fd, i; fd = open (name, 0); if (fd < 0) return -1; while (len > 0) { int n = read(fd, buf, sizeof(buf)); if (n < 0) { close(fd); return n; } for (i = 0; i < (n/sizeof(buf[0])); i++) { sum[0] += buf[i]; i++; sum[1] += buf[i]; } len -= n; } close (fd); memcpy (res, &sum, sizeof(sum)); return 0; } #if 0 static int md5sumFile (const char *name, int len, int32_t sum[4]) { int32_t buf[1024*2]; int fd, cnt; struct md5 md5; fd = open (name, 0); if (fd < 0) return -1; md5_init(&md5); while (len > 0) { int n = read(fd, buf, sizeof(buf)); if (n < 0) { close(fd); return n; } md5_update(&md5, buf, n); len -= n; } md5_finito(&md5, (unsigned char *)sum); close (fd); return 0; } #endif /* * Create a sequence of random 64 bit blocks. * The sequence is indexed with a long long and * based on an initial des key used as a seed. */ static des_key_schedule sequence_seed; static u_int32_t sequence_index[2]; /* * Random number generator based on ideas from truerand in cryptolib * as described on page 424 in Applied Cryptography 2 ed. by Bruce * Schneier. */ static volatile int counter; static volatile unsigned char *gdata; /* Global data */ static volatile int igdata; /* Index into global data */ static int gsize; #if !defined(WIN32) && !defined(__EMX__) && !defined(__OS2__) && !defined(__CYGWIN32__) /* Visual C++ 4.0 (Windows95/NT) */ static RETSIGTYPE sigALRM(int sig) { if (igdata < gsize) gdata[igdata++] ^= counter & 0xff; #ifndef HAVE_SIGACTION signal(SIGALRM, sigALRM); /* Reinstall SysV signal handler */ #endif SIGRETURN(0); } #endif #if !defined(HAVE_RANDOM) && defined(HAVE_RAND) #ifndef srandom #define srandom srand #endif #ifndef random #define random rand #endif #endif static void des_not_rand_data(unsigned char *data, int size) { int i; srandom (time (NULL)); for(i = 0; i < size; ++i) data[i] ^= random() % 0x100; } #if !defined(WIN32) && !defined(__EMX__) && !defined(__OS2__) && !defined(__CYGWIN32__) #ifndef HAVE_SETITIMER static void pacemaker(struct timeval *tv) { fd_set fds; pid_t pid; pid = getppid(); while(1){ FD_ZERO(&fds); FD_SET(0, &fds); select(1, &fds, NULL, NULL, tv); kill(pid, SIGALRM); } } #endif /* * Generate size bytes of "random" data using timed interrupts. * It takes about 40ms/byte random data. * It's not neccessary to be root to run it. */ void des_rand_data(unsigned char *data, int size) { struct itimerval tv, otv; #ifdef HAVE_SIGACTION struct sigaction sa, osa; #else RETSIGTYPE (*osa)(int); #endif int i, j; #ifndef HAVE_SETITIMER pid_t pid; #endif char *rnd_devices[] = {"/dev/random", "/dev/srandom", "/dev/urandom", NULL}; char **p; for(p = rnd_devices; *p; p++) { int fd = open(*p, O_RDONLY | O_NDELAY); if(fd >= 0 && read(fd, data, size) == size) { close(fd); return; } close(fd); } /* Paranoia? Initialize data from /dev/mem if we can read it. */ if (size >= 8) sumFile("/dev/mem", (1024*1024*2), data); gdata = data; gsize = size; igdata = 0; #ifdef HAVE_SIGACTION /* Setup signal handler */ sa.sa_handler = sigALRM; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); sigaction(SIGALRM, &sa, &osa); #else osa = signal(SIGALRM, sigALRM); #endif /* Start timer */ tv.it_value.tv_sec = 0; tv.it_value.tv_usec = 10 * 1000; /* 10 ms */ tv.it_interval = tv.it_value; #ifdef HAVE_SETITIMER setitimer(ITIMER_REAL, &tv, &otv); #else pid = fork(); if(pid == -1){ des_not_rand_data(data, size); return; } if(pid == 0) pacemaker(&tv.it_interval); #endif for(i = 0; i < 4; i++) { for (igdata = 0; igdata < size;) /* igdata++ in sigALRM */ counter++; for (j = 0; j < size; j++) /* Only use 2 bits each lap */ gdata[j] = (gdata[j]>>2) | (gdata[j]<<6); } #ifdef HAVE_SETITIMER setitimer(ITIMER_REAL, &otv, 0); #else kill(pid, SIGKILL); waitpid(pid, NULL, 0); #endif #ifdef HAVE_SIGACTION sigaction(SIGALRM, &osa, 0); #else signal(SIGALRM, osa != SIG_ERR ? osa : SIG_DFL); #endif } #else void des_rand_data(unsigned char *p, int s) { des_not_rand_data (p, s); } #endif void des_generate_random_block(des_cblock *block) { des_rand_data((unsigned char *)block, sizeof(*block)); } /* * Generate a "random" DES key. */ void des_rand_data_key(des_cblock *key) { unsigned char data[8]; des_key_schedule sched; do { des_rand_data(data, sizeof(data)); des_rand_data((unsigned char*)key, sizeof(des_cblock)); des_set_odd_parity(key); des_key_sched(key, sched); des_ecb_encrypt(&data, key, sched, DES_ENCRYPT); memset(&data, 0, sizeof(data)); memset(&sched, 0, sizeof(sched)); des_set_odd_parity(key); } while(des_is_weak_key(key)); } /* * Generate "random" data by checksumming /dev/mem * * It's neccessary to be root to run it. Returns -1 if there were any * problems with permissions. */ int des_mem_rand8(unsigned char *data) { return 1; } /* * In case the generator does not get initialized use this as fallback. */ static int initialized; static void do_initialize(void) { des_cblock default_seed; do { des_generate_random_block(&default_seed); des_set_odd_parity(&default_seed); } while (des_is_weak_key(&default_seed)); des_init_random_number_generator(&default_seed); } #define zero_long_long(ll) do { ll[0] = ll[1] = 0; } while (0) #define incr_long_long(ll) do { if (++ll[0] == 0) ++ll[1]; } while (0) #define set_sequence_number(ll) \ memcpy((char *)sequence_index, (ll), sizeof(sequence_index)); /* * Set the sequnce number to this value (a long long). */ void des_set_sequence_number(unsigned char *ll) { set_sequence_number(ll); } /* * Set the generator seed and reset the sequence number to 0. */ void des_set_random_generator_seed(des_cblock *seed) { des_key_sched(seed, sequence_seed); zero_long_long(sequence_index); initialized = 1; } /* * Generate a sequence of random des keys * using the random block sequence, fixup * parity and skip weak keys. */ int des_new_random_key(des_cblock *key) { if (!initialized) do_initialize(); do { des_ecb_encrypt((des_cblock *) sequence_index, key, sequence_seed, DES_ENCRYPT); incr_long_long(sequence_index); /* random key must have odd parity and not be weak */ des_set_odd_parity(key); } while (des_is_weak_key(key)); return(0); } /* * des_init_random_number_generator: * * Initialize the sequence of random 64 bit blocks. The input seed * can be a secret key since it should be well hidden and is also not * kept. * */ void des_init_random_number_generator(des_cblock *seed) { struct timeval now; des_cblock uniq; des_cblock new_key; gettimeofday(&now, (struct timezone *)0); des_generate_random_block(&uniq); /* Pick a unique random key from the shared sequence. */ des_set_random_generator_seed(seed); set_sequence_number((unsigned char *)&uniq); des_new_random_key(&new_key); /* Select a new nonshared sequence, */ des_set_random_generator_seed(&new_key); /* and use the current time to pick a key for the new sequence. */ set_sequence_number((unsigned char *)&now); des_new_random_key(&new_key); des_set_random_generator_seed(&new_key); } /* This is for backwards compatibility. */ void des_random_key(des_cblock ret) { des_new_random_key((des_cblock *)ret); } #ifdef TESTRUN int main() { unsigned char data[8]; int i; while (1) { if (sumFile("/dev/mem", (1024*1024*8), data) != 0) { perror("sumFile"); exit(1); } for (i = 0; i < 8; i++) printf("%02x", data[i]); printf("\n"); } } #endif #ifdef TESTRUN2 int main() { des_cblock data; int i; while (1) { do_initialize(); des_random_key(data); for (i = 0; i < 8; i++) printf("%02x", data[i]); printf("\n"); } } #endif \ No newline at end of file diff --git a/mac/libdes/src/rpc_des.h b/mac/libdes/src/rpc_des.h deleted file mode 100755 index 86dda940..00000000 --- a/mac/libdes/src/rpc_des.h +++ /dev/null @@ -1 +0,0 @@ -/* crypto/des/rpc_des.h */ /* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@mincom.oz.au). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@mincom.oz.au). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@mincom.oz.au)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ /* @(#)des.h 2.2 88/08/10 4.0 RPCSRC; from 2.7 88/02/08 SMI */ /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape * media and as a part of the software program in whole or part. Users * may copy or modify Sun RPC without charge, but are not authorized * to license or distribute it to anyone else except as part of a product or * program developed by the user. * * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. * * Sun RPC is provided with no support and without any obligation on the * part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC * OR ANY PART THEREOF. * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 */ /* * Generic DES driver interface * Keep this file hardware independent! * Copyright (c) 1986 by Sun Microsystems, Inc. */ #define DES_MAXLEN 65536 /* maximum # of bytes to encrypt */ #define DES_QUICKLEN 16 /* maximum # of bytes to encrypt quickly */ #ifdef HEADER_DES_H #undef ENCRYPT #undef DECRYPT #endif enum desdir { ENCRYPT, DECRYPT }; enum desmode { CBC, ECB }; /* * parameters to ioctl call */ struct desparams { unsigned char des_key[8]; /* key (with low bit parity) */ enum desdir des_dir; /* direction */ enum desmode des_mode; /* mode */ unsigned char des_ivec[8]; /* input vector */ unsigned des_len; /* number of bytes to crypt */ union { unsigned char UDES_data[DES_QUICKLEN]; unsigned char *UDES_buf; } UDES; # define des_data UDES.UDES_data /* direct data here if quick */ # define des_buf UDES.UDES_buf /* otherwise, pointer to data */ }; /* * Encrypt an arbitrary sized buffer */ #define DESIOCBLOCK _IOWR(d, 6, struct desparams) /* * Encrypt of small amount of data, quickly */ #define DESIOCQUICK _IOWR(d, 7, struct desparams) \ No newline at end of file diff --git a/mac/libdes/src/rpc_enc.c b/mac/libdes/src/rpc_enc.c deleted file mode 100755 index eae7b1ea..00000000 --- a/mac/libdes/src/rpc_enc.c +++ /dev/null @@ -1 +0,0 @@ -/* crypto/des/rpc_enc.c */ /* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@mincom.oz.au). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@mincom.oz.au). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@mincom.oz.au)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ #include "rpc_des.h" #include "des_locl.h" #include "des_ver.h" #ifndef NOPROTO int _des_crypt(char *buf,int len,struct desparams *desp); #else int _des_crypt(); #endif int _des_crypt(buf, len, desp) char *buf; int len; struct desparams *desp; { des_key_schedule ks; int enc; des_set_key((des_cblock *)desp->des_key,ks); enc=(desp->des_dir == ENCRYPT)?DES_ENCRYPT:DES_DECRYPT; if (desp->des_mode == CBC) des_ecb_encrypt((des_cblock *)desp->UDES.UDES_buf, (des_cblock *)desp->UDES.UDES_buf,ks,enc); else { des_ncbc_encrypt((des_cblock *)desp->UDES.UDES_buf, (des_cblock *)desp->UDES.UDES_buf, (long)len,ks, (des_cblock *)desp->des_ivec,enc); #ifdef undef /* len will always be %8 if called from common_crypt * in secure_rpc. * Libdes's cbc encrypt does not copy back the iv, * so we have to do it here. */ /* It does now :-) eay 20/09/95 */ a=(char *)&(desp->UDES.UDES_buf[len-8]); b=(char *)&(desp->des_ivec[0]); *(a++)= *(b++); *(a++)= *(b++); *(a++)= *(b++); *(a++)= *(b++); *(a++)= *(b++); *(a++)= *(b++); *(a++)= *(b++); *(a++)= *(b++); #endif } return(1); } \ No newline at end of file diff --git a/mac/libdes/src/rpw.c b/mac/libdes/src/rpw.c deleted file mode 100755 index c10c24f7..00000000 --- a/mac/libdes/src/rpw.c +++ /dev/null @@ -1 +0,0 @@ -/* crypto/des/rpw.c */ /* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@mincom.oz.au). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@mincom.oz.au). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@mincom.oz.au)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ #ifdef HAVE_CONFIG_H #include #endif #include #include "des.h" int main(argc,argv) int argc; char *argv[]; { des_cblock k,k1; int i; printf("read passwd\n"); if ((i=des_read_password((C_Block *)k,"Enter password:",0)) == 0) { printf("password = "); for (i=0; i<8; i++) printf("%02x ",k[i]); } else printf("error %d\n",i); printf("\n"); printf("read 2passwds and verify\n"); if ((i=des_read_2passwords((C_Block *)k,(C_Block *)k1, "Enter verified password:",1)) == 0) { printf("password1 = "); for (i=0; i<8; i++) printf("%02x ",k[i]); printf("\n"); printf("password2 = "); for (i=0; i<8; i++) printf("%02x ",k1[i]); printf("\n"); exit(1); } else { printf("error %d\n",i); exit(0); } #ifdef LINT return(0); #endif } \ No newline at end of file diff --git a/mac/libdes/src/set_key.c b/mac/libdes/src/set_key.c deleted file mode 100755 index 432034ac..00000000 --- a/mac/libdes/src/set_key.c +++ /dev/null @@ -1 +0,0 @@ -/* crypto/des/set_key.c */ /* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@mincom.oz.au). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@mincom.oz.au). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@mincom.oz.au)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ /* set_key.c v 1.4 eay 24/9/91 * 1.4 Speed up by 400% :-) * 1.3 added register declarations. * 1.2 unrolled make_key_sched a bit more * 1.1 added norm_expand_bits * 1.0 First working version */ #include "des_locl.h" #include "podd.h" #include "sk.h" #ifndef NOPROTO static int check_parity(des_cblock (*key)); #else static int check_parity(); #endif int des_check_key=0; void des_set_odd_parity(key) des_cblock (*key); { int i; for (i=0; i>(n))^(b))&(m)),\ * (b)^=(t),\ * (a)=((a)^((t)<<(n)))) */ #define HPERM_OP(a,t,n,m) ((t)=((((a)<<(16-(n)))^(a))&(m)),\ (a)=(a)^(t)^(t>>(16-(n)))) /* return 0 if key parity is odd (correct), * return -1 if key parity error, * return -2 if illegal weak key. */ int des_set_key(key, schedule) des_cblock (*key); des_key_schedule schedule; { static int shifts2[16]={0,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0}; register DES_LONG c,d,t,s,t2; register unsigned char *in; register DES_LONG *k; register int i; if (des_check_key) { if (!check_parity(key)) return(-1); if (des_is_weak_key(key)) return(-2); } k=(DES_LONG *)schedule; in=(unsigned char *)key; c2l(in,c); c2l(in,d); /* do PC1 in 60 simple operations */ /* PERM_OP(d,c,t,4,0x0f0f0f0fL); HPERM_OP(c,t,-2, 0xcccc0000L); HPERM_OP(c,t,-1, 0xaaaa0000L); HPERM_OP(c,t, 8, 0x00ff0000L); HPERM_OP(c,t,-1, 0xaaaa0000L); HPERM_OP(d,t,-8, 0xff000000L); HPERM_OP(d,t, 8, 0x00ff0000L); HPERM_OP(d,t, 2, 0x33330000L); d=((d&0x00aa00aaL)<<7L)|((d&0x55005500L)>>7L)|(d&0xaa55aa55L); d=(d>>8)|((c&0xf0000000L)>>4); c&=0x0fffffffL; */ /* I now do it in 47 simple operations :-) * Thanks to John Fletcher (john_fletcher@lccmail.ocf.llnl.gov) * for the inspiration. :-) */ PERM_OP (d,c,t,4,0x0f0f0f0fL); HPERM_OP(c,t,-2,0xcccc0000L); HPERM_OP(d,t,-2,0xcccc0000L); PERM_OP (d,c,t,1,0x55555555L); PERM_OP (c,d,t,8,0x00ff00ffL); PERM_OP (d,c,t,1,0x55555555L); d= (((d&0x000000ffL)<<16L)| (d&0x0000ff00L) | ((d&0x00ff0000L)>>16L)|((c&0xf0000000L)>>4L)); c&=0x0fffffffL; for (i=0; i>2L)|(c<<26L)); d=((d>>2L)|(d<<26L)); } else { c=((c>>1L)|(c<<27L)); d=((d>>1L)|(d<<27L)); } c&=0x0fffffffL; d&=0x0fffffffL; /* could be a few less shifts but I am to lazy at this * point in time to investigate */ s= des_skb[0][ (c )&0x3f ]| des_skb[1][((c>> 6)&0x03)|((c>> 7L)&0x3c)]| des_skb[2][((c>>13)&0x0f)|((c>>14L)&0x30)]| des_skb[3][((c>>20)&0x01)|((c>>21L)&0x06) | ((c>>22L)&0x38)]; t= des_skb[4][ (d )&0x3f ]| des_skb[5][((d>> 7L)&0x03)|((d>> 8L)&0x3c)]| des_skb[6][ (d>>15L)&0x3f ]| des_skb[7][((d>>21L)&0x0f)|((d>>22L)&0x30)]; /* table contained 0213 4657 */ t2=((t<<16L)|(s&0x0000ffffL))&0xffffffffL; *(k++)=ROTATE(t2,30)&0xffffffffL; t2=((s>>16L)|(t&0xffff0000L)); *(k++)=ROTATE(t2,26)&0xffffffffL; } return(0); } int des_key_sched(key, schedule) des_cblock (*key); des_key_schedule schedule; { return(des_set_key(key,schedule)); } \ No newline at end of file diff --git a/mac/libdes/src/sha.c b/mac/libdes/src/sha.c deleted file mode 100755 index 818abd81..00000000 --- a/mac/libdes/src/sha.c +++ /dev/null @@ -1 +0,0 @@ -/* * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Hgskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the Kungliga Tekniska * Hgskolan and its contributors. * * 4. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #include "config.h" RCSID("$Id: sha.c,v 1.2 2001/12/04 02:06:31 rjs3 Exp $"); #endif #include #include #include "sha.h" #ifndef min #define min(a,b) (((a)>(b))?(b):(a)) #endif #define A m->counter[0] #define B m->counter[1] #define C m->counter[2] #define D m->counter[3] #define E m->counter[4] #define X data void sha_init (struct sha *m) { m->offset = 0; m->sz = 0; A = 0x67452301; B = 0xefcdab89; C = 0x98badcfe; D = 0x10325476; E = 0xc3d2e1f0; } static inline u_int32_t cshift (u_int32_t x, unsigned int n) { return (x << n) | (x >> (32 - n)); } #define F0(x,y,z) ((x & y) | (~x & z)) #define F1(x,y,z) (x ^ y ^ z) #define F2(x,y,z) ((x & y) | (x & z) | (y & z)) #define F3(x,y,z) F1(x,y,z) #define K0 0x5a827999 #define K1 0x6ed9eba1 #define K2 0x8f1bbcdc #define K3 0xca62c1d6 #define DO(t,f,k) \ do { \ u_int32_t temp; \ \ temp = cshift(AA, 5) + f(BB,CC,DD) + EE + data[t] + k; \ EE = DD; \ DD = CC; \ CC = cshift(BB, 30); \ BB = AA; \ AA = temp; \ } while(0) static inline void calc (struct sha *m, u_int32_t *in) { u_int32_t AA, BB, CC, DD, EE; u_int32_t data[80]; int i; AA = A; BB = B; CC = C; DD = D; EE = E; for (i = 0; i < 16; ++i) data[i] = in[i]; for (i = 16; i < 80; ++i) data[i] = cshift(data[i-3] ^ data[i-8] ^ data[i-14] ^ data[i-16], 1); /* t=[0,19] */ DO(0,F0,K0); DO(1,F0,K0); DO(2,F0,K0); DO(3,F0,K0); DO(4,F0,K0); DO(5,F0,K0); DO(6,F0,K0); DO(7,F0,K0); DO(8,F0,K0); DO(9,F0,K0); DO(10,F0,K0); DO(11,F0,K0); DO(12,F0,K0); DO(13,F0,K0); DO(14,F0,K0); DO(15,F0,K0); DO(16,F0,K0); DO(17,F0,K0); DO(18,F0,K0); DO(19,F0,K0); /* t=[20,39] */ DO(20,F1,K1); DO(21,F1,K1); DO(22,F1,K1); DO(23,F1,K1); DO(24,F1,K1); DO(25,F1,K1); DO(26,F1,K1); DO(27,F1,K1); DO(28,F1,K1); DO(29,F1,K1); DO(30,F1,K1); DO(31,F1,K1); DO(32,F1,K1); DO(33,F1,K1); DO(34,F1,K1); DO(35,F1,K1); DO(36,F1,K1); DO(37,F1,K1); DO(38,F1,K1); DO(39,F1,K1); /* t=[40,59] */ DO(40,F2,K2); DO(41,F2,K2); DO(42,F2,K2); DO(43,F2,K2); DO(44,F2,K2); DO(45,F2,K2); DO(46,F2,K2); DO(47,F2,K2); DO(48,F2,K2); DO(49,F2,K2); DO(50,F2,K2); DO(51,F2,K2); DO(52,F2,K2); DO(53,F2,K2); DO(54,F2,K2); DO(55,F2,K2); DO(56,F2,K2); DO(57,F2,K2); DO(58,F2,K2); DO(59,F2,K2); /* t=[60,79] */ DO(60,F3,K3); DO(61,F3,K3); DO(62,F3,K3); DO(63,F3,K3); DO(64,F3,K3); DO(65,F3,K3); DO(66,F3,K3); DO(67,F3,K3); DO(68,F3,K3); DO(69,F3,K3); DO(70,F3,K3); DO(71,F3,K3); DO(72,F3,K3); DO(73,F3,K3); DO(74,F3,K3); DO(75,F3,K3); DO(76,F3,K3); DO(77,F3,K3); DO(78,F3,K3); DO(79,F3,K3); A += AA; B += BB; C += CC; D += DD; E += EE; } /* * From `Performance analysis of SHA' by Joseph D. Touch */ static inline u_int32_t swap_u_int32_t (u_int32_t t) { #if !defined(WORDS_BIGENDIAN) #define ROL(x,n) ((x)<<(n))|((x)>>(32-(n))) u_int32_t temp1, temp2; temp1 = ROL(t,16); temp2 = temp1 >> 8; temp1 &= 0x00ff00ff; temp2 &= 0x00ff00ff; temp1 <<= 8; return temp1 | temp2; #else return t; #endif } struct x32{ unsigned int a:32; unsigned int b:32; }; void sha_update (struct sha *m, const void *v, size_t len) { const unsigned char *p = v; m->sz += len; while(len > 0){ size_t l = min(len, 64 - m->offset); memcpy(m->save + m->offset, p, l); m->offset += l; p += l; len -= l; if(m->offset == 64){ #if !defined(WORDS_BIGENDIAN) || defined(_CRAY) int i; u_int32_t current[16]; struct x32 *u = (struct x32*)m->save; for(i = 0; i < 8; i++){ current[2*i+0] = swap_u_int32_t(u[i].a); current[2*i+1] = swap_u_int32_t(u[i].b); } calc(m, current); #else calc(m, (u_int32_t*)m->save); #endif m->offset = 0; } } } void sha_finito (struct sha *m, void *res) { static unsigned char zeros[72]; u_int32_t len; unsigned int dstart = (120 - m->offset - 1) % 64 + 1; *zeros = 0x80; memset (zeros + 1, 0, sizeof(zeros) - 1); len = 8 * m->sz; zeros[dstart+7] = (len >> 0) & 0xff; zeros[dstart+6] = (len >> 8) & 0xff; zeros[dstart+5] = (len >> 16) & 0xff; zeros[dstart+4] = (len >> 24) & 0xff; sha_update (m, zeros, dstart + 8); { int i; unsigned char *r = (unsigned char*)res; for (i = 0; i < 5; ++i) { r[4*i+3] = m->counter[i] & 0xFF; r[4*i+2] = (m->counter[i] >> 8) & 0xFF; r[4*i+1] = (m->counter[i] >> 16) & 0xFF; r[4*i] = (m->counter[i] >> 24) & 0xFF; } } #if 0 { int i; u_int32_t *r = (u_int32_t *)res; for (i = 0; i < 5; ++i) r[i] = swap_u_int32_t (m->counter[i]); } #endif } \ No newline at end of file diff --git a/mac/libdes/src/sha.h b/mac/libdes/src/sha.h deleted file mode 100755 index 779369ae..00000000 --- a/mac/libdes/src/sha.h +++ /dev/null @@ -1 +0,0 @@ -/* * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Hgskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the Kungliga Tekniska * Hgskolan and its contributors. * * 4. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* $Id: sha.h,v 1.2 2001/12/04 02:06:31 rjs3 Exp $ */ #include #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_SYS_BITYPES_H #include #endif #ifdef KRB5 #include #elif defined(KRB4) #include #endif struct sha { unsigned int offset; unsigned int sz; u_int32_t counter[5]; unsigned char save[64]; }; void sha_init (struct sha *m); void sha_update (struct sha *m, const void *v, size_t len); void sha_finito (struct sha *m, void *res); \ No newline at end of file diff --git a/mac/libdes/src/shifts.pl b/mac/libdes/src/shifts.pl deleted file mode 100755 index 9f8eb853..00000000 --- a/mac/libdes/src/shifts.pl +++ /dev/null @@ -1 +0,0 @@ -#/usr/local/bin/perl sub lab_shift { local(*a,$n)=@_; local(@r,$i,$j,$k,$d,@z); @r=&shift(*a,$n); foreach $i (0 .. 31) { @z=split(/\^/,$r[$i]); for ($j=0; $j <= $#z; $j++) { ($d)=($z[$j] =~ /^(..)/); ($k)=($z[$j] =~ /\[(.*)\]$/); $k.=",$n" if ($k ne ""); $k="$n" if ($k eq ""); $d="$d[$k]"; $z[$j]=$d; } $r[$i]=join('^',@z); } return(@r); } sub shift { local(*a,$n)=@_; local(@f); if ($n > 0) { @f=&shiftl(*a,$n); } else { @f=&shiftr(*a,-$n); } return(@f); } sub rotate { local(*a,$n)=@_; local(@f); if ($n > 0) { @f=&rotatel(*a,$n); } else { @f=&rotater(*a,-$n); } return(@f); } sub rotater { local(*a,$n)=@_; local(@f,@g); @f=&shiftr(*a,$n); @g=&shiftl(*a,32-$n); $#f=31; $#g=31; return(&or(*f,*g)); } sub rotatel { local(*a,$n)=@_; local(@f,@g); @f=&shiftl(*a,$n); @g=&shiftr(*a,32-$n); $#f=31; $#g=31; return(&or(*f,*g)); } sub shiftr { local(*a,$n)=@_; local(@r,$i); $#r=31; foreach $i (0 .. 31) { if (($i+$n) > 31) { $r[$i]="--"; } else { $r[$i]=$a[$i+$n]; } } return(@r); } sub shiftl { local(*a,$n)=@_; local(@r,$i); $#r=31; foreach $i (0 .. 31) { if ($i < $n) { $r[$i]="--"; } else { $r[$i]=$a[$i-$n]; } } return(@r); } sub printit { local(@a)=@_; local($i); foreach $i (0 .. 31) { printf "%2s ",$a[$i]; print "\n" if (($i%8) == 7); } print "\n"; } sub xor { local(*a,*b)=@_; local(@r,$i); $#r=31; foreach $i (0 .. 31) { $r[$i]=&compress($a[$i].'^'.$b[$i]); # $r[$i]=$a[$i]."^".$b[$i]; } return(@r); } sub and { local(*a,$m)=@_; local(@r,$i); $#r=31; foreach $i (0 .. 31) { $r[$i]=(($m & (1<<$i))?($a[$i]):('--')); } return(@r); } sub or { local(*a,*b)=@_; local(@r,$i); $#r=31; foreach $i (0 .. 31) { $r[$i]='--' if (($a[$i] eq '--') && ($b[$i] eq '--')); $r[$i]=$a[$i] if (($a[$i] ne '--') && ($b[$i] eq '--')); $r[$i]=$b[$i] if (($a[$i] eq '--') && ($b[$i] ne '--')); $r[$i]='++' if (($a[$i] ne '--') && ($b[$i] ne '--')); } return(@r); } sub compress { local($s)=@_; local($_,$i,@a,%a,$r); $s =~ s/\^\^/\^/g; $s =~ s/^\^//; $s =~ s/\^$//; @a=split(/\^/,$s); while ($#a >= 0) { $_=shift(@a); next unless /\d/; $a{$_}++; } foreach $i (sort keys %a) { next if ($a{$i}%2 == 0); $r.="$i^"; } chop($r); return($r); } 1; \ No newline at end of file diff --git a/mac/libdes/src/sk.h b/mac/libdes/src/sk.h deleted file mode 100755 index 27d7c80a..00000000 --- a/mac/libdes/src/sk.h +++ /dev/null @@ -1 +0,0 @@ -/* crypto/des/sk.h */ /* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@mincom.oz.au). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@mincom.oz.au). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@mincom.oz.au)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ static const DES_LONG des_skb[8][64]={ { /* for C bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ 0x00000000L,0x00000010L,0x20000000L,0x20000010L, 0x00010000L,0x00010010L,0x20010000L,0x20010010L, 0x00000800L,0x00000810L,0x20000800L,0x20000810L, 0x00010800L,0x00010810L,0x20010800L,0x20010810L, 0x00000020L,0x00000030L,0x20000020L,0x20000030L, 0x00010020L,0x00010030L,0x20010020L,0x20010030L, 0x00000820L,0x00000830L,0x20000820L,0x20000830L, 0x00010820L,0x00010830L,0x20010820L,0x20010830L, 0x00080000L,0x00080010L,0x20080000L,0x20080010L, 0x00090000L,0x00090010L,0x20090000L,0x20090010L, 0x00080800L,0x00080810L,0x20080800L,0x20080810L, 0x00090800L,0x00090810L,0x20090800L,0x20090810L, 0x00080020L,0x00080030L,0x20080020L,0x20080030L, 0x00090020L,0x00090030L,0x20090020L,0x20090030L, 0x00080820L,0x00080830L,0x20080820L,0x20080830L, 0x00090820L,0x00090830L,0x20090820L,0x20090830L, },{ /* for C bits (numbered as per FIPS 46) 7 8 10 11 12 13 */ 0x00000000L,0x02000000L,0x00002000L,0x02002000L, 0x00200000L,0x02200000L,0x00202000L,0x02202000L, 0x00000004L,0x02000004L,0x00002004L,0x02002004L, 0x00200004L,0x02200004L,0x00202004L,0x02202004L, 0x00000400L,0x02000400L,0x00002400L,0x02002400L, 0x00200400L,0x02200400L,0x00202400L,0x02202400L, 0x00000404L,0x02000404L,0x00002404L,0x02002404L, 0x00200404L,0x02200404L,0x00202404L,0x02202404L, 0x10000000L,0x12000000L,0x10002000L,0x12002000L, 0x10200000L,0x12200000L,0x10202000L,0x12202000L, 0x10000004L,0x12000004L,0x10002004L,0x12002004L, 0x10200004L,0x12200004L,0x10202004L,0x12202004L, 0x10000400L,0x12000400L,0x10002400L,0x12002400L, 0x10200400L,0x12200400L,0x10202400L,0x12202400L, 0x10000404L,0x12000404L,0x10002404L,0x12002404L, 0x10200404L,0x12200404L,0x10202404L,0x12202404L, },{ /* for C bits (numbered as per FIPS 46) 14 15 16 17 19 20 */ 0x00000000L,0x00000001L,0x00040000L,0x00040001L, 0x01000000L,0x01000001L,0x01040000L,0x01040001L, 0x00000002L,0x00000003L,0x00040002L,0x00040003L, 0x01000002L,0x01000003L,0x01040002L,0x01040003L, 0x00000200L,0x00000201L,0x00040200L,0x00040201L, 0x01000200L,0x01000201L,0x01040200L,0x01040201L, 0x00000202L,0x00000203L,0x00040202L,0x00040203L, 0x01000202L,0x01000203L,0x01040202L,0x01040203L, 0x08000000L,0x08000001L,0x08040000L,0x08040001L, 0x09000000L,0x09000001L,0x09040000L,0x09040001L, 0x08000002L,0x08000003L,0x08040002L,0x08040003L, 0x09000002L,0x09000003L,0x09040002L,0x09040003L, 0x08000200L,0x08000201L,0x08040200L,0x08040201L, 0x09000200L,0x09000201L,0x09040200L,0x09040201L, 0x08000202L,0x08000203L,0x08040202L,0x08040203L, 0x09000202L,0x09000203L,0x09040202L,0x09040203L, },{ /* for C bits (numbered as per FIPS 46) 21 23 24 26 27 28 */ 0x00000000L,0x00100000L,0x00000100L,0x00100100L, 0x00000008L,0x00100008L,0x00000108L,0x00100108L, 0x00001000L,0x00101000L,0x00001100L,0x00101100L, 0x00001008L,0x00101008L,0x00001108L,0x00101108L, 0x04000000L,0x04100000L,0x04000100L,0x04100100L, 0x04000008L,0x04100008L,0x04000108L,0x04100108L, 0x04001000L,0x04101000L,0x04001100L,0x04101100L, 0x04001008L,0x04101008L,0x04001108L,0x04101108L, 0x00020000L,0x00120000L,0x00020100L,0x00120100L, 0x00020008L,0x00120008L,0x00020108L,0x00120108L, 0x00021000L,0x00121000L,0x00021100L,0x00121100L, 0x00021008L,0x00121008L,0x00021108L,0x00121108L, 0x04020000L,0x04120000L,0x04020100L,0x04120100L, 0x04020008L,0x04120008L,0x04020108L,0x04120108L, 0x04021000L,0x04121000L,0x04021100L,0x04121100L, 0x04021008L,0x04121008L,0x04021108L,0x04121108L, },{ /* for D bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ 0x00000000L,0x10000000L,0x00010000L,0x10010000L, 0x00000004L,0x10000004L,0x00010004L,0x10010004L, 0x20000000L,0x30000000L,0x20010000L,0x30010000L, 0x20000004L,0x30000004L,0x20010004L,0x30010004L, 0x00100000L,0x10100000L,0x00110000L,0x10110000L, 0x00100004L,0x10100004L,0x00110004L,0x10110004L, 0x20100000L,0x30100000L,0x20110000L,0x30110000L, 0x20100004L,0x30100004L,0x20110004L,0x30110004L, 0x00001000L,0x10001000L,0x00011000L,0x10011000L, 0x00001004L,0x10001004L,0x00011004L,0x10011004L, 0x20001000L,0x30001000L,0x20011000L,0x30011000L, 0x20001004L,0x30001004L,0x20011004L,0x30011004L, 0x00101000L,0x10101000L,0x00111000L,0x10111000L, 0x00101004L,0x10101004L,0x00111004L,0x10111004L, 0x20101000L,0x30101000L,0x20111000L,0x30111000L, 0x20101004L,0x30101004L,0x20111004L,0x30111004L, },{ /* for D bits (numbered as per FIPS 46) 8 9 11 12 13 14 */ 0x00000000L,0x08000000L,0x00000008L,0x08000008L, 0x00000400L,0x08000400L,0x00000408L,0x08000408L, 0x00020000L,0x08020000L,0x00020008L,0x08020008L, 0x00020400L,0x08020400L,0x00020408L,0x08020408L, 0x00000001L,0x08000001L,0x00000009L,0x08000009L, 0x00000401L,0x08000401L,0x00000409L,0x08000409L, 0x00020001L,0x08020001L,0x00020009L,0x08020009L, 0x00020401L,0x08020401L,0x00020409L,0x08020409L, 0x02000000L,0x0A000000L,0x02000008L,0x0A000008L, 0x02000400L,0x0A000400L,0x02000408L,0x0A000408L, 0x02020000L,0x0A020000L,0x02020008L,0x0A020008L, 0x02020400L,0x0A020400L,0x02020408L,0x0A020408L, 0x02000001L,0x0A000001L,0x02000009L,0x0A000009L, 0x02000401L,0x0A000401L,0x02000409L,0x0A000409L, 0x02020001L,0x0A020001L,0x02020009L,0x0A020009L, 0x02020401L,0x0A020401L,0x02020409L,0x0A020409L, },{ /* for D bits (numbered as per FIPS 46) 16 17 18 19 20 21 */ 0x00000000L,0x00000100L,0x00080000L,0x00080100L, 0x01000000L,0x01000100L,0x01080000L,0x01080100L, 0x00000010L,0x00000110L,0x00080010L,0x00080110L, 0x01000010L,0x01000110L,0x01080010L,0x01080110L, 0x00200000L,0x00200100L,0x00280000L,0x00280100L, 0x01200000L,0x01200100L,0x01280000L,0x01280100L, 0x00200010L,0x00200110L,0x00280010L,0x00280110L, 0x01200010L,0x01200110L,0x01280010L,0x01280110L, 0x00000200L,0x00000300L,0x00080200L,0x00080300L, 0x01000200L,0x01000300L,0x01080200L,0x01080300L, 0x00000210L,0x00000310L,0x00080210L,0x00080310L, 0x01000210L,0x01000310L,0x01080210L,0x01080310L, 0x00200200L,0x00200300L,0x00280200L,0x00280300L, 0x01200200L,0x01200300L,0x01280200L,0x01280300L, 0x00200210L,0x00200310L,0x00280210L,0x00280310L, 0x01200210L,0x01200310L,0x01280210L,0x01280310L, },{ /* for D bits (numbered as per FIPS 46) 22 23 24 25 27 28 */ 0x00000000L,0x04000000L,0x00040000L,0x04040000L, 0x00000002L,0x04000002L,0x00040002L,0x04040002L, 0x00002000L,0x04002000L,0x00042000L,0x04042000L, 0x00002002L,0x04002002L,0x00042002L,0x04042002L, 0x00000020L,0x04000020L,0x00040020L,0x04040020L, 0x00000022L,0x04000022L,0x00040022L,0x04040022L, 0x00002020L,0x04002020L,0x00042020L,0x04042020L, 0x00002022L,0x04002022L,0x00042022L,0x04042022L, 0x00000800L,0x04000800L,0x00040800L,0x04040800L, 0x00000802L,0x04000802L,0x00040802L,0x04040802L, 0x00002800L,0x04002800L,0x00042800L,0x04042800L, 0x00002802L,0x04002802L,0x00042802L,0x04042802L, 0x00000820L,0x04000820L,0x00040820L,0x04040820L, 0x00000822L,0x04000822L,0x00040822L,0x04040822L, 0x00002820L,0x04002820L,0x00042820L,0x04042820L, 0x00002822L,0x04002822L,0x00042822L,0x04042822L, }}; \ No newline at end of file diff --git a/mac/libdes/src/speed.c b/mac/libdes/src/speed.c deleted file mode 100755 index 0c4e1816..00000000 --- a/mac/libdes/src/speed.c +++ /dev/null @@ -1 +0,0 @@ -/* crypto/des/speed.c */ /* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@mincom.oz.au). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@mincom.oz.au). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@mincom.oz.au)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ /* 11-Sep-92 Andrew Daviel Support for Silicon Graphics IRIX added */ /* 06-Apr-92 Luke Brennan Support for VMS and add extra signal calls */ #ifdef HAVE_CONFIG_H #include #endif #if !defined(MSDOS) && !defined(WIN32) #define TIMES #endif #include #ifdef HAVE_UNISTD_H #include #endif #include #ifdef HAVE_TIME_H #include #endif #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_SYS_TIMES_H #include #endif #ifdef VMS #include struct tms { time_t tms_utime; time_t tms_stime; time_t tms_uchild; /* I dunno... */ time_t tms_uchildsys; /* so these names are a guess :-) */ } #endif #ifdef HAVE_SYS_TIMEB_H #include #endif #include #ifdef HAVE_SYS_PARAM_H #include #endif #include "des.h" /* The following if from times(3) man page. It may need to be changed */ #ifndef HZ #ifndef CLK_TCK #ifndef VMS #define HZ 100.0 #else /* VMS */ #define HZ 100.0 #endif #else /* CLK_TCK */ #define HZ ((double)CLK_TCK) #endif #endif #define BUFSIZE ((long)1024) long run=0; #ifndef NOPROTO double Time_F(int s); #else double Time_F(); #endif #ifdef SIGALRM #if defined(__STDC__) || defined(sgi) #define SIGRETTYPE void #else #define SIGRETTYPE int #endif #ifndef NOPROTO SIGRETTYPE sig_done(int sig); #else SIGRETTYPE sig_done(); #endif SIGRETTYPE sig_done(sig) int sig; { signal(SIGALRM,sig_done); run=0; #ifdef LINT sig=sig; #endif } #endif #define START 0 #define STOP 1 double Time_F(s) int s; { double ret; #ifdef TIMES static struct tms tstart,tend; if (s == START) { times(&tstart); return(0); } else { times(&tend); ret=((double)(tend.tms_utime-tstart.tms_utime))/HZ; return((ret == 0.0)?1e-6:ret); } #else /* !times() */ static struct timeb tstart,tend; long i; if (s == START) { ftime(&tstart); return(0); } else { ftime(&tend); i=(long)tend.millitm-(long)tstart.millitm; ret=((double)(tend.time-tstart.time))+((double)i)/1000.0; return((ret == 0.0)?1e-6:ret); } #endif } int main(argc,argv) int argc; char **argv; { long count; static unsigned char buf[BUFSIZE]; static des_cblock key ={0x12,0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0}; static des_cblock key2={0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12}; static des_cblock key3={0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12,0x34}; des_key_schedule sch,sch2,sch3; double a,b,c,d,e; #ifndef SIGALRM long ca,cb,cc,cd,ce; #endif #ifndef TIMES printf("To get the most acurate results, try to run this\n"); printf("program when this computer is idle.\n"); #endif des_set_key((C_Block *)key2,sch2); des_set_key((C_Block *)key3,sch3); #ifndef SIGALRM printf("First we calculate the approximate speed ...\n"); des_set_key((C_Block *)key,sch); count=10; do { long i; DES_LONG data[2]; count*=2; Time_F(START); for (i=count; i; i--) des_encrypt(data,&(sch[0]),DES_ENCRYPT); d=Time_F(STOP); } while (d < 3.0); ca=count; cb=count*3; cc=count*3*8/BUFSIZE+1; cd=count*8/BUFSIZE+1; ce=count/20+1; printf("Doing set_key %ld times\n",ca); #define COND(d) (count != (d)) #define COUNT(d) (d) #else #define COND(c) (run) #define COUNT(d) (count) signal(SIGALRM,sig_done); printf("Doing set_key for 10 seconds\n"); alarm(10); #endif Time_F(START); for (count=0,run=1; COND(ca); count++) des_set_key((C_Block *)key,sch); d=Time_F(STOP); printf("%ld set_key's in %.2f seconds\n",count,d); a=((double)COUNT(ca))/d; #ifdef SIGALRM printf("Doing des_encrypt's for 10 seconds\n"); alarm(10); #else printf("Doing des_encrypt %ld times\n",cb); #endif Time_F(START); for (count=0,run=1; COND(cb); count++) { DES_LONG data[2]; des_encrypt(data,&(sch[0]),DES_ENCRYPT); } d=Time_F(STOP); printf("%ld des_encrypt's in %.2f second\n",count,d); b=((double)COUNT(cb)*8)/d; #ifdef SIGALRM printf("Doing des_cbc_encrypt on %ld byte blocks for 10 seconds\n", BUFSIZE); alarm(10); #else printf("Doing des_cbc_encrypt %ld times on %ld byte blocks\n",cc, BUFSIZE); #endif Time_F(START); for (count=0,run=1; COND(cc); count++) des_ncbc_encrypt((C_Block *)buf,(C_Block *)buf,BUFSIZE,&(sch[0]), (C_Block *)&(key[0]),DES_ENCRYPT); d=Time_F(STOP); printf("%ld des_cbc_encrypt's of %ld byte blocks in %.2f second\n", count,BUFSIZE,d); c=((double)COUNT(cc)*BUFSIZE)/d; #ifdef SIGALRM printf("Doing des_ede_cbc_encrypt on %ld byte blocks for 10 seconds\n", BUFSIZE); alarm(10); #else printf("Doing des_ede_cbc_encrypt %ld times on %ld byte blocks\n",cd, BUFSIZE); #endif Time_F(START); for (count=0,run=1; COND(cd); count++) des_ede3_cbc_encrypt((C_Block *)buf,(C_Block *)buf,BUFSIZE, &(sch[0]), &(sch2[0]), &(sch3[0]), (C_Block *)&(key[0]), DES_ENCRYPT); d=Time_F(STOP); printf("%ld des_ede_cbc_encrypt's of %ld byte blocks in %.2f second\n", count,BUFSIZE,d); d=((double)COUNT(cd)*BUFSIZE)/d; #ifdef SIGALRM printf("Doing crypt for 10 seconds\n"); alarm(10); #else printf("Doing crypt %ld times\n",ce); #endif Time_F(START); for (count=0,run=1; COND(ce); count++) crypt("testing1","ef"); e=Time_F(STOP); printf("%ld crypts in %.2f second\n",count,e); e=((double)COUNT(ce))/e; printf("set_key per sec = %12.2f (%5.1fuS)\n",a,1.0e6/a); printf("DES raw ecb bytes per sec = %12.2f (%5.1fuS)\n",b,8.0e6/b); printf("DES cbc bytes per sec = %12.2f (%5.1fuS)\n",c,8.0e6/c); printf("DES ede cbc bytes per sec = %12.2f (%5.1fuS)\n",d,8.0e6/d); printf("crypt per sec = %12.2f (%5.1fuS)\n",e,1.0e6/e); exit(0); #if defined(LINT) || defined(MSDOS) return(0); #endif } \ No newline at end of file diff --git a/mac/libdes/src/spr.h b/mac/libdes/src/spr.h deleted file mode 100755 index 2718e519..00000000 --- a/mac/libdes/src/spr.h +++ /dev/null @@ -1 +0,0 @@ -/* crypto/des/spr.h */ /* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@mincom.oz.au). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@mincom.oz.au). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@mincom.oz.au)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ const DES_LONG des_SPtrans[8][64]={ { /* nibble 0 */ 0x02080800L, 0x00080000L, 0x02000002L, 0x02080802L, 0x02000000L, 0x00080802L, 0x00080002L, 0x02000002L, 0x00080802L, 0x02080800L, 0x02080000L, 0x00000802L, 0x02000802L, 0x02000000L, 0x00000000L, 0x00080002L, 0x00080000L, 0x00000002L, 0x02000800L, 0x00080800L, 0x02080802L, 0x02080000L, 0x00000802L, 0x02000800L, 0x00000002L, 0x00000800L, 0x00080800L, 0x02080002L, 0x00000800L, 0x02000802L, 0x02080002L, 0x00000000L, 0x00000000L, 0x02080802L, 0x02000800L, 0x00080002L, 0x02080800L, 0x00080000L, 0x00000802L, 0x02000800L, 0x02080002L, 0x00000800L, 0x00080800L, 0x02000002L, 0x00080802L, 0x00000002L, 0x02000002L, 0x02080000L, 0x02080802L, 0x00080800L, 0x02080000L, 0x02000802L, 0x02000000L, 0x00000802L, 0x00080002L, 0x00000000L, 0x00080000L, 0x02000000L, 0x02000802L, 0x02080800L, 0x00000002L, 0x02080002L, 0x00000800L, 0x00080802L, },{ /* nibble 1 */ 0x40108010L, 0x00000000L, 0x00108000L, 0x40100000L, 0x40000010L, 0x00008010L, 0x40008000L, 0x00108000L, 0x00008000L, 0x40100010L, 0x00000010L, 0x40008000L, 0x00100010L, 0x40108000L, 0x40100000L, 0x00000010L, 0x00100000L, 0x40008010L, 0x40100010L, 0x00008000L, 0x00108010L, 0x40000000L, 0x00000000L, 0x00100010L, 0x40008010L, 0x00108010L, 0x40108000L, 0x40000010L, 0x40000000L, 0x00100000L, 0x00008010L, 0x40108010L, 0x00100010L, 0x40108000L, 0x40008000L, 0x00108010L, 0x40108010L, 0x00100010L, 0x40000010L, 0x00000000L, 0x40000000L, 0x00008010L, 0x00100000L, 0x40100010L, 0x00008000L, 0x40000000L, 0x00108010L, 0x40008010L, 0x40108000L, 0x00008000L, 0x00000000L, 0x40000010L, 0x00000010L, 0x40108010L, 0x00108000L, 0x40100000L, 0x40100010L, 0x00100000L, 0x00008010L, 0x40008000L, 0x40008010L, 0x00000010L, 0x40100000L, 0x00108000L, },{ /* nibble 2 */ 0x04000001L, 0x04040100L, 0x00000100L, 0x04000101L, 0x00040001L, 0x04000000L, 0x04000101L, 0x00040100L, 0x04000100L, 0x00040000L, 0x04040000L, 0x00000001L, 0x04040101L, 0x00000101L, 0x00000001L, 0x04040001L, 0x00000000L, 0x00040001L, 0x04040100L, 0x00000100L, 0x00000101L, 0x04040101L, 0x00040000L, 0x04000001L, 0x04040001L, 0x04000100L, 0x00040101L, 0x04040000L, 0x00040100L, 0x00000000L, 0x04000000L, 0x00040101L, 0x04040100L, 0x00000100L, 0x00000001L, 0x00040000L, 0x00000101L, 0x00040001L, 0x04040000L, 0x04000101L, 0x00000000L, 0x04040100L, 0x00040100L, 0x04040001L, 0x00040001L, 0x04000000L, 0x04040101L, 0x00000001L, 0x00040101L, 0x04000001L, 0x04000000L, 0x04040101L, 0x00040000L, 0x04000100L, 0x04000101L, 0x00040100L, 0x04000100L, 0x00000000L, 0x04040001L, 0x00000101L, 0x04000001L, 0x00040101L, 0x00000100L, 0x04040000L, },{ /* nibble 3 */ 0x00401008L, 0x10001000L, 0x00000008L, 0x10401008L, 0x00000000L, 0x10400000L, 0x10001008L, 0x00400008L, 0x10401000L, 0x10000008L, 0x10000000L, 0x00001008L, 0x10000008L, 0x00401008L, 0x00400000L, 0x10000000L, 0x10400008L, 0x00401000L, 0x00001000L, 0x00000008L, 0x00401000L, 0x10001008L, 0x10400000L, 0x00001000L, 0x00001008L, 0x00000000L, 0x00400008L, 0x10401000L, 0x10001000L, 0x10400008L, 0x10401008L, 0x00400000L, 0x10400008L, 0x00001008L, 0x00400000L, 0x10000008L, 0x00401000L, 0x10001000L, 0x00000008L, 0x10400000L, 0x10001008L, 0x00000000L, 0x00001000L, 0x00400008L, 0x00000000L, 0x10400008L, 0x10401000L, 0x00001000L, 0x10000000L, 0x10401008L, 0x00401008L, 0x00400000L, 0x10401008L, 0x00000008L, 0x10001000L, 0x00401008L, 0x00400008L, 0x00401000L, 0x10400000L, 0x10001008L, 0x00001008L, 0x10000000L, 0x10000008L, 0x10401000L, },{ /* nibble 4 */ 0x08000000L, 0x00010000L, 0x00000400L, 0x08010420L, 0x08010020L, 0x08000400L, 0x00010420L, 0x08010000L, 0x00010000L, 0x00000020L, 0x08000020L, 0x00010400L, 0x08000420L, 0x08010020L, 0x08010400L, 0x00000000L, 0x00010400L, 0x08000000L, 0x00010020L, 0x00000420L, 0x08000400L, 0x00010420L, 0x00000000L, 0x08000020L, 0x00000020L, 0x08000420L, 0x08010420L, 0x00010020L, 0x08010000L, 0x00000400L, 0x00000420L, 0x08010400L, 0x08010400L, 0x08000420L, 0x00010020L, 0x08010000L, 0x00010000L, 0x00000020L, 0x08000020L, 0x08000400L, 0x08000000L, 0x00010400L, 0x08010420L, 0x00000000L, 0x00010420L, 0x08000000L, 0x00000400L, 0x00010020L, 0x08000420L, 0x00000400L, 0x00000000L, 0x08010420L, 0x08010020L, 0x08010400L, 0x00000420L, 0x00010000L, 0x00010400L, 0x08010020L, 0x08000400L, 0x00000420L, 0x00000020L, 0x00010420L, 0x08010000L, 0x08000020L, },{ /* nibble 5 */ 0x80000040L, 0x00200040L, 0x00000000L, 0x80202000L, 0x00200040L, 0x00002000L, 0x80002040L, 0x00200000L, 0x00002040L, 0x80202040L, 0x00202000L, 0x80000000L, 0x80002000L, 0x80000040L, 0x80200000L, 0x00202040L, 0x00200000L, 0x80002040L, 0x80200040L, 0x00000000L, 0x00002000L, 0x00000040L, 0x80202000L, 0x80200040L, 0x80202040L, 0x80200000L, 0x80000000L, 0x00002040L, 0x00000040L, 0x00202000L, 0x00202040L, 0x80002000L, 0x00002040L, 0x80000000L, 0x80002000L, 0x00202040L, 0x80202000L, 0x00200040L, 0x00000000L, 0x80002000L, 0x80000000L, 0x00002000L, 0x80200040L, 0x00200000L, 0x00200040L, 0x80202040L, 0x00202000L, 0x00000040L, 0x80202040L, 0x00202000L, 0x00200000L, 0x80002040L, 0x80000040L, 0x80200000L, 0x00202040L, 0x00000000L, 0x00002000L, 0x80000040L, 0x80002040L, 0x80202000L, 0x80200000L, 0x00002040L, 0x00000040L, 0x80200040L, },{ /* nibble 6 */ 0x00004000L, 0x00000200L, 0x01000200L, 0x01000004L, 0x01004204L, 0x00004004L, 0x00004200L, 0x00000000L, 0x01000000L, 0x01000204L, 0x00000204L, 0x01004000L, 0x00000004L, 0x01004200L, 0x01004000L, 0x00000204L, 0x01000204L, 0x00004000L, 0x00004004L, 0x01004204L, 0x00000000L, 0x01000200L, 0x01000004L, 0x00004200L, 0x01004004L, 0x00004204L, 0x01004200L, 0x00000004L, 0x00004204L, 0x01004004L, 0x00000200L, 0x01000000L, 0x00004204L, 0x01004000L, 0x01004004L, 0x00000204L, 0x00004000L, 0x00000200L, 0x01000000L, 0x01004004L, 0x01000204L, 0x00004204L, 0x00004200L, 0x00000000L, 0x00000200L, 0x01000004L, 0x00000004L, 0x01000200L, 0x00000000L, 0x01000204L, 0x01000200L, 0x00004200L, 0x00000204L, 0x00004000L, 0x01004204L, 0x01000000L, 0x01004200L, 0x00000004L, 0x00004004L, 0x01004204L, 0x01000004L, 0x01004200L, 0x01004000L, 0x00004004L, },{ /* nibble 7 */ 0x20800080L, 0x20820000L, 0x00020080L, 0x00000000L, 0x20020000L, 0x00800080L, 0x20800000L, 0x20820080L, 0x00000080L, 0x20000000L, 0x00820000L, 0x00020080L, 0x00820080L, 0x20020080L, 0x20000080L, 0x20800000L, 0x00020000L, 0x00820080L, 0x00800080L, 0x20020000L, 0x20820080L, 0x20000080L, 0x00000000L, 0x00820000L, 0x20000000L, 0x00800000L, 0x20020080L, 0x20800080L, 0x00800000L, 0x00020000L, 0x20820000L, 0x00000080L, 0x00800000L, 0x00020000L, 0x20000080L, 0x20820080L, 0x00020080L, 0x20000000L, 0x00000000L, 0x00820000L, 0x20800080L, 0x20020080L, 0x20020000L, 0x00800080L, 0x20820000L, 0x00000080L, 0x00800080L, 0x20020000L, 0x20820080L, 0x00800000L, 0x20800000L, 0x20000080L, 0x00820000L, 0x00020080L, 0x20020080L, 0x20800000L, 0x00000080L, 0x20820000L, 0x00820080L, 0x00000000L, 0x20000000L, 0x20800080L, 0x00020000L, 0x00820080L, }}; \ No newline at end of file diff --git a/mac/libdes/src/str2key.c b/mac/libdes/src/str2key.c deleted file mode 100755 index 86366b68..00000000 --- a/mac/libdes/src/str2key.c +++ /dev/null @@ -1 +0,0 @@ -/* crypto/des/str2key.c */ /* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@mincom.oz.au). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@mincom.oz.au). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@mincom.oz.au)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ #include "des_locl.h" extern int des_check_key; void des_string_to_key(str, key) char *str; des_cblock (*key); { des_key_schedule ks; int i,length; register unsigned char j; memset(key,0,8); length=strlen(str); #ifdef OLD_STR_TO_KEY for (i=0; i>4)&0x0f); j=((j<<2)&0xcc)|((j>>2)&0x33); j=((j<<1)&0xaa)|((j>>1)&0x55); (*key)[7-(i%8)]^=j; } } #endif des_set_odd_parity((des_cblock *)key); i=des_check_key; des_check_key=0; des_set_key((des_cblock *)key,ks); des_check_key=i; des_cbc_cksum((des_cblock *)str,(des_cblock *)key,(long)length,ks, (des_cblock *)key); memset(ks,0,sizeof(ks)); des_set_odd_parity((des_cblock *)key); } void des_string_to_2keys(str, key1, key2) char *str; des_cblock (*key1); des_cblock (*key2); { des_key_schedule ks; int i,length; register unsigned char j; memset(key1,0,8); memset(key2,0,8); length=strlen(str); #ifdef OLD_STR_TO_KEY if (length <= 8) { for (i=0; i>4)&0x0f); j=((j<<2)&0xcc)|((j>>2)&0x33); j=((j<<1)&0xaa)|((j>>1)&0x55); if ((i%16) < 8) (*key1)[7-(i%8)]^=j; else (*key2)[7-(i%8)]^=j; } } if (length <= 8) memcpy(key2,key1,8); #endif des_set_odd_parity((des_cblock *)key1); des_set_odd_parity((des_cblock *)key2); i=des_check_key; des_check_key=0; des_set_key((des_cblock *)key1,ks); des_cbc_cksum((des_cblock *)str,(des_cblock *)key1,(long)length,ks, (des_cblock *)key1); des_set_key((des_cblock *)key2,ks); des_cbc_cksum((des_cblock *)str,(des_cblock *)key2,(long)length,ks, (des_cblock *)key2); des_check_key=i; memset(ks,0,sizeof(ks)); des_set_odd_parity(key1); des_set_odd_parity(key2); } \ No newline at end of file diff --git a/mac/libdes/src/supp.c b/mac/libdes/src/supp.c deleted file mode 100755 index 5ea66316..00000000 --- a/mac/libdes/src/supp.c +++ /dev/null @@ -1 +0,0 @@ -/* crypto/des/supp.c */ /* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@mincom.oz.au). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@mincom.oz.au). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@mincom.oz.au)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ /* * Copyright (c) 1995 * Mark Murray. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Mark Murray * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY MARK MURRAY AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: supp.c,v 1.2 2001/12/04 02:06:32 rjs3 Exp $ */ #include #include "des_locl.h" void des_cblock_print_file(cb, fp) des_cblock *cb; FILE *fp; { int i; unsigned int *p = (unsigned int *)cb; fprintf(fp, " 0x { "); for (i = 0; i < 8; i++) { fprintf(fp, "%x", p[i]); if (i != 7) fprintf(fp, ", "); } fprintf(fp, " }"); } \ No newline at end of file diff --git a/mac/libdes/src/testdes.pl b/mac/libdes/src/testdes.pl deleted file mode 100755 index 16c4172a..00000000 --- a/mac/libdes/src/testdes.pl +++ /dev/null @@ -1 +0,0 @@ -#!/usr/local/bin/perl # des.pl tesing code require 'des.pl'; $num_tests=34; @key_data=( 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF, 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xFE,0xDC,0xBA,0x98,0x76,0x54,0x32,0x10, 0x7C,0xA1,0x10,0x45,0x4A,0x1A,0x6E,0x57, 0x01,0x31,0xD9,0x61,0x9D,0xC1,0x37,0x6E, 0x07,0xA1,0x13,0x3E,0x4A,0x0B,0x26,0x86, 0x38,0x49,0x67,0x4C,0x26,0x02,0x31,0x9E, 0x04,0xB9,0x15,0xBA,0x43,0xFE,0xB5,0xB6, 0x01,0x13,0xB9,0x70,0xFD,0x34,0xF2,0xCE, 0x01,0x70,0xF1,0x75,0x46,0x8F,0xB5,0xE6, 0x43,0x29,0x7F,0xAD,0x38,0xE3,0x73,0xFE, 0x07,0xA7,0x13,0x70,0x45,0xDA,0x2A,0x16, 0x04,0x68,0x91,0x04,0xC2,0xFD,0x3B,0x2F, 0x37,0xD0,0x6B,0xB5,0x16,0xCB,0x75,0x46, 0x1F,0x08,0x26,0x0D,0x1A,0xC2,0x46,0x5E, 0x58,0x40,0x23,0x64,0x1A,0xBA,0x61,0x76, 0x02,0x58,0x16,0x16,0x46,0x29,0xB0,0x07, 0x49,0x79,0x3E,0xBC,0x79,0xB3,0x25,0x8F, 0x4F,0xB0,0x5E,0x15,0x15,0xAB,0x73,0xA7, 0x49,0xE9,0x5D,0x6D,0x4C,0xA2,0x29,0xBF, 0x01,0x83,0x10,0xDC,0x40,0x9B,0x26,0xD6, 0x1C,0x58,0x7F,0x1C,0x13,0x92,0x4F,0xEF, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x1F,0x1F,0x1F,0x1F,0x0E,0x0E,0x0E,0x0E, 0xE0,0xFE,0xE0,0xFE,0xF1,0xFE,0xF1,0xFE, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF, 0xFE,0xDC,0xBA,0x98,0x76,0x54,0x32,0x10, ); @plain_data=( 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x01, 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF, 0x01,0xA1,0xD6,0xD0,0x39,0x77,0x67,0x42, 0x5C,0xD5,0x4C,0xA8,0x3D,0xEF,0x57,0xDA, 0x02,0x48,0xD4,0x38,0x06,0xF6,0x71,0x72, 0x51,0x45,0x4B,0x58,0x2D,0xDF,0x44,0x0A, 0x42,0xFD,0x44,0x30,0x59,0x57,0x7F,0xA2, 0x05,0x9B,0x5E,0x08,0x51,0xCF,0x14,0x3A, 0x07,0x56,0xD8,0xE0,0x77,0x47,0x61,0xD2, 0x76,0x25,0x14,0xB8,0x29,0xBF,0x48,0x6A, 0x3B,0xDD,0x11,0x90,0x49,0x37,0x28,0x02, 0x26,0x95,0x5F,0x68,0x35,0xAF,0x60,0x9A, 0x16,0x4D,0x5E,0x40,0x4F,0x27,0x52,0x32, 0x6B,0x05,0x6E,0x18,0x75,0x9F,0x5C,0xCA, 0x00,0x4B,0xD6,0xEF,0x09,0x17,0x60,0x62, 0x48,0x0D,0x39,0x00,0x6E,0xE7,0x62,0xF2, 0x43,0x75,0x40,0xC8,0x69,0x8F,0x3C,0xFA, 0x07,0x2D,0x43,0xA0,0x77,0x07,0x52,0x92, 0x02,0xFE,0x55,0x77,0x81,0x17,0xF1,0x2A, 0x1D,0x9D,0x5C,0x50,0x18,0xF7,0x28,0xC2, 0x30,0x55,0x32,0x28,0x6D,0x6F,0x29,0x5A, 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF, 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF, 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF); @cipher_data=( 0x8C,0xA6,0x4D,0xE9,0xC1,0xB1,0x23,0xA7, 0x73,0x59,0xB2,0x16,0x3E,0x4E,0xDC,0x58, 0x95,0x8E,0x6E,0x62,0x7A,0x05,0x55,0x7B, 0xF4,0x03,0x79,0xAB,0x9E,0x0E,0xC5,0x33, 0x17,0x66,0x8D,0xFC,0x72,0x92,0x53,0x2D, 0x8A,0x5A,0xE1,0xF8,0x1A,0xB8,0xF2,0xDD, 0x8C,0xA6,0x4D,0xE9,0xC1,0xB1,0x23,0xA7, 0xED,0x39,0xD9,0x50,0xFA,0x74,0xBC,0xC4, 0x69,0x0F,0x5B,0x0D,0x9A,0x26,0x93,0x9B, 0x7A,0x38,0x9D,0x10,0x35,0x4B,0xD2,0x71, 0x86,0x8E,0xBB,0x51,0xCA,0xB4,0x59,0x9A, 0x71,0x78,0x87,0x6E,0x01,0xF1,0x9B,0x2A, 0xAF,0x37,0xFB,0x42,0x1F,0x8C,0x40,0x95, 0x86,0xA5,0x60,0xF1,0x0E,0xC6,0xD8,0x5B, 0x0C,0xD3,0xDA,0x02,0x00,0x21,0xDC,0x09, 0xEA,0x67,0x6B,0x2C,0xB7,0xDB,0x2B,0x7A, 0xDF,0xD6,0x4A,0x81,0x5C,0xAF,0x1A,0x0F, 0x5C,0x51,0x3C,0x9C,0x48,0x86,0xC0,0x88, 0x0A,0x2A,0xEE,0xAE,0x3F,0xF4,0xAB,0x77, 0xEF,0x1B,0xF0,0x3E,0x5D,0xFA,0x57,0x5A, 0x88,0xBF,0x0D,0xB6,0xD7,0x0D,0xEE,0x56, 0xA1,0xF9,0x91,0x55,0x41,0x02,0x0B,0x56, 0x6F,0xBF,0x1C,0xAF,0xCF,0xFD,0x05,0x56, 0x2F,0x22,0xE4,0x9B,0xAB,0x7C,0xA1,0xAC, 0x5A,0x6B,0x61,0x2C,0xC2,0x6C,0xCE,0x4A, 0x5F,0x4C,0x03,0x8E,0xD1,0x2B,0x2E,0x41, 0x63,0xFA,0xC0,0xD0,0x34,0xD9,0xF7,0x93, 0x61,0x7B,0x3A,0x0C,0xE8,0xF0,0x71,0x00, 0xDB,0x95,0x86,0x05,0xF8,0xC8,0xC6,0x06, 0xED,0xBF,0xD1,0xC6,0x6C,0x29,0xCC,0xC7, 0x35,0x55,0x50,0xB2,0x15,0x0E,0x24,0x51, 0xCA,0xAA,0xAF,0x4D,0xEA,0xF1,0xDB,0xAE, 0xD5,0xD4,0x4F,0xF7,0x20,0x68,0x3D,0x0D, 0x2A,0x2B,0xB0,0x08,0xDF,0x97,0xC2,0xF2); print "Doing ecb tests\n"; for ($i=0; $i<$num_tests; $i++) { printf "Doing test $i\n"; $key =pack("C8",splice(@key_data ,0,8)); $data=pack("C8",splice(@plain_data ,0,8)); $res =pack("C8",splice(@cipher_data,0,8)); @ks= &des_set_key($key); $out1= &des_ecb_encrypt(*ks,1,$data); $out2= &des_ecb_encrypt(*ks,0,$out1); $out3= &des_ecb_encrypt(*ks,0,$res); &eprint("encryption failure",$res,$out1) if ($out1 ne $res); &eprint("encryption/decryption failure",$data,$out2) if ($out2 ne $data); &eprint("decryption failure",$data,$out3) if ($data ne $out3); } print "Done\n"; print "doing speed test over 30 seconds\n"; $SIG{'ALRM'}='done'; sub done {$done=1;} $done=0; $count=0; $d=pack("C8",0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef); @ks= &des_set_key($d); alarm(30); $start=(times)[0]; while (!$done) { $count++; $d=&des_ecb_encrypt(*ks,1,$d); } $end=(times)[0]; $t=$end-$start; printf "$count DESs in %.2f seconds is %.2f DESs/sec or %.2f bytes/sec\n", 1.0*$t,1.0*$count/$t,$count*8.0/$t; sub eprint { local($s,$c,$e)=@_; local(@k); @k=unpack("C8",$c); printf "%02x%02x%02x%02x %02x%02x%02x%02x - ",unpack("C8",$c); printf "%02x%02x%02x%02x %02x%02x%02x%02x :",unpack("C8",$e); print " $s\n"; } \ No newline at end of file diff --git a/mac/libdes/src/times b/mac/libdes/src/times deleted file mode 100755 index 9a249833..00000000 --- a/mac/libdes/src/times +++ /dev/null @@ -1 +0,0 @@ -existing library on a DEC 3000/500 set_key per sec = 256294.06 ( 3.9uS) DES ecb bytes per sec = 3553694.40 ( 2.3uS) DES cbc bytes per sec = 3661004.80 ( 2.2uS) DES ede cbc bytes per sec = 1353115.99 ( 5.9uS) crypt per sec = 16829.40 ( 59.4uS) Intel P6/200 (NEXTSTEP) - cc -O3 (cc: gcc 2.5.8) set_key per sec = 219220.82 ( 4.6uS) DES ecb bytes per sec = 2438014.04 ( 3.3uS) DES cbc bytes per sec = 2467648.85 ( 3.2uS) DES ede cbc bytes per sec = 942121.58 ( 8.5uS) crypt per sec = 11398.73 ( 87.7uS) # DECstation Alpha 3000 Model 700 AXP / OSF1 V3.0 # gcc 2.6.3 / Young libdes 3.21 set_key per sec = 149369.74 ( 6.7uS) DES ecb bytes per sec = 2011976.68 ( 4.0uS) DES cbc bytes per sec = 2002245.35 ( 4.0uS) DES ede cbc bytes per sec = 793677.19 ( 10.1uS) crypt per sec = 9244.52 (108.2uS) # Sun Ultra I gcc 2.7.2 / Young libdes 3.21 set_key per sec = 147172.22 ( 6.8uS) DES ecb bytes per sec = 1815054.70 ( 4.4uS) DES cbc bytes per sec = 1829405.18 ( 4.4uS) DES ede cbc bytes per sec = 714490.23 ( 11.2uS) crypt per sec = 8896.24 (112.4uS) SGI Challenge (MIPS R4400 200mhz) - gcc -O2 set_key per sec = 114141.13 ( 8.8uS) DES ecb bytes per sec = 1573472.84 ( 5.1uS) DES cbc bytes per sec = 1580418.20 ( 5.1uS) crypt per sec = 7137.84 (140.1uS) DEC Alpha DEC 4000/710 AXP OSF/1 v 3.0 - gcc -O2 2.6.1 set_key per sec = 123138.49 ( 8.1uS) DES ecb bytes per sec = 1407546.76 ( 5.7uS) DES cbc bytes per sec = 1404103.21 ( 5.7uS) crypt per sec = 7746.76 (129.1uS) DEC Alpha DEC 4000/710 AXP OSF/1 v 3.0 - cc -O4 'DEC Compiler Driver 3.11' set_key per sec = 135160.83 ( 7.4uS) DES ecb bytes per sec = 1267753.22 ( 6.3uS) DES cbc bytes per sec = 1260564.90 ( 6.3uS) crypt per sec = 6479.37 (154.3uS) SGI Challenge (MIPS R4400 200mhz) - cc -O2 set_key per sec = 124000.10 ( 8.1uS) DES ecb bytes per sec = 1338138.45 ( 6.0uS) DES cbc bytes per sec = 1356515.84 ( 5.9uS) crypt per sec = 6223.92 (160.7uS) Intel P5/133 (NEXTSTEP) - cc -O3 (cc: gcc 2.5.8) set_key per sec = 81923.10 ( 12.2uS) DES ecb bytes per sec = 1104711.61 ( 7.2uS) DES cbc bytes per sec = 1091536.05 ( 7.3uS) DES ede cbc bytes per sec = 410502.62 ( 19.5uS) crypt per sec = 4849.60 (206.2uS) Sun SPARC 20 (NEXTSTEP) - cc -O3 (cc: gcc 2.5.8) set_key per sec = 60973.05 ( 16.4uS) DES ecb bytes per sec = 806032.15 ( 9.9uS) DES cbc bytes per sec = 801534.95 ( 10.0uS) DES ede cbc bytes per sec = 298799.73 ( 26.8uS) crypt per sec = 3678.42 (271.9uS) SGI Indy (MIPS R4600 133mhz) -cc -O2 set_key per sec = 88470.54 ( 11.3uS) DES ecb bytes per sec = 1023040.33 ( 7.8uS) DES cbc bytes per sec = 1033610.01 ( 7.7uS) crypt per sec = 4641.51 (215.4uS) HP-UX 9000/887 cc +O3 set_key per sec = 76824.30 ( 13.0uS) DES ecb bytes per sec = 1048911.20 ( 7.6uS) DES cbc bytes per sec = 1072332.80 ( 7.5uS) crypt per sec = 4968.64 (201.3uS) IRIX 5.2 IP22 (R4000) cc -O2 (galilo) set_key per sec = 60615.73 ( 16.5uS) DES ecb bytes per sec = 584741.32 ( 13.7uS) DES cbc bytes per sec = 584306.94 ( 13.7uS) crypt per sec = 3049.33 (327.9uS) HP-UX 9000/867 cc -O set_key per sec = 48600.00 ( 20.6uS) DES ecb bytes per sec = 616235.14 ( 13.0uS) DES cbc bytes per sec = 638669.44 ( 12.5uS) crypt per sec = 3016.68 (331.5uS) HP-UX 9000/867 gcc -O2 set_key per sec = 52120.50 ( 19.2uS) DES ecb bytes per sec = 715156.55 ( 11.2uS) DES cbc bytes per sec = 724424.28 ( 11.0uS) crypt per sec = 3295.87 (303.4uS) DGUX AViiON mc88110 gcc -O2 set_key per sec = 55604.91 ( 18.0uS) DES ecb bytes per sec = 658513.25 ( 12.1uS) DES cbc bytes per sec = 675552.71 ( 11.8uS) crypt per sec = 3438.10 (290.9uS) Sparc 10 cc -O2 (orb) set_key per sec = 53002.30 ( 18.9uS) DES ecb bytes per sec = 705250.40 ( 11.3uS) DES cbc bytes per sec = 714342.40 ( 11.2uS) crypt per sec = 2943.99 (339.7uS) Sparc 10 gcc -O2 (orb) set_key per sec = 58681.21 ( 17.0uS) DES ecb bytes per sec = 772390.20 ( 10.4uS) DES cbc bytes per sec = 774144.00 ( 10.3uS) crypt per sec = 3606.90 (277.2uS) DEC Alpha DEC 4000/610 AXP OSF/1 v 1.3 - gcc v 2.3.3 set_key per sec = 101840.19 ( 9.8uS) DES ecb bytes per sec = 1223712.35 ( 6.5uS) DES cbc bytes per sec = 1230542.98 ( 6.5uS) crypt per sec = 6428.75 (155.6uS) DEC Alpha DEC 4000/610 APX OSF/1 v 1.3 - cc -O2 - OSF/1 AXP set_key per sec = 114198.91 ( 8.8uS) DES ecb bytes per sec = 1022710.93 ( 7.8uS) DES cbc bytes per sec = 1008821.93 ( 7.9uS) crypt per sec = 5454.13 (183.3uS) DEC Alpha - DEC 3000/500 AXP OSF/1 - cc -O2 - 02/12/92 set_key per sec = 83587.04 ( 12.0uS) DES ecb bytes per sec = 822620.82 ( 9.7uS) DES cbc bytes per sec = 832929.60 ( 9.6uS) crypt per sec = 4807.62 (208.0uS) sun sparc 10/30 - gcc -O2 set_key per sec = 42005.24 ( 23.8uS) DES ecb bytes per sec = 555949.47 ( 14.4uS) DES cbc bytes per sec = 549440.28 ( 14.6uS) crypt per sec = 2580.25 (387.6uS) PA-RISC 1.1 HP 710 set_key per sec = 38916.86 DES ecb bytes per sec = 505971.82 DES cbc bytes per sec = 515381.13 crypt per sec = 2438.24 iris (spike) cc -O2 set_key per sec = 23128.83 ( 43.2uS) DES ecb bytes per sec = 261577.94 ( 30.6uS) DES cbc bytes per sec = 261746.41 ( 30.6uS) crypt per sec = 1231.76 (811.8uS) sun sparc 10/30 - cc -O4 set_key per sec = 38379.86 ( 26.1uS) DES ecb bytes per sec = 460051.34 ( 17.4uS) DES cbc bytes per sec = 464970.54 ( 17.2uS) crypt per sec = 2092.64 (477.9uS) sun sparc 2 - gcc2 -O2 set_key per sec = 21559.10 DES ecb bytes per sec = 305566.92 DES cbc bytes per sec = 303497.50 crypt per sec = 1410.48 RS/6000 model 320 set_key per sec = 14371.93 DES ecb bytes per sec = 222231.26 DES cbc bytes per sec = 223926.79 crypt per sec = 981.20 80486dx/66MHz Solaris 2.1 - gcc -O2 (gcc 2.6.3) set_key per sec = 26814.15 ( 37.3uS) DES ecb bytes per sec = 345029.95 ( 23.2uS) DES cbc bytes per sec = 344064.00 ( 23.3uS) crypt per sec = 1551.97 (644.3uS) 80486dx/50MHz Solaris 2.1 - gcc -O2 (gcc 2.5.2) set_key per sec = 18558.29 ( 53.9uS) DES ecb bytes per sec = 240873.90 ( 33.2uS) DES cbc bytes per sec = 239993.37 ( 33.3uS) crypt per sec = 1073.67 (931.4uS) 80486dx/50MHz Solaris 2.1 - cc -xO4 (cc: PC2.0.1 30 April 1993) set_key per sec = 18302.79 ( 54.6uS) DES ecb bytes per sec = 242640.29 ( 33.0uS) DES cbc bytes per sec = 239568.89 ( 33.4uS) crypt per sec = 1057.92 (945.2uS) 68030 HP400 set_key per sec = 5251.28 DES ecb bytes per sec = 56186.56 DES cbc bytes per sec = 58681.53 crypt per sec = 276.15 80486sx/33MHz MSDOS Turbo C v 2.0 set_key per sec = 1883.22 (531.0uS) DES ecb bytes per sec = 63393.31 (126.2uS) DES cbc bytes per sec = 63416.83 (126.1uS) crypt per sec = 158.71 (6300.6uS) 80486sx/33MHz MSDOS djgpp gcc 1.39 (32bit compiler) set_key per sec = 12603.08 (79.3) DES ecb bytes per sec = 158875.15 (50.4) DES cbc bytes per sec = 159893.85 (50.0) crypt per sec = 780.24 (1281.7) Version 1.99 26/08/92 8MHz 68000 Atari-ST gcc 2.1 -O2 MiNT 0.94 set_key per sec = 325.68 (3070.5uS) DES ecb bytes per sec = 4173.67 (1916.8uS) DES cbc bytes per sec = 4249.89 (1882.4uS) crypt per sec = 20.19 (49521.6uS) 8088/4.77mh MSDOS Turbo C v 2.0 set_key per sec = 35.09 DES ecb bytes per sec = 563.63 crypt per sec = 2.69 \ No newline at end of file diff --git a/mac/libdes/src/typemap b/mac/libdes/src/typemap deleted file mode 100755 index 1b4d07b1..00000000 --- a/mac/libdes/src/typemap +++ /dev/null @@ -1 +0,0 @@ -# # DES SECTION # deschar * T_DESCHARP des_cblock * T_CBLOCK des_cblock T_CBLOCK des_key_schedule T_SCHEDULE des_key_schedule * T_SCHEDULE INPUT T_CBLOCK $var=(des_cblock *)SvPV($arg,len); if (len < DES_KEY_SZ) { croak(\"$var needs to be at least %u bytes long\",DES_KEY_SZ); } T_SCHEDULE $var=(des_key_schedule *)SvPV($arg,len); if (len < DES_SCHEDULE_SZ) { croak(\"$var needs to be at least %u bytes long\", DES_SCHEDULE_SZ); } OUTPUT T_CBLOCK sv_setpvn($arg,(char *)$var,DES_KEY_SZ); T_SCHEDULE sv_setpvn($arg,(char *)$var,DES_SCHEDULE_SZ); T_DESCHARP sv_setpvn($arg,(char *)$var,len); \ No newline at end of file diff --git a/mac/libdes/src/version.h b/mac/libdes/src/version.h deleted file mode 100755 index 4674d833..00000000 --- a/mac/libdes/src/version.h +++ /dev/null @@ -1 +0,0 @@ -/* lib/des/version.h */ /* Copyright (C) 1995 Eric Young (eay@mincom.oz.au) * All rights reserved. * * This file is part of an SSL implementation written * by Eric Young (eay@mincom.oz.au). * The implementation was written so as to conform with Netscapes SSL * specification. This library and applications are * FREE FOR COMMERCIAL AND NON-COMMERCIAL USE * as long as the following conditions are aheared to. * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. If this code is used in a product, * Eric Young should be given attribution as the author of the parts used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Eric Young (eay@mincom.oz.au) * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ extern char *DES_version; \ No newline at end of file diff --git a/mac/libdes/src/vms.com b/mac/libdes/src/vms.com deleted file mode 100755 index 885ea8e3..00000000 --- a/mac/libdes/src/vms.com +++ /dev/null @@ -1,90 +0,0 @@ -$! --- VMS.com --- -$! -$ GoSub defines -$ GoSub linker_options -$ If (P1 .nes. "") -$ Then -$ GoSub 'P1' -$ Else -$ GoSub lib -$ GoSub destest -$ GoSub rpw -$ GoSub speed -$ GoSub des -$ EndIF -$! -$ Exit -$! -$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -$! -$DEFINES: -$ OPT_FILE := "VAX_LINKER_OPTIONS.OPT" -$! -$ CC_OPTS := "/NODebug/OPTimize/NOWarn" -$! -$ LINK_OPTS := "/NODebug/NOTraceback/Contiguous" -$! -$ OBJS = "cbc_cksm.obj,cbc_enc.obj,ecb_enc.obj,pcbc_enc.obj," + - - "qud_cksm.obj,rand_key.obj,read_pwd.obj,set_key.obj," + - - "str2key.obj,enc_read.obj,enc_writ.obj,fcrypt.obj," + - - "cfb_enc.obj,3ecb_enc.obj,ofb_enc.obj" - - -$! -$ LIBDES = "cbc_cksm.c,cbc_enc.c,ecb_enc.c,enc_read.c," + - - "enc_writ.c,pcbc_enc.c,qud_cksm.c,rand_key.c," + - - "read_pwd.c,set_key.c,str2key.c,fcrypt.c," + - - "cfb_enc.c,3ecb_enc.c,ofb_enc.c" -$ Return -$! -$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -$! -$LINKER_OPTIONS: -$ If (f$search(OPT_FILE) .eqs. "") -$ Then -$ Create 'OPT_FILE' -$DECK -! Default system options file to link against the sharable C runtime library -! -Sys$Share:VAXcRTL.exe/Share -$EOD -$ EndIF -$ Return -$! -$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -$! -$LIB: -$ CC 'CC_OPTS' 'LIBDES' -$ If (f$search("LIBDES.OLB") .nes. "") -$ Then Library /Object /Replace libdes 'OBJS' -$ Else Library /Create /Object libdes 'OBJS' -$ EndIF -$ Return -$! -$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -$! -$DESTEST: -$ CC 'CC_OPTS' destest -$ Link 'link_opts' /Exec=destest destest.obj,libdes/LIBRARY,'opt_file'/Option -$ Return -$! -$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -$! -$RPW: -$ CC 'CC_OPTS' rpw -$ Link 'link_opts' /Exec=rpw rpw.obj,libdes/LIBRARY,'opt_file'/Option -$ Return -$! -$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -$! -$SPEED: -$ CC 'CC_OPTS' speed -$ Link 'link_opts' /Exec=speed speed.obj,libdes/LIBRARY,'opt_file'/Option -$ Return -$! -$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -$! -$DES: -$ CC 'CC_OPTS' des -$ Link 'link_opts' /Exec=des des.obj,libdes/LIBRARY,'opt_file'/Option -$ Return diff --git a/mac/libdes/src/xcbc_enc.c b/mac/libdes/src/xcbc_enc.c deleted file mode 100755 index 62645b9a..00000000 --- a/mac/libdes/src/xcbc_enc.c +++ /dev/null @@ -1 +0,0 @@ -/* crypto/des/xcbc_enc.c */ /* Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@mincom.oz.au). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@mincom.oz.au). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@mincom.oz.au)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@mincom.oz.au)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ #include "des_locl.h" /* RSA's DESX */ static unsigned char desx_white_in2out[256]={ 0xBD,0x56,0xEA,0xF2,0xA2,0xF1,0xAC,0x2A,0xB0,0x93,0xD1,0x9C,0x1B,0x33,0xFD,0xD0, 0x30,0x04,0xB6,0xDC,0x7D,0xDF,0x32,0x4B,0xF7,0xCB,0x45,0x9B,0x31,0xBB,0x21,0x5A, 0x41,0x9F,0xE1,0xD9,0x4A,0x4D,0x9E,0xDA,0xA0,0x68,0x2C,0xC3,0x27,0x5F,0x80,0x36, 0x3E,0xEE,0xFB,0x95,0x1A,0xFE,0xCE,0xA8,0x34,0xA9,0x13,0xF0,0xA6,0x3F,0xD8,0x0C, 0x78,0x24,0xAF,0x23,0x52,0xC1,0x67,0x17,0xF5,0x66,0x90,0xE7,0xE8,0x07,0xB8,0x60, 0x48,0xE6,0x1E,0x53,0xF3,0x92,0xA4,0x72,0x8C,0x08,0x15,0x6E,0x86,0x00,0x84,0xFA, 0xF4,0x7F,0x8A,0x42,0x19,0xF6,0xDB,0xCD,0x14,0x8D,0x50,0x12,0xBA,0x3C,0x06,0x4E, 0xEC,0xB3,0x35,0x11,0xA1,0x88,0x8E,0x2B,0x94,0x99,0xB7,0x71,0x74,0xD3,0xE4,0xBF, 0x3A,0xDE,0x96,0x0E,0xBC,0x0A,0xED,0x77,0xFC,0x37,0x6B,0x03,0x79,0x89,0x62,0xC6, 0xD7,0xC0,0xD2,0x7C,0x6A,0x8B,0x22,0xA3,0x5B,0x05,0x5D,0x02,0x75,0xD5,0x61,0xE3, 0x18,0x8F,0x55,0x51,0xAD,0x1F,0x0B,0x5E,0x85,0xE5,0xC2,0x57,0x63,0xCA,0x3D,0x6C, 0xB4,0xC5,0xCC,0x70,0xB2,0x91,0x59,0x0D,0x47,0x20,0xC8,0x4F,0x58,0xE0,0x01,0xE2, 0x16,0x38,0xC4,0x6F,0x3B,0x0F,0x65,0x46,0xBE,0x7E,0x2D,0x7B,0x82,0xF9,0x40,0xB5, 0x1D,0x73,0xF8,0xEB,0x26,0xC7,0x87,0x97,0x25,0x54,0xB1,0x28,0xAA,0x98,0x9D,0xA5, 0x64,0x6D,0x7A,0xD4,0x10,0x81,0x44,0xEF,0x49,0xD6,0xAE,0x2E,0xDD,0x76,0x5C,0x2F, 0xA7,0x1C,0xC9,0x09,0x69,0x9A,0x83,0xCF,0x29,0x39,0xB9,0xE9,0x4C,0xFF,0x43,0xAB, }; void des_xwhite_in2out(des_key,in_white,out_white) des_cblock (*des_key); des_cblock (*in_white); des_cblock (*out_white); { unsigned char *key,*in,*out; int out0,out1; int i; key=(unsigned char *)des_key; in=(unsigned char *)in_white; out=(unsigned char *)out_white; out[0]=out[1]=out[2]=out[3]=out[4]=out[5]=out[6]=out[7]=0; out0=out1=0; for (i=0; i<8; i++) { out[i]=key[i]^desx_white_in2out[out0^out1]; out0=out1; out1=(int)out[i&0x07]; } out0=out[0]; out1=out[i]; for (i=0; i<8; i++) { out[i]=in[i]^desx_white_in2out[out0^out1]; out0=out1; out1=(int)out[i&0x07]; } } void des_xcbc_encrypt(input, output, length, schedule, ivec, inw,outw,encrypt) des_cblock (*input); des_cblock (*output); long length; des_key_schedule schedule; des_cblock (*ivec); des_cblock (*inw); des_cblock (*outw); int encrypt; { register DES_LONG tin0,tin1; register DES_LONG tout0,tout1,xor0,xor1; register DES_LONG inW0,inW1,outW0,outW1; register unsigned char *in,*out; register long l=length; DES_LONG tin[2]; unsigned char *iv; in=(unsigned char *)inw; c2l(in,inW0); c2l(in,inW1); in=(unsigned char *)outw; c2l(in,outW0); c2l(in,outW1); in=(unsigned char *)input; out=(unsigned char *)output; iv=(unsigned char *)ivec; if (encrypt) { c2l(iv,tout0); c2l(iv,tout1); for (l-=8; l>=0; l-=8) { c2l(in,tin0); c2l(in,tin1); tin0^=tout0^inW0; tin[0]=tin0; tin1^=tout1^inW1; tin[1]=tin1; des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); tout0=tin[0]^outW0; l2c(tout0,out); tout1=tin[1]^outW1; l2c(tout1,out); } if (l != -8) { c2ln(in,tin0,tin1,l+8); tin0^=tout0^inW0; tin[0]=tin0; tin1^=tout1^inW1; tin[1]=tin1; des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); tout0=tin[0]^outW0; l2c(tout0,out); tout1=tin[1]^outW1; l2c(tout1,out); } iv=(unsigned char *)ivec; l2c(tout0,iv); l2c(tout1,iv); } else { c2l(iv,xor0); c2l(iv,xor1); for (l-=8; l>0; l-=8) { c2l(in,tin0); tin[0]=tin0^outW0; c2l(in,tin1); tin[1]=tin1^outW1; des_encrypt((DES_LONG *)tin,schedule,DES_DECRYPT); tout0=tin[0]^xor0^inW0; tout1=tin[1]^xor1^inW1; l2c(tout0,out); l2c(tout1,out); xor0=tin0; xor1=tin1; } if (l != -8) { c2l(in,tin0); tin[0]=tin0^outW0; c2l(in,tin1); tin[1]=tin1^outW1; des_encrypt((DES_LONG *)tin,schedule,DES_DECRYPT); tout0=tin[0]^xor0^inW0; tout1=tin[1]^xor1^inW1; l2cn(tout0,tout1,out,l+8); xor0=tin0; xor1=tin1; } iv=(unsigned char *)ivec; l2c(xor0,iv); l2c(xor1,iv); } tin0=tin1=tout0=tout1=xor0=xor1=0; inW0=inW1=outW0=outW1=0; tin[0]=tin[1]=0; } \ No newline at end of file From a5a26f140e7ca719ab81aedf7e7239bff4487ac2 Mon Sep 17 00:00:00 2001 From: Bastian Germann Date: Wed, 19 Jul 2023 22:30:36 +0200 Subject: [PATCH 721/796] otp: Include crypto-compat Including the module gets rid of a version differentiation in the OTP implementation. Signed-off-by: Bastian Germann --- plugins/otp.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/plugins/otp.c b/plugins/otp.c index e3850bad..197c993c 100644 --- a/plugins/otp.c +++ b/plugins/otp.c @@ -56,6 +56,9 @@ #include #include /* XXX hack for OpenBSD/OpenSSL cruftiness */ +/* for legacy libcrypto support */ +#include "crypto-compat.h" + #include #include @@ -97,22 +100,14 @@ static EVP_MD_CTX *_plug_EVP_MD_CTX_new(const sasl_utils_t *utils) { utils->log(NULL, SASL_LOG_DEBUG, "_plug_EVP_MD_CTX_new()"); -#if OPENSSL_VERSION_NUMBER >= 0x10100000L return EVP_MD_CTX_new(); -#else - return utils->malloc(sizeof(EVP_MD_CTX)); -#endif } static void _plug_EVP_MD_CTX_free(EVP_MD_CTX *ctx, const sasl_utils_t *utils) { utils->log(NULL, SASL_LOG_DEBUG, "_plug_EVP_MD_CTX_free()"); -#if OPENSSL_VERSION_NUMBER >= 0x10100000L EVP_MD_CTX_free(ctx); -#else - utils->free(ctx); -#endif } /* Convert the binary data into ASCII hex */ From 794b9a701438d836861e95f65bf79f5bf9460556 Mon Sep 17 00:00:00 2001 From: stf <7o5rfu92t@ctrlc.hu> Date: Wed, 18 Jan 2023 19:51:42 +0100 Subject: [PATCH 722/796] opaque mechanism from https://github.com/stef/libopaque/tree/master/sasl Signed-off-by: stf <7o5rfu92t@ctrlc.hu> --- configure.ac | 48 + plugins/Makefile.am | 17 +- plugins/crypto_kdf_hkdf_sha512.h | 49 + plugins/kdf_hkdf_sha512.c | 96 ++ plugins/makeinit.sh | 2 +- plugins/opaque.c | 769 +++++++++++++ plugins/opaque.h | 333 ++++++ plugins/opaque_impl.c | 1757 ++++++++++++++++++++++++++++++ 8 files changed, 3067 insertions(+), 4 deletions(-) create mode 100644 plugins/crypto_kdf_hkdf_sha512.h create mode 100644 plugins/kdf_hkdf_sha512.c create mode 100644 plugins/opaque.c create mode 100644 plugins/opaque.h create mode 100644 plugins/opaque_impl.c diff --git a/configure.ac b/configure.ac index 8c18aa99..e6603b10 100644 --- a/configure.ac +++ b/configure.ac @@ -697,6 +697,54 @@ else AC_MSG_RESULT(disabled) fi +dnl OPAQUE +AC_CHECK_LIB(libopaque, opaque_CreateCredentialRequest, [AC_SUBST([LIB_OPAQUE], ["-lopaque"]) AC_DEFINE([HAVE_LIBOPAQUE], [1],[opaque library])],have_libopaque="no",-lopaque) + +AC_ARG_ENABLE(opaque, [ --enable-opaque enable OPAQUE authentication [[yes]] ], + opaque=$enableval, + opaque=yes) + +if test "$have_libopaque" = no; then + AC_CHECK_LIB(sodium, crypto_core_ristretto255_scalar_invert, [AC_SUBST([LIB_SODIUM], ["-lsodium"]) AC_DEFINE([HAVE_LIBSODIUM], [1],[sodium library])],have_sodium="no",-lsodium) + AC_CHECK_LIB(sodium, crypto_kdf_hkdf_sha512_expand,need_internal_hkdf="no",need_internal_hkdf="yes",-lsodium) + + if test "$have_sodium" = no; then + AC_MSG_WARN(neither libopaque nor libsodium found -- OPAQUE will be disabled) + opaque=no + else + opaque=internal + fi +else + opaque=yes +fi + +AC_MSG_CHECKING(OPAQUE) +if test "$opaque" != no; then + AM_CONDITIONAL(OPAQUE_INTERNAL,test "$opaque" = internal) + AM_CONDITIONAL(INTERNAL_HKDF,test "$need_internal_hkdf" = yes) + if test "$opaque" = internal; then + AC_MSG_RESULT(internal) + OPAQUE_LIBS="-lsodium" + if test "$enable_static" = yes; then + SASL_STATIC_SRCS="$SASL_STATIC_SRCS \$(top_srcdir)/plugins/opaque.c \$(top_srcdir)/plugins/opaque_impl.c" + SASL_STATIC_OBJS="$SASL_STATIC_OBJS opaque.o opaque_impl.o kdf_hkdf_sha512." + AC_DEFINE(STATIC_OPAQUE, [], [Link OPAQUE Statically]) + fi + else + AC_MSG_RESULT(enabled) + OPAQUE_LIBS="-lopaque" + + if test "$enable_static" = yes; then + SASL_STATIC_SRCS="$SASL_STATIC_SRCS \$(top_srcdir)/plugins/opaque.c" + SASL_STATIC_OBJS="$SASL_STATIC_OBJS opaque.o kdf_hkdf_sha512.o" + AC_DEFINE(STATIC_OPAQUE, [], [Link OPAQUE Statically]) + fi + fi + SASL_MECHS="$SASL_MECHS libopaque.la" + AC_SUBST(OPAQUE_LIBS) +else + AC_MSG_RESULT(disabled) +fi AC_MSG_CHECKING(to include LDAP support) AC_ARG_WITH(ldap, [ --with-ldap=DIR use LDAP (in DIR) for saslauthd [no] ], diff --git a/plugins/Makefile.am b/plugins/Makefile.am index 95b825b3..5dfdb5b0 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -63,12 +63,20 @@ noinst_SCRIPTS = makeinit.sh LIB_MYSQL = @LIB_MYSQL@ +if OPAQUE_INTERNAL +OPAQUE_INTERNAL_IMPL_SRC = opaque_impl.c +if INTERNAL_HKDF +OPAQUE_INTERNAL_IMPL_SRC += kdf_hkdf_sha512.c +endif +endif + plugindir = @plugindir@ plugin_LTLIBRARIES = @SASL_MECHS@ EXTRA_LTLIBRARIES = libplain.la libanonymous.la libkerberos4.la libcrammd5.la \ libgs2.la libgssapiv2.la libdigestmd5.la liblogin.la libsrp.la libotp.la \ - libscram.la libntlm.la libpassdss.la libsasldb.la libsql.la libldapdb.la + libscram.la libntlm.la libpassdss.la libsasldb.la libsql.la libldapdb.la \ + libopaque.la libplain_la_SOURCES = plain.c plain_init.c libplain_la_DEPENDENCIES = $(COMPAT_OBJS) $(PLUGIN_COMMON_OBJS) @@ -110,6 +118,10 @@ libsrp_la_SOURCES = srp.c srp_init.c libsrp_la_DEPENDENCIES = $(COMPAT_OBJS) $(PLUGIN_COMMON_OBJS) $(CRYPTO_COMPAT_OBJS) libsrp_la_LIBADD = $(SRP_LIBS) $(LIB_SOCKET) $(COMPAT_OBJS) $(PLUGIN_COMMON_OBJS) $(CRYPTO_COMPAT_OBJS) +libopaque_la_SOURCES = opaque.c opaque_init.c $(OPAQUE_INTERNAL_IMPL_SRC) +libopaque_la_DEPENDENCIES = $(COMPAT_OBJS) $(PLUGIN_COMMON_OBJS) $(CRYPTO_COMPAT_OBJS) +libopaque_la_LIBADD = $(OPAQUE_LIBS) $(LIB_SOCKET) $(COMPAT_OBJS) $(PLUGIN_COMMON_OBJS) $(CRYPTO_COMPAT_OBJS) + libotp_la_SOURCES = otp.c otp_init.c otp.h libotp_la_DEPENDENCIES = $(COMPAT_OBJS) $(PLUGIN_COMMON_OBJS) libotp_la_LIBADD = $(OTP_LIBS) $(LIB_SOCKET) $(COMPAT_OBJS) $(PLUGIN_COMMON_OBJS) @@ -137,11 +149,10 @@ libsql_la_LDFLAGS = $(LIB_MYSQL) $(LIB_PGSQL) $(LIB_SQLITE) $(LIB_SQLITE3) \ libsql_la_DEPENDENCIES = $(COMPAT_OBJS) $(PLUGIN_COMMON_OBJS) libsql_la_LIBADD = $(COMPAT_OBJS) $(PLUGIN_COMMON_OBJS) - # Instructions for making the _init files init_src=anonymous_init.c crammd5_init.c digestmd5_init.c scram_init.c gs2_init.c gssapiv2_init.c \ -kerberos4_init.c login_init.c plain_init.c srp_init.c otp_init.c ntlm_init.c \ +kerberos4_init.c login_init.c plain_init.c srp_init.c opaque_init.c otp_init.c ntlm_init.c \ passdss_init.c sasldb_init.c sql_init.c ldapdb_init.c diff --git a/plugins/crypto_kdf_hkdf_sha512.h b/plugins/crypto_kdf_hkdf_sha512.h new file mode 100644 index 00000000..a2379dc3 --- /dev/null +++ b/plugins/crypto_kdf_hkdf_sha512.h @@ -0,0 +1,49 @@ +#ifndef crypto_kdf_hkdf_sha512_H +#define crypto_kdf_hkdf_sha512_H + +#include +#include +#include + +#include + +#ifdef __cplusplus +# ifdef __GNUC__ +# pragma GCC diagnostic ignored "-Wlong-long" +# endif +extern "C" { +#endif + +#define crypto_kdf_hkdf_sha512_KEYBYTES crypto_auth_hmacsha512_BYTES +SODIUM_EXPORT +size_t crypto_kdf_hkdf_sha512_keybytes(void); + +#define crypto_kdf_hkdf_sha512_BYTES_MIN 0U +SODIUM_EXPORT +size_t crypto_kdf_hkdf_sha512_bytes_min(void); + +#define crypto_kdf_hkdf_sha512_BYTES_MAX (0xff * crypto_auth_hmacsha512_BYTES) +SODIUM_EXPORT +size_t crypto_kdf_hkdf_sha512_bytes_max(void); + +SODIUM_EXPORT +int crypto_kdf_hkdf_sha512_extract(unsigned char prk[crypto_kdf_hkdf_sha512_KEYBYTES], + const unsigned char *salt, size_t salt_len, + const unsigned char *ikm, size_t ikm_len) + __attribute__ ((nonnull(1))); + +SODIUM_EXPORT +void crypto_kdf_hkdf_sha512_keygen(unsigned char prk[crypto_kdf_hkdf_sha512_KEYBYTES]) + __attribute__ ((nonnull)); + +SODIUM_EXPORT +int crypto_kdf_hkdf_sha512_expand(unsigned char *out, size_t out_len, + const char *ctx, size_t ctx_len, + const unsigned char prk[crypto_kdf_hkdf_sha512_KEYBYTES]) + __attribute__ ((nonnull(1))); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/plugins/kdf_hkdf_sha512.c b/plugins/kdf_hkdf_sha512.c new file mode 100644 index 00000000..f201db97 --- /dev/null +++ b/plugins/kdf_hkdf_sha512.c @@ -0,0 +1,96 @@ +#include +#include + +#include "sodium/crypto_auth_hmacsha512.h" +#include "sodium/crypto_kdf.h" +#include "crypto_kdf_hkdf_sha512.h" +#include "sodium/randombytes.h" +#include "sodium/utils.h" + +int +crypto_kdf_hkdf_sha512_extract( + unsigned char prk[crypto_kdf_hkdf_sha512_KEYBYTES], + const unsigned char *salt, size_t salt_len, const unsigned char *ikm, + size_t ikm_len) +{ + crypto_auth_hmacsha512_state st; + + crypto_auth_hmacsha512_init(&st, salt, salt_len); + crypto_auth_hmacsha512_update(&st, ikm, ikm_len); + crypto_auth_hmacsha512_final(&st, prk); + sodium_memzero(&st, sizeof st); + + return 0; +} + +void +crypto_kdf_hkdf_sha512_keygen(unsigned char prk[crypto_kdf_hkdf_sha512_KEYBYTES]) +{ + randombytes_buf(prk, crypto_kdf_hkdf_sha512_KEYBYTES); +} + +int +crypto_kdf_hkdf_sha512_expand(unsigned char *out, size_t out_len, + const char *ctx, size_t ctx_len, + const unsigned char prk[crypto_kdf_hkdf_sha512_KEYBYTES]) +{ + crypto_auth_hmacsha512_state st; + unsigned char tmp[crypto_auth_hmacsha512_BYTES]; + size_t i; + size_t left; + unsigned char counter = 1U; + + if (out_len > crypto_kdf_hkdf_sha512_BYTES_MAX) { + errno = EINVAL; + return -1; + } + for (i = (size_t) 0U; i + crypto_auth_hmacsha512_BYTES <= out_len; + i += crypto_auth_hmacsha512_BYTES) { + crypto_auth_hmacsha512_init(&st, prk, crypto_kdf_hkdf_sha512_KEYBYTES); + if (i != (size_t) 0U) { + crypto_auth_hmacsha512_update(&st, + &out[i - crypto_auth_hmacsha512_BYTES], + crypto_auth_hmacsha512_BYTES); + } + crypto_auth_hmacsha512_update(&st, + (const unsigned char *) ctx, ctx_len); + crypto_auth_hmacsha512_update(&st, &counter, (size_t) 1U); + crypto_auth_hmacsha512_final(&st, &out[i]); + counter++; + } + if ((left = out_len & (crypto_auth_hmacsha512_BYTES - 1U)) != (size_t) 0U) { + crypto_auth_hmacsha512_init(&st, prk, crypto_kdf_hkdf_sha512_KEYBYTES); + if (i != (size_t) 0U) { + crypto_auth_hmacsha512_update(&st, + &out[i - crypto_auth_hmacsha512_BYTES], + crypto_auth_hmacsha512_BYTES); + } + crypto_auth_hmacsha512_update(&st, + (const unsigned char *) ctx, ctx_len); + crypto_auth_hmacsha512_update(&st, &counter, (size_t) 1U); + crypto_auth_hmacsha512_final(&st, tmp); + memcpy(&out[i], tmp, left); + sodium_memzero(tmp, sizeof tmp); + } + sodium_memzero(&st, sizeof st); + + return 0; +} + +size_t +crypto_kdf_hkdf_sha512_keybytes(void) +{ + return crypto_kdf_hkdf_sha512_KEYBYTES; +} + +size_t +crypto_kdf_hkdf_sha512_bytes_min(void) +{ + return crypto_kdf_hkdf_sha512_BYTES_MIN; +} + +size_t +crypto_kdf_hkdf_sha512_bytes_max(void) +{ + return crypto_kdf_hkdf_sha512_BYTES_MAX; +} diff --git a/plugins/makeinit.sh b/plugins/makeinit.sh index 3131877a..cd076d7e 100644 --- a/plugins/makeinit.sh +++ b/plugins/makeinit.sh @@ -1,6 +1,6 @@ plugin_init="$1" # mechanism plugins -for mech in anonymous crammd5 digestmd5 scram gssapiv2 kerberos4 login ntlm otp passdss plain srp gs2; do +for mech in anonymous crammd5 digestmd5 scram gssapiv2 kerberos4 login ntlm otp passdss plain srp opaque gs2; do if [ ${plugin_init} = "${mech}_init.c" ];then echo " diff --git a/plugins/opaque.c b/plugins/opaque.c new file mode 100644 index 00000000..c7c6bfb5 --- /dev/null +++ b/plugins/opaque.c @@ -0,0 +1,769 @@ +#include +#include +#include "plugin_common.h" + +static const uint8_t OPAQUE_CONTEXT[]="SASL OPAQUE Mechanism"; +static const size_t OPAQUE_CONTEXT_BYTES=sizeof OPAQUE_CONTEXT - 1; + +static int get_idu_ids(const char** ids, unsigned short *idu_len, const char* user_realm, const char *serverFQDN, const char *input) { + const char *ptr; + // search for @ separating user from realm + for(ptr = input;*ptr && ptr >= input;ptr++) { + if(*ptr != '@') continue; + if(*(ptr+1)==0) break; // '@\0' + // found @ and it is not followed by a \0 + if(ptr-1-input > 65535) { + return !SASL_OK; // username too big + } + if(ids) { + *ids = ptr+1; + } + *idu_len=ptr-input; + return SASL_OK; + } + + if(ptr 65535) { + return !SASL_OK; // username too big + } + + *idu_len=ptr-input; + + if(ids) { + if(user_realm && *user_realm) { + *ids = user_realm; + } else { + *ids = serverFQDN; + } + if(*ids==NULL || strlen(*ids)>65535) { + return !SASL_OK; + } + } + return SASL_OK; +} + +/* The main OPAQUE context */ +typedef struct context { + int state; + + char *authid; /* authentication id (server) */ + char *userid; /* authorization id (server) */ + + uint8_t *client_sec; + uint8_t *sk; + uint8_t *authU; + + /* copy of utils from the params structures */ + const sasl_utils_t *utils; + + /* per-step mem management */ + char *out_buf; + unsigned out_buf_len; +} context_t; + +static int opaque_server_mech_new(void *glob_context __attribute__((unused)), + sasl_server_params_t *params, + const char *challenge __attribute__((unused)), + unsigned challen __attribute__((unused)), + void **conn_context) { + context_t *ctx; + + /* holds state are in */ + ctx = params->utils->malloc(sizeof(context_t)); + if (ctx == NULL) { + (params->utils)->seterror( (params->utils)->conn, 0, "Out of Memory in " __FILE__ " near line %d", __LINE__ ); + return SASL_NOMEM; + } + + memset(ctx, 0, sizeof(context_t)); + + ctx->state = 1; + ctx->utils = params->utils; + + *conn_context = ctx; + + return SASL_OK; +} + +/* + * Dispose of a OPAQUE context (could be server or client) + */ +static void opaque_common_mech_dispose(void *conn_context, const sasl_utils_t *utils) { + context_t *ctx = (context_t *) conn_context; + + if (!ctx) return; + + if (ctx->authid) utils->free(ctx->authid); + if (ctx->userid) utils->free(ctx->userid); + if (ctx->client_sec) utils->free(ctx->client_sec); + if (ctx->sk) utils->free(ctx->sk); + if (ctx->authU) utils->free(ctx->authU); + + utils->free(ctx); +} + +static int opaque_setpass(void *glob_context __attribute__((unused)), + sasl_server_params_t *sparams, + const char *userstr, + const char *pass, + unsigned passlen, + const char *oldpass __attribute__((unused)), + unsigned oldpasslen __attribute__((unused)), + unsigned flags) { + int r; + uint16_t idU_len; + const char *realm = NULL; + sasl_secret_t *sec = NULL; + struct propctx *propctx = NULL; + const char *store_request[] = { "cmusaslsecretOPAQUE", NULL }; + + /* Do we have a backend that can store properties? */ + if (!sparams->utils->auxprop_store || + sparams->utils->auxprop_store(NULL, NULL, NULL) != SASL_OK) { + (sparams->utils)->seterror( (sparams->utils)->conn, 0, "OPAQUE: auxprop backend can't store properties"); + return SASL_NOMECH; + } + + r = get_idu_ids(&realm, &idU_len, sparams->user_realm, sparams->serverFQDN, userstr); + if (r) { + sparams->utils->seterror(sparams->utils->conn, 0, "Error parsing user"); + return r; + } + char user[idU_len+1]; + memcpy(user,userstr,idU_len); + user[idU_len]=0; + + if ((flags & SASL_SET_DISABLE) || pass == NULL) { + sec = NULL; + } else { + uint8_t rec[OPAQUE_USER_RECORD_LEN]; + const Opaque_Ids ids={idU_len,(uint8_t*)userstr,strlen(realm),(uint8_t*)realm}; + //fprintf(stderr,"idU: \"%s\"(%d), idS: \"%s\"(%d)\n", ids.idU, ids.idU_len, ids.idS, ids.idS_len); + + r = opaque_Register((uint8_t*)pass, passlen, NULL, &ids, rec, NULL); + if(r) { + sparams->utils->seterror(sparams->utils->conn, 0, "Error registering with opaque"); + goto end; + } + /* Put 'rec' into sasl_secret_t. + * This will be base64 encoded, so make sure its big enough. + */ + const unsigned long alloclen = (sizeof(rec)/3 + 1) * 4 + 1; + sec = sparams->utils->malloc(sizeof(sasl_secret_t)+alloclen); + if (!sec) { + r = SASL_NOMEM; + goto end; + } + sec->len = 0; // clear len, as we are downcasting from unsigned long to unsigned int ↓ + sparams->utils->encode64((char*)rec, sizeof(rec), (char *) sec->data, alloclen, (unsigned*) &sec->len); + + /* Clean everything up */ + end: + + if (r) return r; + } + + /* do the store */ + propctx = sparams->utils->prop_new(0); + if (!propctx) + r = SASL_FAIL; + if (!r) + r = sparams->utils->prop_request(propctx, store_request); + if (!r) + r = sparams->utils->prop_set(propctx, "cmusaslsecretOPAQUE", + (char *) (sec ? sec->data : NULL), + (sec ? sec->len : 0)); + if (!r) + r = sparams->utils->auxprop_store(sparams->utils->conn, propctx, user); + if (propctx) + sparams->utils->prop_dispose(&propctx); + + if (r) { + sparams->utils->seterror(sparams->utils->conn, 0, + "Error putting OPAQUE secret"); + goto cleanup; + } + + sparams->utils->log(NULL, SASL_LOG_DEBUG, "Setpass for OPAQUE successful\n"); + +cleanup: + + if (sec) sparams->utils->free(sec); + return r; +} + +static int opaque_mech_avail(void *glob_context __attribute__((unused)), + sasl_server_params_t *sparams __attribute__((unused)), + void **conn_context __attribute__((unused))) { + return SASL_OK; +} + + +static int opaque_server_mech_step1(context_t *ctx, + sasl_server_params_t *params, + const char *clientin, + unsigned clientinlen, + const char **serverout, + unsigned *serveroutlen, + sasl_out_params_t *oparams) { + int result; + char *realm = NULL; + char *authid = NULL; + char *user = NULL; + const char *password_request[] = { "*cmusaslsecretOPAQUE", SASL_AUX_PASSWORD, NULL }; + struct propval auxprop_values[3]; + + //fprintf(stderr, "opaque server step 1\n"); + if(clientinlen < OPAQUE_USER_SESSION_PUBLIC_LEN+2) { + SETERROR(params->utils, "Invalid client input in OPAQUE step 1"); + //fprintf(stderr, "bad inputsize: %d\n", clientinlen); + return SASL_BADPARAM; + } + + /* Expect: + * Credential Request + * authentication identity \0 + * authorization identity \0 + */ + + authid = (char*) clientin + OPAQUE_USER_SESSION_PUBLIC_LEN; + size_t authid_len, user_len; + authid_len = strlen(authid); + if(authid_len > 65535) { + SETERROR(params->utils, "Authid too big in OPAQUE step 1"); + return SASL_BADPARAM; + } + + user = authid+authid_len+1; + user_len = strlen(user); + if(user_len > 65535) { + SETERROR(params->utils, "User too big in OPAQUE step 1"); + return SASL_BADPARAM; + } + if(user_len+authid_len+OPAQUE_USER_SESSION_PUBLIC_LEN+2 != clientinlen) { + SETERROR(params->utils, "Params sizes do not add up to input size in OPAQUE step 1"); + return SASL_BADPARAM; + } + + //fprintf(stderr,"user(%ld): \"%s\"\n", user_len, user); + //fprintf(stderr,"authid(%ld): \"%s\"\n", authid_len, authid); + + /* Get the realm */ + result = _plug_parseuser(params->utils, &user, &realm, params->user_realm, params->serverFQDN, authid); + if (result) { + SETERROR(params->utils, "Error getting realm"); + goto cleanup; + } + + /* Get user secret */ + result = params->utils->prop_request(params->propctx, password_request); + if (result != SASL_OK) goto cleanup; + + /* this will trigger the getting of the aux properties */ + result = params->canon_user(params->utils->conn, authid, 0, SASL_CU_AUTHID, oparams); + if (result != SASL_OK) goto cleanup; + + result = params->canon_user(params->utils->conn, user, 0, SASL_CU_AUTHZID, oparams); + if (result != SASL_OK) goto cleanup; + + result = params->utils->prop_getnames(params->propctx, password_request, auxprop_values); + if (result < 0 || ((!auxprop_values[0].name || !auxprop_values[0].values))) { + /* We didn't find this username */ + SETERROR(params->utils, "no record in database"); + result = params->transition ? SASL_TRANS : SASL_NOUSER; + goto cleanup; + } + + //if(auxprop_values[0].name) { + // fprintf(stderr, "ap_v[0] name: %s size %d\n", auxprop_values[0].name, auxprop_values[0].valsize); + //} + + + uint8_t rec[OPAQUE_USER_RECORD_LEN+1]; // +1 because for some + // utterly braindead reason + // decode64 actually puts a + // terminating 0 at the end + // of the decoded buffer. + unsigned outlen; + + result = params->utils->decode64(auxprop_values[0].values[0], auxprop_values[0].valsize, + (char*)rec, sizeof(rec), + &outlen); + if(result) { + goto cleanup; + } + + if(outlen!=OPAQUE_USER_RECORD_LEN) { + SETERROR(params->utils, "Invalid OPAQUE record size\n"); + goto cleanup; + } + + //fprintf(stderr,"user(%ld): \"%s\"\n", strlen(user), user); + //fprintf(stderr,"realm(%ld): \"%s\"\n", strlen(realm), realm); + const unsigned short realm_len = strlen(realm); + const Opaque_Ids ids={strlen(user),(uint8_t*)user,realm_len,(uint8_t*)realm}; + //fprintf(stderr,"idU: \"%s\"(%d), idS: \"%s\"(%d)\n", ids.idU, ids.idU_len, ids.idS, ids.idS_len); + + ctx->out_buf = params->utils->malloc(OPAQUE_SERVER_SESSION_LEN+realm_len+1); + if (ctx->out_buf == NULL) { + MEMERROR(params->utils); + result = SASL_NOMEM; + goto cleanup; + } + ctx->out_buf_len=OPAQUE_SERVER_SESSION_LEN+realm_len+1; + memcpy(ctx->out_buf + OPAQUE_SERVER_SESSION_LEN, realm, realm_len+1); + + ctx->sk = params->utils->malloc(OPAQUE_SHARED_SECRETBYTES); + if (ctx->sk == NULL) { + MEMERROR(params->utils); + result = SASL_NOMEM; + goto cleanup; + } + + ctx->authU = params->utils->malloc(crypto_auth_hmacsha512_BYTES); + if (ctx->authU == NULL) { + MEMERROR(params->utils); + result = SASL_NOMEM; + goto cleanup; + } + + if(0!=opaque_CreateCredentialResponse((uint8_t*)clientin, rec, &ids, + OPAQUE_CONTEXT, OPAQUE_CONTEXT_BYTES, + (uint8_t*)ctx->out_buf, ctx->sk, ctx->authU)) { + SETERROR(params->utils,"opaque_CreateCredentialResponse failed.\n"); + goto cleanup; + } + + *serverout = ctx->out_buf; + *serveroutlen = ctx->out_buf_len; + + ctx->state = 2; + result = SASL_CONTINUE; + + cleanup: + if (realm) params->utils->free(realm); + + return result; +} + +static int opaque_server_mech_step2(context_t *ctx, + sasl_server_params_t *params, + const char *clientin, + unsigned clientinlen, + const char **serverout __attribute__((unused)), + unsigned *serveroutlen __attribute__((unused)), + sasl_out_params_t *oparams) { + if(clientinlen!=crypto_auth_hmacsha512_BYTES) { + SETERROR(params->utils, "Invalid client input in OPAQUE step 2"); + //fprintf(stderr, "bad inputsize: %d\n", clientinlen); + return SASL_BADPARAM; + } + + if(-1==opaque_UserAuth(ctx->authU, (const uint8_t*)clientin)) { + return SASL_BADAUTH; + } + + /* set oparams */ + oparams->doneflag = 1; + + return SASL_OK; +} + +static int opaque_server_mech_step(void *conn_context, + sasl_server_params_t *sparams, + const char *clientin, + unsigned clientinlen, + const char **serverout, + unsigned *serveroutlen, + sasl_out_params_t *oparams) { + context_t *ctx = (context_t *) conn_context; + + if (!sparams + || !serverout + || !serveroutlen + || !oparams) + return SASL_BADPARAM; + + *serverout = NULL; + *serveroutlen = 0; + + if (ctx == NULL) { + return SASL_BADPROT; + } + + sparams->utils->log(NULL, SASL_LOG_DEBUG, "OPAQUE server step %d\n", ctx->state); + + switch (ctx->state) { + + case 1: + return opaque_server_mech_step1(ctx, sparams, clientin, clientinlen, serverout, serveroutlen, oparams); + + case 2: + return opaque_server_mech_step2(ctx, sparams, clientin, clientinlen, serverout, serveroutlen, oparams); + + default: + sparams->utils->seterror(sparams->utils->conn, 0, "Invalid OPAQUE server step %d", ctx->state); + return SASL_FAIL; + } + + return SASL_FAIL; /* should never get here */ +} + + +static sasl_server_plug_t opaque_server_plugins[] = { + { + "OPAQUE", /* mech_name */ + 0, /* max_ssf */ + SASL_SEC_NOPLAINTEXT + | SASL_SEC_NOACTIVE + | SASL_SEC_NODICTIONARY + | SASL_SEC_FORWARD_SECRECY + | SASL_SEC_NOANONYMOUS + | SASL_SEC_MUTUAL_AUTH, /* security_flags */ + SASL_FEAT_WANT_CLIENT_FIRST + | SASL_FEAT_ALLOWS_PROXY, /* features */ + NULL, /* glob_context */ + &opaque_server_mech_new, /* mech_new */ + &opaque_server_mech_step, /* mech_step */ + &opaque_common_mech_dispose, /* mech_dispose */ + NULL, /* mech_free */ + &opaque_setpass, /* setpass */ + NULL, /* user_query */ + NULL, /* idle */ + &opaque_mech_avail, /* mech avail */ + NULL /* spare */ + } +}; + +int opaque_server_plug_init(const sasl_utils_t *utils, + int maxversion, + int *out_version, + const sasl_server_plug_t **pluglist, + int *plugcount, + const char *plugname __attribute__((unused))) { + if (maxversion < SASL_SERVER_PLUG_VERSION) { + utils->seterror(utils->conn, 0, "OPAQUE version mismatch"); + return SASL_BADVERS; + } + + *out_version = SASL_SERVER_PLUG_VERSION; + *pluglist = opaque_server_plugins; + *plugcount = 1; + + return SASL_OK; +} + + + +/////////////////////////// client stuff /////////////////////////// + +static int opaque_client_mech_new(void *glob_context __attribute__((unused)), + sasl_client_params_t *params, + void **conn_context) { + context_t *ctx; + + /* holds state are in */ + ctx = params->utils->malloc(sizeof(context_t)); + if (ctx == NULL) { + (params->utils)->seterror( (params->utils)->conn, 0, "Out of Memory in " __FILE__ " near line %d", __LINE__ ); + return SASL_NOMEM; + } + + memset(ctx, 0, sizeof(context_t)); + + ctx->state = 1; + ctx->utils = params->utils; + + *conn_context = ctx; + + return SASL_OK; +} + +static int opaque_client_mech_step1(context_t *ctx, + sasl_client_params_t *params, + const char *serverin __attribute__((unused)), + unsigned serverinlen, + sasl_interact_t **prompt_need, + const char **clientout, + unsigned *clientoutlen, + sasl_out_params_t *oparams) { + + const char *authid = NULL, *userid = NULL; + sasl_secret_t *password = NULL; + unsigned int free_password = 0; /* set if we need to free password */ + int auth_result = SASL_OK; + int pass_result = SASL_OK; + int user_result = SASL_OK; + int result; + + if (serverinlen > 0) { + params->utils->seterror(params->utils->conn, 0, "Invalid input to OPAQUE client 1st step\n"); + return SASL_BADPROT; + } + + /* try to get the authid */ + if (oparams->authid==NULL) { + auth_result = _plug_get_authid(params->utils, &authid, prompt_need); + + if ((auth_result != SASL_OK) && (auth_result != SASL_INTERACT)) + return auth_result; + } + + /* try to get the userid */ + if (oparams->user == NULL) { + user_result = _plug_get_userid(params->utils, &userid, prompt_need); + + if ((user_result != SASL_OK) && (user_result != SASL_INTERACT)) + return user_result; + } + + /* try to get the password */ + if (password == NULL) { + pass_result=_plug_get_password(params->utils, &password, + &free_password, prompt_need); + + if ((pass_result != SASL_OK) && (pass_result != SASL_INTERACT)) + return pass_result; + } + + /* free prompts we got */ + if (prompt_need && *prompt_need) { + params->utils->free(*prompt_need); + *prompt_need = NULL; + } + + /* if there are prompts not filled in */ + if ((auth_result == SASL_INTERACT) || (user_result == SASL_INTERACT) || + (pass_result == SASL_INTERACT)) { + /* make the prompt list */ + result = + _plug_make_prompts(params->utils, prompt_need, + user_result == SASL_INTERACT ? + "Please enter your authorization name" : NULL, + NULL, + auth_result == SASL_INTERACT ? + "Please enter your authentication name" : NULL, + NULL, + pass_result == SASL_INTERACT ? + "Please enter your password" : NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL); + if (result != SASL_OK) return result; + + return SASL_INTERACT; + } + + if (!password) { + PARAMERROR(params->utils); + return SASL_BADPARAM; + } + //fprintf(stderr, "got password(%ld): %s\n",password->len, password->data); + + if (!userid || !*userid) { + result = params->canon_user(params->utils->conn, authid, 0, SASL_CU_AUTHID | SASL_CU_AUTHZID, oparams); + } + else { + result = params->canon_user(params->utils->conn, authid, 0, SASL_CU_AUTHID, oparams); + if (result != SASL_OK) return result; + + result = params->canon_user(params->utils->conn, userid, 0, SASL_CU_AUTHZID, oparams); + } + if (result != SASL_OK) return result; + + //fprintf(stderr, "userid: \"%s\"\n", oparams->user); + //fprintf(stderr, "authid: \"%s\"\n", oparams->authid); + /* Send out: + * + * U - authentication identity + * I - authorization identity + * + * { utf8(U) utf8(I) utf8(sid) os(cn) } + */ + + ctx->client_sec = params->utils->malloc(OPAQUE_USER_SESSION_SECRET_LEN+password->len); + if (ctx->client_sec == NULL) { + MEMERROR(params->utils); + return SASL_NOMEM; + } + + *clientoutlen = (OPAQUE_USER_SESSION_PUBLIC_LEN + + strlen(oparams->authid) + 1 + + strlen(oparams->user) + 1); + + ctx->out_buf = params->utils->malloc(*clientoutlen); + if (ctx->out_buf == NULL) { + MEMERROR(params->utils); + clientoutlen=0; + return SASL_NOMEM; + } + ctx->out_buf_len=*clientoutlen; + + opaque_CreateCredentialRequest(password->data, password->len, ctx->client_sec, (uint8_t*)ctx->out_buf); + char *ptr = ctx->out_buf + OPAQUE_USER_SESSION_PUBLIC_LEN; + memcpy(ptr, oparams->authid, strlen(oparams->authid)); + ptr+=strlen(oparams->authid); + ptr++[0]=0; + memcpy(ptr, oparams->user, strlen(oparams->user)); + ptr+=strlen(oparams->user); + ptr[0]=0; + + *clientout = ctx->out_buf; + + ctx->state = 2; + + result = SASL_CONTINUE; + +//cleanup: + + return result; +} + +static int opaque_client_mech_step2(context_t *ctx, + sasl_client_params_t *params, + const char *serverin, + unsigned serverinlen, + sasl_interact_t **prompt_need __attribute__((unused)), + const char **clientout, + unsigned *clientoutlen, + sasl_out_params_t *oparams) { + int result; + if(serverinlenutils,"Server Response has incorrect size\n"); + return SASL_BADPARAM; + } + if(!ctx->client_sec) { + SETERROR(params->utils,"Missing secret OPAQUE client context\n"); + return SASL_FAIL; + } + + const char* realm = serverin + OPAQUE_SERVER_SESSION_LEN; + size_t realm_len=strlen(realm); + if(realm_len > 65535) { + SETERROR(params->utils, "Realm too big in OPAQUE step 2"); + return SASL_BADPARAM; + } + + result = _plug_buf_alloc(params->utils, + &ctx->out_buf, &ctx->out_buf_len, + crypto_auth_hmacsha512_BYTES); + if(result) { + MEMERROR(params->utils); + return SASL_NOMEM; + } + + uint16_t idU_len; + result = get_idu_ids(NULL, &idU_len, NULL, NULL, oparams->user); + if (result) { + params->utils->seterror(params->utils->conn, 0, "Error parsing user"); + return SASL_BADPARAM; + } + + const Opaque_Ids ids={idU_len,(uint8_t*)oparams->user,realm_len,(uint8_t*)realm}; + //fprintf(stderr,"idU: \"%s\"(%d), idS: \"%s\"(%d)\n", ids.idU, ids.idU_len, ids.idS, ids.idS_len); + + ctx->sk = params->utils->malloc(OPAQUE_SHARED_SECRETBYTES); + if (ctx->sk == NULL) { + MEMERROR(params->utils); + result = SASL_NOMEM; + goto cleanup; + } + + result = opaque_RecoverCredentials((uint8_t*) serverin, ctx->client_sec, + OPAQUE_CONTEXT, OPAQUE_CONTEXT_BYTES, &ids, + ctx->sk, (uint8_t*)ctx->out_buf, NULL); + if(result) { + SETERROR(params->utils, "Failed to recover OPAQUE credentials\n"); + result = SASL_BADAUTH; + goto cleanup; + } + + *clientout = ctx->out_buf; + *clientoutlen = crypto_auth_hmacsha512_BYTES; + + ctx->state = 3; + + result = SASL_CONTINUE; + +cleanup: + + return result; +} + +static int opaque_client_mech_step(void *conn_context, + sasl_client_params_t *params, + const char *serverin, + unsigned serverinlen, + sasl_interact_t **prompt_need, + const char **clientout, + unsigned *clientoutlen, + sasl_out_params_t *oparams) { + context_t *ctx = (context_t *) conn_context; + + params->utils->log(NULL, SASL_LOG_DEBUG, + "OPAQUE client step %d\n", ctx->state); + + *clientout = NULL; + *clientoutlen = 0; + + switch (ctx->state) { + + case 1: + return opaque_client_mech_step1(ctx, params, serverin, serverinlen, prompt_need, clientout, clientoutlen, oparams); + + case 2: + return opaque_client_mech_step2(ctx, params, serverin, serverinlen, prompt_need, clientout, clientoutlen, oparams); + + default: + params->utils->log(NULL, SASL_LOG_ERR, "Invalid OPAQUE client step %d\n", ctx->state); + return SASL_FAIL; + } + + return SASL_FAIL; /* should never get here */ +} + + +static sasl_client_plug_t opaque_client_plugins[] = +{ + { + "OPAQUE", /* mech_name */ + 0, /* max_ssf */ + SASL_SEC_NOPLAINTEXT + | SASL_SEC_NOANONYMOUS + | SASL_SEC_NOACTIVE + | SASL_SEC_NODICTIONARY + | SASL_SEC_FORWARD_SECRECY + | SASL_SEC_MUTUAL_AUTH, /* security_flags */ + SASL_FEAT_WANT_CLIENT_FIRST + | SASL_FEAT_ALLOWS_PROXY, /* features */ + NULL, /* required_prompts */ + NULL, /* glob_context */ + &opaque_client_mech_new, /* mech_new */ + &opaque_client_mech_step, /* mech_step */ + &opaque_common_mech_dispose, /* mech_dispose */ + NULL, /* mech_free */ + NULL, /* idle */ + NULL, /* spare */ + NULL /* spare */ + } +}; + +int opaque_client_plug_init(const sasl_utils_t *utils __attribute__((unused)), + int maxversion, + int *out_version, + const sasl_client_plug_t **pluglist, + int *plugcount, + const char *plugname __attribute__((unused))) { + if (maxversion < SASL_CLIENT_PLUG_VERSION) { + utils->seterror(utils->conn, 0, "OPAQUE version mismatch"); + return SASL_BADVERS; + } + + *out_version = SASL_CLIENT_PLUG_VERSION; + *pluglist = opaque_client_plugins; + *plugcount=1; + + return SASL_OK; +} diff --git a/plugins/opaque.h b/plugins/opaque.h new file mode 100644 index 00000000..4a53d649 --- /dev/null +++ b/plugins/opaque.h @@ -0,0 +1,333 @@ +/** + * @file opaque.h + */ + +#ifndef opaque_h +#define opaque_h +#ifdef __cplusplus +extern "C" { +#endif +#include +#include +#include + +/** + * sk is a shared secret. In opaque.h, we do not report its byte size in functions + * like opaque_CreateCredentialResponse. We centralize its size here so that if + * the algorithm to calculate sk changes, we can just change it in one place. + */ +#define OPAQUE_SHARED_SECRETBYTES 64 +#define OPAQUE_ENVELOPE_NONCEBYTES 32 +#define OPAQUE_NONCE_BYTES 32 + +#define OPAQUE_REGISTRATION_RECORD_LEN ( \ + /* client_public_key */ crypto_scalarmult_BYTES+ \ + /* masking_key */ crypto_hash_sha512_BYTES+ \ + /* envelope nonce */ OPAQUE_ENVELOPE_NONCEBYTES+ \ + /* envelope mac */ crypto_auth_hmacsha512_BYTES) + +#define OPAQUE_USER_RECORD_LEN ( \ + /* kU */ crypto_core_ristretto255_SCALARBYTES+ \ + /* skS */ crypto_scalarmult_SCALARBYTES+ \ + OPAQUE_REGISTRATION_RECORD_LEN) + +#define OPAQUE_USER_SESSION_PUBLIC_LEN ( \ + /* blinded */ crypto_core_ristretto255_BYTES+ \ + /* X_u */ crypto_scalarmult_BYTES+ \ + /* nonceU */ OPAQUE_NONCE_BYTES) + +#define OPAQUE_USER_SESSION_SECRET_LEN ( \ + /* r */ crypto_core_ristretto255_SCALARBYTES+ \ + /* x_u */ crypto_scalarmult_SCALARBYTES+ \ + /* nonceU */ OPAQUE_NONCE_BYTES+ \ + /* blinded */ crypto_core_ristretto255_BYTES+ \ + /* ke1 */ OPAQUE_USER_SESSION_PUBLIC_LEN+ \ + /* pwdU_len */ sizeof(uint16_t)) + +#define OPAQUE_SERVER_SESSION_LEN ( \ + /* Z */ crypto_core_ristretto255_BYTES+ \ + /* masking_nonce */ 32+ \ + /* server_public_key */ crypto_scalarmult_BYTES+ \ + /* nonceS */ OPAQUE_NONCE_BYTES+ \ + /* X_s */ crypto_scalarmult_BYTES+ \ + /* auth */ crypto_auth_hmacsha512_BYTES+ \ + /* envelope nonce */ OPAQUE_ENVELOPE_NONCEBYTES+ \ + /* envelope mac */ crypto_auth_hmacsha512_BYTES) + +#define OPAQUE_REGISTER_USER_SEC_LEN ( \ + /* r */ crypto_core_ristretto255_SCALARBYTES+ \ + /* pwdU_len */ sizeof(uint16_t)) + +#define OPAQUE_REGISTER_PUBLIC_LEN ( \ + /* Z */ crypto_core_ristretto255_BYTES+ \ + /* pkS */ crypto_scalarmult_BYTES) + +#define OPAQUE_REGISTER_SECRET_LEN ( \ + /* skS */ crypto_scalarmult_SCALARBYTES+ \ + /* kU */ crypto_core_ristretto255_SCALARBYTES) + +/** + struct to store the IDs of the user/server. + + If the ids are the default, then set these values to NULL/0. The + defaults are always the long-term public keys of the respective + party. If your system needs different user ids, like for example + the server DNS host name or the users email addres, then provide + them via this struct. If only one is "custom" and the other is + default, that is also ok. + */ +typedef struct { + uint16_t idU_len; /**< length of idU, most useful if idU is binary */ + uint8_t *idU; /**< pointer to the id of the user/client in the opaque protocol */ + uint16_t idS_len; /**< length of idS, needed for binary ids */ + uint8_t *idS; /**< pointer to the id of the server in the opaque protocol */ +} Opaque_Ids; + +/** + This function implements the storePwdFile function from the paper + it is not specified by the RFC. This function runs on the server + and creates a new output record rec of secret key material. The + server needs to implement the storage of this record and any + binding to user names or as the paper suggests sid. + + @param [in] pwdU - the users password + @param [in] pwdU_len - length of the users password + @param [in] skS - in case of global server keys this is the servers + private key, should be set to NULL if per/user keys are to be + generated + @param [in] ids - the ids of the user and server, see Opaque_Ids + @param [out] rec - the opaque record the server needs to + store. this is a pointer to memory allocated by the caller, + and must be large enough to hold the record and take into + account the variable length of idU and idS in case these are + included in the envelope. + @param [out] export_key - optional pointer to pre-allocated (and + protected) memory for an extra_key that can be used to + encrypt/authenticate additional data. + @return the function returns 0 if everything is correct + */ +int opaque_Register(const uint8_t *pwdU, const uint16_t pwdU_len, + const uint8_t skS[crypto_scalarmult_SCALARBYTES], + const Opaque_Ids *ids, + uint8_t rec[OPAQUE_USER_RECORD_LEN], + uint8_t export_key[crypto_hash_sha512_BYTES]); + +/** + This function initiates a new OPAQUE session, is the same as the + function defined in the paper with the name usrSession. + + @param [in] pwdU - users input password + @param [in] pwdU_len - length of the users password + @param [out] sec - private context, it is essential that the memory + allocate for this buffer be **OPAQUE_USER_SESSION_SECRET_LEN+pwdU_len**. + The User should protect the sec value (e.g. with sodium_mlock()) + until opaque_RecoverCredentials. + @param [out] pub - the message to be sent to the server + @return the function returns 0 if everything is correct + */ +int opaque_CreateCredentialRequest(const uint8_t *pwdU, const uint16_t pwdU_len, +#ifdef __cplusplus + uint8_t *sec/*[OPAQUE_USER_SESSION_SECRET_LEN+pwdU_len]*/, +#else + uint8_t sec[OPAQUE_USER_SESSION_SECRET_LEN+pwdU_len], +#endif + + uint8_t pub[OPAQUE_USER_SESSION_PUBLIC_LEN]); + +/** + This is the same function as defined in the paper with name + srvSession name. This function runs on the server and + receives the output pub from the user running opaque_CreateCredentialRequest(), + furthermore the server needs to load the user record created when + registering the user with opaque_Register() or + opaque_StoreUserRecord(). These input parameters are + transformed into a secret/shared session key sk and a response resp + to be sent back to the user. + @param [in] pub - the pub output of the opaque_CreateCredentialRequest() + @param [in] rec - the recorded created during "registration" and stored by the server + @param [in] ids - the id if the client and server + @param [in] ctx - a context of this instantiation of this protocol, e.g. "AppABCv12.34" + @param [in] ctx_len - a context of this instantiation of this protocol + @param [out] resp - servers response to be sent to the client where + it is used as input into opaque_RecoverCredentials() + @param [out] sk - the shared secret established between the user & server + @param [out] sec - the current context necessary for the explicit + authentication of the user in opaque_UserAuth(). This + param is optional if no explicit user auth is necessary it can be + set to NULL + @return the function returns 0 if everything is correct + */ +int opaque_CreateCredentialResponse(const uint8_t pub[OPAQUE_USER_SESSION_PUBLIC_LEN], + const uint8_t rec[OPAQUE_USER_RECORD_LEN], + const Opaque_Ids *ids, + const uint8_t *ctx, const uint16_t ctx_len, + uint8_t resp[OPAQUE_SERVER_SESSION_LEN], + uint8_t sk[OPAQUE_SHARED_SECRETBYTES], + uint8_t authU[crypto_auth_hmacsha512_BYTES]); + +/** + This is the same function as defined in the paper with the + usrSessionEnd name. It is run by the user and receives as input the + response from the previous server opaque_CreateCredentialResponse() + function as well as the sec value from running the + opaque_CreateCredentialRequest() function that initiated this + instantiation of this protocol, All these input parameters are + transformed into a shared/secret session key pk, which should be + the same as the one calculated by the + opaque_CreateCredentialResponse() function. + + @param [in] resp - the response sent from the server running opaque_CreateCredentialResponse() + @param [in] sec - the private sec output of the client initiating + this instantiation of this protocol using opaque_CreateCredentialRequest() + @param [in] ctx - a context of this instantiation of this protocol, e.g. "AppABCv12.34" + @param [in] ctx_len - a context of this instantiation of this protocol + @param [in] ids - The ids of the server/client in case they are not the default. + @param [out] sk - the shared secret established between the user & server + @param [out] authU - the authentication code to be sent to the + server in case explicit user authentication is required, optional + set to NULL if not needed + @param [out] export_key - key used to encrypt/authenticate extra + material not stored directly in the envelope + @return the function returns 0 if the protocol is executed correctly +*/ +int opaque_RecoverCredentials(const uint8_t resp[OPAQUE_SERVER_SESSION_LEN], + const uint8_t *sec/*[OPAQUE_USER_SESSION_SECRET_LEN+pwdU_len]*/, + const uint8_t *ctx, const uint16_t ctx_len, + const Opaque_Ids *ids, + uint8_t sk[OPAQUE_SHARED_SECRETBYTES], + uint8_t authU[crypto_auth_hmacsha512_BYTES], + uint8_t export_key[crypto_hash_sha512_BYTES]); + +/** + Explicit User Authentication. + + This is a function not explicitly specified in the original paper. In the + irtf cfrg draft authentication is done using a hmac of the session + transcript with different keys coming out of a hkdf after the key + exchange. + + @param [in] authU0 - the authU value returned by opaque_CreateCredentialResponse() + @param [in] authU is the authentication token sent by the user. + @return the function returns 0 if the hmac verifies correctly. + */ +int opaque_UserAuth(const uint8_t authU0[crypto_auth_hmacsha512_BYTES], + const uint8_t authU[crypto_auth_hmacsha512_BYTES]); + +/** + Alternative user initialization, user registration as specified by the RFC + */ + + +/** + Initial step to start registering a new user/client with the server. + The user inputs its password pwdU, and receives a secret context sec + and a blinded value blinded as output. sec should be protected until + step 3 of this registration protocol and the value blinded should be + passed to the server. + @param [in] pwdU - the users password + @param [in] pwdU_len - length of the users password + @param [out] sec - a secret context needed for the 3rd step in this + registration protocol - this needs to be protected and sanitized + after usage. + @param [out] request - the blinded hashed password as per the OPRF, + this needs to be sent to the server together with any other + important and implementation specific info such as user/client id, + envelope configuration etc. + @return the function returns 0 if everything is correct. + */ +int opaque_CreateRegistrationRequest(const uint8_t *pwdU, + const uint16_t pwdU_len, +#ifdef __cplusplus + uint8_t *sec/*[OPAQUE_REGISTER_USER_SEC_LEN+pwdU_len]*/, +#else + uint8_t sec[OPAQUE_REGISTER_USER_SEC_LEN+pwdU_len], +#endif + + uint8_t request[crypto_core_ristretto255_BYTES]); + +/** + 2nd step of registration: Server evaluates OPRF - Global Server Key Version + + This function is essentially the same as + opaque_CreateRegistrationResponse(), except this function does not + generate a per-user long-term key, but instead expects the servers + to supply a long-term pubkey as a parameter, this might be one + unique global key, or it might be a per-user key derived from a + server secret. + + This function is called CreateRegistrationResponse in the rfc. + The server receives blinded from the users invocation of its + opaque_CreateRegistrationRequest() function, it outputs a value sec + which needs to be protected until step 4 by the server. This + function also outputs a value pub which needs to be passed to the + user. + @param [in] request - the blinded password as per the OPRF. + @param [in] skS - the servers long-term private key, optional, set + to NULL if you want this implementation to generate a unique key + for this record. + @param [out] sec - the private key and the OPRF secret of the server. + @param [out] pub - the evaluated OPRF and pubkey of the server to + be passed to the client into opaque_FinalizeRequest() + @return the function returns 0 if everything is correct. + */ +int opaque_CreateRegistrationResponse(const uint8_t request[crypto_core_ristretto255_BYTES], + const uint8_t skS[crypto_scalarmult_SCALARBYTES], + uint8_t sec[OPAQUE_REGISTER_SECRET_LEN], + uint8_t pub[OPAQUE_REGISTER_PUBLIC_LEN]); + +/** + Client finalizes registration by concluding the OPRF, generating + its own keys and enveloping it all. + + This function is called FinalizeRequest in the rfc. This function + is run by the user, taking as input the context sec that was an + output of the user running opaque_CreateRegistrationRequest(), and the + output pub from the server of opaque_CreateRegistrationResponse(). + + @param [in] sec - output from opaque_CreateRegistrationRequest(), + should be sanitized after usage. + @param [in] pub - response from the server running + opaque_CreateRegistrationResponse() + @param [in] ids - if ids are not the default value + @param [out] reg_rec - the opaque registration record containing + the users data. + @param [out] export_key - key used to encrypt/authenticate extra + material not stored directly in the envelope. Optional, if not + needed set to NULL. + + @return the function returns 0 if everything is correct. + */ +int opaque_FinalizeRequest( + const uint8_t *sec/*[OPAQUE_REGISTER_USER_SEC_LEN+pwdU_len]*/, + + const uint8_t pub[OPAQUE_REGISTER_PUBLIC_LEN], + const Opaque_Ids *ids, + uint8_t reg_rec[OPAQUE_REGISTRATION_RECORD_LEN], + uint8_t export_key[crypto_hash_sha512_BYTES]); + +/** + Final Registration step - server adds own info to the record to be stored. + + The rfc does not explicitly specify this function. + The server combines the sec value from its run of its + opaque_CreateRegistrationResponse() function with the rec output of + the users opaque_FinalizeRequest() function, creating the + final record, which should be the same as the output of the 1-step + storePwdFile() init function of the paper. The server should save + this record in combination with a user id and/or sid value as + suggested in the paper. + + @param [in] sec - the private value of the server running + opaque_CreateRegistrationResponse() in step 2 of the registration + protocol + @param [in] reg_rec - the registration record from the client running + opaque_FinalizeRequest() + @param [out] rec - the final record to be stored by the server. + */ +void opaque_StoreUserRecord(const uint8_t sec[OPAQUE_REGISTER_SECRET_LEN], + const uint8_t recU[OPAQUE_REGISTRATION_RECORD_LEN], + uint8_t rec[OPAQUE_USER_RECORD_LEN]); +#ifdef __cplusplus +} +#endif +#endif // opaque_h diff --git a/plugins/opaque_impl.c b/plugins/opaque_impl.c new file mode 100644 index 00000000..0b2030df --- /dev/null +++ b/plugins/opaque_impl.c @@ -0,0 +1,1757 @@ +/* + @copyright 2018-21, opaque@ctrlc.hu + This file is part of libopaque. + + libopaque is free software: you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + libopaque 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 libopaque. If not, see . + + This file implements the Opaque protocol as specified by the IRTF CFRG +*/ + +#include "opaque.h" +#if _WIN32 == 1 || _WIN64 == 1 +#include +#else +#include +#endif +#ifdef CFRG_TEST_VEC +#include "tests/cfrg_test_vector_decl.h" +#endif + +#ifndef HAVE_SODIUM_HKDF +#include "crypto_kdf_hkdf_sha512.h" +#endif + +#define VOPRF "VOPRF10" + +#define OPAQUE_RWDU_BYTES 64 +#define OPAQUE_HANDSHAKE_SECRETBYTES 64 +#define OPAQUE_NONCE_BYTES 32 +#define OPAQUE_ENVELOPE_BYTES (OPAQUE_ENVELOPE_NONCEBYTES + crypto_auth_hmacsha512_BYTES) +#define OPAQUE_HMAC_SHA512_BYTES 64 +#define OPAQUE_HMAC_SHA512_KEYBYTES 64 + +typedef struct { + uint8_t nonce[OPAQUE_ENVELOPE_NONCEBYTES]; + uint8_t auth_tag[crypto_auth_hmacsha512_BYTES]; +} __attribute((packed)) Opaque_Envelope; + +typedef struct { + uint8_t client_public_key[crypto_scalarmult_BYTES]; + uint8_t masking_key[crypto_hash_sha512_BYTES]; + Opaque_Envelope envelope; +} __attribute((packed)) Opaque_RegistrationRecord; + + +// user specific record stored at server upon registration +typedef struct { + uint8_t kU[crypto_core_ristretto255_SCALARBYTES]; + uint8_t skS[crypto_scalarmult_SCALARBYTES]; + Opaque_RegistrationRecord recU; +} __attribute((packed)) Opaque_UserRecord; + +typedef struct { + uint8_t blinded[crypto_core_ristretto255_BYTES]; + uint8_t nonceU[OPAQUE_NONCE_BYTES]; + uint8_t X_u[crypto_scalarmult_BYTES]; +} __attribute((packed)) Opaque_UserSession; + +typedef struct { + uint8_t blind[crypto_core_ristretto255_SCALARBYTES]; + uint8_t x_u[crypto_scalarmult_SCALARBYTES]; + uint8_t nonceU[OPAQUE_NONCE_BYTES]; + uint8_t blinded[crypto_core_ristretto255_BYTES]; + uint8_t ke1[OPAQUE_USER_SESSION_PUBLIC_LEN]; + uint16_t pwdU_len; + uint8_t pwdU[]; +} __attribute((packed)) Opaque_UserSession_Secret; + +typedef struct { + uint8_t Z[crypto_core_ristretto255_BYTES]; + uint8_t masking_nonce[32]; + uint8_t masked_response[crypto_scalarmult_BYTES+sizeof(Opaque_Envelope)]; + uint8_t nonceS[OPAQUE_NONCE_BYTES]; + uint8_t X_s[crypto_scalarmult_BYTES]; + uint8_t auth[crypto_auth_hmacsha512_BYTES]; +} __attribute((packed)) Opaque_ServerSession; + +typedef struct { + uint8_t blind[crypto_core_ristretto255_SCALARBYTES]; + uint16_t pwdU_len; + uint8_t pwdU[]; +} Opaque_RegisterUserSec; + +typedef struct { + uint8_t Z[crypto_core_ristretto255_BYTES]; + uint8_t pkS[crypto_scalarmult_BYTES]; +} __attribute((packed)) Opaque_RegisterSrvPub; + +typedef struct { + uint8_t skS[crypto_scalarmult_SCALARBYTES]; + uint8_t kU[crypto_core_ristretto255_SCALARBYTES]; +} __attribute((packed)) Opaque_RegisterSrvSec; + +typedef struct { + uint8_t sk[OPAQUE_SHARED_SECRETBYTES]; + uint8_t km2[OPAQUE_HMAC_SHA512_KEYBYTES]; + uint8_t km3[OPAQUE_HMAC_SHA512_KEYBYTES]; +} __attribute((packed)) Opaque_Keys; + +// sodium defines an hmac with 32B as key, opaque as 64 +static void opaque_hmacsha512(const uint8_t key[OPAQUE_HMAC_SHA512_KEYBYTES], + const uint8_t *authenticated, const size_t auth_len, + uint8_t mac[OPAQUE_HMAC_SHA512_BYTES]) { + crypto_auth_hmacsha512_state st; + crypto_auth_hmacsha512_init(&st, key, OPAQUE_HMAC_SHA512_KEYBYTES); + crypto_auth_hmacsha512_update(&st, authenticated, auth_len); + crypto_auth_hmacsha512_final(&st, mac); + sodium_memzero(&st,sizeof st); +} + +/** + * This function generates an OPRF private key. + * + * This is the KeyGen OPRF function defined in the RFC: + * > OPAQUE only requires an OPRF private key. We write (kU, _) = KeyGen() to denote + * > use of this function for generating secret key kU (and discarding the + * > corresponding public key). + * + * @param [out] kU - the per-user OPRF private key + */ +static void oprf_KeyGen(uint8_t kU[crypto_core_ristretto255_SCALARBYTES]) { +#ifdef CFRG_TEST_VEC + memcpy(kU,oprf_key,oprf_key_len); +#else + crypto_core_ristretto255_scalar_random(kU); +#endif +} + +/** + * This function computes the OPRF output using input x, N, and domain separation + * tag info. + * + * This is the Finalize OPRF function defined in the RFC. + * + * @param [in] x - a value used to compute OPRF (for OPAQUE, this is pwdU, the + * user's password) + * @param [in] x_len - the length of param x in bytes + * @param [in] N - a serialized OPRF group element, a byte array of fixed length, + * an output of oprf_Unblind + * @param [in] info - a domain separation tag + * @param [in] info_len - the length of param info in bytes + * @param [out] y - an OPRF output + * @return The function returns 0 if everything is correct. + */ +static int oprf_Finalize(const uint8_t *x, const uint16_t x_len, + const uint8_t N[crypto_core_ristretto255_BYTES], + uint8_t rwdU[OPAQUE_RWDU_BYTES]) { + // according to paper: hash(pwd||H0^k) + // acccording to voprf IRTF CFRG specification: hash(htons(len(pwd))||pwd|| + // htons(len(H0_k))||H0_k||| + // htons(len("Finalize-"VOPRF"-\x00\x00\x01"))||"Finalize-"VOPRF"-\x00\x00\x01") + crypto_hash_sha512_state state; + if(-1==sodium_mlock(&state,sizeof state)) { + return -1; + } + crypto_hash_sha512_init(&state); + // pwd + uint16_t size=htons(x_len); + crypto_hash_sha512_update(&state, (uint8_t*) &size, 2); + crypto_hash_sha512_update(&state, x, x_len); +#if (defined TRACE || defined CFRG_TEST_VEC) + dump(x,x_len,"finalize input"); +#endif + // H0_k + size=htons(crypto_core_ristretto255_BYTES); + crypto_hash_sha512_update(&state, (uint8_t*) &size, 2); + crypto_hash_sha512_update(&state, N, crypto_core_ristretto255_BYTES); + //const uint8_t DST[]="Finalize-"VOPRF"-\x00\x00\x01"; + const uint8_t DST[]="Finalize"; + const uint8_t DST_size=sizeof DST -1; + //size=htons(DST_size); + //crypto_hash_sha512_update(&state, (uint8_t*) &size, 2); + crypto_hash_sha512_update(&state, DST, DST_size); + + // - concat(y, Harden(y, params)) + uint8_t concated[2*crypto_hash_sha512_BYTES]; + uint8_t *y=concated, *hardened=concated+crypto_hash_sha512_BYTES; + if(-1==sodium_mlock(&concated,sizeof concated)) { + sodium_munlock(&state, sizeof state); + return -1; + } + crypto_hash_sha512_final(&state, y); + sodium_munlock(&state, sizeof state); + +#if (defined TRACE || defined CFRG_TEST_VEC) + dump((uint8_t*) y, crypto_hash_sha512_BYTES, "output "); +#endif + +#ifdef CFRG_TEST_VEC + // testvectors use identity as MHF + memcpy(hardened, y, crypto_hash_sha512_BYTES); +#else + // salt - according to the irtf draft this could be all zeroes + uint8_t salt[crypto_pwhash_SALTBYTES]={0}; + if (crypto_pwhash(hardened, crypto_hash_sha512_BYTES, + (const char*) y, crypto_hash_sha512_BYTES, salt, + crypto_pwhash_OPSLIMIT_INTERACTIVE, + crypto_pwhash_MEMLIMIT_INTERACTIVE, + crypto_pwhash_ALG_DEFAULT) != 0) { + /* out of memory */ + sodium_munlock(concated, sizeof(concated)); + return -1; + } +#endif +#if (defined TRACE|| defined CFRG_TEST_VEC) + dump(concated, sizeof concated, "concated"); +#endif + crypto_kdf_hkdf_sha512_extract(rwdU, NULL, 0, concated, sizeof concated); + sodium_munlock(concated, sizeof(concated)); + +#if (defined TRACE|| defined CFRG_TEST_VEC) + dump((uint8_t*) rwdU, OPAQUE_RWDU_BYTES, "rwdU "); +#endif + + return 0; +} + +/* expand_loop + 10. b_i = H(strxor(b_0, b_(i - 1)) || I2OSP(i, 1) || DST_prime) + */ +static void expand_loop(const uint8_t *b_0, const uint8_t *b_i, const uint8_t i, const uint8_t *dst_prime, const uint8_t dst_prime_len, uint8_t *b_ii) { + uint8_t xored[crypto_hash_sha512_BYTES]; + unsigned j; + for(j=0;j 255 + * 3. DST_prime = DST || I2OSP(len(DST), 1) + * 4. Z_pad = I2OSP(0, r_in_bytes) + * 5. l_i_b_str = I2OSP(len_in_bytes, 2) + * 6. msg_prime = Z_pad || msg || l_i_b_str || I2OSP(0, 1) || DST_prime + * 7. b_0 = H(msg_prime) + * 8. b_1 = H(b_0 || I2OSP(1, 1) || DST_prime) + * 9. for i in (2, ..., ell): + * 10. b_i = H(strxor(b_0, b_(i - 1)) || I2OSP(i, 1) || DST_prime) + * 11. uniform_bytes = b_1 || ... || b_ell + * 12. return substr(uniform_bytes, 0, len_in_bytes) + */ +static int expand_message_xmd(const uint8_t *msg, const uint8_t msg_len, const uint8_t *dst, const uint8_t dst_len, const uint8_t len_in_bytes, uint8_t *uniform_bytes) { + // 1. ell = ceil(len_in_bytes / b_in_bytes) + const uint8_t ell = (len_in_bytes + crypto_hash_sha512_BYTES-1) / crypto_hash_sha512_BYTES; +#ifdef TRACE + fprintf(stderr, "ell %d\n", ell); + dump(msg, msg_len, "msg"); + dump(dst, dst_len, "dst"); +#endif + + // 2. ABORT if ell > 255 + if(ell>255) return -1; + // 3. DST_prime = DST || I2OSP(len(DST), 1) + uint8_t dst_prime[dst_len+1]; + memcpy(dst_prime, dst, dst_len); + dst_prime[dst_len] = dst_len; +#ifdef TRACE + dump(dst_prime, sizeof dst_prime, "dst_prime"); +#endif + // 4. Z_pad = I2OSP(0, r_in_bytes) + //const uint8_t r_in_bytes = 128; // for sha512 + uint8_t z_pad[128 /*r_in_bytes*/] = {0}; // supress gcc error: variable-sized object may not be initialized +#ifdef TRACE + dump(z_pad, sizeof z_pad, "z_pad"); +#endif + // 5. l_i_b_str = I2OSP(len_in_bytes, 2) + const uint16_t l_i_b = htons(len_in_bytes); + const uint8_t *l_i_b_str = (uint8_t*) &l_i_b; + // 6. msg_prime = Z_pad || msg || l_i_b_str || I2OSP(0, 1) || DST_prime + uint8_t msg_prime[sizeof z_pad + msg_len + sizeof l_i_b + 1 + sizeof dst_prime], + *ptr = msg_prime; + memcpy(ptr, z_pad, sizeof z_pad); + ptr += sizeof z_pad; + memcpy(ptr, msg, msg_len); + ptr += msg_len; + memcpy(ptr, l_i_b_str, sizeof l_i_b); + ptr += sizeof l_i_b; + *ptr = 0; + ptr++; + memcpy(ptr, dst_prime, sizeof dst_prime); +#ifdef TRACE + dump(msg_prime, sizeof msg_prime, "msg_prime"); +#endif + // 7. b_0 = H(msg_prime) + uint8_t b_0[crypto_hash_sha512_BYTES]; + crypto_hash_sha512(b_0, msg_prime, sizeof msg_prime); +#ifdef TRACE + dump(b_0, sizeof b_0, "b_0"); +#endif + // 8. b_1 = H(b_0 || I2OSP(1, 1) || DST_prime) + uint8_t b_i[crypto_hash_sha512_BYTES]; + crypto_hash_sha512_state state; + crypto_hash_sha512_init(&state); + crypto_hash_sha512_update(&state, b_0, sizeof b_0); + crypto_hash_sha512_update(&state,(uint8_t*) &"\x01", 1); + crypto_hash_sha512_update(&state, dst_prime, sizeof dst_prime); + crypto_hash_sha512_final(&state, b_i); +#ifdef TRACE + dump(b_i, sizeof b_i, "b_1"); +#endif + // 9. for i in (2, ..., ell): + unsigned left = len_in_bytes; + uint8_t *out = uniform_bytes; + unsigned clen = (left>sizeof b_i)?sizeof b_i:left; + memcpy(out, b_i, clen); + out+=clen; + left-=clen; + int i; + uint8_t b_ii[crypto_hash_sha512_BYTES]; + for(i=2;i<=ell;i+=2) { + // 11. uniform_bytes = b_1 || ... || b_ell + // 12. return substr(uniform_bytes, 0, len_in_bytes) + // 10. b_i = H(strxor(b_0, b_(i - 1)) || I2OSP(i, 1) || DST_prime) + expand_loop(b_0, b_i, i, dst_prime, sizeof dst_prime, b_ii); + clen = (left>sizeof b_ii)?sizeof b_ii:left; + memcpy(out, b_ii, clen); + out+=clen; + left-=clen; + // unrolled next iteration so we don't have to swap b_i and b_ii + expand_loop(b_0, b_ii, i+1, dst_prime, sizeof dst_prime, b_i); + clen = (left>sizeof b_i)?sizeof b_i:left; + memcpy(out, b_i, clen); + out+=clen; + left-=clen; + } + return 0; +} + +/* hash-to-ristretto255 - as defined by https://github.com/cfrg/draft-irtf-cfrg-hash-to-curve/blob/master/draft-irtf-cfrg-hash-to-curve.md#hashing-to-ristretto255-appx-ristretto255 + * Steps: + * -1. context-string = \x0 + htons(1) // contextString = I2OSP(modeBase(==0), 1) || I2OSP(suite.ID(==1), 2) + * 0. dst="VOPRF06-HashToGroup-" + context-string (==\x00\x00\x01) + * 1. uniform_bytes = expand_message(msg, DST, 64) + * 2. P = ristretto255_map(uniform_bytes) + * 3. return P + */ +static int voprf_hash_to_group(const uint8_t *msg, const uint8_t msg_len, uint8_t p[crypto_core_ristretto255_BYTES]) { + const uint8_t dst[] = "HashToGroup-"VOPRF"-\x00\x00\x01"; + const uint8_t dst_len = (sizeof dst) - 1; + uint8_t uniform_bytes[crypto_core_ristretto255_HASHBYTES]={0}; + if(0!=sodium_mlock(uniform_bytes,sizeof uniform_bytes)) { + return -1; + } + if(0!=expand_message_xmd(msg, msg_len, dst, dst_len, crypto_core_ristretto255_HASHBYTES, uniform_bytes)) { + sodium_munlock(uniform_bytes,sizeof uniform_bytes); + return -1; + } +#if (defined TRACE || defined CFRG_TEST_VEC) + dump(uniform_bytes, sizeof uniform_bytes, "uniform_bytes"); +#endif + crypto_core_ristretto255_from_hash(p, uniform_bytes); + sodium_munlock(uniform_bytes,sizeof uniform_bytes); +#if (defined TRACE || defined CFRG_TEST_VEC) + dump(p, crypto_core_ristretto255_BYTES, "hashed-to-curve"); +#endif + return 0; +} + +static int voprf_hash_to_scalar(const uint8_t *msg, const uint8_t msg_len, const uint8_t *dst, const uint8_t dst_len, uint8_t p[crypto_core_ristretto255_SCALARBYTES]) { + //const uint8_t dst[] = "HashToScalar-"VOPRF"-\x00\x00\x01"; + //const uint8_t dst_len = (sizeof dst) - 1; + uint8_t uniform_bytes[crypto_core_ristretto255_HASHBYTES]={0}; + if(0!=sodium_mlock(uniform_bytes,sizeof uniform_bytes)) { + return -1; + } + if(0!=expand_message_xmd(msg, msg_len, dst, dst_len, crypto_core_ristretto255_HASHBYTES, uniform_bytes)) { + sodium_munlock(uniform_bytes,sizeof uniform_bytes); + return -1; + } +#if (defined TRACE || defined CFRG_TEST_VEC) + dump(uniform_bytes, sizeof uniform_bytes, "uniform_bytes"); +#endif + crypto_core_ristretto255_scalar_reduce(p, uniform_bytes); + sodium_munlock(uniform_bytes,sizeof uniform_bytes); +#if (defined TRACE || defined CFRG_TEST_VEC) + dump(p, crypto_core_ristretto255_BYTES, "hashed-to-scalar"); +#endif + return 0; +} + +static int deriveKeyPair(const uint8_t *seed, const size_t seed_len, const uint8_t *info, const uint16_t info_len, uint8_t skS[crypto_core_ristretto255_SCALARBYTES], uint8_t pkS[crypto_core_ristretto255_BYTES]) { + const uint8_t ctx[] = "DeriveKeyPair"VOPRF"-\x00\x00\x01"; + uint8_t hashinput[seed_len + 2 + info_len + 1], *ptr= hashinput; + memcpy(ptr,seed,seed_len); + ptr+=seed_len; + *((uint16_t*) ptr)=htons(info_len); + ptr+=2; + memcpy(ptr,info,info_len); + ptr+=info_len; + ptr[0]=0; + memset(skS,0,crypto_core_ristretto255_SCALARBYTES); + int i; + while(1) { + if(ptr[0]>16) return 1; // DeriveKeyPairError + for(i=crypto_core_ristretto255_SCALARBYTES/sizeof(uint32_t);i>0;i--) { + if((((uint32_t*)skS)[i-1])!=0) break; + } + if(i!=0) break; + if(0!=voprf_hash_to_scalar(hashinput,sizeof hashinput, ctx, sizeof ctx -1,skS)) return -1; + ptr[0]++; + } + + // P_u := g^p_u + crypto_scalarmult_ristretto255_base(pkS, skS); + return 0; +} + +static int prf(const uint8_t *pwdU, const uint16_t pwdU_len, + const uint8_t kU[crypto_core_ristretto255_SCALARBYTES], + uint8_t rwdU[OPAQUE_RWDU_BYTES]) { + // F_k(pwd) = H(pwd, (H0(pwd))^k) for key k ∈ Z_q + uint8_t H0[crypto_core_ristretto255_BYTES]; + if(0!=sodium_mlock(H0,sizeof H0)) { + return -1; + } + // sets α := (H^0(pw))^r + if(0!=voprf_hash_to_group(pwdU, pwdU_len, H0)) return -1; +#ifdef TRACE + dump(H0,sizeof H0, "H0"); +#endif + + // H0 ^ k + uint8_t N[crypto_core_ristretto255_BYTES]; + if(0!=sodium_mlock(N,sizeof N)) { + sodium_munlock(H0,sizeof H0); + return -1; + } + if (crypto_scalarmult_ristretto255(N, kU, H0) != 0) { + sodium_munlock(H0,sizeof H0); + sodium_munlock(N,sizeof N); + return -1; + } + sodium_munlock(H0,sizeof H0); +#ifdef TRACE + dump(N, sizeof N, "N"); +#endif + + // 2. rwdU = Finalize(pwdU, N, "OPAQUE01") + if(0!=oprf_Finalize(pwdU, pwdU_len, N, rwdU)) { + sodium_munlock(N,sizeof N); + return -1; + } + sodium_munlock(N,sizeof N); + + return 0; +} + +/** + * This function converts input x into an element of the OPRF group, randomizes it + * by some scalar r, producing blinded, and outputs (r, blinded). + * + * This is the Blind OPRF function defined in the RFC. + * + * @param [in] x - the value to blind (for OPAQUE, this is pwdU, the user's + * password) + * @param [in] x_len - the length of param x in bytes + * @param [out] r - an OPRF scalar value used for randomization + * @param [out] blinded - a serialized OPRF group element, a byte array of fixed length, + * the blinded version of x, an input to oprf_Evaluate + * @return The function returns 0 if everything is correct. + */ +static int oprf_Blind(const uint8_t *x, const uint16_t x_len, + uint8_t r[crypto_core_ristretto255_SCALARBYTES], + uint8_t blinded[crypto_core_ristretto255_BYTES]) { +#if (defined TRACE || defined CFRG_TEST_VEC) + dump(x, x_len, "input"); +#endif + uint8_t H0[crypto_core_ristretto255_BYTES]; + if(0!=sodium_mlock(H0,sizeof H0)) { + return -1; + } + // sets α := (H^0(pw))^r + if(0!=voprf_hash_to_group(x, x_len, H0)) return -1; +#if (defined TRACE || defined CFRG_TEST_VEC) + dump(H0,sizeof H0, "H0 "); +#endif + + // U picks r +#ifdef CFRG_TEST_VEC + static int vecidx=0; + const unsigned char *rtest[2] = {blind_registration, blind_login}; + const unsigned int rtest_len = 32; + memcpy(r,rtest[vecidx++ % 2],rtest_len); +#else + crypto_core_ristretto255_scalar_random(r); +#endif + +#ifdef TRACE + dump(r, crypto_core_ristretto255_SCALARBYTES, "r"); +#endif + // H^0(pw)^r + if (crypto_scalarmult_ristretto255(blinded, r, H0) != 0) { + sodium_munlock(H0,sizeof H0); + return -1; + } + sodium_munlock(H0,sizeof H0); +#if (defined TRACE || defined CFRG_TEST_VEC) + dump(blinded, crypto_core_ristretto255_BYTES, "blinded"); +#endif + return 0; +} + +/** + * This function evaluates input element blinded using private key k, yielding output + * element Z. + * + * This is the Evaluate OPRF function defined in the RFC. + * + * @param [in] k - a private key (for OPAQUE, this is kU, the user's OPRF private + * key) + * @param [in] blinded - a serialized OPRF group element, a byte array of fixed length, + * an output of oprf_Blind (for OPAQUE, this is the blinded pwdU, the user's + * password) + * @param [out] Z - a serialized OPRF group element, a byte array of fixed length, + * an input to oprf_Unblind + * @return The function returns 0 if everything is correct. + */ +static int oprf_Evaluate(const uint8_t k[crypto_core_ristretto255_SCALARBYTES], + const uint8_t blinded[crypto_core_ristretto255_BYTES], + uint8_t Z[crypto_core_ristretto255_BYTES]) { + return crypto_scalarmult_ristretto255(Z, k, blinded); +} + +/** + * This function removes random scalar r from Z, yielding output N. + * + * This is the Unblind OPRF function defined in the RFC. + * + * @param [in] r - an OPRF scalar value used for randomization in oprf_Blind + * @param [in] Z - a serialized OPRF group element, a byte array of fixed length, + * an output of oprf_Evaluate + * @param [out] N - a serialized OPRF group element with random scalar r removed, + * a byte array of fixed length, an input to oprf_Finalize + * @return The function returns 0 if everything is correct. + */ +static int oprf_Unblind(const uint8_t r[crypto_core_ristretto255_SCALARBYTES], + const uint8_t Z[crypto_core_ristretto255_BYTES], + uint8_t N[crypto_core_ristretto255_BYTES]) { +#ifdef TRACE + dump((uint8_t*) r, crypto_core_ristretto255_SCALARBYTES, "r "); + dump((uint8_t*) Z, crypto_core_ristretto255_BYTES, "Z "); +#endif + + // (a) Checks that β ∈ G ∗ . If not, outputs (abort, sid , ssid ) and halts; + if(crypto_core_ristretto255_is_valid_point(Z) != 1) return -1; + + // (b) Computes rw := H(pw, β^1/r ); + // invert r = 1/r + uint8_t ir[crypto_core_ristretto255_SCALARBYTES]; + if(-1==sodium_mlock(ir, sizeof ir)) return -1; + if (crypto_core_ristretto255_scalar_invert(ir, r) != 0) { + sodium_munlock(ir, sizeof ir); + return -1; + } +#ifdef TRACE + dump((uint8_t*) ir, sizeof ir, "r^-1 "); +#endif + + // H0 = β^(1/r) + // beta^(1/r) = h(pwd)^k + if (crypto_scalarmult_ristretto255(N, ir, Z) != 0) { + sodium_munlock(ir, sizeof ir); + return -1; + } +#ifdef TRACE + dump((uint8_t*) N, crypto_core_ristretto255_BYTES, "N "); +#endif + + sodium_munlock(ir, sizeof ir); + return 0; +} + +static void hkdf_expand_label(uint8_t* res, const uint8_t secret[crypto_kdf_hkdf_sha512_KEYBYTES], const char *label, const char transcript[crypto_hash_sha512_BYTES], const size_t len) { + // construct a hkdf label + // struct { + // uint16 length = Length; + // opaque label<8..255> = "OPAQUE-" + Label; + // opaque context<0..255> = Context; + // } HkdfLabel; + const size_t llen = strlen((const char*) label); + uint8_t hkdflabel[2+2+7/*"OPAQUE-"*/+llen+(transcript!=NULL?crypto_hash_sha512_BYTES:0)]; + + *((uint16_t*) hkdflabel)=htons(len); + + uint8_t *ptr=hkdflabel+2; + *(ptr)=(7+llen); + ptr+=1; + + memcpy(ptr,"OPAQUE-",7); + ptr+=7; + + memcpy(ptr,label,llen); + ptr+=llen; + + if(transcript!=NULL) { + *(ptr)=crypto_hash_sha512_BYTES; + ptr+=1; + memcpy(ptr, transcript, crypto_hash_sha512_BYTES); + } else { + *(ptr)=0; + } + +#if (defined TRACE || defined CFRG_TEST_VEC) + dump(hkdflabel, sizeof(hkdflabel), "expanded label"); + if(transcript!=NULL) dump((const uint8_t*) transcript,crypto_hash_sha512_BYTES, "transcript: "); +#endif + + crypto_kdf_hkdf_sha512_expand(res, len, (const char*) hkdflabel, sizeof(hkdflabel), secret); +} + +// derive keys according to irtf cfrg draft +static int derive_keys(Opaque_Keys* keys, const uint8_t ikm[crypto_scalarmult_BYTES * 3], const char info[crypto_hash_sha512_BYTES]) { + uint8_t prk[64]; + if(-1==sodium_mlock(prk, sizeof prk)) return -1; +#ifdef TRACE + dump(ikm, crypto_scalarmult_BYTES*3, "ikm "); + dump((uint8_t*) info, crypto_hash_sha512_BYTES, "info "); +#endif + // 1. prk = HKDF-Extract(salt=0, IKM) + crypto_kdf_hkdf_sha512_extract(prk, NULL, 0, ikm, crypto_scalarmult_BYTES*3); +#if (defined TRACE || defined CFRG_TEST_VEC) + dump(prk, sizeof prk, "prk"); +#endif + + // 2. handshake_secret = Derive-Secret(., "handshake secret", info) + uint8_t handshake_secret[OPAQUE_HANDSHAKE_SECRETBYTES]; + if(-1==sodium_mlock(handshake_secret, sizeof handshake_secret)) { + sodium_munlock(prk,sizeof(prk)); + return -1; + } + const char handshake_secret_label[]="HandshakeSecret"; + hkdf_expand_label(handshake_secret, prk, handshake_secret_label, info, sizeof(handshake_secret)); + + // 3. keys->sk = Derive-Secret(., "session secret", info) + const char session_key_label[]="SessionKey"; + hkdf_expand_label(keys->sk, prk, session_key_label, info, OPAQUE_SHARED_SECRETBYTES); + sodium_munlock(prk,sizeof(prk)); + + // 4. Km2 = Derive-Secret(handshake_secret, "ServerMAC", "") + //Km2 = HKDF-Expand-Label(handshake_secret, "server mac", "", Hash.length) + const char server_mac_label[]="ServerMAC"; + hkdf_expand_label(keys->km2, handshake_secret, server_mac_label, NULL, OPAQUE_HMAC_SHA512_KEYBYTES); + // 5. Km3 = Derive-Secret(handshake_secret, "ClientMAC", "") + //Km3 = HKDF-Expand-Label(handshake_secret, "client mac", "", Hash.length) + const char client_mac_label[]="ClientMAC"; + hkdf_expand_label(keys->km3, handshake_secret, client_mac_label, NULL, OPAQUE_HMAC_SHA512_KEYBYTES); + sodium_munlock(handshake_secret, sizeof handshake_secret); +#ifdef TRACE + dump(keys->sk, OPAQUE_SHARED_SECRETBYTES, "keys->sk"); + dump(keys->km2, OPAQUE_HMAC_SHA512_KEYBYTES, "keys->km2"); + dump(keys->km3, OPAQUE_HMAC_SHA512_KEYBYTES, "keys->km3"); +#endif + return 0; +} + +/** if one of the peers ID is missing, set it to the peers public key */ +static void fix_ids(const uint8_t pkU[crypto_scalarmult_BYTES], + const uint8_t pkS[crypto_scalarmult_BYTES], + const Opaque_Ids *ids_in, + Opaque_Ids *ids_out) { + if(ids_in->idS==NULL || ids_in->idS_len==0) { + ids_out->idS=(uint8_t*)pkS; + ids_out->idS_len=crypto_scalarmult_BYTES; + } else { + ids_out->idS=ids_in->idS; + ids_out->idS_len=ids_in->idS_len; + } + if(ids_in->idU==NULL || ids_in->idU_len==0) { + ids_out->idU=(uint8_t*)pkU; + ids_out->idU_len=crypto_scalarmult_BYTES; + } else { + ids_out->idU=ids_in->idU; + ids_out->idU_len=ids_in->idU_len; + } +} + +static void calc_preamble(char preamble[crypto_hash_sha512_BYTES], + crypto_hash_sha512_state *state, + const uint8_t pkU[crypto_scalarmult_BYTES], + const uint8_t pkS[crypto_scalarmult_BYTES], + const uint8_t ke1[OPAQUE_USER_SESSION_PUBLIC_LEN], + const Opaque_ServerSession *ke2, + const uint8_t *ctx, const uint16_t ctx_len, + const Opaque_Ids *ids0) { + crypto_hash_sha512_init(state); + + Opaque_Ids ids; + fix_ids(pkU, pkS, ids0, &ids); + +#ifdef TRACE + fprintf(stderr,"calc preamble\n"); + dump(ids.idU, ids.idU_len,"idU "); + dump(ids.idS, ids.idS_len,"idS "); + dump(pkU, crypto_scalarmult_BYTES, "pkU"); + dump(pkS,crypto_scalarmult_BYTES, "pkS"); + dump(ke1, OPAQUE_USER_SESSION_PUBLIC_LEN, "ke1"); + dump(ctx, ctx_len, "ctx"); + dump((uint8_t*)ke2, + /* credential_response */ + /*Z*/ crypto_core_ristretto255_BYTES + + /*masking_nonce*/ 32+ + /*masked_response*/ crypto_scalarmult_BYTES+sizeof(Opaque_Envelope)+ + /*nonceS*/OPAQUE_NONCE_BYTES+ + /*X_s*/crypto_scalarmult_BYTES, "ke2"); +#endif + + //1. preamble = hash("RFCXXXX", + // note the spec it self does not say hash here, but + // https://github.com/cfrg/draft-irtf-cfrg-opaque/pull/147 + // and later uses all hash this value + const uint8_t rfc[]="RFCXXXX"; + const uint8_t rfc_len=sizeof rfc -1; + crypto_hash_sha512_update(state, rfc, rfc_len); + + // I2OSP(len(context), 2), context, + uint16_t len = htons(ctx_len); + crypto_hash_sha512_update(state, (uint8_t*) &len, 2); + crypto_hash_sha512_update(state, ctx, ctx_len); + + // I2OSP(len(client_identity), 2), client_identity, + len = htons(ids.idU_len); + crypto_hash_sha512_update(state, (uint8_t*) &len, 2); + crypto_hash_sha512_update(state, ids.idU, ids.idU_len); + + // ke1, + crypto_hash_sha512_update(state, ke1, OPAQUE_USER_SESSION_PUBLIC_LEN); + + // I2OSP(len(server_identity), 2), server_identity, + len = htons(ids.idS_len); + crypto_hash_sha512_update(state, (uint8_t*) &len, 2); + crypto_hash_sha512_update(state, ids.idS, ids.idS_len); + + // ke2.credential_response, + // ke2.AuthResponse.server_nonce, ke2.AuthResponse.server_keyshare) + // see type Opaque_ServerSession + crypto_hash_sha512_update(state, (uint8_t*)ke2, + /* credential_response */ + /*Z*/ crypto_core_ristretto255_BYTES + + /*masking_nonce*/ 32+ + /*masked_response*/ crypto_scalarmult_BYTES+sizeof(Opaque_Envelope)+ + /*nonceS*/OPAQUE_NONCE_BYTES+ + /*X_s*/crypto_scalarmult_BYTES); + + // We need to copy the state here, because the caller of this function + // may re-use it later. After calling the `final` function below, + // the passed-in state must not be used again. + crypto_hash_sha512_state copied_state; + memcpy(&copied_state, state, sizeof(crypto_hash_sha512_state)); + crypto_hash_sha512_final(&copied_state, (uint8_t *) preamble); +} + +// implements server end of triple-dh +static int server_3dh(Opaque_Keys *keys, + const uint8_t ix[crypto_scalarmult_SCALARBYTES], + const uint8_t ex[crypto_scalarmult_SCALARBYTES], + const uint8_t Ip[crypto_scalarmult_BYTES], + const uint8_t Ep[crypto_scalarmult_BYTES], + const char preamble[crypto_hash_sha512_BYTES]) { + uint8_t sec[crypto_scalarmult_BYTES * 3], *ptr = sec; + if(-1==sodium_mlock(sec, sizeof sec)) { + return -1; + } + +#if (defined TRACE || defined CFRG_TEST_VEC) + dump(ix, crypto_scalarmult_SCALARBYTES, "skS"); + dump(ex, crypto_scalarmult_SCALARBYTES, "ekS"); + dump(Ip, crypto_scalarmult_BYTES, "pkU"); + dump(Ep, crypto_scalarmult_BYTES, "epkU"); +#endif + + if(0!=crypto_scalarmult_ristretto255(ptr,ex,Ep)) return 1; + ptr+=crypto_scalarmult_BYTES; + if(0!=crypto_scalarmult_ristretto255(ptr,ix,Ep)) return 1; + ptr+=crypto_scalarmult_BYTES; + if(0!=crypto_scalarmult_ristretto255(ptr,ex,Ip)) return 1; +#if (defined TRACE || defined CFRG_TEST_VEC) + dump(sec, 96, "3dh s ikm"); +#endif + + if(0!=derive_keys(keys, sec, preamble)) { + sodium_munlock(sec,sizeof(sec)); + return -1; + } + sodium_munlock(sec,sizeof(sec)); +#if (defined TRACE || defined CFRG_TEST_VEC) + dump((uint8_t*) keys, sizeof(Opaque_Keys), "keys "); +#endif + + return 0; +} + +// implements user end of triple-dh +static int user_3dh(Opaque_Keys *keys, + const uint8_t ix[crypto_scalarmult_SCALARBYTES], + const uint8_t ex[crypto_scalarmult_SCALARBYTES], + const uint8_t Ip[crypto_scalarmult_BYTES], + const uint8_t Ep[crypto_scalarmult_BYTES], + const char preamble[crypto_hash_sha512_BYTES]) { + uint8_t sec[crypto_scalarmult_BYTES * 3], *ptr = sec; + if(-1==sodium_mlock(sec, sizeof sec)) { + return -1; + } + + if(0!=crypto_scalarmult_ristretto255(ptr,ex,Ep)) return 1; + ptr+=crypto_scalarmult_BYTES; + if(0!=crypto_scalarmult_ristretto255(ptr,ex,Ip)) return 1; + ptr+=crypto_scalarmult_BYTES; + if(0!=crypto_scalarmult_ristretto255(ptr,ix,Ep)) return 1; +#if (defined TRACE || defined CFRG_TEST_VEC) + dump(sec, 96, "3dh u ikm"); +#endif + + // and hash for the result SK = f_K(0) + if(0!=derive_keys(keys, sec, preamble)) { + sodium_munlock(sec,sizeof(sec)); + return -1; + } + sodium_munlock(sec,sizeof(sec)); +#if (defined TRACE || defined CFRG_TEST_VEC) + dump((uint8_t*) keys, sizeof(Opaque_Keys), "keys "); +#endif + + return 0; +} + +static int skU_from_rwd(const uint8_t rwd[OPAQUE_RWDU_BYTES], const uint8_t nonce[OPAQUE_NONCE_BYTES], uint8_t skU[crypto_scalarmult_BYTES]) { + char info[OPAQUE_NONCE_BYTES+10]; + memcpy(info, nonce, OPAQUE_NONCE_BYTES); + memcpy(info+OPAQUE_NONCE_BYTES, "PrivateKey", 10); + uint8_t seed[crypto_core_ristretto255_SCALARBYTES]; + if(-1==sodium_mlock(seed, sizeof seed)) { + return -1; + } + crypto_kdf_hkdf_sha512_expand(seed, crypto_core_ristretto255_SCALARBYTES, info, sizeof info, rwd); + + uint8_t dst[24]="OPAQUE-DeriveAuthKeyPair"; + if(0!=voprf_hash_to_scalar(seed, sizeof seed, dst, sizeof dst, skU)) { + sodium_munlock(seed, sizeof seed); + return -1; + } + + sodium_munlock(seed, sizeof seed); + return 0; +} + +static int create_envelope(const uint8_t rwdU[OPAQUE_RWDU_BYTES], + const uint8_t server_public_key[crypto_scalarmult_BYTES], + const Opaque_Ids *ids, + Opaque_Envelope *env, + uint8_t client_public_key[crypto_scalarmult_BYTES], + uint8_t masking_key[crypto_hash_sha512_BYTES], + uint8_t export_key[crypto_hash_sha512_BYTES]) { + + // 1. envelope_nonce = random(Nn) +#ifdef CFRG_TEST_VEC + memcpy(env->nonce, envelope_nonce, envelope_nonce_len); +#else + randombytes(env->nonce, OPAQUE_ENVELOPE_NONCEBYTES); +#endif + + uint8_t concated[OPAQUE_ENVELOPE_NONCEBYTES+10], + *label = concated+OPAQUE_ENVELOPE_NONCEBYTES; + memcpy(concated, env->nonce, OPAQUE_ENVELOPE_NONCEBYTES); + + // 2. masking_key = HKDF-Expand(randomized_pwd, "MaskingKey", Nh) + const uint8_t masking_key_info[10]="MaskingKey"; + crypto_kdf_hkdf_sha512_expand(masking_key, crypto_hash_sha512_BYTES, + (const char*) masking_key_info, sizeof masking_key_info, + rwdU); +#if (defined CFRG_TEST_VEC || defined TRACE) + dump(masking_key_info, sizeof masking_key_info, "masking_key_info"); + dump(rwdU, OPAQUE_RWDU_BYTES, "rwdU"); + dump(masking_key, crypto_hash_sha512_BYTES, "masking_key"); +#endif + + // 3. auth_key = HKDF-Expand(randomized_pwd, concat(envelope_nonce, "AuthKey"), Nh) + uint8_t auth_key[OPAQUE_HMAC_SHA512_KEYBYTES]; + if(-1==sodium_mlock(auth_key, sizeof auth_key)) { + return -1; + } + memcpy(label, "AuthKey", 7); + crypto_kdf_hkdf_sha512_expand(auth_key, sizeof auth_key, + (const char*) concated, OPAQUE_ENVELOPE_NONCEBYTES+7, + rwdU); + +#if (defined CFRG_TEST_VEC || defined TRACE) + dump(auth_key,sizeof auth_key, "auth_key "); +#endif + + // 4. export_key = HKDF-Expand(randomized_pwd, concat(envelope_nonce, "ExportKey"), Nh) + if(NULL!=export_key) { + memcpy(label, "ExportKey", 9); +#if (defined CFRG_TEST_VEC || defined TRACE) + dump(concated, OPAQUE_ENVELOPE_NONCEBYTES+9, "export_key_info"); +#endif + crypto_kdf_hkdf_sha512_expand(export_key, crypto_hash_sha512_BYTES, + (const char*) concated, OPAQUE_ENVELOPE_NONCEBYTES+9, + rwdU); +#if (defined CFRG_TEST_VEC || defined TRACE) + dump(export_key,crypto_hash_sha512_BYTES, "export_key "); +#endif + } + + // 5. seed = Expand(randomized_pwd, concat(envelope_nonce, "PrivateKey"), Nseed) + memcpy(label, "PrivateKey", 10); + uint8_t seed[crypto_core_ristretto255_SCALARBYTES]; + if(-1==sodium_mlock(seed, sizeof seed)) { + sodium_munlock(auth_key, sizeof auth_key); + return -1; + } + crypto_kdf_hkdf_sha512_expand(seed, crypto_core_ristretto255_SCALARBYTES, + (const char*) concated, OPAQUE_ENVELOPE_NONCEBYTES+10, + rwdU); + + // 6. _, client_public_key = DeriveAuthKeyPair(seed) + uint8_t client_secret_key[crypto_scalarmult_SCALARBYTES]; + if(-1==sodium_mlock(client_secret_key, sizeof client_secret_key)) { + sodium_munlock(auth_key, sizeof auth_key); + return -1; + } + const uint8_t dst[24]="OPAQUE-DeriveAuthKeyPair"; + if(0!=deriveKeyPair(seed, sizeof seed, dst, sizeof dst, client_secret_key, client_public_key)) { + sodium_munlock(seed, sizeof seed); + sodium_munlock(client_secret_key, sizeof client_secret_key); + sodium_munlock(auth_key, sizeof auth_key); + return -1; + } + sodium_munlock(seed, sizeof seed); +#if (defined CFRG_TEST_VEC || defined TRACE) + dump(client_secret_key, crypto_scalarmult_SCALARBYTES, "client_secret_key"); +#endif + sodium_munlock(client_secret_key, sizeof client_secret_key); +#if (defined CFRG_TEST_VEC || defined TRACE) + dump(client_public_key, crypto_scalarmult_BYTES, "client_public_key"); +#endif + + // complete ids in case they are NULL and need to be set to the pk[US] + Opaque_Ids ids_completed; + fix_ids(client_public_key, server_public_key, ids, &ids_completed); + + uint8_t authenticated[OPAQUE_NONCE_BYTES+ + crypto_scalarmult_BYTES+ + ids_completed.idS_len+2+ + ids_completed.idU_len+2], + *ptr=authenticated; + + // nonce + memcpy(ptr, env->nonce, OPAQUE_NONCE_BYTES); + ptr+=OPAQUE_NONCE_BYTES; + // server_public_key + memcpy(ptr, server_public_key, crypto_scalarmult_BYTES); + ptr+=crypto_scalarmult_BYTES; + // server_identity + uint16_t size = htons(ids_completed.idS_len); + memcpy(ptr,(uint8_t*) &size, 2); + ptr+=2; + memcpy(ptr,ids_completed.idS,ids_completed.idS_len); + ptr+=ids_completed.idS_len; + // client_identity + size = htons(ids_completed.idU_len); + memcpy(ptr,(uint8_t*) &size, 2); + ptr+=2; + memcpy(ptr,ids_completed.idU,ids_completed.idU_len); + + opaque_hmacsha512(auth_key, // key + authenticated, // in + sizeof authenticated, // len(in) + env->auth_tag); // out + +#if (defined CFRG_TEST_VEC || defined TRACE) + dump(authenticated, sizeof authenticated, "authenticated"); + dump(auth_key, sizeof auth_key, "auth_key"); + dump(env->auth_tag, crypto_auth_hmacsha512_BYTES, "auth_tag"); +#endif + sodium_munlock(auth_key, sizeof auth_key); + +#if (defined CFRG_TEST_VEC || defined TRACE) + dump((uint8_t *)env, OPAQUE_ENVELOPE_BYTES, "envU"); +#endif + + return 0; +} + +// (StorePwdFile, sid , U, pw): S computes k_s ←_R Z_q , rw := F_k_s (pw), +// p_s ←_R Z_q , p_u ←_R Z_q , P_s := g^p_s , P_u := g^p_u , c ← AuthEnc_rw (p_u, P_u, P_s); +// it records file[sid] := {k_s, p_s, P_s, P_u, c}. +int opaque_Register(const uint8_t *pwdU, const uint16_t pwdU_len, + const uint8_t skS[crypto_scalarmult_SCALARBYTES], + const Opaque_Ids *ids, + uint8_t _rec[OPAQUE_USER_RECORD_LEN], + uint8_t export_key[crypto_hash_sha512_BYTES]) { + Opaque_UserRecord *rec = (Opaque_UserRecord *)_rec; + +#ifdef TRACE + dump(ids->idU, ids->idU_len,"idU "); + dump(ids->idS, ids->idS_len,"idS "); +#endif + + // k_s ←_R Z_q + // 1. (kU, _) = KeyGen() + oprf_KeyGen(rec->kU); + + // rw := F_k_s (pw), + uint8_t rwdU[OPAQUE_RWDU_BYTES]; + if(-1==sodium_mlock(rwdU,sizeof rwdU)) { + return -1; + } + + if(prf(pwdU, pwdU_len, rec->kU, rwdU)!=0) { + sodium_munlock(rwdU,sizeof rwdU); + return -1; + } +#ifdef TRACE + dump(rwdU, sizeof rwdU, "rwdU"); +#endif + + // p_s ←_R Z_q + if(skS==NULL) { + randombytes(rec->skS, crypto_scalarmult_SCALARBYTES); // random server secret key + } else { + memcpy(rec->skS, skS, crypto_scalarmult_SCALARBYTES); + } + + // P_s := g^p_s + uint8_t server_public_key[crypto_scalarmult_BYTES]; + crypto_scalarmult_ristretto255_base(server_public_key, rec->skS); + + uint8_t client_private_key[crypto_scalarmult_SCALARBYTES]; + if(-1==sodium_mlock(client_private_key,sizeof client_private_key)) { + sodium_munlock(rwdU,sizeof rwdU); + return -1; + } + if(0!=skU_from_rwd(rwdU, (uint8_t*) &rec->recU.envelope, client_private_key)) { + sodium_munlock(client_private_key,sizeof client_private_key); + sodium_munlock(rwdU, sizeof rwdU); + return -1; + } + // P_u := g^p_u + crypto_scalarmult_base(rec->recU.client_public_key, client_private_key); + sodium_munlock(client_private_key,sizeof client_private_key); + + if(0!=create_envelope(rwdU, server_public_key, ids, &rec->recU.envelope, rec->recU.client_public_key, rec->recU.masking_key, export_key)) { + sodium_munlock(rwdU, sizeof rwdU); + return -1; + } + sodium_munlock(rwdU, sizeof rwdU); + +#ifdef TRACE + dump(_rec, OPAQUE_USER_RECORD_LEN, "user rec"); +#endif + return 0; +} + +//(UsrSession, sid , ssid , S, pw): U picks r, x_u ←_R Z_q ; sets α := (H^0(pw))^r and +//X_u := g^x_u ; sends α and X_u to S. +// more or less corresponds to CreateCredentialRequest in the irtf draft +int opaque_CreateCredentialRequest(const uint8_t *pwdU, const uint16_t pwdU_len, uint8_t _sec[OPAQUE_USER_SESSION_SECRET_LEN+pwdU_len], uint8_t _pub[OPAQUE_USER_SESSION_PUBLIC_LEN]) { + Opaque_UserSession_Secret *sec = (Opaque_UserSession_Secret*) _sec; + Opaque_UserSession *pub = (Opaque_UserSession*) _pub; +#ifdef TRACE + memset(_sec, 0, OPAQUE_USER_SESSION_SECRET_LEN+pwdU_len); + memset(_pub, 0, OPAQUE_USER_SESSION_PUBLIC_LEN); +#endif + + // 1. (blind, blinded) = Blind(pwdU) + if(0!=oprf_Blind(pwdU, pwdU_len, sec->blind, pub->blinded)) return -1; +#ifdef TRACE + dump(_sec,OPAQUE_USER_SESSION_SECRET_LEN+pwdU_len, "sec "); + dump(_pub,OPAQUE_USER_SESSION_PUBLIC_LEN, "pub "); +#endif + memcpy(sec->blinded, pub->blinded, crypto_core_ristretto255_BYTES); + + // x_u ←_R Z_q +#ifdef CFRG_TEST_VEC + memcpy(sec->x_u, client_private_keyshare, crypto_scalarmult_SCALARBYTES); +#else + randombytes(sec->x_u, crypto_scalarmult_SCALARBYTES); +#endif + + // nonceU +#ifdef CFRG_TEST_VEC + memcpy(sec->nonceU, client_nonce, OPAQUE_NONCE_BYTES); +#else + randombytes(sec->nonceU, OPAQUE_NONCE_BYTES); +#endif + memcpy(pub->nonceU, sec->nonceU, OPAQUE_NONCE_BYTES); + + // X_u := g^x_u + crypto_scalarmult_ristretto255_base(pub->X_u, sec->x_u); + + sec->pwdU_len = pwdU_len; + memcpy(sec->pwdU, pwdU, pwdU_len); + + // keep ke1 for later + memcpy(sec->ke1, _pub, OPAQUE_USER_SESSION_PUBLIC_LEN); + +#ifdef TRACE + dump(_sec,OPAQUE_USER_SESSION_SECRET_LEN+pwdU_len, "sec "); + dump(_pub,OPAQUE_USER_SESSION_PUBLIC_LEN, "pub "); +#endif + return 0; +} + +// more or less corresponds to CreateCredentialResponse in the irtf draft +// 2. (SvrSession, sid , ssid ): On input α from U, S proceeds as follows: +// (a) Checks that α ∈ G^∗ If not, outputs (abort, sid , ssid ) and halts; +// (b) Retrieves file[sid] = {k_s, p_s, P_s, P_u, c}; +// (c) Picks x_s ←_R Z_q and computes β := α^k_s and X_s := g^x_s ; +// (d) Computes K := KE(p_s, x_s, P_u, X_u) and SK := f K (0); +// (e) Sends β, X s and c to U; +// (f) Outputs (sid , ssid , SK). +int opaque_CreateCredentialResponse(const uint8_t _pub[OPAQUE_USER_SESSION_PUBLIC_LEN], const uint8_t _rec[OPAQUE_USER_RECORD_LEN], const Opaque_Ids *ids, const uint8_t *ctx, const uint16_t ctx_len, uint8_t _resp[OPAQUE_SERVER_SESSION_LEN], uint8_t sk[OPAQUE_SHARED_SECRETBYTES], uint8_t authU[crypto_auth_hmacsha512_BYTES]) { + + Opaque_UserSession *pub = (Opaque_UserSession *) _pub; + Opaque_UserRecord *rec = (Opaque_UserRecord *) _rec; + Opaque_ServerSession *resp = (Opaque_ServerSession *) _resp; + +#ifdef TRACE + dump(_pub, sizeof(Opaque_UserSession), "session srv pub "); + dump(_rec, OPAQUE_USER_RECORD_LEN, "session srv rec "); +#endif + + // (a) Checks that α ∈ G^∗ . If not, outputs (abort, sid , ssid ) and halts; + if(crypto_core_ristretto255_is_valid_point(pub->blinded)!=1) return -1; + + // (b) Retrieves file[sid] = {k_s, p_s, P_s, P_u, c}; + // provided as parameter rec +#ifdef TRACE + dump(rec->kU, sizeof(rec->kU), "session srv kU "); + dump(pub->blinded, sizeof(pub->blinded), "session srv blinded "); +#endif + + // computes β := α^k_s + // 1. Z = Evaluate(DeserializeScalar(credentialFile.kU), request.data) + if (oprf_Evaluate(rec->kU, pub->blinded, resp->Z) != 0) { + return -1; + } +#if (defined TRACE || defined CFRG_TEST_VEC) + dump(resp->Z, sizeof resp->Z, "EvaluationElement"); +#endif + + // 4. masking_nonce = random(Nn) + // 5. credential_response_pad = Expand(record.masking_key, concat(masking_nonce, "CredentialResponsePad"), Npk + Ne) +#ifdef CFRG_TEST_VEC + struct { + uint8_t nonce[32]; + uint8_t dst[21]; + } __attribute((packed)) masking_info = { + .nonce = {0}, + .dst = "CredentialResponsePad"}; + memcpy(masking_info.nonce, masking_nonce, masking_nonce_len); +#else + struct { + uint8_t nonce[32]; + uint8_t dst[21]; + } __attribute((packed)) masking_info = { + .nonce = {0}, + .dst = "CredentialResponsePad"}; + randombytes(masking_info.nonce, sizeof masking_info.nonce); +#endif + uint8_t response_pad[crypto_scalarmult_BYTES+sizeof(Opaque_Envelope)]; + if(-1==sodium_mlock(response_pad, sizeof response_pad)) { + return -1; + } + crypto_kdf_hkdf_sha512_expand(response_pad, sizeof response_pad, + (const char*) &masking_info, sizeof masking_info, + rec->recU.masking_key); + memcpy(resp->masking_nonce, masking_info.nonce, sizeof masking_info.nonce); + + // recalc server_public_key as we need it for the next step + uint8_t pkS[crypto_scalarmult_BYTES]; + crypto_scalarmult_ristretto255_base(pkS, rec->skS); +#if (defined TRACE || defined CFRG_TEST_VEC) + dump(pkS, sizeof pkS, "server_public_key"); +#endif + + memcpy(resp->masked_response, pkS, sizeof pkS); + + // 6. masked_response = xor(credential_response_pad, concat(server_public_key, record.envelope)) + unsigned i; + for(i=0;imasked_response[i] = response_pad[i] ^ resp->masked_response[i]; + for(;imasked_response[i] = response_pad[i] ^ ((uint8_t*)(&rec->recU.envelope))[i-crypto_scalarmult_BYTES]; + sodium_munlock(response_pad, sizeof response_pad); + +#if (defined TRACE || defined CFRG_TEST_VEC) + dump(_resp, sizeof (resp->Z) + crypto_scalarmult_BYTES+sizeof(Opaque_Envelope) + sizeof(masking_info.nonce), "resp(z+mn+mr)" ); +#endif + + // this is the ake function Response() as per the irtf cfrg draft + // 1. server_nonce = random(Nn) + // nonceS +#ifdef CFRG_TEST_VEC + memcpy(resp->nonceS, server_nonce, OPAQUE_NONCE_BYTES); +#else + randombytes(resp->nonceS, OPAQUE_NONCE_BYTES); +#endif + + // 2. server_private_keyshare, server_keyshare = GenerateAuthKeyPair() + // (c) Picks x_s ←_R Z_q + uint8_t x_s[crypto_scalarmult_SCALARBYTES]; + if(-1==sodium_mlock(x_s,sizeof x_s)) return -1; +#ifdef CFRG_TEST_VEC + memcpy(x_s, server_private_keyshare, sizeof x_s); +#else + randombytes(x_s, crypto_scalarmult_SCALARBYTES); +#endif + +#ifdef TRACE + dump(x_s, sizeof(x_s), "session srv x_s "); +#endif + // X_s := g^x_s; + crypto_scalarmult_ristretto255_base(resp->X_s, x_s); + +#if (defined TRACE || defined CFRG_TEST_VEC) + dump(resp->X_s, sizeof(resp->X_s), "server_keyshare"); +#endif + // 3. Create inner_ke2 ike2 with (credential_response, server_nonce, server_keyshare) + // should already be all in place + + // 4. preamble = Preamble(client_identity, ke1, server_identity, ike2) + // mixing in things from the irtf cfrg spec + char preamble[crypto_hash_sha512_BYTES]; + crypto_hash_sha512_state preamble_state; + calc_preamble(preamble, &preamble_state, rec->recU.client_public_key, pkS, _pub, resp, ctx, ctx_len, (Opaque_Ids*) ids); + Opaque_Keys keys; + if(-1==sodium_mlock(&keys,sizeof(keys))) { + sodium_munlock(x_s,sizeof x_s); + return -1; + } + + // (d) Computes K := KE(p_s, x_s, P_u, X_u) and SK := f_K(0); +#ifdef TRACE + dump(rec->skS,crypto_scalarmult_SCALARBYTES, "rec->skS "); + dump(x_s,crypto_scalarmult_SCALARBYTES, "x_s "); + //dump(rec->pkU,crypto_scalarmult_BYTES, "rec->pkU "); + dump(pub->X_u,crypto_scalarmult_BYTES, "pub->X_u "); +#endif + // 5. ikm = TripleDHIKM(server_secret, ke1.client_keyshare, + // server_private_key, ke1.client_keyshare, + // server_secret, client_public_key) + // 6. Km2, Km3, session_key = DeriveKeys(ikm, preamble) + if(0!=server_3dh(&keys, rec->skS, x_s, rec->recU.client_public_key, pub->X_u, preamble)) { + sodium_munlock(x_s, sizeof(x_s)); + sodium_munlock(&keys,sizeof(keys)); + return -1; + } + sodium_munlock(x_s, sizeof(x_s)); +#if (defined TRACE || defined CFRG_TEST_VEC) + dump(keys.sk, sizeof(keys.sk), "srv sk "); + dump(keys.km2,OPAQUE_HMAC_SHA512_KEYBYTES,"session srv km2 "); + dump(keys.km3,OPAQUE_HMAC_SHA512_KEYBYTES,"session srv km3 "); +#endif + + // 7. server_mac = MAC(Km2, Hash(preamble)) + opaque_hmacsha512(keys.km2, + (uint8_t*)preamble, // in + crypto_hash_sha512_BYTES, // len(in) + resp->auth); // out +#ifdef TRACE + dump(resp->auth, sizeof resp->auth, "resp->auth "); + dump(keys.km2, sizeof keys.km2, "km2 "); +#endif + + // 8. expected_client_mac = MAC(Km3, Hash(concat(preamble, server_mac)) + crypto_hash_sha512_update(&preamble_state, resp->auth, crypto_auth_hmacsha512_BYTES); + crypto_hash_sha512_final(&preamble_state, (uint8_t *) preamble); +#if (defined TRACE || defined CFRG_TEST_VEC) + dump(resp->auth, crypto_auth_hmacsha512_BYTES, "server mac"); + dump((uint8_t*)preamble, sizeof preamble, "auth preamble"); +#endif + if(NULL!=authU) { + opaque_hmacsha512(keys.km3, // key + (uint8_t*)preamble, // in + crypto_hash_sha512_BYTES, // len(in) + authU); // out + } + + memcpy(sk,keys.sk,sizeof(keys.sk)); + sodium_munlock(&keys,sizeof(keys)); + +#ifdef TRACE + dump(resp->auth, sizeof(resp->auth), "session srv auth "); + dump(authU, crypto_auth_hmacsha512_BYTES, "authU"); + dump(_resp, OPAQUE_SERVER_SESSION_LEN, "resp"); +#endif + + return 0; +} + +// more or less corresponds to RecoverCredentials in the irtf draft +// 3. On β, X_s and c from S, U proceeds as follows: +// (a) Checks that β ∈ G ∗ . If not, outputs (abort, sid , ssid ) and halts; +// (b) Computes rw := H(key, pw|β^1/r ); +// (c) Computes AuthDec_rw(c). If the result is ⊥, outputs (abort, sid , ssid ) and halts. +// Otherwise sets (p_u, P_u, P_s ) := AuthDec_rw (c); +// (d) Computes K := KE(p_u, x_u, P_s, X_s) and SK := f_K(0); +// (e) Outputs (sid, ssid, SK). +int opaque_RecoverCredentials(const uint8_t _resp[OPAQUE_SERVER_SESSION_LEN], + const uint8_t *_sec/*[OPAQUE_USER_SESSION_SECRET_LEN+pwdU_len]*/, + const uint8_t *ctx, const uint16_t ctx_len, + const Opaque_Ids *ids0, + uint8_t sk[OPAQUE_SHARED_SECRETBYTES], + uint8_t authU[crypto_auth_hmacsha512_BYTES], + uint8_t export_key[crypto_hash_sha512_BYTES]) { + + Opaque_ServerSession *resp = (Opaque_ServerSession *) _resp; + Opaque_UserSession_Secret *sec = (Opaque_UserSession_Secret *) _sec; + +#ifdef TRACE + dump(sec->pwdU,sec->pwdU_len, "session user finish pwdU "); + dump(_sec,OPAQUE_USER_SESSION_SECRET_LEN, "session user finish sec "); + dump(_resp,OPAQUE_SERVER_SESSION_LEN, "session user finish resp "); +#endif + + // 1. (client_private_key, server_public_key, export_key) = + // RecoverCredentials(state.password, state.blind, ke2.CredentialResponse, + // server_identity, client_identity) + // 1.1. y = Finalize(password, blind, response.data, nil) + // 1.2. randomized_pwd = Extract("", concat(y, Harden(y, params))) + uint8_t N[crypto_core_ristretto255_BYTES]; + if(-1==sodium_mlock(N, sizeof N)) return -1; + // 1. N = Unblind(blind, response.data) + if(0!=oprf_Unblind(sec->blind, resp->Z, N)) { + sodium_munlock(N, sizeof N); + return -1; + } +#if (defined TRACE || defined CFRG_TEST_VEC) + dump(N, sizeof N, "unblinded"); +#endif + + // rw = H(pw, β^(1/r)) + uint8_t rwdU[OPAQUE_RWDU_BYTES]; + if(-1==sodium_mlock(rwdU,sizeof rwdU)) { + sodium_munlock(N, sizeof N); + return -1; + } + // 1.2. y = Finalize(pwdU, N, "OPAQUE01") + if(0!=oprf_Finalize(sec->pwdU, sec->pwdU_len, N, rwdU)) { + sodium_munlock(N, sizeof N); + sodium_munlock(rwdU,sizeof rwdU); + return -1; + } + sodium_munlock(N,sizeof N); + +#if (defined TRACE || defined CFRG_TEST_VEC) + dump(rwdU, sizeof rwdU, "rwdU"); +#endif + + // 1.3. masking_key = HKDF-Expand(randomized_pwd, "MaskingKey", Nh) + const uint8_t masking_key_info[10]="MaskingKey"; + uint8_t masking_key[crypto_hash_sha512_BYTES]; + if(-1==sodium_mlock(masking_key,sizeof masking_key)) { + sodium_munlock(rwdU,sizeof rwdU); + return -1; + } + crypto_kdf_hkdf_sha512_expand(masking_key, crypto_hash_sha512_BYTES, + (const char*) masking_key_info, sizeof masking_key_info, + rwdU); + + // 1.4. credential_response_pad = Expand(masking_key, + // concat(response.masking_nonce, "CredentialResponsePad"), Npk + Ne) + + // 1.5. credential_response_pad = Expand(record.masking_key, concat(masking_nonce, "CredentialResponsePad"), Npk + Ne) + struct { + uint8_t nonce[32]; + uint8_t dst[21]; + } __attribute((packed)) masking_info = { + .nonce = {0}, + .dst = "CredentialResponsePad"}; + memcpy(masking_info.nonce, resp->masking_nonce, sizeof masking_info.nonce); + + uint8_t response_pad[crypto_scalarmult_BYTES+sizeof(Opaque_Envelope)]; + if(-1==sodium_mlock(response_pad,sizeof response_pad)) { + sodium_munlock(masking_key,sizeof masking_key); + sodium_munlock(rwdU,sizeof rwdU); + return -1; + } + crypto_kdf_hkdf_sha512_expand(response_pad, sizeof response_pad, + (const char*) &masking_info, sizeof masking_info, + masking_key); + sodium_munlock(masking_key,sizeof masking_key); + + // 1.5. concat(server_public_key, envelope) = xor(credential_response_pad, + // response.masked_response) + Opaque_Envelope env; + if(-1==sodium_mlock(&env,sizeof env)) { + sodium_mlock(response_pad,sizeof response_pad); + sodium_munlock(rwdU,sizeof rwdU); + return -1; + } + uint8_t server_public_key[crypto_scalarmult_BYTES], *env_ptr=(uint8_t*) &env; + unsigned i; + for(i=0;imasked_response[i]; + for(;imasked_response[i]; + sodium_mlock(response_pad,sizeof response_pad); + +#if (defined TRACE || defined CFRG_TEST_VEC) + dump(server_public_key, sizeof server_public_key, "server_public_key"); + dump(env.nonce, sizeof env.nonce, "env.nonce"); + dump(env.auth_tag, sizeof env.auth_tag, "env.auth_tag"); +#endif + + // 1.6. (client_private_key, export_key) = + // Recover(randomized_pwd, server_public_key, envelope, + // server_identity, client_identity) + + uint8_t concated[OPAQUE_ENVELOPE_NONCEBYTES+10], + *label = concated+OPAQUE_ENVELOPE_NONCEBYTES; + memcpy(concated, env.nonce, OPAQUE_ENVELOPE_NONCEBYTES); + + // 1.6.1. auth_key = Expand(randomized_pwd, concat(envelope.nonce, "AuthKey"), Nh) + uint8_t auth_key[OPAQUE_HMAC_SHA512_KEYBYTES]; + if(-1==sodium_mlock(auth_key, sizeof auth_key)) { + sodium_munlock(rwdU,sizeof rwdU); + return -1; + } + memcpy(label, "AuthKey", 7); + crypto_kdf_hkdf_sha512_expand(auth_key, sizeof auth_key, + (const char*) concated, OPAQUE_ENVELOPE_NONCEBYTES+7, + rwdU); + +#ifdef TRACE + dump(auth_key,sizeof auth_key, "auth_key "); +#endif + + if(NULL!=export_key) { + // 1.6.2. export_key = Expand(randomized_pwd, concat(envelope.nonce, "ExportKey", Nh) + memcpy(label, "ExportKey", 9); +#if (defined TRACE || defined CFRG_TEST_VEC) + dump(concated, OPAQUE_ENVELOPE_NONCEBYTES+9, "export_key_info"); +#endif + crypto_kdf_hkdf_sha512_expand(export_key, crypto_hash_sha512_BYTES, + (const char*) concated, OPAQUE_ENVELOPE_NONCEBYTES+9, + rwdU); +#ifdef TRACE + dump(export_key,crypto_hash_sha512_BYTES, "export_key "); +#endif + } + + // 1.6.3. seed = Expand(randomized_pwd, concat(envelope.nonce, "PrivateKey"), Nseed) + memcpy(label, "PrivateKey", 10); + uint8_t seed[crypto_core_ristretto255_SCALARBYTES]; + if(-1==sodium_mlock(seed, sizeof seed)) { + sodium_munlock(auth_key, sizeof auth_key); + sodium_munlock(rwdU,sizeof rwdU); + return -1; + } + crypto_kdf_hkdf_sha512_expand(seed, crypto_core_ristretto255_SCALARBYTES, + (const char*) concated, OPAQUE_ENVELOPE_NONCEBYTES+10, + rwdU); + sodium_munlock(rwdU,sizeof rwdU); + + // 1.6.4. client_private_key, client_public_key = DeriveAuthKeyPair(seed) + uint8_t client_secret_key[crypto_scalarmult_SCALARBYTES]; + if(-1==sodium_mlock(client_secret_key, sizeof client_secret_key)) { + sodium_munlock(seed, sizeof seed); + sodium_munlock(auth_key, sizeof auth_key); + return -1; + } + const uint8_t dst[24]="OPAQUE-DeriveAuthKeyPair"; + uint8_t client_public_key[crypto_scalarmult_BYTES]; + if(0!=deriveKeyPair(seed, sizeof seed, dst, sizeof dst, client_secret_key, client_public_key)) { + sodium_munlock(seed, sizeof seed); + sodium_munlock(client_secret_key, sizeof client_secret_key); + sodium_munlock(auth_key, sizeof auth_key); + return -1; + } + sodium_munlock(seed, sizeof seed); +#if (defined CFRG_TEST_VEC || defined TRACE) + dump(client_secret_key, crypto_scalarmult_SCALARBYTES, "client_secret_key"); +#endif +#if (defined CFRG_TEST_VEC || defined TRACE) + dump(client_public_key, crypto_scalarmult_BYTES, "client_public_key"); +#endif + + // 1.6.5. cleartext_creds = CreateCleartextCredentials(server_public_key, + // client_public_key, server_identity, client_identity) + + Opaque_Ids ids; + fix_ids(client_public_key, server_public_key, ids0, &ids); + uint8_t authenticated[OPAQUE_NONCE_BYTES+ + crypto_scalarmult_BYTES+ + ids.idS_len+2+ + ids.idU_len+2], + *ptr=authenticated; + + // nonce + memcpy(ptr, env.nonce, OPAQUE_NONCE_BYTES); + ptr+=OPAQUE_NONCE_BYTES; + // server_public_key + memcpy(ptr, server_public_key, crypto_scalarmult_BYTES); + ptr+=crypto_scalarmult_BYTES; + // server_identity + uint16_t size = htons(ids.idS_len); + memcpy(ptr,(uint8_t*) &size, 2); + ptr+=2; + memcpy(ptr,ids.idS,ids.idS_len); + ptr+=ids.idS_len; + // client_identity + size = htons(ids.idU_len); + memcpy(ptr,(uint8_t*) &size, 2); + ptr+=2; + memcpy(ptr,ids.idU,ids.idU_len); + + // 1.6.6. expected_tag = MAC(auth_key, concat(envelope.nonce, cleartext_creds)) + uint8_t auth_tag[crypto_auth_hmacsha512_BYTES]; + opaque_hmacsha512(auth_key, // key + authenticated, // in + sizeof authenticated, // len(in) + auth_tag); // out + +#if (defined TRACE || defined CFRG_TEST_VEC) + dump(authenticated, sizeof authenticated, "authenticated"); + dump(auth_key, sizeof auth_key, "auth_key"); + dump(env.auth_tag, crypto_auth_hmacsha512_BYTES, "env auth_tag"); + dump(auth_tag, crypto_hash_sha512_BYTES, "auth tag "); +#endif + sodium_munlock(auth_key, sizeof auth_key); + + // 1.6.7. If !ct_equal(envelope.auth_tag, expected_tag), + // raise KeyRecoveryError + if(0!=sodium_memcmp(env.auth_tag, auth_tag, sizeof auth_tag)) { + sodium_munlock(client_secret_key, sizeof client_secret_key); + return -1; + } + + // 2. (ke3, session_key) = + // ClientFinalize(client_identity, client_private_key, server_identity, + + // 2.2. preamble = Preamble(client_identity, state.ke1, server_identity, ke2.inner_ke2) + char preamble[crypto_hash_sha512_BYTES]; + crypto_hash_sha512_state preamble_state; + calc_preamble(preamble, &preamble_state, client_public_key, server_public_key, sec->ke1, resp, ctx, ctx_len, &ids); + + Opaque_Keys keys; + if(-1==sodium_mlock(&keys,sizeof(keys))) { + sodium_munlock(client_secret_key, sizeof client_secret_key); + return -1; + } + // 2.1. ikm = TripleDHIKM(state.client_secret, ke2.server_keyshare, + // state.client_secret, server_public_key, client_private_key, ke2.server_keyshare) + // 2.3. Km2, Km3, session_key = DeriveKeys(ikm, preamble) + if(0!=user_3dh(&keys, client_secret_key, sec->x_u, server_public_key, resp->X_s, preamble)) { + sodium_munlock(client_secret_key, sizeof client_secret_key); + sodium_munlock(&keys, sizeof(keys)); + return -1; + } + sodium_munlock(client_secret_key, sizeof client_secret_key); + + // 2.4. expected_server_mac = MAC(Km2, Hash(preamble)) + uint8_t authS[crypto_auth_hmacsha512_BYTES]; + opaque_hmacsha512(keys.km2, + (uint8_t*)preamble, // in + crypto_hash_sha512_BYTES, // len(in) + authS); // out + + // 2.5. If !ct_equal(ke2.server_mac, expected_server_mac), + // raise HandshakeError + if (sodium_memcmp(authS, resp->auth, sizeof authS)!=0) { + sodium_munlock(&keys, sizeof(keys)); + return -1; + } + + // 2.6. client_mac = MAC(Km3, Hash(concat(preamble, expected_server_mac)) + crypto_hash_sha512_update(&preamble_state, authS, crypto_auth_hmacsha512_BYTES); + crypto_hash_sha512_final(&preamble_state, (uint8_t *) preamble); + if(NULL!=authU) { + opaque_hmacsha512(keys.km3, // key + (uint8_t*)preamble, // in + crypto_hash_sha512_BYTES, // len(in) + authU); // out + } + + // 2.7. Create KE3 ke3 with client_mac + // 2.8. Output (ke3, session_key) + memcpy(sk,keys.sk,sizeof(keys.sk)); + + sodium_munlock(&keys, sizeof(keys)); + return 0; +} + +// extra function to implement the hmac based auth as defined in the irtf cfrg draft +int opaque_UserAuth(const uint8_t authU0[crypto_auth_hmacsha512_BYTES], const uint8_t authU[crypto_auth_hmacsha512_BYTES]) { + return sodium_memcmp(authU0, authU, crypto_auth_hmacsha512_BYTES); +} + +// variant where the secrets of U never touch S unencrypted + +// U computes: blinded PW +// called CreateRegistrationRequest in the irtf cfrg rfc draft +int opaque_CreateRegistrationRequest(const uint8_t *pwdU, const uint16_t pwdU_len, uint8_t _sec[OPAQUE_REGISTER_USER_SEC_LEN+pwdU_len], uint8_t blinded[crypto_core_ristretto255_BYTES]) { + Opaque_RegisterUserSec *sec = (Opaque_RegisterUserSec *) _sec; + memcpy(&sec->pwdU, pwdU, pwdU_len); + sec->pwdU_len = pwdU_len; + // 1. (blind, blinded) = Blind(pwdU) + return oprf_Blind(pwdU, pwdU_len, sec->blind, blinded); +} + +// initUser: S +// (1) checks α ∈ G^∗ If not, outputs (abort, sid , ssid ) and halts; +// (2) generates k_s ←_R Z_q, +// (3) computes: β := α^k_s, +// (4) finally generates: p_s ←_R Z_q, P_s := g^p_s; +// called CreateRegistrationResponse in the irtf cfrg rfc draft +int opaque_CreateRegistrationResponse(const uint8_t blinded[crypto_core_ristretto255_BYTES], const uint8_t skS[crypto_scalarmult_SCALARBYTES], uint8_t _sec[OPAQUE_REGISTER_SECRET_LEN], uint8_t _pub[OPAQUE_REGISTER_PUBLIC_LEN]) { + Opaque_RegisterSrvSec *sec = (Opaque_RegisterSrvSec *) _sec; + Opaque_RegisterSrvPub *pub = (Opaque_RegisterSrvPub *) _pub; + + // (a) Checks that α ∈ G^∗ . If not, outputs (abort, sid , ssid ) and halts; + if(crypto_core_ristretto255_is_valid_point(blinded)!=1) return -1; + + // k_s ←_R Z_q + // 1. (kU, _) = KeyGen() + oprf_KeyGen(sec->kU); + + // computes β := α^k_s + // 2. Z = Evaluate(kU, request.data) + if (oprf_Evaluate(sec->kU, blinded, pub->Z) != 0) { + return -1; + } +#if (defined TRACE || defined CFRG_TEST_VEC) + dump(sec->kU, sizeof sec->kU, "kU"); + dump(pub->Z, sizeof pub->Z, "EvaluationElement"); +#endif + + if(skS==NULL) { + randombytes(sec->skS, crypto_scalarmult_SCALARBYTES); // random server long-term key + } else { + memcpy(sec->skS, skS, crypto_scalarmult_SCALARBYTES); + } + +#ifdef TRACE + dump((uint8_t*) sec->skS, sizeof sec->skS, "skS "); +#endif + // P_s := g^p_s + crypto_scalarmult_ristretto255_base(pub->pkS, sec->skS); + +#ifdef TRACE + dump((uint8_t*) pub->pkS, sizeof pub->pkS, "pkS "); +#endif + + return 0; +} + +// user computes: +// (a) Checks that β ∈ G ∗ . If not, outputs (abort, sid , ssid ) and halts; +// (b) Computes rw := H(key, pw | β^1/r ); +// (c) p_u ←_R Z_q +// (d) P_u := g^p_u, +// (e) c ← AuthEnc_rw (p_u, P_u, P_s); +// called FinalizeRequest in the irtf cfrg rfc draft +int opaque_FinalizeRequest(const uint8_t *_sec/*[OPAQUE_REGISTER_USER_SEC_LEN+pwdU_len]*/, + const uint8_t _pub[OPAQUE_REGISTER_PUBLIC_LEN], + const Opaque_Ids *ids, + uint8_t _rec[OPAQUE_REGISTRATION_RECORD_LEN], + uint8_t export_key[crypto_hash_sha512_BYTES]) { + + Opaque_RegisterUserSec *sec = (Opaque_RegisterUserSec *) _sec; + Opaque_RegisterSrvPub *pub = (Opaque_RegisterSrvPub *) _pub; + Opaque_RegistrationRecord *rec = (Opaque_RegistrationRecord *) _rec; + + uint8_t N[crypto_core_ristretto255_BYTES]; + if(-1==sodium_mlock(N, sizeof N)) return -1; + // 1. N = Unblind(blind, response.data) + if(0!=oprf_Unblind(sec->blind, pub->Z, N)) { + sodium_munlock(N, sizeof N); + return -1; + } +#if (defined TRACE || defined CFRG_TEST_VEC) + dump(N, sizeof N, "unblinded"); +#endif + + uint8_t rwdU[OPAQUE_RWDU_BYTES]; + if(-1==sodium_mlock(rwdU, sizeof rwdU)) { + sodium_munlock(N, sizeof N); + return -1; + } + // 2. y = Finalize(pwdU, N, "OPAQUE01") + if(0!=oprf_Finalize(sec->pwdU, sec->pwdU_len, N, rwdU)) { + sodium_munlock(N, sizeof N); + sodium_munlock(rwdU, sizeof(rwdU)); + return -1; + } + sodium_munlock(N,sizeof N); + + if(0!=create_envelope(rwdU, pub->pkS, ids, &rec->envelope, rec->client_public_key, rec->masking_key, export_key)) { + sodium_munlock(rwdU, sizeof rwdU); + return -1; + } + sodium_munlock(rwdU, sizeof rwdU); + +#if (defined TRACE || defined CFRG_TEST_VEC) + dump(_rec, OPAQUE_REGISTRATION_RECORD_LEN, "record"); +#endif + +#ifdef TRACE + dump(_rec, OPAQUE_REGISTRATION_RECORD_LEN, "registration rec "); +#endif + + return 0; +} + +// S records file[sid ] := {k_s, p_s, P_s, P_u, c}. +// called StoreUserRecord in the irtf cfrg rfc draft +void opaque_StoreUserRecord(const uint8_t _sec[OPAQUE_REGISTER_SECRET_LEN], const uint8_t recU[OPAQUE_REGISTRATION_RECORD_LEN], uint8_t _rec[OPAQUE_USER_RECORD_LEN]) { + Opaque_RegisterSrvSec *sec = (Opaque_RegisterSrvSec *) _sec; + Opaque_UserRecord *rec = (Opaque_UserRecord *) _rec; + + memcpy(rec->kU, sec->kU, sizeof rec->kU); + memcpy(rec->skS, sec->skS, crypto_scalarmult_SCALARBYTES); + memcpy((uint8_t*)&rec->recU, recU, OPAQUE_REGISTRATION_RECORD_LEN); + //crypto_scalarmult_base(rec->pkS, skS); +#ifdef TRACE + dump((uint8_t*) rec, OPAQUE_USER_RECORD_LEN, "user rec "); +#endif +} From f2446064d27ddbca8046cc092bd5b06085e0e651 Mon Sep 17 00:00:00 2001 From: stf <7o5rfu92t@ctrlc.hu> Date: Wed, 18 Jan 2023 20:07:49 +0100 Subject: [PATCH 723/796] added licenses to the files not having them Signed-off-by: stf <7o5rfu92t@ctrlc.hu> --- plugins/kdf_hkdf_sha512.c | 19 +++++++++++++++++++ plugins/opaque.c | 18 ++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/plugins/kdf_hkdf_sha512.c b/plugins/kdf_hkdf_sha512.c index f201db97..427d3960 100644 --- a/plugins/kdf_hkdf_sha512.c +++ b/plugins/kdf_hkdf_sha512.c @@ -1,3 +1,22 @@ +/* + * ISC License + * + * Copyright (c) 2013-2023 + * Frank Denis + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + #include #include diff --git a/plugins/opaque.c b/plugins/opaque.c index c7c6bfb5..81c6d2f6 100644 --- a/plugins/opaque.c +++ b/plugins/opaque.c @@ -1,3 +1,21 @@ +/* + @copyright 2018-21, opaque@ctrlc.hu + This file is part of the cyrus-sasl opaque mechansim. + + The cyrus-sasl opaque mechanism is free software: you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + The cyrus-sasl opaque mechanism 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 The cyrus-sasl opaque mechanism. If not, see . +*/ + #include #include #include "plugin_common.h" From 5392c39aa2dde6feb7a41a20635b19b889f06727 Mon Sep 17 00:00:00 2001 From: Bastian Germann Date: Fri, 21 Jul 2023 20:33:40 +0200 Subject: [PATCH 724/796] Correct m4 syntax error 0b104e52fe (Fix #718 - Remove BDB support) has removed a m4 fi and a configure.ac test verb. Recover them. Signed-off-by: Bastian Germann --- configure.ac | 2 +- m4/sasldb.m4 | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index aeb6b521..ab78da2e 100644 --- a/configure.ac +++ b/configure.ac @@ -160,7 +160,7 @@ AC_ARG_ENABLE(keep_db_open, [ --enable-keep-db-open keep handle to DB open fo keep_db_open=no) # Disable if LMDB is not used -if "$dblib" != lmdb; then +if test "$dblib" != lmdb; then keep_db_open=no fi diff --git a/m4/sasldb.m4 b/m4/sasldb.m4 index 18e95dc5..d0bcd699 100644 --- a/m4/sasldb.m4 +++ b/m4/sasldb.m4 @@ -76,6 +76,7 @@ dnl named. arg. SASL_DB_LIB="-lgdbm", dblib="no")], dblib="no") fi + fi ;; none) ;; From 20001728ccc3a2061b3ce160e10ec308279b22a0 Mon Sep 17 00:00:00 2001 From: Bastian Germann Date: Fri, 21 Jul 2023 20:33:40 +0200 Subject: [PATCH 725/796] Correct m4 syntax error 0b104e52fe (Fix #718 - Remove BDB support) has removed a m4 fi and a configure.ac test verb. Recover them. Signed-off-by: Bastian Germann --- configure.ac | 2 +- m4/sasldb.m4 | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 1a4f7336..ff2cdcf4 100644 --- a/configure.ac +++ b/configure.ac @@ -160,7 +160,7 @@ AC_ARG_ENABLE(keep_db_open, [ --enable-keep-db-open keep handle to DB open fo keep_db_open=no) # Disable if LMDB is not used -if "$dblib" != lmdb; then +if test "$dblib" != lmdb; then keep_db_open=no fi diff --git a/m4/sasldb.m4 b/m4/sasldb.m4 index 18e95dc5..d0bcd699 100644 --- a/m4/sasldb.m4 +++ b/m4/sasldb.m4 @@ -76,6 +76,7 @@ dnl named. arg. SASL_DB_LIB="-lgdbm", dblib="no")], dblib="no") fi + fi ;; none) ;; From d7ebceabf3395eadbfb70234c5def13dc8a1cdf4 Mon Sep 17 00:00:00 2001 From: Bastian Germann Date: Fri, 15 Apr 2022 02:03:44 +0200 Subject: [PATCH 726/796] utils: Include missing manpages Signed-off-by: Bastian Germann --- utils/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/Makefile.am b/utils/Makefile.am index 9846884b..dcb93126 100644 --- a/utils/Makefile.am +++ b/utils/Makefile.am @@ -50,7 +50,7 @@ EXTRA_PROGRAMS = saslpasswd2 sasldblistusers2 testsuite testsuitestatic smtptest noinst_PROGRAMS = dbconverter-2 -man_MANS = $(SASL_DB_MANS) pluginviewer.8 +man_MANS = $(SASL_DB_MANS) saslpasswd2.8 pluginviewer.8 saslpasswd2_LDADD = ../sasldb/libsasldb.la $(all_sasl_libs) saslpasswd2_SOURCES = saslpasswd.c @@ -91,7 +91,7 @@ libsfsasl2_la_LDFLAGS = -version-info 1:0:0 -export-dynamic -rpath $(libdir) AM_CPPFLAGS=-DLIBSASL_EXPORTS=1 -I$(top_srcdir)/include -I$(top_builddir)/include @SASL_DB_INC@ -DPLUGINDIR='"${plugindir}"' -EXTRA_DIST = saslpasswd2.8 sasldblistusers2.8 pluginviewer.8 sfsasl.h sfsasl.c smtptest.c testsuite.c pluginviewer.c NTMakefile +EXTRA_DIST = saslpasswd2.8 sasldbconverter2.8 sasldblistusers2.8 sasltestsuite.8 pluginviewer.8 sfsasl.h sfsasl.c smtptest.c testsuite.c pluginviewer.c NTMakefile sfsasl.lo: sfsasl.c $(LIBTOOL) --mode=compile $(COMPILE) @SFIO_INC_FLAGS@ -c $(srcdir)/sfsasl.c From d776d25585f2a7cee04dc12ec44950ee666d7aad Mon Sep 17 00:00:00 2001 From: Bastian Germann Date: Fri, 15 Apr 2022 02:25:12 +0200 Subject: [PATCH 727/796] Makefile.am: Include useful READMEs README is included in dist but the referenced README.md is not. Include it as well as README.ldapdb which contains license info. Signed-off-by: Bastian Germann --- Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 102e2a3e..a5ede533 100644 --- a/Makefile.am +++ b/Makefile.am @@ -67,7 +67,7 @@ endif SUBDIRS=include sasldb common lib plugins utils $(PWC) $(SAM) $(SAD) tests EXTRA_DIST=config doc docsrc win32 mac dlcompat-20010505 NTMakefile \ - INSTALL.TXT libsasl2.pc.in + README.md README.ldapdb INSTALL.TXT libsasl2.pc.in dist_man3_MANS = \ man/sasl.3 \ From 7388c565880c6f78331d2df9354d2adc59acfed6 Mon Sep 17 00:00:00 2001 From: Bastian Germann Date: Fri, 15 Apr 2022 02:27:51 +0200 Subject: [PATCH 728/796] saslauthd: Include useful READMEs The saslauthd's READMEs contain useful info, so include them in the dist. Signed-off-by: Bastian Germann --- saslauthd/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/saslauthd/Makefile.am b/saslauthd/Makefile.am index 4db605f4..0d6d6d04 100644 --- a/saslauthd/Makefile.am +++ b/saslauthd/Makefile.am @@ -31,7 +31,7 @@ testsaslauthd_LDADD = @LIB_SOCKET@ saslcache_SOURCES = saslcache.c EXTRA_DIST = testsaslauthd.8 saslauthd.mdoc include \ - LDAP_SASLAUTHD + LDAP_SASLAUTHD README.cache README.ipc AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include -I$(top_builddir)/common -I$(top_srcdir)/common DEFS = @DEFS@ -DSASLAUTHD_CONF_FILE_DEFAULT=\"@sysconfdir@/saslauthd.conf\" -I. -I$(srcdir) -I.. From d88de177560752ad3cc393115918225e8bc939e6 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Sat, 22 Jul 2023 20:44:07 +0100 Subject: [PATCH 729/796] More for aa0cf8b47a1998eaa21fe97fe5e88e3c305b1465 Remove dangling SASL_KRB_LIB macros. Signed-off-by: Howard Chu --- saslauthd/Makefile.am | 3 +-- utils/Makefile.am | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/saslauthd/Makefile.am b/saslauthd/Makefile.am index 0d6d6d04..c20dbcae 100644 --- a/saslauthd/Makefile.am +++ b/saslauthd/Makefile.am @@ -21,8 +21,7 @@ saslauthd_SOURCES = mechanisms.c globals.h \ utils.c utils.h \ ipc_unix.c ipc_doors.c saslauthd-main.c saslauthd-main.h saslauthd_DEPENDENCIES = saslauthd-main.o $(LTLIBOBJS_FULL) -saslauthd_LDADD = @SASL_KRB_LIB@ \ - @GSSAPIBASE_LIBS@ @LIB_CRYPT@ @LIB_SIA@ \ +saslauthd_LDADD = @GSSAPIBASE_LIBS@ @LIB_CRYPT@ @LIB_SIA@ \ @LIB_SOCKET@ @SASL_DB_LIB@ @LIB_PAM@ @LDAP_LIBS@ $(LTLIBOBJS_FULL) $(CRYPTO_COMPAT_OBJS) $(LIBSASLDB_OBJS) -lcrypto testsaslauthd_SOURCES = testsaslauthd.c utils.c diff --git a/utils/Makefile.am b/utils/Makefile.am index dcb93126..193929d6 100644 --- a/utils/Makefile.am +++ b/utils/Makefile.am @@ -43,7 +43,7 @@ ################################################################ all_sasl_libs = ../lib/libsasl2.la $(SASL_DB_LIB) $(LIB_SOCKET) -all_sasl_static_libs = ../lib/.libs/libsasl2.a $(SASL_DB_LIB) $(LIB_SOCKET) $(GSSAPIBASE_LIBS) $(GSSAPI_LIBS) $(SASL_KRB_LIB) $(LIB_DES) $(PLAIN_LIBS) $(SRP_LIBS) $(LIB_MYSQL) $(LIB_PGSQL) $(LIB_SQLITE) +all_sasl_static_libs = ../lib/.libs/libsasl2.a $(SASL_DB_LIB) $(LIB_SOCKET) $(GSSAPIBASE_LIBS) $(GSSAPI_LIBS) $(LIB_DES) $(PLAIN_LIBS) $(SRP_LIBS) $(LIB_MYSQL) $(LIB_PGSQL) $(LIB_SQLITE) sbin_PROGRAMS = @SASL_DB_UTILS@ @SMTPTEST_PROGRAM@ pluginviewer EXTRA_PROGRAMS = saslpasswd2 sasldblistusers2 testsuite testsuitestatic smtptest pluginviewer From 9bb745d247832cfa7f15513138a71cfbf0b57cdd Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Sat, 22 Jul 2023 20:47:18 +0100 Subject: [PATCH 730/796] More for eb77d5baf156e7609c9add92834864b37d3c7fb4 OpenSSL API uses pointers to key sched. Signed-off-by: Howard Chu --- plugins/digestmd5.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/plugins/digestmd5.c b/plugins/digestmd5.c index febaa902..237ddd08 100644 --- a/plugins/digestmd5.c +++ b/plugins/digestmd5.c @@ -873,8 +873,8 @@ static int dec_3des(context_t *text, DES_ede2_cbc_encrypt((void *) input, (void *) output, inputlen, - c->keysched, - c->keysched2, + &c->keysched, + &c->keysched2, &c->ivec, DES_DECRYPT); @@ -921,8 +921,8 @@ static int enc_3des(context_t *text, DES_ede2_cbc_encrypt((void *) output, (void *) output, len, - c->keysched, - c->keysched2, + &c->keysched, + &c->keysched2, &c->ivec, DES_ENCRYPT); @@ -944,11 +944,11 @@ static int init_3des(context_t *text, /* setup enc context */ slidebits(keybuf, enckey); - if (DES_key_sched((DES_cblock *) keybuf, c->keysched) < 0) + if (DES_key_sched((DES_cblock *) keybuf, &c->keysched) < 0) return SASL_FAIL; slidebits(keybuf, enckey + 7); - if (DES_key_sched((DES_cblock *) keybuf, c->keysched2) < 0) + if (DES_key_sched((DES_cblock *) keybuf, &c->keysched2) < 0) return SASL_FAIL; memcpy(c->ivec, ((char *) enckey) + 8, 8); @@ -957,11 +957,11 @@ static int init_3des(context_t *text, /* setup dec context */ c++; slidebits(keybuf, deckey); - if (DES_key_sched((DES_cblock *) keybuf, c->keysched) < 0) + if (DES_key_sched((DES_cblock *) keybuf, &c->keysched) < 0) return SASL_FAIL; slidebits(keybuf, deckey + 7); - if (DES_key_sched((DES_cblock *) keybuf, c->keysched2) < 0) + if (DES_key_sched((DES_cblock *) keybuf, &c->keysched2) < 0) return SASL_FAIL; memcpy(c->ivec, ((char *) deckey) + 8, 8); @@ -991,7 +991,7 @@ static int dec_des(context_t *text, DES_cbc_encrypt((void *) input, (void *) output, inputlen, - c->keysched, + &c->keysched, &c->ivec, DES_DECRYPT); @@ -1042,7 +1042,7 @@ static int enc_des(context_t *text, DES_cbc_encrypt((void *) output, (void *) output, len, - c->keysched, + &c->keysched, &c->ivec, DES_ENCRYPT); @@ -1068,7 +1068,7 @@ static int init_des(context_t *text, /* setup enc context */ slidebits(keybuf, enckey); - DES_key_sched((DES_cblock *) keybuf, c->keysched); + DES_key_sched((DES_cblock *) keybuf, &c->keysched); memcpy(c->ivec, ((char *) enckey) + 8, 8); @@ -1077,7 +1077,7 @@ static int init_des(context_t *text, /* setup dec context */ c++; slidebits(keybuf, deckey); - DES_key_sched((DES_cblock *) keybuf, c->keysched); + DES_key_sched((DES_cblock *) keybuf, &c->keysched); memcpy(c->ivec, ((char *) deckey) + 8, 8); From b0a587383e0d4e9852ec973accc0854a10b0f128 Mon Sep 17 00:00:00 2001 From: Bastian Germann Date: Fri, 21 Jul 2023 23:20:45 +0200 Subject: [PATCH 731/796] sample: Rename dprint function The function name collides with a macro defined by glibc for gcc < 4.3 and clang. Rename to prevent that. Fixes #657 Signed-off-by: Bastian Germann --- sample/client.c | 12 ++++++------ sample/common.c | 2 +- sample/common.h | 2 +- sample/server.c | 16 ++++++++-------- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/sample/client.c b/sample/client.c index bc8e3dc2..acb289fb 100644 --- a/sample/client.c +++ b/sample/client.c @@ -252,9 +252,9 @@ int mysasl_negotiate(FILE *in, FILE *out, sasl_conn_t *conn) int r, c; /* get the capability list */ - dprintf(0, "receiving capability list... "); + debug_printf(0, "receiving capability list... "); len = recv_string(in, buf, sizeof buf); - dprintf(0, "%s\n", buf); + debug_printf(0, "%s\n", buf); if (mech) { /* make sure that 'mech' appears in 'buf' */ @@ -273,7 +273,7 @@ int mysasl_negotiate(FILE *in, FILE *out, sasl_conn_t *conn) return -1; } - dprintf(1, "using mechanism %s\n", chosenmech); + debug_printf(1, "using mechanism %s\n", chosenmech); /* we send up to 3 strings; the mechanism chosen, the presence of initial response, @@ -287,7 +287,7 @@ int mysasl_negotiate(FILE *in, FILE *out, sasl_conn_t *conn) } for (;;) { - dprintf(2, "waiting for server reply...\n"); + debug_printf(2, "waiting for server reply...\n"); c = fgetc(in); switch (c) { @@ -314,10 +314,10 @@ int mysasl_negotiate(FILE *in, FILE *out, sasl_conn_t *conn) } if (data) { - dprintf(2, "sending response length %d...\n", len); + debug_printf(2, "sending response length %d...\n", len); send_string(out, data, len); } else { - dprintf(2, "sending null response...\n"); + debug_printf(2, "sending null response...\n"); send_string(out, "", 0); } } diff --git a/sample/common.c b/sample/common.c index 712549fd..9ae1cc3f 100644 --- a/sample/common.c +++ b/sample/common.c @@ -127,7 +127,7 @@ int recv_string(FILE *f, char *buf, int buflen) int debuglevel = 0; -int dprintf(int lvl, const char *fmt, ...) +int debug_printf(int lvl, const char *fmt, ...) { va_list ap; int ret = 0; diff --git a/sample/common.h b/sample/common.h index 819d0101..9f53e724 100644 --- a/sample/common.h +++ b/sample/common.h @@ -43,7 +43,7 @@ extern int send_string(FILE *f, const char *s, int l); extern int recv_string(FILE *f, char *buf, int buflen); extern int debuglevel; -extern int dprintf(int lvl, const char *fmt, ...); +extern int debug_printf(int lvl, const char *fmt, ...); extern void saslerr(int why, const char *what); extern void saslfail(int why, const char *what); diff --git a/sample/server.c b/sample/server.c index 262b0178..43974765 100644 --- a/sample/server.c +++ b/sample/server.c @@ -227,17 +227,17 @@ int mysasl_negotiate(FILE *in, FILE *out, sasl_conn_t *conn) /* generate the capability list */ if (mech) { - dprintf(2, "forcing use of mechanism %s\n", mech); + debug_printf(2, "forcing use of mechanism %s\n", mech); data = strdup(mech); len = strlen(data); } else { int count; - dprintf(1, "generating client mechanism list... "); + debug_printf(1, "generating client mechanism list... "); r = sasl_listmech(conn, NULL, NULL, " ", NULL, &data, (unsigned int *) &len, &count); if (r != SASL_OK) saslfail(r, "generating mechanism list"); - dprintf(1, "%d mechanisms\n", count); + debug_printf(1, "%d mechanisms\n", count); } /* send capability list to client */ @@ -245,7 +245,7 @@ int mysasl_negotiate(FILE *in, FILE *out, sasl_conn_t *conn) if (mech) free((void *) data); - dprintf(1, "waiting for client mechanism...\n"); + debug_printf(1, "waiting for client mechanism...\n"); len = recv_string(in, chosenmech, sizeof chosenmech); if (len <= 0) { printf("client didn't choose mechanism\n"); @@ -290,16 +290,16 @@ int mysasl_negotiate(FILE *in, FILE *out, sasl_conn_t *conn) while (r == SASL_CONTINUE) { if (data) { - dprintf(2, "sending response length %d...\n", len); + debug_printf(2, "sending response length %d...\n", len); fputc('C', out); /* send CONTINUE to client */ send_string(out, data, len); } else { - dprintf(2, "sending null response...\n"); + debug_printf(2, "sending null response...\n"); fputc('C', out); /* send CONTINUE to client */ send_string(out, "", 0); } - dprintf(1, "waiting for client reply...\n"); + debug_printf(1, "waiting for client reply...\n"); len = recv_string(in, buf, sizeof buf); if (len < 0) { printf("client disconnected\n"); @@ -324,7 +324,7 @@ int mysasl_negotiate(FILE *in, FILE *out, sasl_conn_t *conn) fputc('O', out); /* send OK to client */ fflush(out); - dprintf(1, "negotiation complete\n"); + debug_printf(1, "negotiation complete\n"); r = sasl_getprop(conn, SASL_USERNAME, (const void **) &userid); printf("successful authentication '%s'\n", userid); From 2ce03b618ad60338e8f9094f5b7ba7ee0aef40bf Mon Sep 17 00:00:00 2001 From: Bastian Germann Date: Fri, 7 Jul 2023 01:13:19 +0200 Subject: [PATCH 732/796] digestmd5: Drop the mechanism The DIGEST-MD5 mechanism has been marked as historic by RFC 6331 for a decade. Drop it from cyrus-sasl. Signed-off-by: Bastian Germann --- config/sasl.spec | 14 - configure.ac | 38 - contrib/tclsasl/tcl/test.tcl | 2 +- doc/legacy/TODO | 5 - doc/legacy/components.html | 4 +- doc/legacy/index.html | 3 - doc/legacy/install.html | 6 +- doc/legacy/mechanisms.html | 18 - doc/legacy/options.html | 8 +- doc/legacy/plugprog.html | 4 +- doc/legacy/readme.html | 1 - doc/legacy/sysadmin.html | 6 +- doc/legacy/testing.txt | 2 +- docsrc/index.rst | 2 +- docsrc/sasl/authentication_mechanisms.rst | 11 - docsrc/sasl/components.rst | 4 +- docsrc/sasl/developer/plugprog.rst | 4 +- docsrc/sasl/developer/testing.rst | 2 +- docsrc/sasl/faqs/crammd5-digestmd5-scram.rst | 6 +- docsrc/sasl/faqs/openldap-sasl-gssapi.rst | 8 +- docsrc/sasl/faqs/plaintextpasswords.rst | 11 +- docsrc/sasl/faqs/rfcs.rst | 1 - docsrc/sasl/installation.rst | 6 +- docsrc/sasl/options.rst | 12 +- docsrc/sasl/quickstart.rst | 1 - .../manpages/library/sasl_listmech.rst | 2 +- docsrc/sasl/sysadmin.rst | 6 +- lib/staticopen.h | 8 - mac/include/sasl_digestmd5_plugin_decl.h | 5 - mac/mac_lib/mac_monolithic_dlopen.c | 6 - man/legacy/sasl_listmech.3 | 2 +- plugins/Makefile.am | 8 +- plugins/NTMakefile | 19 +- plugins/digestmd5.c | 4456 ----------------- plugins/makeinit.sh | 2 +- plugins/securid.c | 1 - sample/Makefile.am | 4 +- sample/http_digest_client.c | 254 - saslauthd/LDAP_SASLAUTHD | 2 +- utils/saslpasswd.c | 2 - win32/cyrus-sasl-all-in-one.sln | 5 - win32/cyrus-sasl-core.sln | 5 - win32/include/config.h | 1 - win32/makeinit.ps1 | 2 +- win32/plugin_digestmd5.vcxproj | 142 - win32/sasl2.vcxproj | 2 - 46 files changed, 46 insertions(+), 5067 deletions(-) delete mode 100755 mac/include/sasl_digestmd5_plugin_decl.h delete mode 100644 plugins/digestmd5.c delete mode 100644 sample/http_digest_client.c delete mode 100644 win32/plugin_digestmd5.vcxproj diff --git a/config/sasl.spec b/config/sasl.spec index 0e6f6bbd..f98952fd 100644 --- a/config/sasl.spec +++ b/config/sasl.spec @@ -37,15 +37,6 @@ CRAM-MD5 is the mandatory-to-implement authentication mechanism for a number of protocols; it uses MD5 with a challenge/response system to authenticate the user. -%package plug-digestmd5 -%summary: SASL DIGEST-MD5 mechanism plugin - -%description plug-digestmd5 -This plugin implements the latest draft of the SASL DIGEST-MD5 -mechanism. Although not yet finalized, this is likely to become the -new mandatory-to-implement authentication system in all new protocols. -It's based on the digest md5 authentication system designed for HTTP. - %package plug-plain %summary: SASL PLAIN mechanism plugin @@ -105,11 +96,6 @@ fi /usr/lib/sasl/libcrammd5.so.1.0.1 /usr/lib/sasl/libcrammd5.so -%files plug-digestmd5 -%doc doc/draft-leach-digest-sasl-01.txt -/usr/lib/sasl/libdigestmd5.so.0.0.1 -/usr/lib/sasl/libdigestmd5.so - %files plug-plain /usr/lib/sasl/libplain.so.1.0.1 /usr/lib/sasl/libplain.so diff --git a/configure.ac b/configure.ac index ff2cdcf4..003a80ec 100644 --- a/configure.ac +++ b/configure.ac @@ -82,11 +82,6 @@ AC_ARG_ENABLE(obsolete_cram_attr, enable_obsolete_cram_attr=$enableval, enable_obsolete_cram_attr=yes) -AC_ARG_ENABLE(obsolete_digest_attr, - [AS_HELP_STRING([--enable-obsolete_digest_attr],[enable support for cmusaslsecretDIGEST-MD5 auxprop property [[yes]]])], - enable_obsolete_digest_attr=$enableval, - enable_obsolete_digest_attr=yes) - AC_PROG_CC AX_PROG_CC_FOR_BUILD AC_PROG_CPP @@ -336,39 +331,6 @@ fi SASL_DES_CHK -dnl DIGEST-MD5 -AC_ARG_ENABLE(digest, [ --enable-digest enable DIGEST-MD5 authentication [[yes]] ], - digest=$enableval, - digest=yes) - -if test "$digest" != no; then - dnl In order to compile digest, we should look for need libdes. - if test -d $digest; then - CPPFLAGS="$CPPFLAGS -I$digest/include" - LDFLAGS="$LDFLAGS -L$digest/lib" - fi - if test "$with_des" = no; then - AC_MSG_WARN(No DES support for DIGEST-MD5) - fi -fi - -AC_MSG_CHECKING(DIGEST-MD5) -if test "$digest" != no -a $ac_cv_lib_crypto_MD5_Init = yes; then - AC_MSG_RESULT(enabled) - SASL_MECHS="$SASL_MECHS libdigestmd5.la" - if test "$enable_obsolete_digest_attr" = yes; then - CPPFLAGS="$CPPFLAGS -DOBSOLETE_DIGEST_ATTR=1" - fi - if test "$enable_static" = yes; then - SASL_STATIC_SRCS="$SASL_STATIC_SRCS \$(top_srcdir)/plugins/digestmd5.c" - SASL_STATIC_OBJS="$SASL_STATIC_OBJS digestmd5.o" - SASL_STATIC_LIBS="$SASL_STATIC_LIBS $LIB_DES" - AC_DEFINE(STATIC_DIGESTMD5, [], [Link DIGEST-MD5 Statically]) - fi -else - AC_MSG_RESULT(disabled) -fi - dnl SCRAM AC_ARG_ENABLE(scram, [ --enable-scram enable SCRAM authentication [[yes]] ], scram=$enableval, diff --git a/contrib/tclsasl/tcl/test.tcl b/contrib/tclsasl/tcl/test.tcl index 3ba701d5..69dab27f 100644 --- a/contrib/tclsasl/tcl/test.tcl +++ b/contrib/tclsasl/tcl/test.tcl @@ -51,7 +51,7 @@ array set client [list \ silent 0 \ service example \ fqdn example.com \ - mechanisms digest-md5 \ + mechanisms cram-md5 \ user "" \ language en-US \ authname fred \ diff --git a/doc/legacy/TODO b/doc/legacy/TODO index 1713937b..9cf05e1e 100644 --- a/doc/legacy/TODO +++ b/doc/legacy/TODO @@ -27,11 +27,6 @@ OTP ) Checking edge cases ) Testing -Digest-MD5 -~~~~~~~~~~ -) Checking wacko cases or even not so wacko cases -) Testing - Kerberos_V4 ~~~~~~~~~~~ ) client-side should set realm diff --git a/doc/legacy/components.html b/doc/legacy/components.html index ada1aa5f..85f6a08a 100644 --- a/doc/legacy/components.html +++ b/doc/legacy/components.html @@ -94,7 +94,7 @@

    Plugins (General)

    Plugins (SASL Mechanisms)

    The simplest types of plugins to understand are those which provide -SASL mechanisms, such as CRAM-MD5, DIGEST-MD5, GSSAPI, PLAIN, SCRAM, SRP, and so on. +SASL mechanisms, such as CRAM-MD5, GSSAPI, PLAIN, SCRAM, SRP, and so on. These mechanisms take care of both server-side and client-side parts of the SASL negotiation. If the given mechanism supports a security layer (that is, makes guarantees about privacy or integrity of data after the @@ -118,7 +118,7 @@

    Plugins (SASL Mechanisms)

    the server have access to a plaintext (or plaintext-equivalent) version of the password.
  • Shared Secret Mechanisms - For these mechanisms, -such as CRAM-MD5, DIGEST-MD5, OTP, SCRAM and SRP, +such as CRAM-MD5, OTP, SCRAM and SRP, there is a shared secret between the server and client (e.g. a password). However, in this case the password itself does not travel on the wire. Instead, the client passes a server a token that proves that it knows diff --git a/doc/legacy/index.html b/doc/legacy/index.html index fcbd97ef..809c0e59 100644 --- a/doc/legacy/index.html +++ b/doc/legacy/index.html @@ -55,9 +55,6 @@

    Documentation

    The One-Time-Password SASL Mechanism
  • The SecurID(r) SASL Mechanism
  • -
  • - Using Digest Authentication as a SASL Mechanism - (Historic)
  • Simple Authentication and Security Layer (SASL)
  • diff --git a/doc/legacy/install.html b/doc/legacy/install.html index c7f3822c..a70290fc 100644 --- a/doc/legacy/install.html +++ b/doc/legacy/install.html @@ -56,7 +56,7 @@

    Slower and Cleaner

    1. What mechanisms do you want to support? Are they plaintext (LOGIN, PLAIN), -shared secret (SCRAM, DIGEST-MD5, CRAM-MD5), or Kerberos (KERBEROS_V4, GSSAPI)? +shared secret (SCRAM, CRAM-MD5), or Kerberos (KERBEROS_V4, GSSAPI)? Perhaps you will use some combination (generally plaintext with one of the other two types).
    2. Given the answer to the previous question, how will the mechanisms @@ -136,9 +136,9 @@

      Build Configuration

      (even when it is disabled via the mech_list
      option).

      As of this writing, modules that are enabled by default but may not -be applicable to all systems include CRAM-MD5, DIGEST-MD5, SCRAM, OTP, KERBEROS_V4, +be applicable to all systems include CRAM-MD5, SCRAM, OTP, KERBEROS_V4, GSSAPI, PLAIN, and ANONYMOUS. These can be disabled with ---disable-cram, --disable-digest, +--disable-cram, --disable-scram, --disable-otp, --disable-krb4, --disable-gssapi, --disable-plain, and --disable-anon respecively. diff --git a/doc/legacy/mechanisms.html b/doc/legacy/mechanisms.html index 6f0902d7..394c3013 100644 --- a/doc/legacy/mechanisms.html +++ b/doc/legacy/mechanisms.html @@ -70,24 +70,6 @@

      SASL Mechanism Properties/Features


      - -DIGEST-MD5 -
      128
      -
      X
      -

      -

      -

      -
      X
      -

      -
      X
      -
      reauth
      -
      initial auth
      -
      X
      -
      X
      -

      -
      X
      - - EXTERNAL
      0
      diff --git a/doc/legacy/options.html b/doc/legacy/options.html index e1cb4dc3..b29ae5ef 100644 --- a/doc/legacy/options.html +++ b/doc/legacy/options.html @@ -135,12 +135,6 @@

      Options for Cyrus SASL

      auxprop -reauth_timeoutDIGEST-MD5 -Length in time (in minutes) that authentication info will be -cached for a fast reauth. A value of 0 will disable reauth. -0 - - saslauthd_pathSASL Library Path to saslauthd run directory (including the "/mux" named pipe) system dependant (generally won't need to be changed) @@ -325,7 +319,7 @@

      Examples:

      ldapdb_uri: ldap://ldap.example.com ldapdb_id: root ldapdb_pw: secret -ldapdb_mech: DIGEST-MD5 +ldapdb_mech: SCRAM ldapdb_canon_attr: uid diff --git a/doc/legacy/plugprog.html b/doc/legacy/plugprog.html index b1b7a3aa..52d90e95 100644 --- a/doc/legacy/plugprog.html +++ b/doc/legacy/plugprog.html @@ -138,7 +138,7 @@

      NOTE: This is a work in progress. Any contributions would be

      If neither flag is set, the mechanism will handle the client-send first situation internally, because the client may or may not send -first. (e.g. DIGEST-MD5). In this case, the plugin must +first. In this case, the plugin must intelligently check for the presence (or absence) of clientin/serverin data. Note that the optional client send-first is only possible when the protocol permits an initial response. @@ -146,7 +146,7 @@

      NOTE: This is a work in progress. Any contributions would be

      The server send last situation is handled by the plugin intelligently setting *serverout when the step function returns SASL_OK. For mechanisms which never send last (e.g. PLAIN), *serverout must be set to NULL. For -mechanisms which always send last (e.g. DIGEST-MD5), *serverout must +mechanisms which always send last, *serverout must point to the success data. For mechanisms in which the server may or may not send last (e.g. SRP), *serverout must be set accordingly. diff --git a/doc/legacy/readme.html b/doc/legacy/readme.html index 781ccaa4..7a72e4fc 100644 --- a/doc/legacy/readme.html +++ b/doc/legacy/readme.html @@ -19,7 +19,6 @@

      FEATURES