1# Copyright (C) 2019-2021 Nicola Di Lieto <nicola.dilieto@gmail.com>
2#
3# This file is part of uacme.
4#
5# uacme is free software: you can redistribute it and/or modify it
6# under the terms of the GNU General Public License as published by
7# the Free Software Foundation, either version 3 of the License, or
8# (at your option) any later version.
9#
10# uacme is distributed in the hope that it will be useful, but
11# WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13# General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18AC_PREREQ(2.53)
19AC_INIT([uacme], [m4_esyscmd([build-aux/git-version-gen .tarball-version])])
20AC_CONFIG_SRCDIR([uacme.c])
21AC_CONFIG_MACRO_DIR([build-aux/m4])
22AC_CONFIG_AUX_DIR([build-aux])
23AM_INIT_AUTOMAKE([subdir-objects])
24AM_MAINTAINER_MODE([disable])
25AM_SILENT_RULES([yes])
26AX_IS_RELEASE([git-directory])
27AX_CHECK_ENABLE_DEBUG([yes])
28
29AC_USE_SYSTEM_EXTENSIONS
30AC_PROG_SED
31AC_PROG_GREP
32AC_PROG_RANLIB
33AC_PROG_INSTALL
34AC_PROG_CC
35AC_PROG_CC_C99
36if test "x$ac_cv_prog_cc_c99" = "xno"; then
37    AC_MSG_ERROR([Could not find a C99 compatible compiler])
38fi
39
40AX_CHECK_COMPILE_FLAG([$CFLAGS -Wall], [WCFLAGS="-Wall"])
41AX_CHECK_COMPILE_FLAG([$CFLAGS -Wextra], [WCFLAGS="$WCFLAGS -Wextra"])
42AX_CHECK_COMPILE_FLAG([$CFLAGS -pedantic], [WCFLAGS="$WCFLAGS -pedantic"])
43AX_CHECK_COMPILE_FLAG([$CFLAGS -fno-strict-aliasing],
44                      [WCFLAGS="$WCFLAGS -fno-strict-aliasing"])
45AC_SUBST([WCFLAGS])
46
47AC_SYS_LARGEFILE
48AC_CHECK_HEADERS([err.h], [],
49                 AC_MSG_ERROR([uacme requires err.h]))
50AC_CHECK_HEADERS([getopt.h], [],
51                 AC_MSG_ERROR([uacme requires sys/wait.h]))
52AC_CHECK_HEADERS([netdb.h], [],
53                 AC_MSG_ERROR([uacme requires netdb.h]))
54AC_CHECK_HEADERS([netinet/in.h], [],
55                 AC_MSG_ERROR([uacme requires netinet/in.h]))
56AC_CHECK_HEADERS([arpa/inet.h], [],
57                 AC_MSG_ERROR([uacme requires arpa/inet.h]))
58AC_CHECK_HEADERS([sys/socket.h], [],
59                 AC_MSG_ERROR([uacme requires sys/socket.h]))
60AC_CHECK_HEADERS([sys/stat.h], [],
61                 AC_MSG_ERROR([uacme requires sys/stat.h]))
62AC_CHECK_HEADERS([sys/types.h], [],
63                 AC_MSG_ERROR([uacme requires sys/types.h]))
64AC_CHECK_HEADERS([sys/wait.h], [],
65                 AC_MSG_ERROR([uacme requires sys/wait.h]))
66AC_CHECK_FUNCS([asprintf vasprintf], [],
67               AC_MSG_ERROR([uacme requires (v)asprintf]))
68AC_CHECK_FUNCS([getopt_long], [],
69               AC_MSG_ERROR([uacme requires getopt_long]))
70AC_CHECK_FUNCS([open_memstream], [],
71               AC_MSG_ERROR([uacme requires open_memstream]))
72AC_CHECK_FUNCS([strcasestr])
73AC_CHECK_FUNCS([setproctitle])
74
75if test -n "$PKG_CONFIG"; then
76    PKGCONFIG="$PKG_CONFIG"
77    if test -z "`$PKGCONFIG --version`"; then
78        AC_MSG_ERROR([PKG_CONFIG is invalid])
79    fi
80else
81    PKG_PROG_PKG_CONFIG([0.28])
82    if test "x$PKG_CONFIG" = "x"; then
83        AC_MSG_ERROR([Could not find pkg-config])
84    else
85        PKGCONFIG="$PKG_CONFIG"
86    fi
87fi
88
89OPT_LIBCURL=yes
90AC_ARG_WITH(libcurl,
91[AS_HELP_STRING([--with-libcurl[[=PATH]]], [PATH is libcurl installation root])],
92OPT_LIBCURL=$withval)
93
94if test "x$OPT_LIBCURL" = "xno"; then
95    AC_MSG_ERROR([libcurl must be enabled])
96fi
97if test "x$OPT_LIBCURL" = "xyes"; then
98    AC_MSG_CHECKING([for libcurl >= 7.38.0])
99    itexists=`$PKGCONFIG --exists 'libcurl >= 7.38.0' >/dev/null 2>&1 && echo 1`
100    if test -z "$itexists"; then
101        AC_MSG_RESULT([no])
102        AC_MSG_ERROR([libcurl not found])
103    else
104        CURL_LDADD=`$PKGCONFIG --libs-only-l libcurl`
105        CURL_LDFLAGS=`$PKGCONFIG --libs-only-L --libs-only-other libcurl`
106        CURL_CPPFLAGS=`$PKGCONFIG --cflags-only-I libcurl`
107        CURL_CFLAGS=`$PKGCONFIG --cflags-only-other libcurl`
108        version=`$PKGCONFIG --modversion libcurl`
109        AC_MSG_RESULT([found $version])
110        AC_MSG_CHECKING([for libcurl https support])
111        https=`$PKGCONFIG --variable=supported_protocols libcurl 2>/dev/null | grep -q HTTPS && echo 1`
112        if test -z "$https"; then
113            AC_MSG_RESULT([no])
114            AC_MSG_ERROR([libcurl does not support https])
115        fi
116        AC_MSG_RESULT([yes])
117    fi
118else
119    CURL_LDADD=-lcurl
120    CURL_LDFLAGS=-L$OPT_LIBCURL/lib$libsuff
121    CURL_CPPFLAGS=-I$OPT_LIBCURL/include
122    CURL_CFLAGS=
123fi
124AC_SUBST(CURL_LDADD)
125AC_SUBST(CURL_LDFLAGS)
126AC_SUBST(CURL_CPPFLAGS)
127AC_SUBST(CURL_CFLAGS)
128
129LIBS_ORIG=$LIBS
130LDFLAGS_ORIG=$LDFLAGS
131CPPFLAGS_ORIG=$CPPFLAGS
132CFLAGS_ORIG=$CFLAGS
133LIBS="$CURL_LDADD $LIBS"
134LDFLAGS="$LDFLAGS $CURL_LDFLAGS"
135CPPFLAGS="$CPPFLAGS $CURL_CPPFLAGS"
136CFLAGS="$CFLAGS $CURL_CFLAGS"
137AC_CHECK_LIB(curl, curl_global_init, [CURL_ENABLED=1],
138             [AC_MSG_ERROR([libcurl check failed])])
139LIBS=$LIBS_ORIG
140LDFLAGS=$LDFLAGS_ORIG
141CPPFLAGS=$CPPFLAGS_ORIG
142CFLAGS=$CFLAGS_ORIG
143
144OPT_MBEDTLS=no
145AC_ARG_WITH(mbedtls,
146[AS_HELP_STRING([--with-mbedtls[[=PATH]]], [build with mbedTLS, PATH is installation root])
147AS_HELP_STRING([--without-mbedtls], [build without mbedTLS])],
148OPT_MBEDTLS=$withval)
149
150OPT_OPENSSL=no
151AC_ARG_WITH(openssl,
152[AS_HELP_STRING([--with-openssl[[=PATH]]], [build with OpenSSL, PATH is installation root])
153AS_HELP_STRING([--without-openssl], [build without OpenSSL])],
154OPT_OPENSSL=$withval)
155
156if test "x$OPT_MBEDTLS" = "xno" -a "x$OPT_OPENSSL" = "xno"; then
157    OPT_GNUTLS=yes
158else
159    OPT_GNUTLS=no
160fi
161AC_ARG_WITH([gnutls],
162[AS_HELP_STRING([--with-gnutls[[=PATH]]], [build with GnuTLS, PATH is installation root])
163AS_HELP_STRING([--without-gnutls], [build without GnuTLS])],
164OPT_GNUTLS=$withval)
165
166if test "x$OPT_GNUTLS" = "xno" -a "x$OPT_MBEDTLS" = "xno" -a "x$OPT_OPENSSL" = "xno"; then
167    AC_MSG_ERROR([One of GnuTLS, OpenSSL or mbedTLS must be enabled])
168fi
169if test "x$OPT_GNUTLS" != "xno" -a "x$OPT_MBEDTLS" != "xno"; then
170    AC_MSG_ERROR([GnuTLS and mbedTLS cannot be both enabled])
171fi
172if test "x$OPT_GNUTLS" != "xno" -a "x$OPT_OPENSSL" != "xno"; then
173    AC_MSG_ERROR([GnuTLS and OpenSSL cannot be both enabled])
174fi
175if test "x$OPT_OPENSSL" != "xno" -a "x$OPT_MBEDTLS" != "xno"; then
176    AC_MSG_ERROR([OpenSSL and mbedTLS cannot be both enabled])
177fi
178
179if test "x$OPT_GNUTLS" != "xno"; then
180    addlib=""
181    if test "x$OPT_GNUTLS" = "xyes"; then
182        AC_MSG_CHECKING([for GnuTLS >= 3.3.30])
183        itexists=`$PKGCONFIG --exists 'gnutls >= 3.3.30' >/dev/null 2>&1 && echo 1`
184        if test -z "$itexists"; then
185            AC_MSG_RESULT([no])
186            AC_MSG_ERROR([gnutls not found])
187        else
188            addlib=`$PKGCONFIG --libs-only-l gnutls`
189            addld=`$PKGCONFIG --libs-only-L gnutls`
190            addcflags=`$PKGCONFIG --cflags-only-I gnutls`
191            version=`$PKGCONFIG --modversion gnutls`
192            gtlslib=`echo $addld | sed -e 's/-L//'`
193            AC_MSG_RESULT([found $version])
194        fi
195    else
196        addlib=-lgnutls
197        addld=-L$OPT_GNUTLS/lib$libsuff
198        addcflags=-I$OPT_GNUTLS/include
199        gtlslib=$OPT_GNUTLS/lib$libsuff
200    fi
201    if test -n "$addlib"; then
202        LIBS="$addlib $LIBS"
203        LDFLAGS="$LDFLAGS $addld"
204        if test "$addcflags" != "-I/usr/include"; then
205            CPPFLAGS="$CPPFLAGS $addcflags"
206        fi
207        AC_CHECK_LIB(gnutls, gnutls_global_init,
208                     [AC_DEFINE(USE_GNUTLS, 1, [if GnuTLS is enabled])
209                      AC_SUBST(USE_GNUTLS, [1])
210                      USE_GNUTLS="yes"],
211                     [AC_MSG_ERROR([gnutls check failed])])
212        AC_CHECK_FUNCS([gnutls_decode_rs_value], [], [NEED_LIBTASN1="yes"])
213        AC_CHECK_FUNCS([gnutls_x509_crq_set_tlsfeatures], [],
214                       [AC_MSG_NOTICE([--must-staple requires GnuTLS 3.5.1 or later])])
215    fi
216fi
217
218if test "x$NEED_LIBTASN1" = "xyes"; then
219    addlib=""
220    AC_MSG_CHECKING([for libtasn1 >= 4.2])
221    itexists=`$PKGCONFIG --exists 'libtasn1 >= 4.2' >/dev/null 2>&1 && echo 1`
222    if test -z "$itexists"; then
223        AC_MSG_RESULT([no])
224        AC_MSG_ERROR([libtasn1 not found])
225    else
226        addlib=`$PKGCONFIG --libs-only-l libtasn1`
227        addld=`$PKGCONFIG --libs-only-L libtasn1`
228        addcflags=`$PKGCONFIG --cflags-only-I libtasn1`
229        version=`$PKGCONFIG --modversion libtasn1`
230        tasn1lib=`echo $addld | sed -e 's/-L//'`
231        AC_MSG_RESULT([found $version])
232    fi
233    if test -n "$addlib"; then
234        LIBS="$addlib $LIBS"
235        LDFLAGS="$LDFLAGS $addld"
236        if test "$addcflags" != "-I/usr/include"; then
237            CPPFLAGS="$CPPFLAGS $addcflags"
238        fi
239        AC_CHECK_LIB(tasn1, asn1_get_tag_der,
240                     [AC_DEFINE(USE_LIBTASN1, 1, [if libtasn1 is enabled])
241                      AC_SUBST(USE_LIBTASN1, [1])
242                      LIBTASN1_ENABLED=1
243                      USE_LIBTASN1="yes"],
244                     [AC_MSG_ERROR([libtasn1 check failed])])
245    fi
246fi
247
248if test "x$OPT_OPENSSL" != "xno"; then
249    addlib=""
250    if test "x$OPT_OPENSSL" = "xyes"; then
251        AC_MSG_CHECKING([for OpenSSL >= 1.1.1])
252        itexists=`$PKGCONFIG --exists 'openssl >= 1.1.1' >/dev/null 2>&1 && echo 1`
253        if test -z "$itexists"; then
254            AC_MSG_RESULT([no])
255            AC_MSG_ERROR([openssl not found])
256        else
257            addlib=`$PKGCONFIG --libs-only-l openssl`
258            addld=`$PKGCONFIG --libs-only-L openssl`
259            addcflags=`$PKGCONFIG --cflags-only-I openssl`
260            version=`$PKGCONFIG --modversion openssl`
261            openssllib=`echo $addld | sed -e 's/-L//'`
262            AC_MSG_RESULT([found $version])
263        fi
264    else
265        addlib="-lssl -lcrypto"
266        addld=-L$OPT_OPENSSL/lib$libsuff
267        addcflags=-I$OPT_OPENSSL/include
268        openssllib=$OPT_OPENSSL/lib$libsuff
269    fi
270    if test -n "$addlib"; then
271        LIBS="$addlib $LIBS"
272        LDFLAGS="$LDFLAGS $addld"
273        if test "$addcflags" != "-I/usr/include"; then
274            CPPFLAGS="$CPPFLAGS $addcflags"
275        fi
276        AC_CHECK_LIB(ssl, OpenSSL_version_num,
277                     [AC_DEFINE(USE_OPENSSL, 1, [if OpenSSL is enabled])
278                      AC_SUBST(USE_OPENSSL, [1])
279                      USE_OPENSSL="yes"],
280                     [AC_MSG_ERROR([openssl check failed])])
281    fi
282fi
283AM_CONDITIONAL(ENABLE_READFILE, test "x$USE_OPENSSL" != "xyes")
284
285if test "x$OPT_MBEDTLS" != "xno"; then
286    addlib="-lmbedtls -lmbedx509 -lmbedcrypto"
287    if test "x$OPT_MBEDTLS" = "xyes"; then
288        addld=""
289        addcflags=""
290    else
291        addld=-L$OPT_MBEDTLS/lib$libsuff
292        addcflags=-I$OPT_MBEDTLS/include
293    fi
294    LIBS="$addlib $LIBS"
295    LDFLAGS="$LDFLAGS $addld"
296    CPPFLAGS="$CPPFLAGS $addcflags"
297    AC_CHECK_LIB(mbedtls, mbedtls_entropy_init,
298                 [AC_DEFINE(USE_MBEDTLS, 1, [if mbedTLS is enabled])
299                  AC_SUBST(USE_MBEDTLS, [1])
300                  USE_MBEDTLS="yes"],
301                 [AC_MSG_ERROR([mbedtls check failed])])
302    if test "x$USE_MBEDTLS" = "xyes"; then
303        AC_MSG_NOTICE([detected mbedTLS])
304        AC_CHECK_FUNCS([mbedtls_x509_crt_parse_der_with_ext_cb])
305    fi
306fi
307
308OPT_UALPN=yes
309AC_ARG_WITH(ualpn,
310[AS_HELP_STRING([--with-ualpn], [enable ualpn])
311AS_HELP_STRING([--without-ualpn], [disable ualpn])], OPT_UALPN=$withval)
312
313if test "x$OPT_UALPN" != "xno"; then
314    AM_PROG_AR
315    AC_CHECK_HEADERS([netinet/tcp.h], [],
316                     AC_MSG_ERROR([ualpn requires netinet/tcp.h]))
317    AC_CHECK_HEADERS([sys/mman.h], [],
318                     AC_MSG_ERROR([ualpn requires sys/mman.h]))
319    AC_CHECK_HEADERS([sys/resource.h], [],
320                     AC_MSG_ERROR([ualpn requires sys/resource.h]))
321    AC_CHECK_HEADERS([sys/uio.h], [],
322                     AC_MSG_ERROR([ualpn requires sys/uio.h]))
323    AC_CHECK_HEADERS([sys/un.h], [],
324                     AC_MSG_ERROR([ualpn requires sys/un.h]))
325    AC_CHECK_FUNCS([mmap],[],
326                   AC_MSG_ERROR([ualpn requires mmap]))
327    AC_MSG_CHECKING([if mmap(MAP_ANON|MAP_SHARED) works])
328    AC_RUN_IFELSE([AC_LANG_SOURCE([#include <sys/mman.h>
329                     int main() {return mmap(0, 4096, PROT_READ|PROT_WRITE,
330                        MAP_ANON|MAP_SHARED, -1, 0) == MAP_FAILED;}])],
331        AC_DEFINE(HAVE_MAP_ANON, 1, [if mmap(MAP_ANON|MAP_SHARED) works])
332        AC_MSG_RESULT([yes]),
333        AC_MSG_RESULT([no])
334        AC_MSG_CHECKING([if mmap("/dev/zero", MAP_SHARED) works])
335        AC_RUN_IFELSE([AC_LANG_SOURCE([#include <sys/mman.h>
336                         #include <sys/stat.h>
337                         #include <fcntl.h>
338                         int main() {return mmap(0, 4096, PROT_READ|PROT_WRITE,
339                            MAP_ANON|MAP_SHARED, open("/dev/zero", O_RDWR), 0) ==
340                            MAP_FAILED;}])],
341            AC_DEFINE(HAVE_MAP_DEVZERO, 1, [if mmap("/dev/zero", MAP_SHARED) works])
342            AC_MSG_RESULT([yes]),
343            AC_MSG_RESULT([no])
344            AC_MSG_ERROR([ualpn requires MAP_ANON or mmap("/dev/zero", MAP_SHARED)])),
345        AC_COMPILE_IFELSE([AC_LANG_SOURCE([#include <sys/mman.h>
346                         int main() {return mmap(0, 4096, PROT_READ|PROT_WRITE,
347                            MAP_ANON|MAP_SHARED, -1, 0) == MAP_FAILED;}])],
348            AC_DEFINE(HAVE_MAP_ANON, 1, [if mmap(MAP_ANON|MAP_SHARED) works])
349            AC_MSG_RESULT([yes]),
350            AC_MSG_RESULT([no])
351            AC_MSG_NOTICE([falling back to mmap("/dev/zero", MAP_SHARED)])
352            AC_DEFINE(HAVE_MAP_DEVZERO, 1, [if mmap("/dev/zero", MAP_SHARED) works])))
353    AC_ARG_ENABLE(splice, AS_HELP_STRING([--disable-splice], [disable splice]))
354    if test "x$enable_splice" != "xno"; then
355        AC_CHECK_FUNCS([splice])
356    fi
357    LIBS_ORIG=$LIBS
358    LIBS=
359    AC_SEARCH_LIBS([sem_init], [pthread], [],
360                   AC_MSG_ERROR([sem_init not found]))
361    AC_SEARCH_LIBS([ev_version_major], [ev], [],
362                   [AC_MSG_NOTICE([libev not found, using included copy])
363                    with_included_libev=yes
364                    m4_include([libev/libev.m4])])
365    UALPN_LDADD=$LIBS
366    LIBS=$LIBS_ORIG
367fi
368AC_SUBST(UALPN_LDADD)
369AM_CONDITIONAL(ENABLE_UALPN, test "x$OPT_UALPN" = "xyes")
370AM_CONDITIONAL(ENABLE_LIBEV, test "x$with_included_libev" = "xyes")
371
372default_docs="yes"
373AC_ARG_ENABLE(docs,
374  [AC_HELP_STRING([--disable-docs], [do not build and install documentation])],
375    [],enable_docs=$default_docs)
376AM_CONDITIONAL(ENABLE_DOCS, test "x$enable_docs" = "xyes")
377if test "x$enable_docs" = "xyes"; then
378    AC_PATH_PROG(A2X, a2x, no)
379    AC_PATH_PROG(ASCIIDOC, asciidoc, no)
380    AS_IF([test "x$A2X" = "xno"], [AC_MSG_ERROR([Could not find a2x.])])
381    AS_IF([test "x$ASCIIDOC" = "xno"], [AC_MSG_ERROR([Could not find asciidoc.])])
382fi
383
384AS_CASE([$prefix:$localstatedir],
385        [NONE:'${prefix}/var' | /usr:'${prefix}/var' | /usr/local:'${prefix}/var'],
386         [localstatedir=/var; AC_MSG_NOTICE([--localstatedir defaulted to /var])])
387AC_SUBST([localstatedir])
388
389AS_CASE([$prefix:$sysconfdir],
390        [NONE:'${prefix}/etc' | /usr:'${prefix}/etc' | /usr/local:'${prefix}/etc'],
391         [sysconfdir=/etc; AC_MSG_NOTICE([--sysconfdir defaulted to /etc])])
392AC_SUBST([sysconfdir])
393
394AC_CONFIG_HEADERS([config.h])
395AC_CONFIG_FILES([Makefile])
396AC_OUTPUT
397
398