Service Authentication (#517)
Add an optional mode that requires clients to authenticate with the server. In this mode, clients need to provide a username and a password, which are checked against a password file on the server. The authentication credentials are protected by an RSA public keypair...the encrypted credentials are sent along with the test parameters. Operationally the use of this feature places the following additional requirements on the build and installation of iperf3: o The presence of the OpenSSL headers and libraries to build iperf3, and the libraries available on the client and server at runtime. o Generation of an RSA public keypair; the private part is used by the server and the public part must be distributed to the clients. o Username/password pairs for all authorized users, to be stored in a file on the server. o Loose time synchronization between the server and clients (to within approximately 30 seconds). o Appropriate command-line flags given on the client and server. Note that iperf3 can be built and run as before, without fulfilling any of these requirements. Partial documentation for this feature is included in this commit. It is anticipated that additional documentation text and editing will follow this merge. Submitted by @ralcini. First suggested by @codyhanson in pull request #242.
Этот коммит содержится в:
родитель
05600c201a
Коммит
a51045de19
124
ax_check_openssl.m4
Обычный файл
124
ax_check_openssl.m4
Обычный файл
@ -0,0 +1,124 @@
|
||||
# ===========================================================================
|
||||
# https://www.gnu.org/software/autoconf-archive/ax_check_openssl.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AX_CHECK_OPENSSL([action-if-found[, action-if-not-found]])
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# Look for OpenSSL in a number of default spots, or in a user-selected
|
||||
# spot (via --with-openssl). Sets
|
||||
#
|
||||
# OPENSSL_INCLUDES to the include directives required
|
||||
# OPENSSL_LIBS to the -l directives required
|
||||
# OPENSSL_LDFLAGS to the -L or -R flags required
|
||||
#
|
||||
# and calls ACTION-IF-FOUND or ACTION-IF-NOT-FOUND appropriately
|
||||
#
|
||||
# This macro sets OPENSSL_INCLUDES such that source files should use the
|
||||
# openssl/ directory in include directives:
|
||||
#
|
||||
# #include <openssl/hmac.h>
|
||||
#
|
||||
# LICENSE
|
||||
#
|
||||
# Copyright (c) 2009,2010 Zmanda Inc. <http://www.zmanda.com/>
|
||||
# Copyright (c) 2009,2010 Dustin J. Mitchell <dustin@zmanda.com>
|
||||
#
|
||||
# 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 10
|
||||
|
||||
AU_ALIAS([CHECK_SSL], [AX_CHECK_OPENSSL])
|
||||
AC_DEFUN([AX_CHECK_OPENSSL], [
|
||||
found=false
|
||||
AC_ARG_WITH([openssl],
|
||||
[AS_HELP_STRING([--with-openssl=DIR],
|
||||
[root of the OpenSSL directory])],
|
||||
[
|
||||
case "$withval" in
|
||||
"" | y | ye | yes | n | no)
|
||||
AC_MSG_ERROR([Invalid --with-openssl value])
|
||||
;;
|
||||
*) ssldirs="$withval"
|
||||
;;
|
||||
esac
|
||||
], [
|
||||
# if pkg-config is installed and openssl has installed a .pc file,
|
||||
# then use that information and don't search ssldirs
|
||||
AC_CHECK_TOOL([PKG_CONFIG], [pkg-config])
|
||||
if test x"$PKG_CONFIG" != x""; then
|
||||
OPENSSL_LDFLAGS=`$PKG_CONFIG openssl --libs-only-L 2>/dev/null`
|
||||
if test $? = 0; then
|
||||
OPENSSL_LIBS=`$PKG_CONFIG openssl --libs-only-l 2>/dev/null`
|
||||
OPENSSL_INCLUDES=`$PKG_CONFIG openssl --cflags-only-I 2>/dev/null`
|
||||
found=true
|
||||
fi
|
||||
fi
|
||||
|
||||
# no such luck; use some default ssldirs
|
||||
if ! $found; then
|
||||
ssldirs="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /usr"
|
||||
fi
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
# note that we #include <openssl/foo.h>, so the OpenSSL headers have to be in
|
||||
# an 'openssl' subdirectory
|
||||
|
||||
if ! $found; then
|
||||
OPENSSL_INCLUDES=
|
||||
for ssldir in $ssldirs; do
|
||||
AC_MSG_CHECKING([for openssl/ssl.h in $ssldir])
|
||||
if test -f "$ssldir/include/openssl/ssl.h"; then
|
||||
OPENSSL_INCLUDES="-I$ssldir/include"
|
||||
OPENSSL_LDFLAGS="-L$ssldir/lib"
|
||||
OPENSSL_LIBS="-lssl -lcrypto"
|
||||
found=true
|
||||
AC_MSG_RESULT([yes])
|
||||
break
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
done
|
||||
|
||||
# if the file wasn't found, well, go ahead and try the link anyway -- maybe
|
||||
# it will just work!
|
||||
fi
|
||||
|
||||
# try the preprocessor and linker with our new flags,
|
||||
# being careful not to pollute the global LIBS, LDFLAGS, and CPPFLAGS
|
||||
|
||||
AC_MSG_CHECKING([whether compiling and linking against OpenSSL works])
|
||||
echo "Trying link with OPENSSL_LDFLAGS=$OPENSSL_LDFLAGS;" \
|
||||
"OPENSSL_LIBS=$OPENSSL_LIBS; OPENSSL_INCLUDES=$OPENSSL_INCLUDES" >&AS_MESSAGE_LOG_FD
|
||||
|
||||
save_LIBS="$LIBS"
|
||||
save_LDFLAGS="$LDFLAGS"
|
||||
save_CPPFLAGS="$CPPFLAGS"
|
||||
LDFLAGS="$LDFLAGS $OPENSSL_LDFLAGS"
|
||||
LIBS="$OPENSSL_LIBS $LIBS"
|
||||
CPPFLAGS="$OPENSSL_INCLUDES $CPPFLAGS"
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM([#include <openssl/ssl.h>], [SSL_new(NULL)])],
|
||||
[
|
||||
AC_MSG_RESULT([yes])
|
||||
$1
|
||||
], [
|
||||
AC_MSG_RESULT([no])
|
||||
$2
|
||||
])
|
||||
CPPFLAGS="$save_CPPFLAGS"
|
||||
LDFLAGS="$save_LDFLAGS"
|
||||
LIBS="$save_LIBS"
|
||||
|
||||
AC_SUBST([OPENSSL_INCLUDES])
|
||||
AC_SUBST([OPENSSL_LIBS])
|
||||
AC_SUBST([OPENSSL_LDFLAGS])
|
||||
])
|
274
configure
поставляемый
274
configure
поставляемый
@ -635,6 +635,10 @@ ac_subst_vars='am__EXEEXT_FALSE
|
||||
am__EXEEXT_TRUE
|
||||
LTLIBOBJS
|
||||
LIBOBJS
|
||||
OPENSSL_LDFLAGS
|
||||
OPENSSL_LIBS
|
||||
OPENSSL_INCLUDES
|
||||
PKG_CONFIG
|
||||
CPP
|
||||
LT_SYS_LIBRARY_PATH
|
||||
OTOOL64
|
||||
@ -765,6 +769,7 @@ with_aix_soname
|
||||
with_gnu_ld
|
||||
with_sysroot
|
||||
enable_libtool_lock
|
||||
with_openssl
|
||||
'
|
||||
ac_precious_vars='build_alias
|
||||
host_alias
|
||||
@ -1420,6 +1425,7 @@ Optional Packages:
|
||||
--with-gnu-ld assume the C compiler uses GNU ld [default=no]
|
||||
--with-sysroot[=DIR] Search for dependent libraries within DIR (or the
|
||||
compiler's sysroot if not specified).
|
||||
--with-openssl=DIR root of the OpenSSL directory
|
||||
|
||||
Some influential environment variables:
|
||||
CC C compiler command
|
||||
@ -2217,6 +2223,63 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
|
||||
ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
|
||||
|
||||
# ===========================================================================
|
||||
# https://www.gnu.org/software/autoconf-archive/ax_check_openssl.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AX_CHECK_OPENSSL([action-if-found[, action-if-not-found]])
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# Look for OpenSSL in a number of default spots, or in a user-selected
|
||||
# spot (via --with-openssl). Sets
|
||||
#
|
||||
# OPENSSL_INCLUDES to the include directives required
|
||||
# OPENSSL_LIBS to the -l directives required
|
||||
# OPENSSL_LDFLAGS to the -L or -R flags required
|
||||
#
|
||||
# and calls ACTION-IF-FOUND or ACTION-IF-NOT-FOUND appropriately
|
||||
#
|
||||
# This macro sets OPENSSL_INCLUDES such that source files should use the
|
||||
# openssl/ directory in include directives:
|
||||
#
|
||||
# #include <openssl/hmac.h>
|
||||
#
|
||||
# LICENSE
|
||||
#
|
||||
# Copyright (c) 2009,2010 Zmanda Inc. <http://www.zmanda.com/>
|
||||
# Copyright (c) 2009,2010 Dustin J. Mitchell <dustin@zmanda.com>
|
||||
#
|
||||
# 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 10
|
||||
|
||||
# This is what autoupdate's m4 run will expand. It fires
|
||||
# the warning (with _au_warn_XXX), outputs it into the
|
||||
# updated configure.ac (with AC_DIAGNOSE), and then outputs
|
||||
# the replacement expansion.
|
||||
|
||||
|
||||
# This is an auxiliary macro that is also run when
|
||||
# autoupdate runs m4. It simply calls m4_warning, but
|
||||
# we need a wrapper so that each warning is emitted only
|
||||
# once. We break the quoting in m4_warning's argument in
|
||||
# order to expand this macro's arguments, not AU_DEFUN's.
|
||||
|
||||
|
||||
# Finally, this is the expansion that is picked up by
|
||||
# autoconf. It tells the user to run autoupdate, and
|
||||
# then outputs the replacement expansion. We do not care
|
||||
# about autoupdate's warning because that contains
|
||||
# information on what to do *after* running autoupdate.
|
||||
|
||||
|
||||
|
||||
ac_ext=c
|
||||
ac_cpp='$CPP $CPPFLAGS'
|
||||
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
|
||||
@ -12673,6 +12736,217 @@ fi
|
||||
done
|
||||
|
||||
|
||||
# Check for OPENSSL support
|
||||
|
||||
found=false
|
||||
|
||||
# Check whether --with-openssl was given.
|
||||
if test "${with_openssl+set}" = set; then :
|
||||
withval=$with_openssl;
|
||||
case "$withval" in
|
||||
"" | y | ye | yes | n | no)
|
||||
as_fn_error $? "Invalid --with-openssl value" "$LINENO" 5
|
||||
;;
|
||||
*) ssldirs="$withval"
|
||||
;;
|
||||
esac
|
||||
|
||||
else
|
||||
|
||||
# if pkg-config is installed and openssl has installed a .pc file,
|
||||
# then use that information and don't search ssldirs
|
||||
if test -n "$ac_tool_prefix"; then
|
||||
# Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
|
||||
set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
$as_echo_n "checking for $ac_word... " >&6; }
|
||||
if ${ac_cv_prog_PKG_CONFIG+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
if test -n "$PKG_CONFIG"; then
|
||||
ac_cv_prog_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test.
|
||||
else
|
||||
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
for as_dir in $PATH
|
||||
do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_prog_PKG_CONFIG="${ac_tool_prefix}pkg-config"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done
|
||||
IFS=$as_save_IFS
|
||||
|
||||
fi
|
||||
fi
|
||||
PKG_CONFIG=$ac_cv_prog_PKG_CONFIG
|
||||
if test -n "$PKG_CONFIG"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
|
||||
$as_echo "$PKG_CONFIG" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
fi
|
||||
if test -z "$ac_cv_prog_PKG_CONFIG"; then
|
||||
ac_ct_PKG_CONFIG=$PKG_CONFIG
|
||||
# Extract the first word of "pkg-config", so it can be a program name with args.
|
||||
set dummy pkg-config; ac_word=$2
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
$as_echo_n "checking for $ac_word... " >&6; }
|
||||
if ${ac_cv_prog_ac_ct_PKG_CONFIG+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
if test -n "$ac_ct_PKG_CONFIG"; then
|
||||
ac_cv_prog_ac_ct_PKG_CONFIG="$ac_ct_PKG_CONFIG" # Let the user override the test.
|
||||
else
|
||||
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
for as_dir in $PATH
|
||||
do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_prog_ac_ct_PKG_CONFIG="pkg-config"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done
|
||||
IFS=$as_save_IFS
|
||||
|
||||
fi
|
||||
fi
|
||||
ac_ct_PKG_CONFIG=$ac_cv_prog_ac_ct_PKG_CONFIG
|
||||
if test -n "$ac_ct_PKG_CONFIG"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_PKG_CONFIG" >&5
|
||||
$as_echo "$ac_ct_PKG_CONFIG" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
if test "x$ac_ct_PKG_CONFIG" = x; then
|
||||
PKG_CONFIG=""
|
||||
else
|
||||
case $cross_compiling:$ac_tool_warned in
|
||||
yes:)
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
|
||||
$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
|
||||
ac_tool_warned=yes ;;
|
||||
esac
|
||||
PKG_CONFIG=$ac_ct_PKG_CONFIG
|
||||
fi
|
||||
else
|
||||
PKG_CONFIG="$ac_cv_prog_PKG_CONFIG"
|
||||
fi
|
||||
|
||||
if test x"$PKG_CONFIG" != x""; then
|
||||
OPENSSL_LDFLAGS=`$PKG_CONFIG openssl --libs-only-L 2>/dev/null`
|
||||
if test $? = 0; then
|
||||
OPENSSL_LIBS=`$PKG_CONFIG openssl --libs-only-l 2>/dev/null`
|
||||
OPENSSL_INCLUDES=`$PKG_CONFIG openssl --cflags-only-I 2>/dev/null`
|
||||
found=true
|
||||
fi
|
||||
fi
|
||||
|
||||
# no such luck; use some default ssldirs
|
||||
if ! $found; then
|
||||
ssldirs="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /usr"
|
||||
fi
|
||||
|
||||
|
||||
fi
|
||||
|
||||
|
||||
|
||||
# note that we #include <openssl/foo.h>, so the OpenSSL headers have to be in
|
||||
# an 'openssl' subdirectory
|
||||
|
||||
if ! $found; then
|
||||
OPENSSL_INCLUDES=
|
||||
for ssldir in $ssldirs; do
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for openssl/ssl.h in $ssldir" >&5
|
||||
$as_echo_n "checking for openssl/ssl.h in $ssldir... " >&6; }
|
||||
if test -f "$ssldir/include/openssl/ssl.h"; then
|
||||
OPENSSL_INCLUDES="-I$ssldir/include"
|
||||
OPENSSL_LDFLAGS="-L$ssldir/lib"
|
||||
OPENSSL_LIBS="-lssl -lcrypto"
|
||||
found=true
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
break
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
done
|
||||
|
||||
# if the file wasn't found, well, go ahead and try the link anyway -- maybe
|
||||
# it will just work!
|
||||
fi
|
||||
|
||||
# try the preprocessor and linker with our new flags,
|
||||
# being careful not to pollute the global LIBS, LDFLAGS, and CPPFLAGS
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiling and linking against OpenSSL works" >&5
|
||||
$as_echo_n "checking whether compiling and linking against OpenSSL works... " >&6; }
|
||||
echo "Trying link with OPENSSL_LDFLAGS=$OPENSSL_LDFLAGS;" \
|
||||
"OPENSSL_LIBS=$OPENSSL_LIBS; OPENSSL_INCLUDES=$OPENSSL_INCLUDES" >&5
|
||||
|
||||
save_LIBS="$LIBS"
|
||||
save_LDFLAGS="$LDFLAGS"
|
||||
save_CPPFLAGS="$CPPFLAGS"
|
||||
LDFLAGS="$LDFLAGS $OPENSSL_LDFLAGS"
|
||||
LIBS="$OPENSSL_LIBS $LIBS"
|
||||
CPPFLAGS="$OPENSSL_INCLUDES $CPPFLAGS"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
#include <openssl/ssl.h>
|
||||
int
|
||||
main ()
|
||||
{
|
||||
SSL_new(NULL)
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
|
||||
$as_echo "#define HAVE_SSL 1" >>confdefs.h
|
||||
|
||||
|
||||
|
||||
else
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
|
||||
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
CPPFLAGS="$save_CPPFLAGS"
|
||||
LDFLAGS="$save_LDFLAGS"
|
||||
LIBS="$save_LIBS"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
LDFLAGS="$LDFLAGS $OPENSSL_LDFLAGS"
|
||||
LIBS="$OPENSSL_LIBS $LIBS"
|
||||
CPPFLAGS="$OPENSSL_INCLUDES $CPPFLAGS"
|
||||
|
||||
# Check for TCP_CONGESTION sockopt (believed to be Linux and FreeBSD only)
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking TCP_CONGESTION socket option" >&5
|
||||
$as_echo_n "checking TCP_CONGESTION socket option... " >&6; }
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
# Initialize the autoconf system for the specified tool, version and mailing list
|
||||
AC_INIT(iperf, 3-CURRENT, https://github.com/esnet/iperf, iperf, http://software.es.net/iperf/)
|
||||
m4_include([ax_check_openssl.m4])
|
||||
AC_LANG(C)
|
||||
|
||||
# Specify where the auxiliary files created by configure should go. The config
|
||||
@ -97,6 +98,14 @@ AC_CHECK_HEADERS([netinet/sctp.h],
|
||||
#endif
|
||||
])
|
||||
|
||||
# Check for OPENSSL support
|
||||
AX_CHECK_OPENSSL(
|
||||
AC_DEFINE([HAVE_SSL], [1], [OpenSSL Is Available])
|
||||
)
|
||||
LDFLAGS="$LDFLAGS $OPENSSL_LDFLAGS"
|
||||
LIBS="$OPENSSL_LIBS $LIBS"
|
||||
CPPFLAGS="$OPENSSL_INCLUDES $CPPFLAGS"
|
||||
|
||||
# Check for TCP_CONGESTION sockopt (believed to be Linux and FreeBSD only)
|
||||
AC_CACHE_CHECK([TCP_CONGESTION socket option],
|
||||
[iperf3_cv_header_tcp_congestion],
|
||||
|
@ -111,6 +111,14 @@ the executable.
|
||||
-1, --one-off
|
||||
handle one client connection, then exit.
|
||||
|
||||
--rsa-private-key-path (if built with OpenSSL support)
|
||||
path to the RSA private key used to decrypt authentication
|
||||
credentials (not password protected)
|
||||
|
||||
--authorized-users-path (if built with OpenSSL support)
|
||||
path to the configuration file containing authorized users
|
||||
credendientals to run iperf tests. File is a comma separated
|
||||
list of usernames and password hashes.
|
||||
|
||||
CLIENT SPECIFIC OPTIONS
|
||||
-c, --client host
|
||||
@ -236,6 +244,46 @@ the executable.
|
||||
--json, the server output is included in a JSON object; other-
|
||||
wise it is appended at the bottom of the human-readable output.
|
||||
|
||||
--username (if built with OpenSSL support)
|
||||
username assigned by server adminitrators to access to the iperf
|
||||
service.
|
||||
|
||||
--rsa-public-key-path (if built with OpenSSL support)
|
||||
path to the RSA public key used to encrypt authentication
|
||||
credentials
|
||||
|
||||
EXAMPLES
|
||||
|
||||
Authentication - RSA Keypair
|
||||
|
||||
Authentication feature requires a pair of public and private RSA
|
||||
keys. The public key is used to encrypt the authentication
|
||||
token containing the user credentials, the private key is used
|
||||
to decrypt the authentication token.
|
||||
An example of linux command to generate correct keypair follows:
|
||||
|
||||
$> openssl genrsa -des3 -out private.pem 2048
|
||||
$> openssl rsa -in private.pem -outform PEM -pubout \
|
||||
-out public.pem
|
||||
$> openssl rsa -in private.pem -out private_not_protected.pem \
|
||||
-outform PEM
|
||||
|
||||
Authentication - Authorized users configuration file
|
||||
|
||||
A simple plaintext file can be provided to iperf3 server in
|
||||
order to specify the authorized user c redentials allowd to use
|
||||
iperf3 server. File can contain commented lines (starting with
|
||||
# char) and is a simple list of comma separated pair of
|
||||
username password hash. Password hash is a sha256 hash of
|
||||
string "{$user}$password":
|
||||
|
||||
$> S_USER=mario S_PASSWD=rossi
|
||||
$> echo -ne "{$S_USER}$S_PASSWD"|sha256sum|awk '{ print $1 }'
|
||||
|
||||
$> cat credentials.csv
|
||||
# file format: username,sha256
|
||||
mario,44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c0....
|
||||
$>
|
||||
|
||||
AUTHORS
|
||||
A list of the contributors to iperf3 can be found within the documenta-
|
||||
@ -247,7 +295,7 @@ the executable.
|
||||
|
||||
|
||||
|
||||
ESnet January 2017 IPERF3(1)
|
||||
ESnet Januar 2017 IPERF3(1)
|
||||
|
||||
The iperf3 manual page will typically be installed in manual
|
||||
section 1.
|
||||
|
@ -10,7 +10,9 @@ Source0: http://stats.es.net/software/iperf-%{version}.tar.gz
|
||||
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
|
||||
|
||||
%if 0%{?el5}
|
||||
BuildRequires: e2fsprogs-devel
|
||||
BuildRequires: e2fsprogs-devel, openssl-devel
|
||||
%else
|
||||
BuildRequires: openssl-devel
|
||||
%endif
|
||||
|
||||
%description
|
||||
|
@ -138,9 +138,9 @@ am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \
|
||||
LTLIBRARIES = $(lib_LTLIBRARIES)
|
||||
libiperf_la_LIBADD =
|
||||
am_libiperf_la_OBJECTS = cjson.lo iperf_api.lo iperf_error.lo \
|
||||
iperf_client_api.lo iperf_locale.lo iperf_server_api.lo \
|
||||
iperf_tcp.lo iperf_udp.lo iperf_sctp.lo iperf_util.lo dscp.lo \
|
||||
net.lo tcp_info.lo tcp_window_size.lo timer.lo units.lo
|
||||
iperf_client_api.lo iperf_locale.lo iperf_auth.lo iperf_server_api.lo \
|
||||
iperf_tcp.lo iperf_udp.lo iperf_sctp.lo iperf_util.lo dscp.lo net.lo \
|
||||
tcp_info.lo tcp_window_size.lo timer.lo units.lo
|
||||
libiperf_la_OBJECTS = $(am_libiperf_la_OBJECTS)
|
||||
AM_V_lt = $(am__v_lt_@AM_V@)
|
||||
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
|
||||
@ -158,6 +158,7 @@ am__objects_1 = iperf3_profile-cjson.$(OBJEXT) \
|
||||
iperf3_profile-iperf_error.$(OBJEXT) \
|
||||
iperf3_profile-iperf_client_api.$(OBJEXT) \
|
||||
iperf3_profile-iperf_locale.$(OBJEXT) \
|
||||
iperf3_profile-iperf_auth.$(OBJEXT) \
|
||||
iperf3_profile-iperf_server_api.$(OBJEXT) \
|
||||
iperf3_profile-iperf_tcp.$(OBJEXT) \
|
||||
iperf3_profile-iperf_udp.$(OBJEXT) \
|
||||
@ -574,7 +575,9 @@ libiperf_la_SOURCES = \
|
||||
iperf_api.c \
|
||||
iperf_api.h \
|
||||
iperf_error.c \
|
||||
iperf_client_api.c \
|
||||
iperf_auth.h \
|
||||
iperf_auth.c \
|
||||
iperf_client_api.c \
|
||||
iperf_locale.c \
|
||||
iperf_locale.h \
|
||||
iperf_server_api.c \
|
||||
@ -582,14 +585,14 @@ libiperf_la_SOURCES = \
|
||||
iperf_tcp.h \
|
||||
iperf_udp.c \
|
||||
iperf_udp.h \
|
||||
iperf_sctp.c \
|
||||
iperf_sctp.h \
|
||||
iperf_sctp.c \
|
||||
iperf_sctp.h \
|
||||
iperf_util.c \
|
||||
iperf_util.h \
|
||||
dscp.c \
|
||||
net.c \
|
||||
net.h \
|
||||
portable_endian.h \
|
||||
portable_endian.h \
|
||||
queue.h \
|
||||
tcp_info.c \
|
||||
tcp_window_size.c \
|
||||
@ -813,6 +816,7 @@ distclean-compile:
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf3_profile-iperf_client_api.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf3_profile-iperf_error.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf3_profile-iperf_locale.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf3_profile-iperf_auth.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf3_profile-iperf_sctp.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf3_profile-iperf_server_api.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf3_profile-iperf_tcp.Po@am__quote@
|
||||
@ -828,6 +832,7 @@ distclean-compile:
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf_client_api.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf_error.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf_locale.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf_auth.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf_sctp.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf_server_api.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf_tcp.Plo@am__quote@
|
||||
@ -961,6 +966,22 @@ iperf3_profile-iperf_locale.obj: iperf_locale.c
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(iperf3_profile_CFLAGS) $(CFLAGS) -c -o iperf3_profile-iperf_locale.obj `if test -f 'iperf_locale.c'; then $(CYGPATH_W) 'iperf_locale.c'; else $(CYGPATH_W) '$(srcdir)/iperf_locale.c'; fi`
|
||||
|
||||
iperf3_profile-iperf_auth.o: iperf_auth.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(iperf3_profile_CFLAGS) $(CFLAGS) -MT iperf3_profile-iperf_auth.o -MD -MP -MF $(DEPDIR)/iperf3_profile-iperf_auth.Tpo -c -o iperf3_profile-iperf_auth.o `test -f 'iperf_auth.c' || echo '$(srcdir)/'`iperf_auth.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/iperf3_profile-iperf_auth.Tpo $(DEPDIR)/iperf3_profile-iperf_auth.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='iperf_auth.c' object='iperf3_profile-iperf_auth.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(iperf3_profile_CFLAGS) $(CFLAGS) -c -o iperf3_profile-iperf_auth.o `test -f 'iperf_auth.c' || echo '$(srcdir)/'`iperf_auth.c
|
||||
|
||||
iperf3_profile-iperf_auth.obj: iperf_auth.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(iperf3_profile_CFLAGS) $(CFLAGS) -MT iperf3_profile-iperf_auth.obj -MD -MP -MF $(DEPDIR)/iperf3_profile-iperf_auth.Tpo -c -o iperf3_profile-iperf_auth.obj `if test -f 'iperf_auth.c'; then $(CYGPATH_W) 'iperf_auth.c'; else $(CYGPATH_W) '$(srcdir)/iperf_auth.c'; fi`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/iperf3_profile-iperf_auth.Tpo $(DEPDIR)/iperf3_profile-iperf_auth.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='iperf_auth.c' object='iperf3_profile-iperf_auth.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(iperf3_profile_CFLAGS) $(CFLAGS) -c -o iperf3_profile-iperf_auth.obj `if test -f 'iperf_auth.c'; then $(CYGPATH_W) 'iperf_auth.c'; else $(CYGPATH_W) '$(srcdir)/iperf_auth.c'; fi`
|
||||
|
||||
|
||||
|
||||
iperf3_profile-iperf_server_api.o: iperf_server_api.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(iperf3_profile_CFLAGS) $(CFLAGS) -MT iperf3_profile-iperf_server_api.o -MD -MP -MF $(DEPDIR)/iperf3_profile-iperf_server_api.Tpo -c -o iperf3_profile-iperf_server_api.o `test -f 'iperf_server_api.c' || echo '$(srcdir)/'`iperf_server_api.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/iperf3_profile-iperf_server_api.Tpo $(DEPDIR)/iperf3_profile-iperf_server_api.Po
|
||||
|
@ -123,6 +123,7 @@ struct iperf_settings
|
||||
iperf_size_t blocks; /* number of blocks (packets) to send */
|
||||
char unit_format; /* -f */
|
||||
int num_ostreams; /* SCTP initmsg settings */
|
||||
char *authtoken; /* Authentication token */
|
||||
};
|
||||
|
||||
struct iperf_test;
|
||||
@ -235,6 +236,8 @@ struct iperf_test
|
||||
int prot_listener;
|
||||
|
||||
int ctrl_sck_mss; /* MSS for the control channel */
|
||||
char *server_rsa_private_key;
|
||||
char *server_authorized_users;
|
||||
|
||||
/* boolean variables for Options */
|
||||
int daemon; /* -D option */
|
||||
|
48
src/iperf3.1
48
src/iperf3.1
@ -85,7 +85,14 @@ write a file with the process ID, most useful when running as a daemon.
|
||||
.TP
|
||||
.BR -1 ", " --one-off
|
||||
handle one client connection, then exit.
|
||||
|
||||
.TP
|
||||
.BR --rsa-private-key-path " \fIfile\fR" " (if built with OpenSSL support)
|
||||
path to the RSA private key used to decrypt authentication credentials (not
|
||||
password protected)
|
||||
.TP
|
||||
.BR --authorized-users-path " \fIfile\fR" " (if built with OpenSSL support)
|
||||
path to the configuration file containing authorized users credendientals to run
|
||||
iperf tests. File is a comma separated list of usernames and password hashes.
|
||||
.SH "CLIENT SPECIFIC OPTIONS"
|
||||
.TP
|
||||
.BR -c ", " --client " \fIhost\fR"
|
||||
@ -222,6 +229,45 @@ JSON format, otherwise it will be in human-readable format).
|
||||
If the client is run with \fB--json\fR, the server output is included
|
||||
in a JSON object; otherwise it is appended at the bottom of the
|
||||
human-readable output.
|
||||
.TP
|
||||
.BR --username " \fIusername\fR" " (if built with OpenSSL support)
|
||||
username assigned by server adminitrators to access to the iperf service.
|
||||
.TP
|
||||
.BR --rsa-public-key-path " \fIfile\fR" " (if built with OpenSSL support)
|
||||
path to the RSA public key used to encrypt authentication credentials
|
||||
|
||||
.SH EXAMPLES
|
||||
.TP
|
||||
.BR "Authentication - RSA Keypair"
|
||||
Authentication feature requires a pair of public and private RSA keys. The
|
||||
public key is used to encrypt the authentication token containing the
|
||||
user credentials, the private key is used to decrypt the authentication token.
|
||||
An example of linux command to generate correct keypair follows:
|
||||
.sp 1
|
||||
.in +.5i $> openssl genrsa -des3 -out private.pem 2048
|
||||
.sp 0
|
||||
$> openssl rsa -in private.pem -outform PEM -pubout -out public.pem
|
||||
.sp 0
|
||||
$> openssl rsa -in private.pem -out private_not_protected.pem -outform PEM
|
||||
.TP
|
||||
.BR "Authentication - Authorized users configuration file"
|
||||
A simple plaintext file can be provided to iperf3 server in order to specify
|
||||
the authorized user credentials allowd to use iperf3 server. File can contain
|
||||
commented lines (starting with # char) and is a simple list of comma separated
|
||||
pair of username password hash. Password hash is a sha256 hash of string
|
||||
"{$user}$password":
|
||||
.sp 1
|
||||
.in +.5i $> S_USER=mario S_PASSWD=rossi
|
||||
.sp 0
|
||||
$> echo -n "{$S_USER}$S_PASSWD" | sha256sum | awk '{ print $1 }'
|
||||
.sp 0
|
||||
$> cat credentials.csv
|
||||
.sp 0
|
||||
# file format: username,sha256
|
||||
.sp 0
|
||||
mario,44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c0....
|
||||
.sp 0
|
||||
$>
|
||||
|
||||
.SH AUTHORS
|
||||
A list of the contributors to iperf3 can be found within the
|
||||
|
149
src/iperf_api.c
149
src/iperf_api.c
@ -77,6 +77,9 @@
|
||||
#include "iperf_util.h"
|
||||
#include "iperf_locale.h"
|
||||
#include "version.h"
|
||||
#if defined(HAVE_SSL)
|
||||
#include "iperf_auth.h"
|
||||
#endif /* HAVE_SSL */
|
||||
|
||||
/* Forwards. */
|
||||
static int send_parameters(struct iperf_test *test);
|
||||
@ -671,6 +674,12 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
|
||||
{"get-server-output", no_argument, NULL, OPT_GET_SERVER_OUTPUT},
|
||||
{"udp-counters-64bit", no_argument, NULL, OPT_UDP_COUNTERS_64BIT},
|
||||
{"no-fq-socket-pacing", no_argument, NULL, OPT_NO_FQ_SOCKET_PACING},
|
||||
#if defined(HAVE_SSL)
|
||||
{"username", required_argument, NULL, OPT_CLIENT_USERNAME},
|
||||
{"rsa-public-key-path", required_argument, NULL, OPT_CLIENT_RSA_PUBLIC_KEY},
|
||||
{"rsa-private-key-path", required_argument, NULL, OPT_SERVER_RSA_PRIVATE_KEY},
|
||||
{"authorized-users-path", required_argument, NULL, OPT_SERVER_AUTHORIZED_USERS},
|
||||
#endif /* HAVE_SSL */
|
||||
{"fq-rate", required_argument, NULL, OPT_FQ_RATE},
|
||||
{"debug", no_argument, NULL, 'd'},
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
@ -688,6 +697,10 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
|
||||
|
||||
blksize = 0;
|
||||
server_flag = client_flag = rate_flag = duration_flag = 0;
|
||||
#if defined(HAVE_SSL)
|
||||
char *client_username = NULL, *client_rsa_public_key = NULL;
|
||||
#endif /* HAVE_SSL */
|
||||
|
||||
while ((flag = getopt_long(argc, argv, "p:f:i:D1VJvsc:ub:t:n:k:l:P:Rw:B:M:N46S:L:ZO:F:A:T:C:dI:hX:", longopts, NULL)) != -1) {
|
||||
switch (flag) {
|
||||
case 'p':
|
||||
@ -981,6 +994,20 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
|
||||
return -1;
|
||||
#endif
|
||||
break;
|
||||
#if defined(HAVE_SSL)
|
||||
case OPT_CLIENT_USERNAME:
|
||||
client_username = strdup(optarg);
|
||||
break;
|
||||
case OPT_CLIENT_RSA_PUBLIC_KEY:
|
||||
client_rsa_public_key = strdup(optarg);
|
||||
break;
|
||||
case OPT_SERVER_RSA_PRIVATE_KEY:
|
||||
test->server_rsa_private_key = strdup(optarg);
|
||||
break;
|
||||
case OPT_SERVER_AUTHORIZED_USERS:
|
||||
test->server_authorized_users = strdup(optarg);
|
||||
break;
|
||||
#endif /* HAVE_SSL */
|
||||
case 'h':
|
||||
usage_long(stdout);
|
||||
exit(0);
|
||||
@ -992,23 +1019,64 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
|
||||
|
||||
/* Set logging to a file if specified, otherwise use the default (stdout) */
|
||||
if (test->logfile) {
|
||||
test->outfile = fopen(test->logfile, "a+");
|
||||
if (test->outfile == NULL) {
|
||||
i_errno = IELOGFILE;
|
||||
return -1;
|
||||
}
|
||||
test->outfile = fopen(test->logfile, "a+");
|
||||
if (test->outfile == NULL) {
|
||||
i_errno = IELOGFILE;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check flag / role compatibility. */
|
||||
if (test->role == 'c' && server_flag) {
|
||||
i_errno = IESERVERONLY;
|
||||
return -1;
|
||||
i_errno = IESERVERONLY;
|
||||
return -1;
|
||||
}
|
||||
if (test->role == 's' && client_flag) {
|
||||
i_errno = IECLIENTONLY;
|
||||
return -1;
|
||||
i_errno = IECLIENTONLY;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if defined(HAVE_SSL)
|
||||
|
||||
if (test->role == 's' && (client_username || client_rsa_public_key)){
|
||||
i_errno = IECLIENTONLY;
|
||||
return -1;
|
||||
} else if (test->role == 'c' && (client_username || client_rsa_public_key) &&
|
||||
!(client_username && client_rsa_public_key)) {
|
||||
i_errno = IESETCLIENTAUTH;
|
||||
return -1;
|
||||
} else if (test->role == 'c' && (client_username && client_rsa_public_key)){
|
||||
|
||||
char *client_password = NULL;
|
||||
size_t s;
|
||||
if (iperf_getpass(&client_password, &s, stdin) < 0){
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strlen(client_username) > 20 || strlen(client_password) > 20){
|
||||
i_errno = IESETCLIENTAUTH;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (test_load_pubkey(client_rsa_public_key) < 0){
|
||||
i_errno = IESETCLIENTAUTH;
|
||||
return -1;
|
||||
}
|
||||
encode_auth_setting(client_username, client_password, client_rsa_public_key, &test->settings->authtoken);
|
||||
}
|
||||
|
||||
if (test->role == 'c' && (test->server_rsa_private_key || test->server_authorized_users)){
|
||||
i_errno = IESERVERONLY;
|
||||
return -1;
|
||||
} else if (test->role == 's' && (test->server_rsa_private_key || test->server_authorized_users) &&
|
||||
!(test->server_rsa_private_key && test->server_authorized_users)) {
|
||||
i_errno = IESETSERVERAUTH;
|
||||
return -1;
|
||||
} else if (test->role == 's' && test->server_rsa_private_key && test_load_private_key(test->server_rsa_private_key) < 0){
|
||||
i_errno = IESETSERVERAUTH;
|
||||
return -1;
|
||||
}
|
||||
#endif //HAVE_SSL
|
||||
if (!test->bind_address && test->bind_port) {
|
||||
i_errno = IEBIND;
|
||||
return -1;
|
||||
@ -1235,6 +1303,29 @@ iperf_create_send_timers(struct iperf_test * test)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(HAVE_SSL)
|
||||
int test_is_authorized(struct iperf_test *test){
|
||||
if ( !(test->server_rsa_private_key && test->server_authorized_users)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (test->settings->authtoken){
|
||||
char *username = NULL, *password = NULL;
|
||||
time_t ts;
|
||||
decode_auth_setting(test->debug, test->settings->authtoken, test->server_rsa_private_key, &username, &password, &ts);
|
||||
int ret = check_authentication(username, password, ts, test->server_authorized_users);
|
||||
if (ret == 0){
|
||||
iperf_printf(test, report_authetication_successed, username, ts);
|
||||
return 0;
|
||||
} else {
|
||||
iperf_printf(test, report_authetication_failed, username, ts);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#endif //HAVE_SSL
|
||||
|
||||
/**
|
||||
* iperf_exchange_parameters - handles the param_Exchange part for client
|
||||
*
|
||||
@ -1256,8 +1347,22 @@ iperf_exchange_parameters(struct iperf_test *test)
|
||||
if (get_parameters(test) < 0)
|
||||
return -1;
|
||||
|
||||
#if defined(HAVE_SSL)
|
||||
if (test_is_authorized(test) < 0){
|
||||
if (iperf_set_send_state(test, SERVER_ERROR) != 0)
|
||||
return -1;
|
||||
i_errno = IEAUTHTEST;
|
||||
err = htonl(i_errno);
|
||||
if (Nwrite(test->ctrl_sck, (char*) &err, sizeof(err), Ptcp) < 0) {
|
||||
i_errno = IECTRLWRITE;
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#endif //HAVE_SSL
|
||||
|
||||
if ((s = test->protocol->listen(test)) < 0) {
|
||||
if (iperf_set_send_state(test, SERVER_ERROR) != 0)
|
||||
if (iperf_set_send_state(test, SERVER_ERROR) != 0)
|
||||
return -1;
|
||||
err = htonl(i_errno);
|
||||
if (Nwrite(test->ctrl_sck, (char*) &err, sizeof(err), Ptcp) < 0) {
|
||||
@ -1366,7 +1471,10 @@ send_parameters(struct iperf_test *test)
|
||||
cJSON_AddNumberToObject(j, "get_server_output", iperf_get_test_get_server_output(test));
|
||||
if (test->udp_counters_64bit)
|
||||
cJSON_AddNumberToObject(j, "udp_counters_64bit", iperf_get_test_udp_counters_64bit(test));
|
||||
|
||||
#if defined(HAVE_SSL)
|
||||
if (test->settings->authtoken)
|
||||
cJSON_AddStringToObject(j, "authtoken", test->settings->authtoken);
|
||||
#endif // HAVE_SSL
|
||||
cJSON_AddStringToObject(j, "client_version", IPERF_VERSION);
|
||||
|
||||
if (test->debug) {
|
||||
@ -1448,7 +1556,10 @@ get_parameters(struct iperf_test *test)
|
||||
iperf_set_test_get_server_output(test, 1);
|
||||
if ((j_p = cJSON_GetObjectItem(j, "udp_counters_64bit")) != NULL)
|
||||
iperf_set_test_udp_counters_64bit(test, 1);
|
||||
|
||||
#if defined(HAVE_SSL)
|
||||
if ((j_p = cJSON_GetObjectItem(j, "authtoken")) != NULL)
|
||||
test->settings->authtoken = strdup(j_p->valuestring);
|
||||
#endif //HAVE_SSL
|
||||
if (test->sender && test->protocol->id == Ptcp && has_tcpinfo_retransmits())
|
||||
test->sender_has_retransmits = 1;
|
||||
cJSON_Delete(j);
|
||||
@ -2764,8 +2875,18 @@ iperf_new_stream(struct iperf_test *test, int s)
|
||||
if (test->tmp_template) {
|
||||
snprintf(template, sizeof(template) / sizeof(char), "%s", test->tmp_template);
|
||||
} else {
|
||||
char buf[] = "/tmp/iperf3.XXXXXX";
|
||||
snprintf(template, sizeof(template) / sizeof(char), "%s", buf);
|
||||
//find the system temporary dir *unix, windows, cygwin support
|
||||
char* tempdir = getenv("TMPDIR");
|
||||
if (tempdir == 0){
|
||||
tempdir = getenv("TEMP");
|
||||
}
|
||||
if (tempdir == 0){
|
||||
tempdir = getenv("TMP");
|
||||
}
|
||||
if (tempdir == 0){
|
||||
tempdir = "/tmp";
|
||||
}
|
||||
snprintf(template, sizeof(template) / sizeof(char), "%s/iperf3.XXXXXX", tempdir);
|
||||
}
|
||||
|
||||
sp = (struct iperf_stream *) malloc(sizeof(struct iperf_stream));
|
||||
|
@ -54,6 +54,10 @@ struct iperf_stream;
|
||||
#define OPT_NO_FQ_SOCKET_PACING 9 /* UNUSED */
|
||||
#define OPT_FQ_RATE 10
|
||||
#define OPT_DSCP 11
|
||||
#define OPT_CLIENT_USERNAME 12
|
||||
#define OPT_CLIENT_RSA_PUBLIC_KEY 13
|
||||
#define OPT_SERVER_RSA_PRIVATE_KEY 14
|
||||
#define OPT_SERVER_AUTHORIZED_USERS 15
|
||||
|
||||
/* states */
|
||||
#define TEST_START 1
|
||||
@ -295,6 +299,8 @@ enum {
|
||||
IEBIND = 19, // Local port specified with no local bind option
|
||||
IEUDPBLOCKSIZE = 20, // Block size invalid
|
||||
IEBADTOS = 21, // Bad TOS value
|
||||
IESETCLIENTAUTH = 22, // Bad configuration of client authentication
|
||||
IESETSERVERAUTH = 23, // Bad configuration of server authentication
|
||||
/* Test errors */
|
||||
IENEWTEST = 100, // Unable to create a new test (check perror)
|
||||
IEINITTEST = 101, // Test initialization failed (check perror)
|
||||
@ -338,6 +344,7 @@ enum {
|
||||
IESETSCTPBINDX= 139, // Unable to process sctp_bindx() parameters
|
||||
IESETPACING= 140, // Unable to set socket pacing rate
|
||||
IESETBUF2= 141, // Socket buffer size incorrect (written value != read value)
|
||||
IEAUTHTEST = 142, // Test authorization failed
|
||||
/* Stream errors */
|
||||
IECREATESTREAM = 200, // Unable to create a new stream (check herror/perror)
|
||||
IEINITSTREAM = 201, // Unable to initialize stream (check herror/perror)
|
||||
|
312
src/iperf_auth.c
Обычный файл
312
src/iperf_auth.c
Обычный файл
@ -0,0 +1,312 @@
|
||||
/*
|
||||
* iperf, Copyright (c) 2014-2017, The Regents of the University of
|
||||
* California, through Lawrence Berkeley National Laboratory (subject
|
||||
* to receipt of any required approvals from the U.S. Dept. of
|
||||
* Energy). All rights reserved.
|
||||
*
|
||||
* If you have questions about your rights to use or distribute this
|
||||
* software, please contact Berkeley Lab's Technology Transfer
|
||||
* Department at TTD@lbl.gov.
|
||||
*
|
||||
* NOTICE. This software is owned by the U.S. Department of Energy.
|
||||
* As such, the U.S. Government has been granted for itself and others
|
||||
* acting on its behalf a paid-up, nonexclusive, irrevocable,
|
||||
* worldwide license in the Software to reproduce, prepare derivative
|
||||
* works, and perform publicly and display publicly. Beginning five
|
||||
* (5) years after the date permission to assert copyright is obtained
|
||||
* from the U.S. Department of Energy, and subject to any subsequent
|
||||
* five (5) year renewals, the U.S. Government is granted for itself
|
||||
* and others acting on its behalf a paid-up, nonexclusive,
|
||||
* irrevocable, worldwide license in the Software to reproduce,
|
||||
* prepare derivative works, distribute copies to the public, perform
|
||||
* publicly and display publicly, and to permit others to do so.
|
||||
*
|
||||
* This code is distributed under a BSD style license, see the LICENSE file
|
||||
* for complete information.
|
||||
*/
|
||||
|
||||
#include "iperf_config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <termios.h>
|
||||
|
||||
#if defined(HAVE_SSL)
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/buffer.h>
|
||||
|
||||
void sha256(const char *string, char outputBuffer[65])
|
||||
{
|
||||
unsigned char hash[SHA256_DIGEST_LENGTH];
|
||||
SHA256_CTX sha256;
|
||||
SHA256_Init(&sha256);
|
||||
SHA256_Update(&sha256, string, strlen(string));
|
||||
SHA256_Final(hash, &sha256);
|
||||
int i = 0;
|
||||
for(i = 0; i < SHA256_DIGEST_LENGTH; i++)
|
||||
{
|
||||
sprintf(outputBuffer + (i * 2), "%02x", hash[i]);
|
||||
}
|
||||
outputBuffer[64] = 0;
|
||||
}
|
||||
|
||||
int check_authentication(const char *username, const char *password, const time_t ts, const char *filename){
|
||||
time_t t = time(NULL);
|
||||
time_t utc_seconds = mktime(localtime(&t));
|
||||
if ( (utc_seconds - ts) < 10 && (utc_seconds - ts) > 0 ){
|
||||
return 1;
|
||||
}
|
||||
|
||||
char passwordHash[65];
|
||||
char salted[strlen(username) + strlen(password) + 3];
|
||||
sprintf(salted, "{%s}%s", username, password);
|
||||
sha256(&salted[0], passwordHash);
|
||||
|
||||
char *s_username, *s_password;
|
||||
int i;
|
||||
FILE *ptr_file;
|
||||
char buf[1024];
|
||||
|
||||
ptr_file =fopen(filename,"r");
|
||||
if (!ptr_file)
|
||||
return 2;
|
||||
|
||||
while (fgets(buf,1024, ptr_file)){
|
||||
//strip the \n or \r\n chars
|
||||
for (i = 0; buf[i] != '\0'; i++){
|
||||
if (buf[i] == '\n' || buf[i] == '\r'){
|
||||
buf[i] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
//skip empty / not completed / comment lines
|
||||
if (strlen(buf) == 0 || strchr(buf, ',') == NULL || buf[0] == '#'){
|
||||
continue;
|
||||
}
|
||||
s_username = strtok(buf, ",");
|
||||
s_password = strtok(NULL, ",");
|
||||
if (strcmp( username, s_username ) == 0 && strcmp( passwordHash, s_password ) == 0){
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
||||
int Base64Encode(unsigned char* buffer, const size_t length, char** b64text) { //Encodes a binary safe base 64 string
|
||||
BIO *bio, *b64;
|
||||
BUF_MEM *bufferPtr;
|
||||
|
||||
b64 = BIO_new(BIO_f_base64());
|
||||
bio = BIO_new(BIO_s_mem());
|
||||
bio = BIO_push(b64, bio);
|
||||
|
||||
BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); //Ignore newlines - write everything in one line
|
||||
BIO_write(bio, buffer, length);
|
||||
BIO_flush(bio);
|
||||
BIO_get_mem_ptr(bio, &bufferPtr);
|
||||
BIO_set_close(bio, BIO_NOCLOSE);
|
||||
BIO_free_all(bio);
|
||||
|
||||
*b64text=(*bufferPtr).data;
|
||||
(*b64text)[(*bufferPtr).length] = '\0';
|
||||
return (0); //success
|
||||
}
|
||||
|
||||
size_t calcDecodeLength(const char* b64input) { //Calculates the length of a decoded string
|
||||
size_t len = strlen(b64input), padding = 0;
|
||||
if (b64input[len-1] == '=' && b64input[len-2] == '=') //last two chars are =
|
||||
padding = 2;
|
||||
else if (b64input[len-1] == '=') //last char is =
|
||||
padding = 1;
|
||||
|
||||
return (len*3)/4 - padding;
|
||||
}
|
||||
|
||||
int Base64Decode(char* b64message, unsigned char** buffer, size_t* length) { //Decodes a base64 encoded string
|
||||
BIO *bio, *b64;
|
||||
|
||||
int decodeLen = calcDecodeLength(b64message);
|
||||
*buffer = (unsigned char*)malloc(decodeLen + 1);
|
||||
(*buffer)[decodeLen] = '\0';
|
||||
|
||||
bio = BIO_new_mem_buf(b64message, -1);
|
||||
b64 = BIO_new(BIO_f_base64());
|
||||
bio = BIO_push(b64, bio);
|
||||
|
||||
BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); //Do not use newlines to flush buffer
|
||||
*length = BIO_read(bio, *buffer, strlen(b64message));
|
||||
assert(*length == decodeLen); //length should equal decodeLen, else something went horribly wrong
|
||||
BIO_free_all(bio);
|
||||
|
||||
return (0); //success
|
||||
}
|
||||
|
||||
|
||||
EVP_PKEY *load_pubkey(const char *file) {
|
||||
BIO *key = NULL;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
|
||||
key = BIO_new_file(file, "r");
|
||||
pkey = PEM_read_bio_PUBKEY(key, NULL, NULL, NULL);
|
||||
|
||||
BIO_free(key);
|
||||
return (pkey);
|
||||
}
|
||||
|
||||
EVP_PKEY *load_key(const char *file) {
|
||||
BIO *key = NULL;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
|
||||
key = BIO_new_file(file, "r");
|
||||
pkey = PEM_read_bio_PrivateKey(key, NULL, NULL, NULL);
|
||||
|
||||
BIO_free(key);
|
||||
return (pkey);
|
||||
}
|
||||
|
||||
|
||||
int test_load_pubkey(const char *file){
|
||||
EVP_PKEY *key = load_pubkey(file);
|
||||
if (key == NULL){
|
||||
return -1;
|
||||
}
|
||||
EVP_PKEY_free(key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_load_private_key(const char *file){
|
||||
EVP_PKEY *key = load_key(file);
|
||||
if (key == NULL){
|
||||
return -1;
|
||||
}
|
||||
EVP_PKEY_free(key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int encrypt_rsa_message(const char *plaintext, const char *public_keyfile, unsigned char **encryptedtext) {
|
||||
EVP_PKEY *public_key = NULL;
|
||||
RSA *rsa = NULL;
|
||||
unsigned char *rsa_buffer = NULL, pad = RSA_PKCS1_PADDING;
|
||||
int keysize, encryptedtext_len, rsa_buffer_len;
|
||||
|
||||
public_key = load_pubkey(public_keyfile);
|
||||
rsa = EVP_PKEY_get1_RSA(public_key);
|
||||
EVP_PKEY_free(public_key);
|
||||
|
||||
keysize = RSA_size(rsa);
|
||||
rsa_buffer = OPENSSL_malloc(keysize * 2);
|
||||
*encryptedtext = (unsigned char*)OPENSSL_malloc(keysize);
|
||||
|
||||
BIO *bioBuff = BIO_new_mem_buf((void*)plaintext, (int)strlen(plaintext));
|
||||
rsa_buffer_len = BIO_read(bioBuff, rsa_buffer, keysize * 2);
|
||||
encryptedtext_len = RSA_public_encrypt(rsa_buffer_len, rsa_buffer, *encryptedtext, rsa, pad);
|
||||
|
||||
RSA_free(rsa);
|
||||
OPENSSL_free(rsa_buffer);
|
||||
OPENSSL_free(bioBuff);
|
||||
|
||||
return encryptedtext_len;
|
||||
}
|
||||
|
||||
int decrypt_rsa_message(const unsigned char *encryptedtext, const int encryptedtext_len, const char *private_keyfile, unsigned char **plaintext) {
|
||||
EVP_PKEY *private_key = NULL;
|
||||
RSA *rsa = NULL;
|
||||
unsigned char *rsa_buffer = NULL, pad = RSA_PKCS1_PADDING;
|
||||
int plaintext_len, rsa_buffer_len, keysize;
|
||||
|
||||
private_key = load_key(private_keyfile);
|
||||
rsa = EVP_PKEY_get1_RSA(private_key);
|
||||
EVP_PKEY_free(private_key);
|
||||
|
||||
keysize = RSA_size(rsa);
|
||||
rsa_buffer = OPENSSL_malloc(keysize * 2);
|
||||
*plaintext = (unsigned char*)OPENSSL_malloc(keysize);
|
||||
|
||||
BIO *bioBuff = BIO_new_mem_buf((void*)encryptedtext, encryptedtext_len);
|
||||
rsa_buffer_len = BIO_read(bioBuff, rsa_buffer, keysize * 2);
|
||||
plaintext_len = RSA_private_decrypt(rsa_buffer_len, rsa_buffer, *plaintext, rsa, pad);
|
||||
|
||||
RSA_free(rsa);
|
||||
OPENSSL_free(rsa_buffer);
|
||||
OPENSSL_free(bioBuff);
|
||||
|
||||
return plaintext_len;
|
||||
}
|
||||
|
||||
int encode_auth_setting(const char *username, const char *password, const char *public_keyfile, char **authtoken){
|
||||
time_t t = time(NULL);
|
||||
time_t utc_seconds = mktime(localtime(&t));
|
||||
char text[150];
|
||||
sprintf (text, "user: %s\npwd: %s\nts: %ld", username, password, utc_seconds);
|
||||
unsigned char *encrypted = NULL;
|
||||
int encrypted_len;
|
||||
encrypted_len = encrypt_rsa_message(text, public_keyfile, &encrypted);
|
||||
Base64Encode(encrypted, encrypted_len, authtoken);
|
||||
return (0); //success
|
||||
}
|
||||
|
||||
int decode_auth_setting(int enable_debug, char *authtoken, const char *private_keyfile, char **username, char **password, time_t *ts){
|
||||
unsigned char *encrypted_b64 = NULL;
|
||||
size_t encrypted_len_b64;
|
||||
Base64Decode(authtoken, &encrypted_b64, &encrypted_len_b64);
|
||||
|
||||
unsigned char *plaintext = NULL;
|
||||
int plaintext_len;
|
||||
plaintext_len = decrypt_rsa_message(encrypted_b64, encrypted_len_b64, private_keyfile, &plaintext);
|
||||
plaintext[plaintext_len] = '\0';
|
||||
|
||||
char s_username[20], s_password[20];
|
||||
sscanf ((char *)plaintext,"user: %s\npwd: %s\nts: %ld", s_username, s_password, ts);
|
||||
if (enable_debug) {
|
||||
printf("Auth Token Content:\n%s\n", plaintext);
|
||||
printf("Auth Token Credentials:\n--> %s %s\n", s_username, s_password);
|
||||
}
|
||||
*username = (char *) calloc(21, sizeof(char *));
|
||||
*password = (char *) calloc(21, sizeof(char *));
|
||||
strncpy(*username, s_username, 20);
|
||||
strncpy(*password, s_password, 20);
|
||||
return (0);
|
||||
}
|
||||
|
||||
#endif //HAVE_SSL
|
||||
|
||||
ssize_t iperf_getpass (char **lineptr, size_t *n, FILE *stream) {
|
||||
struct termios old, new;
|
||||
ssize_t nread;
|
||||
|
||||
/* Turn echoing off and fail if we can't. */
|
||||
if (tcgetattr (fileno (stream), &old) != 0)
|
||||
return -1;
|
||||
new = old;
|
||||
new.c_lflag &= ~ECHO;
|
||||
if (tcsetattr (fileno (stream), TCSAFLUSH, &new) != 0)
|
||||
return -1;
|
||||
|
||||
/* Read the password. */
|
||||
printf("Password: ");
|
||||
nread = getline (lineptr, n, stream);
|
||||
|
||||
/* Restore terminal. */
|
||||
(void) tcsetattr (fileno (stream), TCSAFLUSH, &old);
|
||||
|
||||
//strip the \n or \r\n chars
|
||||
char *buf = *lineptr;
|
||||
int i;
|
||||
for (i = 0; buf[i] != '\0'; i++){
|
||||
if (buf[i] == '\n' || buf[i] == '\r'){
|
||||
buf[i] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return nread;
|
||||
}
|
||||
|
||||
|
36
src/iperf_auth.h
Обычный файл
36
src/iperf_auth.h
Обычный файл
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* iperf, Copyright (c) 2014-2017, The Regents of the University of
|
||||
* California, through Lawrence Berkeley National Laboratory (subject
|
||||
* to receipt of any required approvals from the U.S. Dept. of
|
||||
* Energy). All rights reserved.
|
||||
*
|
||||
* If you have questions about your rights to use or distribute this
|
||||
* software, please contact Berkeley Lab's Technology Transfer
|
||||
* Department at TTD@lbl.gov.
|
||||
*
|
||||
* NOTICE. This software is owned by the U.S. Department of Energy.
|
||||
* As such, the U.S. Government has been granted for itself and others
|
||||
* acting on its behalf a paid-up, nonexclusive, irrevocable,
|
||||
* worldwide license in the Software to reproduce, prepare derivative
|
||||
* works, and perform publicly and display publicly. Beginning five
|
||||
* (5) years after the date permission to assert copyright is obtained
|
||||
* from the U.S. Department of Energy, and subject to any subsequent
|
||||
* five (5) year renewals, the U.S. Government is granted for itself
|
||||
* and others acting on its behalf a paid-up, nonexclusive,
|
||||
* irrevocable, worldwide license in the Software to reproduce,
|
||||
* prepare derivative works, distribute copies to the public, perform
|
||||
* publicly and display publicly, and to permit others to do so.
|
||||
*
|
||||
* This code is distributed under a BSD style license, see the LICENSE file
|
||||
* for complete information.
|
||||
*/
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
int test_load_pubkey(const char *public_keyfile);
|
||||
int test_load_private_key(const char *private_keyfile);
|
||||
int encode_auth_setting(const char *username, const char *password, const char *public_keyfile, char **authtoken);
|
||||
int decode_auth_setting(int enable_debug, const char *authtoken, const char *private_keyfile, char **username, char **password, time_t *ts);
|
||||
int check_authentication(const char *username, const char *password, const time_t ts, const char *filename);
|
||||
ssize_t iperf_getpass (char **lineptr, size_t *n, FILE *stream);
|
@ -30,6 +30,9 @@
|
||||
/* Define to 1 if you have the `sendfile' function. */
|
||||
#undef HAVE_SENDFILE
|
||||
|
||||
/* Define to 1 if you have the OPENSSL suppoert */
|
||||
#undef HAVE_SSL
|
||||
|
||||
/* Have SO_MAX_PACING_RATE sockopt. */
|
||||
#undef HAVE_SO_MAX_PACING_RATE
|
||||
|
||||
|
@ -128,9 +128,15 @@ iperf_strerror(int i_errno)
|
||||
case IEUDPBLOCKSIZE:
|
||||
snprintf(errstr, len, "block size invalid (minimum = %d bytes, maximum = %d bytes)", MIN_UDP_BLOCKSIZE, MAX_UDP_BLOCKSIZE);
|
||||
break;
|
||||
case IEBADTOS:
|
||||
snprintf(errstr, len, "bad TOS value (must be between 0 and 255 inclusive)");
|
||||
break;
|
||||
case IEBADTOS:
|
||||
snprintf(errstr, len, "bad TOS value (must be between 0 and 255 inclusive)");
|
||||
break;
|
||||
case IESETCLIENTAUTH:
|
||||
snprintf(errstr, len, "you must specify username (max 20 chars), password (max 20 chars) and a path to a valid public rsa client to be used");
|
||||
break;
|
||||
case IESETSERVERAUTH:
|
||||
snprintf(errstr, len, "you must specify path to a valid private rsa server to be used and a user credential file");
|
||||
break;
|
||||
case IEMSS:
|
||||
snprintf(errstr, len, "TCP MSS too large (maximum = %d bytes)", MAX_MSS);
|
||||
break;
|
||||
@ -168,6 +174,9 @@ iperf_strerror(int i_errno)
|
||||
snprintf(errstr, len, "test initialization failed");
|
||||
perr = 1;
|
||||
break;
|
||||
case IEAUTHTEST:
|
||||
snprintf(errstr, len, "test authorization failed");
|
||||
break;
|
||||
case IELISTEN:
|
||||
snprintf(errstr, len, "unable to start listener for connections");
|
||||
perr = 1;
|
||||
|
@ -117,6 +117,11 @@ const char usage_longstr[] = "Usage: iperf3 [-s|-c host] [options]\n"
|
||||
" -D, --daemon run the server as a daemon\n"
|
||||
" -I, --pidfile file write PID file\n"
|
||||
" -1, --one-off handle one client connection then exit\n"
|
||||
#if defined(HAVE_SSL)
|
||||
" --rsa-private-key-path path to the RSA private key used to decrypt authentication credentials\n"
|
||||
" --authorized-users-path path to the configuration file containing user credendial authorized to use iperf server\n"
|
||||
" file with username and password comma separated, one per line\n"
|
||||
#endif //HAVE_SSL
|
||||
"Client specific:\n"
|
||||
" -c, --client <host> run in client mode, connecting to <host>\n"
|
||||
#if defined(HAVE_SCTP)
|
||||
@ -158,6 +163,10 @@ const char usage_longstr[] = "Usage: iperf3 [-s|-c host] [options]\n"
|
||||
" -T, --title str prefix every output line with this string\n"
|
||||
" --get-server-output get results from server\n"
|
||||
" --udp-counters-64bit use 64-bit counters in UDP test packets\n"
|
||||
#if defined(HAVE_SSL)
|
||||
" --username username to access to the server test\n"
|
||||
" --rsa-public-key-path path to the RSA public key used to encrypt authentication credentials\n"
|
||||
#endif //HAVESSL
|
||||
|
||||
#ifdef NOT_YET_SUPPORTED /* still working on these */
|
||||
#endif
|
||||
@ -249,6 +258,12 @@ const char report_time[] =
|
||||
const char report_connecting[] =
|
||||
"Connecting to host %s, port %d\n";
|
||||
|
||||
const char report_authetication_successed[] =
|
||||
"Authentication successed for user '%s' ts %ld\n";
|
||||
|
||||
const char report_authetication_failed[] =
|
||||
"Authentication failed for user '%s' ts %ld\n";
|
||||
|
||||
const char report_reverse[] =
|
||||
"Reverse mode, remote host %s is sending\n";
|
||||
|
||||
|
@ -54,6 +54,8 @@ extern const char report_reverse[] ;
|
||||
extern const char report_accepted[] ;
|
||||
extern const char report_cookie[] ;
|
||||
extern const char report_connected[] ;
|
||||
extern const char report_authetication_successed[] ;
|
||||
extern const char report_authetication_failed[] ;
|
||||
extern const char report_window[] ;
|
||||
extern const char report_autotune[] ;
|
||||
extern const char report_omit_done[] ;
|
||||
|
Загрузка…
Ссылка в новой задаче
Block a user