dnl ProFTPD - mod_sftp
dnl Copyright (c) 2012-2023 TJ Saunders <tj@castaglia.org>
dnl
dnl This program is free software; you can redistribute it and/or modify
dnl it under the terms of the GNU General Public License as published by
dnl the Free Software Foundation; either version 2 of the License, or
dnl (at your option) any later version.
dnl
dnl This program is distributed in the hope that it will be useful,
dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
dnl GNU General Public License for more details.
dnl
dnl You should have received a copy of the GNU General Public License
dnl along with this program; if not, write to the Free Software
dnl Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
dnl
dnl Process this file with autoconf to produce a configure script.

AC_INIT(./mod_sftp.c)

AC_CANONICAL_SYSTEM

ostype=`echo $build_os | sed 's/\..*$//g' | sed 's/-.*//g' | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ`

AC_PROG_CC
AC_PROG_CPP
AC_AIX
AC_ISC_POSIX
AC_MINIX

dnl Need to support/handle the --with-includes and --with-libraries options
AC_ARG_WITH(includes,
  [AC_HELP_STRING(
    [--with-includes=LIST],
    [add additional include paths to proftpd. LIST is a colon-separated list of include paths to add e.g. --with-includes=/some/mysql/include:/my/include])
  ],
  [ ac_addl_includes=`echo "$withval" | sed -e 's/:/ /g'` ;
    for ainclude in $ac_addl_includes; do
      if test x"$ac_build_addl_includes" = x ; then
        ac_build_addl_includes="-I$ainclude"
      else
        ac_build_addl_includes="-I$ainclude $ac_build_addl_includes"
      fi
    done
    CPPFLAGS="$CPPFLAGS $ac_build_addl_includes"
  ])

AC_ARG_WITH(libraries,
  [AC_HELP_STRING(
    [--with-libraries=LIST],
    [add additional library paths to proftpd. LIST is a colon-separated list of include paths to add e.g. --with-libraries=/some/mysql/libdir:/my/libs])
  ],
  [ ac_addl_libdirs=`echo "$withval" | sed -e 's/:/ /g'` ;
    for alibdir in $ac_addl_libdirs; do
      if test x"$ac_build_addl_libdirs" = x ; then
        ac_build_addl_libdirs="-L$alibdir"
      else
        ac_build_addl_libdirs="-L$alibdir $ac_build_addl_libdirs"
      fi
    done
    LDFLAGS="$LDFLAGS $ac_build_addl_libdirs"
  ])

AC_HEADER_STDC
AC_CHECK_HEADERS(stdlib.h unistd.h limits.h fcntl.h)
AC_CHECK_HEADER(zlib.h,
  [AC_DEFINE(HAVE_ZLIB_H, 1, [Define if zlib.h is present.])
   MODULE_LIBS="$MODULE_LIBS -lz"
  ])

dnl Check for a crippled OpenSSL library (e.g. Solaris 10).  More details
dnl can be found in:
dnl
dnl   http://fixunix.com/ssh/73273-openssh-solaris-10-amd64.html
dnl   http://marc.info/?l=openssh-unix-dev&m=113245772008292&w=2
dnl   http://opensolaris.org/os/project/crypto/Documentation/sunwcry/
dnl
dnl So for those users stuck using the Solaris 10 whose OpenSSL does
dnl not provide support for AES ciphers longer than 128 bits, we need to
dnl check and disable those symbols.  Otherwise mod_sftp fails to build due
dnl to linker errors.

AC_MSG_CHECKING([whether linking with OpenSSL functions requires -ldl])
saved_libs="$LIBS"
LIBS="-lcrypto -ldl $LIBS"

AC_TRY_LINK(
  [
    #include <openssl/evp.h>
  ], [
    SSLeay_add_all_algorithms();
  ], [
    AC_MSG_RESULT(yes)
    LIBS="$saved_libs -ldl"
  ], [
    AC_MSG_RESULT(no)
    LIBS="$saved_libs"
  ]
)

AC_MSG_CHECKING([whether linking with OpenSSL functions requires -lz])
saved_libs="$LIBS"
LIBS="-lcrypto -lz $LIBS"

