diff options
author | Daiki Ueno <ueno@gnu.org> | 2020-10-30 09:50:05 +0000 |
---|---|---|
committer | Daiki Ueno <ueno@gnu.org> | 2020-10-30 09:50:05 +0000 |
commit | cc89b3c82a13fc88a6fbfb1e4d47278bebcf913a (patch) | |
tree | d915a35fa5d4353fb371d37f402d5759aa845114 | |
parent | f8c64c0c5bb23d04fb86a1fa524c2730ea8d048a (diff) | |
parent | e6f959a70235aaf2c31f719d66ff085f1ac85414 (diff) | |
download | gnutls-cc89b3c82a13fc88a6fbfb1e4d47278bebcf913a.tar.gz |
Merge branch 'wip/dueno/psk-colon' into 'master'
psktool: encode username if it contains special character
Closes #1103
See merge request gnutls/gnutls!1345
-rw-r--r-- | .gitlab-ci.yml | 2 | ||||
-rw-r--r-- | bootstrap.conf | 14 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | lib/psk.c | 5 | ||||
-rw-r--r-- | src/psk.c | 102 | ||||
-rw-r--r-- | src/srptool.c | 2 | ||||
-rw-r--r-- | tests/suite/mini-record-timing.c | 29 |
7 files changed, 110 insertions, 46 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 82f52e5365..f09ebbf075 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -686,7 +686,7 @@ Debian.cross.i686-linux-gnu: - export CC_FOR_BUILD="ccache gcc" - export CC="ccache $host-gcc" - ./bootstrap - - sed -i '/errno.==.EINVAL/d' gl/tests/test-strerror.c + - sed -i '/errno.==.EINVAL/d' src/gl/tests/test-strerror.c - mkdir -p build - cd build # Debian's softhsm package is not multiarch yet. Missing softhsm libraries diff --git a/bootstrap.conf b/bootstrap.conf index 8f7da96fd1..9e5a834cb5 100644 --- a/bootstrap.conf +++ b/bootstrap.conf @@ -19,16 +19,18 @@ source_base=gl tests_base=gl/tests m4_base=m4 gnulib_name=libgnu -gnulib_tool_option_extras="--with-tests --avoid=alignof-tests --avoid=lock-tests --avoid=lseek-tests --lgpl=2" +gnulib_tool_option_extras="--without-tests --avoid=alignof-tests --avoid=lock-tests --avoid=lseek-tests --lgpl=2" use_libtool=1 checkout_only_file= local_gl_dir=gl/override/ required_submodules="tests/suite/tls-fuzzer/python-ecdsa tests/suite/tls-fuzzer/tlsfuzzer tests/suite/tls-fuzzer/tlslite-ng devel/nettle devel/libtasn1" -# Reproduce by: gnulib-tool --import --local-dir=gl/override --lib=libgnu --source-base=gl --m4-base=gl/m4 --doc-base=doc --tests-base=gl/tests --aux-dir=build-aux --with-tests --avoid=alignof-tests --avoid=lock-tests --avoid=lseek-tests --lgpl=2 --no-conditional-dependencies --libtool --macro-prefix=gl --no-vc-files alloca attribute byteswap c-ctype extensions fopen-gnu func gendocs getline gettext-h gettimeofday hash-pjw-bare havelib intprops ldd lib-msvc-compat lib-symbol-versions maintainer-makefile manywarnings memmem-simple minmax netdb netinet_in pmccabe2html read-file secure_getenv snprintf stdint strcase strndup strtok_r strverscmp sys_socket sys_stat threadlib time_r unistd vasprintf verify vsnprintf warnings - +# Those modules are common to lib/ and src/. +common_modules=" +alloca attribute byteswap c-ctype c-strcase fopen-gnu func getline gettext-h gettimeofday hash hash-pjw-bare arpa_inet inet_ntop inet_pton intprops memmem-simple minmax netdb netinet_in read-file secure_getenv setsockopt snprintf stdint stpcpy strcase strdup-posix strndup strtok_r strverscmp sys_socket sys_stat sys_types threadlib time_r unistd valgrind-tests vasprintf verify vsnprintf +" gnulib_modules=" -alloca attribute byteswap c-ctype c-strcase extensions fopen-gnu func gendocs getline gettext-h gettimeofday hash hash-pjw-bare havelib arpa_inet inet_ntop inet_pton intprops ldd lib-msvc-compat lib-symbol-versions maintainer-makefile manywarnings memmem-simple minmax netdb netinet_in pmccabe2html read-file secure_getenv setsockopt snprintf stdint stpcpy strcase strdup-posix strndup strtok_r strverscmp sys_socket sys_stat sys_types threadlib time_r unistd valgrind-tests vasprintf verify vsnprintf warnings +$common_modules extensions gendocs havelib ldd lib-msvc-compat lib-symbol-versions maintainer-makefile manywarnings pmccabe2html warnings " unistring_modules=" @@ -36,7 +38,7 @@ unictype/category-all unictype/property-default-ignorable-code-point unictype/pr " src_modules=" -accept bind close connect getaddrinfo getpass gettext-h arpa_inet inet_ntop inet_pton inttypes listen linked-list minmax parse-datetime progname read-file recv recvfrom select send sendto servent setsockopt shutdown socket sockets socklen stpcpy xalloc xlist xsize +$common_modules accept bind close close-stream connect getaddrinfo getpass inttypes listen linked-list parse-datetime progname read-file recv recvfrom select send sendto servent setsockopt shutdown socket sockets socklen xalloc xlist xsize " # Build prerequisites @@ -95,7 +97,7 @@ bootstrap_post_import_hook () ${GNULIB_SRCDIR}/gnulib-tool --import --local-dir=lib/unistring/override --lib=libunistring --source-base=lib/unistring --m4-base=lib/unistring/m4 --doc-base=doc --aux-dir=build-aux --lgpl=3orGPLv2 --no-conditional-dependencies --libtool --without-tests --macro-prefix=unistring ${unistring_modules} - ${GNULIB_SRCDIR}/gnulib-tool --import --local-dir=src/gl/override --lib=libgnu_gpl --source-base=src/gl --m4-base=src/gl/m4 --doc-base=doc --aux-dir=build-aux --no-conditional-dependencies --libtool --macro-prefix=ggl --without-tests --no-vc-files ${src_modules} + ${GNULIB_SRCDIR}/gnulib-tool --import --local-dir=src/gl/override --lib=libgnu_gpl --source-base=src/gl --m4-base=src/gl/m4 --doc-base=doc --tests-base=src/gl/tests --aux-dir=build-aux --no-conditional-dependencies --libtool --macro-prefix=ggl --with-tests --no-vc-files ${src_modules} # git -C ${GNULIB_SRCDIR} reset --hard diff --git a/configure.ac b/configure.ac index e485699f30..42e3c0bc3f 100644 --- a/configure.ac +++ b/configure.ac @@ -1209,7 +1209,6 @@ AC_CONFIG_FILES([ libdane/includes/Makefile libdane/gnutls-dane.pc gl/Makefile - gl/tests/Makefile guile/Makefile guile/src/Makefile lib/Makefile @@ -1231,6 +1230,7 @@ AC_CONFIG_FILES([ src/Makefile src/args-std.def src/gl/Makefile + src/gl/tests/Makefile tests/Makefile tests/windows/Makefile tests/cert-tests/Makefile @@ -231,6 +231,11 @@ gnutls_psk_allocate_server_credentials(gnutls_psk_server_credentials_t * * #gnutls_psk_server_credentials_t type. This password file * holds usernames and keys and will be used for PSK authentication. * + * Each entry in the file consists of a username, followed by a colon + * (':') and a hex-encoded key. If the username contains a colon or + * any other special character, it can be hex-encoded preceded by a + * '#'. + * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise * an error code is returned. **/ @@ -37,11 +37,13 @@ int main(int argc, char **argv) #include <stdio.h> #include <string.h> #include <stdlib.h> +#include <errno.h> #include <gnutls/gnutls.h> #include <psktool-args.h> #include <gnutls/crypto.h> /* for random */ +#include <stdbool.h> #include <sys/types.h> #include <sys/stat.h> @@ -54,9 +56,11 @@ int main(int argc, char **argv) /* Gnulib portability files. */ #include <minmax.h> +#include "close-stream.h" #include "getpass.h" -static int write_key(const char *username, const char *key, int key_size, +static int write_key(const char *username, + const unsigned char *key, size_t key_size, const char *passwd_file); #define MAX_KEY_SIZE 512 @@ -67,11 +71,8 @@ int main(int argc, char **argv) struct passwd *pwd; #endif unsigned char key[MAX_KEY_SIZE]; - char hex_key[MAX_KEY_SIZE * 2 + 1]; - int key_size; - gnutls_datum_t dkey; + size_t key_size; const char *passwd, *username; - size_t hex_key_size = sizeof(hex_key); if ((ret = gnutls_global_init()) < 0) { fprintf(stderr, "global_init: %s\n", gnutls_strerror(ret)); @@ -123,16 +124,7 @@ int main(int argc, char **argv) exit(1); } - dkey.data = key; - dkey.size = key_size; - - ret = gnutls_hex_encode(&dkey, hex_key, &hex_key_size); - if (ret < 0) { - fprintf(stderr, "HEX encoding error\n"); - exit(1); - } - - ret = write_key(username, hex_key, hex_key_size, passwd); + ret = write_key(username, key, key_size, passwd); if (ret == 0) printf("Key stored to %s\n", passwd); @@ -175,19 +167,18 @@ static int filecopy(const char *src, const char *dst) } static int -write_key(const char *username, const char *key, int key_size, +write_key(const char *username, const unsigned char *key, size_t key_size, const char *passwd_file) { FILE *fp; char line[5 * 1024]; char *p, *pp; char tmpname[1024]; - - - /* delete previous entry */ + gnutls_datum_t tmp, _username = { NULL, 0 }, _key = { NULL, 0 }; struct stat st; FILE *fp2; - int put; + bool put; + int ret = 0; if (strlen(passwd_file) + 5 > sizeof(tmpname)) { fprintf(stderr, "file '%s' is tooooo long\n", passwd_file); @@ -223,8 +214,49 @@ write_key(const char *username, const char *key, int key_size, return -1; } - put = 0; - do { + /* encode username if it contains special characters */ + if (strcspn(username, ":\n") != strlen(username)) { + char *new_data; + + tmp.data = (void *)username; + tmp.size = strlen(username); + + ret = gnutls_hex_encode2(&tmp, &_username); + if (ret < 0) { + fprintf(stderr, "HEX encoding error\n"); + ret = -1; + goto out; + } + + /* prepend '#' */ + new_data = gnutls_realloc(_username.data, _username.size + 2); + if (!new_data) { + ret = -1; + goto out; + } + memmove(_username.data + 1, _username.data, _username.size); + new_data[0] = '#'; + new_data[_username.size] = '\0'; + _username.data = (void *)new_data; + _username.size += 1; + } else { + _username.data = (void *)strdup(username); + _username.size = strlen(username); + } + + /* encode key */ + tmp.data = (void *)key; + tmp.size = key_size; + + ret = gnutls_hex_encode2(&tmp, &_key); + if (ret < 0) { + fprintf(stderr, "HEX encoding error\n"); + ret = -1; + goto out; + } + + put = false; + while (true) { p = fgets(line, sizeof(line) - 1, fp2); if (p == NULL) break; @@ -233,28 +265,34 @@ write_key(const char *username, const char *key, int key_size, if (pp == NULL) continue; - if (strncmp(p, username, - MAX(strlen(username), + if (strncmp(p, (const char *) _username.data, + MAX(_username.size, (unsigned int) (pp - p))) == 0) { - put = 1; - fprintf(fp, "%s:%s\n", username, key); + put = true; + fprintf(fp, "%s:%s\n", _username.data, _key.data); } else { fputs(line, fp); } } - while (1); - if (put == 0) { - fprintf(fp, "%s:%s\n", username, key); + if (!put) { + fprintf(fp, "%s:%s\n", _username.data, _key.data); + } + + out: + if (close_stream(fp) == EOF) { + fprintf(stderr, "Error writing %s: %s\n", + passwd_file, strerror(errno)); + ret = -1; } - fclose(fp); fclose(fp2); (void)remove(tmpname); + gnutls_free(_username.data); + gnutls_free(_key.data); - - return 0; + return ret; } #endif /* ENABLE_PSK */ diff --git a/src/srptool.c b/src/srptool.c index 7da14afa6c..a9715e6a37 100644 --- a/src/srptool.c +++ b/src/srptool.c @@ -529,6 +529,7 @@ crypt_int(const char *username, const char *passwd, int salt_size, p = fgets(line, sizeof(line) - 1, fp); } while (p != NULL && atoi(p) != uindex); + fclose(fp); if (p == NULL) { fprintf(stderr, "Cannot find entry in %s\n", tpasswd_conf); @@ -536,7 +537,6 @@ crypt_int(const char *username, const char *passwd, int salt_size, } line[sizeof(line) - 1] = 0; - fclose(fp); if ((iindex = read_conf_values(&g, &n, line)) < 0) { fprintf(stderr, "Cannot parse conf file '%s'\n", tpasswd_conf); diff --git a/tests/suite/mini-record-timing.c b/tests/suite/mini-record-timing.c index 093f3d5d32..4cdd78f472 100644 --- a/tests/suite/mini-record-timing.c +++ b/tests/suite/mini-record-timing.c @@ -495,11 +495,30 @@ static void ch_handler(int sig) wait(&status); if (WEXITSTATUS(status) != 0 || (WIFSIGNALED(status) && WTERMSIG(status) == SIGSEGV)) { - if (WIFSIGNALED(status)) - fprintf(stderr, "Child died with sigsegv\n"); - else - fprintf(stderr, "Child died with status %d\n", - WEXITSTATUS(status)); + /* This code must be async-signal-safe. */ + if (WIFSIGNALED(status)) { + const char msg[] = "Child died with sigsegv\n"; + write(STDERR_FILENO, "Child died with sigsegv\n", sizeof(msg)); + } else { + char buf[64] = { 0 }; + char *p; + + p = stpcpy(buf, "Child died with status "); + + status = WEXITSTATUS(status) & 0377; + if (status > 100) { + *p++ = '0' + status / 100; + status %= 100; + } + if (status > 10) { + *p++ = '0' + status / 10; + status %= 10; + } + *p++ = '0' + status; + *p++ = '\n'; + + write(STDERR_FILENO, buf, p - buf); + } } return; } |