diff --git a/MANIFEST b/MANIFEST index 2a58f6fa6..f470c6065 100644 --- a/MANIFEST +++ b/MANIFEST @@ -240,6 +240,7 @@ lib/util/ttysize.c lib/util/unlinkat.c lib/util/util.exp.in lib/util/utimens.c +lib/util/uuid.c lib/util/vsyslog.c lib/zlib/Makefile.in lib/zlib/adler32.c diff --git a/include/sudo_util.h b/include/sudo_util.h index 21b5e182f..7437099f9 100644 --- a/include/sudo_util.h +++ b/include/sudo_util.h @@ -315,4 +315,10 @@ __dso_public char *sudo_ttyname_dev_v1(dev_t tdev, char *name, size_t namelen); __dso_public void sudo_get_ttysize_v1(int *rowp, int *colp); #define sudo_get_ttysize(_a, _b) sudo_get_ttysize_v1((_a), (_b)) +/* uuid.c */ +__dso_public void sudo_uuid_create_v1(unsigned char uuid_out[16]); +#define sudo_uuid_create(_a) sudo_uuid_create_v1((_a)) +__dso_public char *sudo_uuid_to_string_v1(unsigned char uuid[16], char *dst, size_t dstsiz); +#define sudo_uuid_to_string(_a, _b, _c) sudo_uuid_to_string_v1((_a), (_b), (_c)) + #endif /* SUDO_UTIL_H */ diff --git a/lib/util/Makefile.in b/lib/util/Makefile.in index 67f98e354..bd32ee32a 100644 --- a/lib/util/Makefile.in +++ b/lib/util/Makefile.in @@ -124,7 +124,7 @@ LTOBJS = @DIGEST@ event.lo fatal.lo key_val.lo gethostname.lo gettime.lo \ roundup.lo secure_path.lo setgroups.lo strsplit.lo strtobool.lo \ strtoid.lo strtomode.lo strtonum.lo sudo_conf.lo \ sudo_debug.lo sudo_dso.lo term.lo ttyname_dev.lo \ - ttysize.lo @COMMON_OBJS@ @LTLIBOBJS@ + ttysize.lo uuid.lo @COMMON_OBJS@ @LTLIBOBJS@ IOBJS = $(LTOBJS:.lo=.i) @@ -1347,6 +1347,14 @@ utimens.i: $(srcdir)/utimens.c $(incdir)/compat/stdbool.h \ $(CC) -E -o $@ $(CPPFLAGS) $< utimens.plog: utimens.i rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/utimens.c --i-file $< --output-file $@ +uuid.lo: $(srcdir)/uuid.c $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \ + $(incdir)/sudo_rand.h $(incdir)/sudo_util.h $(top_builddir)/config.h + $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/uuid.c +uuid.i: $(srcdir)/uuid.c $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \ + $(incdir)/sudo_rand.h $(incdir)/sudo_util.h $(top_builddir)/config.h + $(CC) -E -o $@ $(CPPFLAGS) $< +uuid.plog: uuid.i + rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/uuid.c --i-file $< --output-file $@ vsyslog.lo: $(srcdir)/vsyslog.c $(incdir)/sudo_compat.h $(top_builddir)/config.h $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/vsyslog.c vsyslog.i: $(srcdir)/vsyslog.c $(incdir)/sudo_compat.h $(top_builddir)/config.h diff --git a/lib/util/util.exp.in b/lib/util/util.exp.in index 6a10b6a82..da0e61b6f 100644 --- a/lib/util/util.exp.in +++ b/lib/util/util.exp.in @@ -122,6 +122,8 @@ sudo_term_noecho_v1 sudo_term_raw_v1 sudo_term_restore_v1 sudo_ttyname_dev_v1 +sudo_uuid_create_v1 +sudo_uuid_to_string_v1 sudo_vfatal_nodebug_v1 sudo_vfatalx_nodebug_v1 sudo_vwarn_nodebug_v1 diff --git a/lib/util/uuid.c b/lib/util/uuid.c new file mode 100644 index 000000000..6ec537bd7 --- /dev/null +++ b/lib/util/uuid.c @@ -0,0 +1,112 @@ +/* + * SPDX-License-Identifier: ISC + * + * Copyright (c) 2020 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This is an open source non-commercial project. Dear PVS-Studio, please check it. + * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + */ + +#include + +#include +#include +#if defined(HAVE_STDINT_H) +# include +#elif defined(HAVE_INTTYPES_H) +# include +#endif +#include +#include + +#include "sudo_compat.h" +#include "sudo_util.h" +#include "sudo_rand.h" + +struct uuid { + uint32_t time_low; + uint16_t time_mid; + uint16_t time_high_and_version; + uint16_t clock_seq_and_variant; + unsigned char node[6]; +}; + +/* + * Create a type 4 (random), variant 1 universally unique identifier (UUID). + */ +void +sudo_uuid_create_v1(unsigned char uuid_out[16]) +{ + union { + struct uuid id; + unsigned char u8[16]; + } uuid; + + arc4random_buf(&uuid, sizeof(uuid)); + + /* Convert fields to host by order. */ + uuid.id.time_low = ntohl(uuid.id.time_low); + uuid.id.time_mid = ntohs(uuid.id.time_mid); + uuid.id.time_high_and_version = ntohs(uuid.id.time_high_and_version); + uuid.id.clock_seq_and_variant = ntohs(uuid.id.clock_seq_and_variant); + + /* Set version to 4 (random) in the high nibble. */ + uuid.id.time_high_and_version &= 0x0fff; + uuid.id.time_high_and_version |= 0x4000; + + /* Set variant to 1 (first two bits are 10) */ + uuid.id.clock_seq_and_variant &= 0x3fff; + uuid.id.clock_seq_and_variant |= 0x8000; + + /* Store fields in network byte order (big endian). */ + uuid.id.time_low = htonl(uuid.id.time_low); + uuid.id.time_mid = htons(uuid.id.time_mid); + uuid.id.time_high_and_version = htons(uuid.id.time_high_and_version); + uuid.id.clock_seq_and_variant = htons(uuid.id.clock_seq_and_variant); + memcpy(uuid_out, &uuid, 16); +} + +/* + * Format a uuid as a 36-byte string (plus one for the NUL). + */ +char * +sudo_uuid_to_string_v1(unsigned char uuid[16], char *dst, size_t dstsiz) +{ + const char hex[] = "0123456789abcdef"; + char *cp = dst; + int i; + + if (dstsiz < sizeof("123e4567-e89b-12d3-a456-426655440000")) + return NULL; + + for (i = 0; i < 16; i++) { + *cp++ = hex[uuid[i] >> 4]; + *cp++ = hex[uuid[i] & 0x0f]; + + switch (i) { + case 4: + case 6: + case 8: + case 10: + *cp++ = '-'; + break; + } + } + *cp = '\0'; + + return dst; +}