AC_TRY_LINK(
  [
    #include <openssl/evp.h>
    #include <openssl/bio.h>
    #include <openssl/comp.h>
  ], [
    BIO *bio;
    SSLeay_add_all_algorithms();
    bio = BIO_new(BIO_f_zlib());
  ], [
    AC_MSG_RESULT(yes)
    LIBS="$saved_libs -lz"
  ], [
    AC_MSG_RESULT(no)
    LIBS="$saved_libs"
  ]
)

AC_MSG_CHECKING([whether OpenSSL has crippled AES support])
LIBS="-lcrypto $LIBS"

AC_TRY_LINK(
  [ #ifdef HAVE_STRING_H
    # include <string.h>
    #endif
    #include <openssl/evp.h>
  ],
  [
    EVP_CIPHER *c;
    c = EVP_aes_192_cbc();
    c = EVP_aes_256_cbc();
  ],
  [
    AC_MSG_RESULT(no)
    LIBS="$saved_libs"
  ],
  [
    AC_MSG_RESULT(yes)
    AC_DEFINE(HAVE_AES_CRIPPLED_OPENSSL, 1, [OpenSSL is missing AES192 and AES256 support])
    LIBS="$saved_libs"
  ]
)

AC_MSG_CHECKING([whether OpenSSL supports SHA256])
LIBS="-lcrypto $LIBS"

AC_TRY_LINK(
  [
    #include <openssl/evp.h>
  ],
  [
    const EVP_MD *md;
    md = EVP_sha256();
  ],
  [
    AC_MSG_RESULT(yes)
    AC_DEFINE(HAVE_SHA256_OPENSSL, 1, [OpenSSL supports SHA224/SHA256])
    LIBS="$saved_libs"
  ],
  [
    AC_MSG_RESULT(no)
    LIBS="$saved_libs"
  ]
)

AC_MSG_CHECKING([whether OpenSSL supports SHA512])
LIBS="-lcrypto $LIBS"

AC_TRY_LINK(
  [
    #include <openssl/evp.h>
  ],
  [
    const EVP_MD *md;
    md = EVP_sha512();
  ],
  [
    AC_MSG_RESULT(yes)
    AC_DEFINE(HAVE_SHA512_OPENSSL, 1, [OpenSSL supports SHA384/SHA512])
    LIBS="$saved_libs"
  ],
  [
    AC_MSG_RESULT(no)
    LIBS="$saved_libs"
  ]
)

AC_MSG_CHECKING([whether OpenSSL supports EVP_aes_128_ctr])
LIBS="-lcrypto $LIBS"

AC_TRY_LINK(
  [
    #include <openssl/evp.h>
  ],
  [
    EVP_CIPHER *cipher;
    cipher = EVP_aes_128_ctr();
  ],
  [
    AC_MSG_RESULT(yes)
    AC_DEFINE(HAVE_EVP_AES_128_CTR_OPENSSL, 1, [OpenSSL supports EVP_aes_128_ctr])
    LIBS="$saved_libs"
  ],
  [
    AC_MSG_RESULT(no)
    LIBS="$saved_libs"
  ]
)

AC_MSG_CHECKING([whether OpenSSL supports EVP_aes_192_ctr])
LIBS="-lcrypto $LIBS"

AC_TRY_LINK(
  [
    #include <openssl/evp.h>
  ],
  [
    EVP_CIPHER *cipher;
    cipher = EVP_aes_192_ctr();
  ],
  [
    AC_MSG_RESULT(yes)
    AC_DEFINE(HAVE_EVP_AES_192_CTR_OPENSSL, 1, [OpenSSL supports EVP_aes_192_ctr])
    LIBS="$saved_libs"
  ],
  [
    AC_MSG_RESULT(no)
    LIBS="$saved_libs"
  ]
)

AC_MSG_CHECKING([whether OpenSSL supports EVP_aes_256_ctr])
LIBS="-lcrypto $LIBS"

