Skip to content

Commit c234848

Browse files
ztzgnkalmar
authored andcommitted
ZOOKEEPER-1112: Add (Cyrus) SASL authentication support to C client library
This is a "respin" of apache#1054, which I withdrew due to some annoying shortcomings. This changeset allows C clients to use SASL to authenticate with the ZooKeeper server. It is loosely based on patches #1 and apache#2 by Tom Klonikowski, at https://reviews.apache.org/r/2252/, but the result has been extensively reworked to follow the semantics of the Java client: * No SASL operations are exposed through the API; * The configuration is provided, and stored, at "handle init time"; * SASL authentication is automatically performed after each (re)connect. It introduces an optional dependency on the Cyrus SASL library, which can either be autodetected (default) or configured using the `--without-sasl`/`--with-sasl[=DIR]` flags, or -DWITH_CYRUS_SASL for CMake/Windows. `TestServerRequireClientSASLAuth.cc` has been renamed to `TestSASLAuth.cc`, and a test has been added which successfully (re)authenticates using the `DIGEST-MD5` mechanism. The code has also been used to successfully authenticate clients via `GSSAPI`/Kerberos. This commit also adds SASL support to the `cli.c` client. Co-authored-by: Tom Klonikowski <klonik_tinformatik.haw-hamburg.de> Author: Damien Diederen <[email protected]> Reviewers: Mate Szalay-Beko <[email protected]>, Norbert Kalmar <[email protected]> Closes apache#1134 from ztzg/ZOOKEEPER-1112-c-client-sasl-support-v2
1 parent b7dd0e4 commit c234848

20 files changed

+1509
-155
lines changed

README_packaging.md

+6-2
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,15 @@ http://bigtop.apache.org/
99
## Requirements
1010

1111
- you need maven to build the java code
12-
- gcc, cppunit, openssl and python-setuptools are required to build C and python bindings. (only needed when using `-Pfull-build`)
12+
- gcc, cppunit, openssl and python-setuptools are required to build C and python bindings (only needed when using `-Pfull-build`). Cyrus SASL is optional, but recommended for a maximally functional client.
1313

1414
On RHEL machine:
1515

1616
```
1717
yum install cppunit
1818
yum install python-setuptools
1919
yum install openssl openssl-devel
20+
yum install cyrus-sasl-md5 cyrus-sasl-gssapi cyrus-sasl-devel
2021
```
2122

