From c25fb103ea8b1a822005afbc791610329fd0295a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 9 Jun 2020 16:19:50 +0200 Subject: [PATCH] lib/util: add generate_unique_u64() helper function Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke --- lib/util/genrand_util.c | 23 +++++++++++++++++++++++ lib/util/samba_util.h | 29 ++++++++++++++++++++++++++++- 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/lib/util/genrand_util.c b/lib/util/genrand_util.c index 05d1f3ef6e5..26b52a1c814 100644 --- a/lib/util/genrand_util.c +++ b/lib/util/genrand_util.c @@ -47,7 +47,30 @@ _PUBLIC_ uint64_t generate_random_u64(void) return BVAL(v, 0); } +static struct generate_unique_u64_state { + uint64_t next_value; + int pid; +} generate_unique_u64_state; +_PUBLIC_ uint64_t generate_unique_u64(uint64_t veto_value) +{ + int pid = getpid(); + + if (unlikely(pid != generate_unique_u64_state.pid)) { + generate_unique_u64_state = (struct generate_unique_u64_state) { + .pid = pid, + .next_value = veto_value, + }; + } + + while (unlikely(generate_unique_u64_state.next_value == veto_value)) { + generate_nonce_buffer( + (void *)&generate_unique_u64_state.next_value, + sizeof(generate_unique_u64_state.next_value)); + } + + return generate_unique_u64_state.next_value++; +} /** Microsoft composed the following rules (among others) for quality diff --git a/lib/util/samba_util.h b/lib/util/samba_util.h index f0aa42e7271..5a81baa80b6 100644 --- a/lib/util/samba_util.h +++ b/lib/util/samba_util.h @@ -94,10 +94,37 @@ _PUBLIC_ int sys_getnameinfo(const struct sockaddr *psa, _PUBLIC_ uint32_t generate_random(void); /** - generate a single random uint64_t + * generate a single random uint64_t + * @see generate_unique_u64 **/ _PUBLIC_ uint64_t generate_random_u64(void); +/** + * @brief Generate random nonces usable for re-use detection. + * + * We have a lot of places which require a unique id that can + * be used as a unique identitier for caching states. + * + * Always using generate_nonce_buffer() has it's performance costs, + * it's typically much better than generate_random_buffer(), but + * still it's overhead we want to avoid in performance critical + * workloads. + * + * We call generate_nonce_buffer() just once per given state + * and process. + * + * This is much lighter than generate_random_u64() and it's + * designed for performance critical code paths. + * + * @veto_value It is garanteed that the return value if different from + * the veto_value. + * + * @return a unique value per given state and process + * + * @see generate_random_u64 + */ +uint64_t generate_unique_u64(uint64_t veto_value); + /** very basic password quality checker **/