AC_TRY_LINK(
  [
    #include <openssl/evp.h>
  ],
  [
    EVP_CIPHER *cipher;
    cipher = EVP_aes_256_ctr();
  ],
  [
    AC_MSG_RESULT(yes)
    AC_DEFINE(HAVE_EVP_AES_256_CTR_OPENSSL, 1, [OpenSSL supports EVP_aes_256_ctr])
    LIBS="$saved_libs"
  ],
  [
    AC_MSG_RESULT(no)
    LIBS="$saved_libs"
  ]
)

AC_MSG_CHECKING([whether OpenSSL supports EVP_aes_256_gcm])
LIBS="-lcrypto $LIBS"

AC_TRY_LINK(
  [
    #include <openssl/evp.h>
  ],
  [
    EVP_CIPHER *cipher;
    cipher = EVP_aes_256_gcm();
  ],
  [
    AC_MSG_RESULT(yes)
    AC_DEFINE(HAVE_EVP_AES_256_GCM_OPENSSL, 1, [OpenSSL supports EVP_aes_256_gcm])
    LIBS="$saved_libs"
  ],
  [
    AC_MSG_RESULT(no)
    LIBS="$saved_libs"
  ]
)

AC_MSG_CHECKING([whether OpenSSL supports EVP_chacha20])
LIBS="-lcrypto $LIBS"

AC_TRY_LINK(
  [
    #include <openssl/evp.h>
  ],
  [
    EVP_CIPHER *cipher;
    cipher = EVP_chacha20();
  ],
  [
    AC_MSG_RESULT(yes)
    AC_DEFINE(HAVE_EVP_CHACHA20_OPENSSL, 1, [OpenSSL supports EVP_chacha20])
    LIBS="$saved_libs"
  ],
  [
    AC_MSG_RESULT(no)
    LIBS="$saved_libs"
  ]
)

AC_MSG_CHECKING([whether OpenSSL supports OSSL_PROVIDER_load])
LIBS="-lcrypto $LIBS"

AC_TRY_LINK(
  [
    #include <openssl/provider.h>
  ],
  [
    OSSL_PROVIDER *provider;
    provider = OSSL_PROVIDER_load(NULL, "default");
  ],
  [
    AC_MSG_RESULT(yes)
    AC_DEFINE(HAVE_OSSL_PROVIDER_LOAD_OPENSSL, 1, [OpenSSL supports OSSL_PROVIDER_load])
    LIBS="$saved_libs"
  ],
  [
    AC_MSG_RESULT(no)
    LIBS="$saved_libs"
  ]
)

AC_MSG_CHECKING([whether OpenSSL supports X448 algorithm])
LIBS="-lcrypto $LIBS"

AC_TRY_LINK(
  [
    #include <openssl/evp.h>
  ],
  [
    EVP_PKEY *pkey;
    EVP_PKEY_CTX *pctx;

    pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_X448, NULL, NULL, 0);
    pctx = EVP_PKEY_CTX_new_id(NID_X448, NULL);
  ],
  [
    AC_MSG_RESULT(yes)
    AC_DEFINE(HAVE_X448_OPENSSL, 1, [OpenSSL supports X448 algorithm])
    LIBS="$saved_libs"
  ],
  [
    AC_MSG_RESULT(no)
    LIBS="$saved_libs"
  ]
)

LIBS="$saved_libs"

INCLUDES="$ac_build_addl_includes"
LIBDIRS="$ac_build_addl_libdirs"

AC_SUBST(INCLUDES)
AC_SUBST(LDFLAGS)
AC_SUBST(LIBDIRS)
AC_SUBST(MODULE_LIBS)

AC_CONFIG_HEADER(mod_sftp.h)
AC_OUTPUT(Makefile)

dnl After everything has been generated, we need to ensure that our API
dnl headers are in the include/ directory, for use by other modules' build
dnl systems.
builddir=../..
if test ! -d $builddir/include/mod_sftp ; then
  mkdir $builddir/include/mod_sftp
fi

for h in $(ls *.h); do
  if test ! -e $builddir/include/mod_sftp/$h ; then
    olddir=`pwd`
    cd $builddir/include/mod_sftp
    ln -s ../../contrib/mod_sftp/$h .
    cd $olddir
  fi
done