2223
On Ubuntu:
@@ -25,6 +26,7 @@ On Ubuntu:
2526
apt-get install cppunit
2627
apt-get install python-setuptools
2728
apt-get install openssl libssl-dev
29+
apt-get install libsasl2-modules-gssapi-mit libsasl2-modules libsasl2-dev
2830
```
2931

3032

@@ -63,7 +65,9 @@ Optional parameters you might consider when using maven:
6365
Use `-Dc-client-openssl=no` to explicitly disable SSL feature in C client. Or use
6466
`-Dc-client-openssl=/path/to/openssl/` if you want to use a non-default / specific
6567
openssl library location.
66-
68+
- `-Dc-client-sasl` - specify SASL support and Cyrus SASL 1.x library location. Works similarly to the
69+
`c-client-openssl` flag above (`yes`, `no`, or path).
70+
6771
Please note: if you don't provide the `-Pfull-build` parameter, then the C client will not be built, the C client tests
6872
will not be executed and the previous C client builds will no be cleaned up (e.g. with simply using `mvn clean`).
6973

dev/docker/Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,4 @@
2020
FROM maven:3.6.3-jdk-8
2121

2222
RUN apt-get update
23-
RUN apt-get install -y g++ cmake autoconf libcppunit-dev libtool openssl libssl-dev
23+
RUN apt-get install -y g++ cmake autoconf libcppunit-dev libtool openssl libssl-dev libsasl2-modules-gssapi-mit libsasl2-modules libsasl2-dev

pom.xml

+2-1
Original file line numberDiff line numberDiff line change
@@ -339,8 +339,9 @@
339339
<spotbugsannotations.version>3.1.9</spotbugsannotations.version>
340340
<checkstyle.version>8.17</checkstyle.version>
341341

342-
<!-- parameter to pass to C client build -->
342+
<!-- parameters to pass to C client build -->
343343
<c-client-openssl>yes</c-client-openssl>
344+
<c-client-sasl>yes</c-client-sasl>
344345

345346
</properties>
346347

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
#
17+
# - Find Cyrus SASL (sasl.h, libsasl2.so)
18+
#
19+
# This module defines
20+
# CYRUS_SASL_INCLUDE_DIR, directory containing headers
21+
# CYRUS_SASL_SHARED_LIB, path to Cyrus SASL's shared library
22+
# CYRUS_SASL_FOUND, whether Cyrus SASL and its plugins have been found
23+
#
24+
# It also defines the following IMPORTED targets:
25+
# CyrusSASL
26+
#
27+
# Hints:
28+
# Set CYRUS_SASL_ROOT_DIR to the root directory of a Cyrus SASL installation.
29+
#
30+
# The initial version of this file was extracted from
31+
# https://github.com/cloudera/kudu, at the following commit:
32+
#
33+
# commit 9806863e78107505a622b44112a897189d9b3c24
34+
# Author: Dan Burkert <[email protected]>
35+
# Date: Mon Nov 30 12:15:36 2015 -0800
36+
#
37+
# Enable C++11
38+
39+
find_path(CYRUS_SASL_INCLUDE_DIR sasl/sasl.h HINTS "${CYRUS_SASL_ROOT_DIR}/include")
40+
find_library(CYRUS_SASL_SHARED_LIB sasl2 HINTS "${CYRUS_SASL_ROOT_DIR}/lib")
41+
42+
include(FindPackageHandleStandardArgs)
43+
find_package_handle_standard_args(CYRUS_SASL REQUIRED_VARS
44+
CYRUS_SASL_SHARED_LIB CYRUS_SASL_INCLUDE_DIR)
45+
46+
if(CYRUS_SASL_FOUND)
47+
if(NOT TARGET CyrusSASL)
48+
add_library(CyrusSASL UNKNOWN IMPORTED)
49+
set_target_properties(CyrusSASL PROPERTIES
50+
INTERFACE_INCLUDE_DIRECTORIES "${CYRUS_SASL_INCLUDE_DIR}"
51+
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
52+
IMPORTED_LOCATION "${CYRUS_SASL_SHARED_LIB}")
53+
endif()
54+
endif()

zookeeper-client/zookeeper-client-c/CMakeLists.txt

+25
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ project(zookeeper VERSION 3.7.0)
2020
2121
set(description "zookeeper C client")
2222

23+
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/../../tools/cmake/Modules")
24+
2325
# general options
2426
if(UNIX)
2527
add_compile_options(-Wall -fPIC)
@@ -61,6 +63,20 @@ if(WANT_SOCK_CLOEXEC AND HAVE_SOCK_CLOEXEC)
6163
set(SOCK_CLOEXEC_ENABLED 1)
6264
endif()
6365

66+
# Cyrus SASL 2.x
67+
option(WITH_CYRUS_SASL "turn ON/OFF Cyrus SASL 2.x support, or define SASL library location (default: ON)" ON)
68+
message("-- using WITH_CYRUS_SASL=${WITH_CYRUS_SASL}")
69+
if(NOT WITH_CYRUS_SASL STREQUAL "OFF")
70+
if(NOT WITH_CYRUS_SASL STREQUAL "ON")
71+
set(CYRUS_SASL_ROOT_DIR "${WITH_CYRUS_SASL}")
72+
endif()
73+
find_package(CyrusSASL)
74+
if(CYRUS_SASL_FOUND)
75+
message("-- Cyrus SASL 2.x found! will build with SASL support.")
76+
else()
77+
message("-- WARNING: unable to find Cyrus SASL 2.x! will build without SASL support.")
78+
endif()
79+
endif()
6480

6581
# The function `to_have(in out)` converts a header name like `arpa/inet.h`
6682
# into an Autotools style preprocessor definition `HAVE_ARPA_INET_H`.
@@ -171,6 +187,10 @@ else()
171187
list(APPEND zookeeper_sources src/st_adaptor.c)
172188
endif()
173189

190+
if(CYRUS_SASL_FOUND)
191+
list(APPEND zookeeper_sources src/zk_sasl.c)
192+
endif()
193+
174194
if(WIN32)
175195
list(APPEND zookeeper_sources src/winport.c)
176196
endif()
@@ -203,6 +223,11 @@ if(WANT_SYNCAPI AND NOT WIN32)
203223
target_link_libraries(zookeeper PUBLIC Threads::Threads)
204224
endif()
205225

226+
if(CYRUS_SASL_FOUND)
227+
target_compile_definitions(zookeeper PUBLIC HAVE_CYRUS_SASL_H)
228+
target_link_libraries(zookeeper PUBLIC CyrusSASL)
229+
endif()
230+
206231
# cli executable
207232
add_executable(cli src/cli.c)
208233
target_link_libraries(cli zookeeper)

zookeeper-client/zookeeper-client-c/LICENSE

+50
Original file line numberDiff line numberDiff line change
@@ -333,3 +333,53 @@
333333
* copied and put under another distribution licence
334334
* [including the GNU Public Licence.]
335335
*/
336+
337+
===========================================================================================
338+
=== The following part contains the license for the Cyrus SASL 2.x library ===
339+
=== used for optional SASL support ===
340+
===========================================================================================
341+
342+
/* CMU libsasl
343+
* Tim Martin
344+
* Rob Earhart
345+
* Rob Siemborski
346+
*/
347+
/*
348+
* Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved.
349+
*
350+
* Redistribution and use in source and binary forms, with or without
351+
* modification, are permitted provided that the following conditions
352+
* are met:
353+
*
354+
* 1. Redistributions of source code must retain the above copyright
355+
* notice, this list of conditions and the following disclaimer.
356+
*
357+
* 2. Redistributions in binary form must reproduce the above copyright
358+
* notice, this list of conditions and the following disclaimer in
359+
* the documentation and/or other materials provided with the
360+
* distribution.
361+
*
362+
* 3. The name "Carnegie Mellon University" must not be used to
363+
* endorse or promote products derived from this software without
364+
* prior written permission. For permission or any other legal
365+
* details, please contact
366+
* Office of Technology Transfer
367+
* Carnegie Mellon University
368+
* 5000 Forbes Avenue
369+
* Pittsburgh, PA 15213-3890
370+
* (412) 268-4387, fax: (412) 268-7395
371+
372+
*
373+
* 4. Redistributions of any form whatsoever must retain the following
374+
* acknowledgment:
375+
* "This product includes software developed by Computing Services
376+
* at Carnegie Mellon University (http://www.cmu.edu/computing/)."
377+
*
378+
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
379+
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
380+
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
381+
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
382+
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
383+
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
384+
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
385+
*/

zookeeper-client/zookeeper-client-c/Makefile.am

+14-8
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,16 @@ if WANT_OPENSSL
1313
OPENSSL_LIB_LDFLAGS = -lssl -lcrypto
1414
endif
1515

16-
AM_CPPFLAGS = -I${srcdir}/include -I${srcdir}/tests -I${srcdir}/generated $(SOLARIS_CPPFLAGS) $(OPENSSL_CPPFLAGS)
16+
if WANT_SASL
17+
SASL_CPPFLAGS = -DHAVE_CYRUS_SASL_H
18+
SASL_LIB_LDFLAGS = -lsasl2
19+
SASL_SRC = src/zk_sasl.c
20+
endif
21+
22+
AM_CPPFLAGS = -I${srcdir}/include -I${srcdir}/tests -I${srcdir}/generated $(SOLARIS_CPPFLAGS) $(OPENSSL_CPPFLAGS) $(SASL_CPPFLAGS)
1723
AM_CFLAGS = -Wall -Werror -Wdeclaration-after-statement
1824
AM_CXXFLAGS = -Wall $(USEIPV6)
19-
LIB_LDFLAGS = -no-undefined -version-info 2 $(SOLARIS_LIB_LDFLAGS) $(OPENSSL_LIB_LDFLAGS)
25+
LIB_LDFLAGS = -no-undefined -version-info 2 $(SOLARIS_LIB_LDFLAGS) $(OPENSSL_LIB_LDFLAGS) $(SASL_LIB_LDFLAGS)
2026

2127
# Additional flags for coverage testing (if enabled)
2228
if ENABLEGCOV
@@ -37,7 +43,7 @@ COMMON_SRC = src/zookeeper.c include/zookeeper.h include/zookeeper_version.h inc
3743
src/recordio.c include/recordio.h include/proto.h \
3844
src/zk_adaptor.h generated/zookeeper.jute.c \
3945
src/zk_log.c src/zk_hashtable.h src/zk_hashtable.c \
40-
src/addrvec.h src/addrvec.c
46+
src/addrvec.h src/addrvec.c $(SASL_SRC)
4147

4248
# These are the symbols (classes, mostly) we want to export from our library.
4349
EXPORT_SYMBOLS = '(zoo_|zookeeper_|zhandle|Z|format_log_message|log_message|logLevel|deallocate_|allocate_|zerror|is_unrecoverable)'
@@ -67,13 +73,13 @@ endif
6773
bin_PROGRAMS = cli_st
6874

6975
cli_st_SOURCES = src/cli.c
70-
cli_st_LDADD = libzookeeper_st.la
76+
cli_st_LDADD = libzookeeper_st.la $(SASL_LIB_LDFLAGS)
7177

7278
if WANT_SYNCAPI
7379
bin_PROGRAMS += cli_mt load_gen
7480

7581
cli_mt_SOURCES = src/cli.c
76-
cli_mt_LDADD = libzookeeper_mt.la
82+
cli_mt_LDADD = libzookeeper_mt.la $(SASL_LIB_LDFLAGS)
7783
cli_mt_CFLAGS = -DTHREADED
7884

7985
load_gen_SOURCES = src/load_gen.c
@@ -113,7 +119,7 @@ TEST_SOURCES = \
113119
tests/ZooKeeperQuorumServer.h \
114120
tests/TestReadOnlyClient.cc \
115121
tests/TestLogClientEnv.cc \
116-
tests/TestServerRequireClientSASLAuth.cc \
122+
tests/TestSASLAuth.cc \
117123
$(NULL)
118124

119125
if SOLARIS
@@ -127,14 +133,14 @@ check_PROGRAMS = zktest-st
127133
TESTS_ENVIRONMENT = ZKROOT=${srcdir}/../.. \
128134
CLASSPATH=$$CLASSPATH:$$CLOVER_HOME/lib/clover*.jar
129135
nodist_zktest_st_SOURCES = $(TEST_SOURCES)
130-
zktest_st_LDADD = libzkst.la libhashtable.la $(CPPUNIT_LIBS) $(OPENSSL_LIB_LDFLAGS) -ldl
136+
zktest_st_LDADD = libzkst.la libhashtable.la $(CPPUNIT_LIBS) $(OPENSSL_LIB_LDFLAGS) $(SASL_LIB_LDFLAGS) -ldl
131137
zktest_st_CXXFLAGS = -DUSE_STATIC_LIB $(CPPUNIT_CFLAGS) $(USEIPV6) $(SOLARIS_CPPFLAGS)
132138
zktest_st_LDFLAGS = -shared $(SYMBOL_WRAPPERS) $(SOLARIS_LIB_LDFLAGS)
133139

134140
if WANT_SYNCAPI
135141
check_PROGRAMS += zktest-mt
136142
nodist_zktest_mt_SOURCES = $(TEST_SOURCES) tests/PthreadMocks.cc
137-
zktest_mt_LDADD = libzkmt.la libhashtable.la -lpthread $(CPPUNIT_LIBS) $(OPENSSL_LIB_LDFLAGS) -ldl
143+
zktest_mt_LDADD = libzkmt.la libhashtable.la -lpthread $(CPPUNIT_LIBS) $(OPENSSL_LIB_LDFLAGS) $(SASL_LIB_LDFLAGS) -ldl
138144
zktest_mt_CXXFLAGS = -DUSE_STATIC_LIB -DTHREADED $(CPPUNIT_CFLAGS) $(USEIPV6)
139145
if SOLARIS
140146
SHELL_SYMBOL_WRAPPERS_MT = cat ${srcdir}/tests/wrappers-mt.opt

zookeeper-client/zookeeper-client-c/README

+2
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ Follow steps 1 and 2 above, and then continue here.
8383
-DWANT_CPPUNIT ON except on Windows, OFF disables the tests
8484
-DWITH_OPENSSL ON by default, OFF disables the SSL support. You can also
8585
specify a custom path by -DWITH_OPENSSL=/path/to/openssl/
86+
-DWITH_CYRUS_SASL ON by default, OFF disables SASL support. You can also
87+
specify a custom path by -DWITH_CYRUS_SASL=/path/to/cyrus-sasl/
8688
-DBUILD_SHARED_LIBS not yet supported, only static libraries are built
8789
other CMake options see "cmake --help" for generic options, such as generator
8890

zookeeper-client/zookeeper-client-c/configure.ac

+30
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,36 @@ fi
143143

144144
AM_CONDITIONAL([WANT_SYNCAPI],[test "x$with_syncapi" != xno])
145145

146+
dnl Cyrus SASL 2.x
147+
AC_ARG_WITH(sasl,
148+
[AC_HELP_STRING([--with-sasl[=DIR]], [build with SASL support via Cyrus SASL 2.x (default=auto)])],
149+
[], [with_sasl=yes])
150+
if test "x$with_sasl" != "xno"; then
151+
saved_CPPFLAGS="$CPPFLAGS"
152+
saved_LDFLAGS="$LDFLAGS"
153+
if test "x$with_sasl" != "xyes" ; then
154+
CPPFLAGS="$CPPFLAGS -I$with_sasl/include"
155+
LDFLAGS="$LDFLAGS -L$with_sasl/lib"
156+
fi
157+
have_sasl=no
158+
AC_CHECK_HEADER(sasl/sasl.h, [
159+
AC_CHECK_LIB(sasl2, sasl_client_init, [have_sasl=yes])])
160+
if test "x$have_sasl" != "xyes"; then
161+
CPPFLAGS="$saved_CPPFLAGS"
162+
LDFLAGS="$saved_LDFLAGS"
163+
fi
164+
fi
165+
if test "x$with_sasl" != xno && test "x$have_sasl" = xno; then
166+
AC_MSG_WARN([cannot build SASL support -- sasl2 not found])
167+
with_sasl=no
168+
fi
169+
if test "x$with_sasl" != xno; then
170+
AC_MSG_NOTICE([building with SASL support])
171+
else
172+
AC_MSG_NOTICE([building without SASL support])
173+
fi
174+
AM_CONDITIONAL([WANT_SASL],[test "x$with_sasl" != xno])
175+
146176
# Checks for header files.
147177
AC_HEADER_STDC
148178
AC_CHECK_HEADERS([arpa/inet.h fcntl.h netdb.h netinet/in.h stdlib.h string.h sys/socket.h sys/time.h unistd.h sys/utsname.h])

zookeeper-client/zookeeper-client-c/include/proto.h

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ extern "C" {
4646
#define ZOO_CLOSE_OP -11
4747
#define ZOO_SETAUTH_OP 100
4848
#define ZOO_SETWATCHES_OP 101
49+
#define ZOO_SASL_OP 102
4950

5051
#ifdef __cplusplus
5152
}

0 commit comments

Comments
 (0)