]> www.infradead.org Git - users/dwmw2/openconnect.git/commitdiff
A simple referenced-counted string
authorTom Carroll <incentivedesign@gmail.com>
Wed, 6 May 2020 05:57:48 +0000 (22:57 -0700)
committerTom Carroll <incentivedesign@gmail.com>
Wed, 6 May 2020 05:59:44 +0000 (22:59 -0700)
An implementation of a simple reference-counted string. The purpose of
this is to simplify password password and handling, and reduce the
number of password copies.

Signed-off-by: Tom Carroll <incentivedesign@gmail.com>
gnutls.c
gnutls.h

index 385dade5fadd3db5cf2fa275a9d423b757a05c3a..e0cedbc6faa5f039a9b80c337b6879da4bf9af26 100644 (file)
--- a/gnutls.c
+++ b/gnutls.c
@@ -2773,3 +2773,42 @@ void destroy_eap_ttls(struct openconnect_info *vpninfo, void *sess)
 {
        gnutls_deinit(sess);
 }
+
+const rcstring *rcstring_new_len(const char *s, size_t len)
+{
+       struct rcstring_st *rcstr;
+       size_t rcstr_size;
+
+       rcstr_size = offsetof(struct rcstring_st, str.data) + len + 1;
+       if (rcstr_size <= len) return NULL;
+       rcstr = malloc(rcstr_size);
+       if (rcstr == NULL) return NULL;
+       rcstr->refcount = 1;
+       rcstr->str.len = len;
+       memcpy(rcstr->str.data, s, len);
+       rcstr->str.data[len] = 0;
+       return rcstr->str.data;
+}
+
+const rcstring *rcstring_new(const char *s)
+{
+       return rcstring_new_len(s, strlen(s));
+}
+
+void rcstring_release_zero(const rcstring *str, void (*zero_func)(char *, size_t))
+{
+       struct rcstring_st *rcstr;
+
+       if (str == NULL) return;
+       rcstr = RCSTRING(str);
+       if (--rcstr->refcount <= 0) {
+               if (zero_func != NULL)
+                       (*zero_func)(rcstr->str.data, rcstr->str.len);
+               free(rcstr);
+       }
+}
+
+void zero_password(char *s, size_t n)
+{
+       clear_mem(s, n);
+}
index 0e7a8176c9f5cb32fa73c01951e8d586efe89da3..edaf58122b623de6d6a19498cb384728c876e307 100644 (file)
--- a/gnutls.h
+++ b/gnutls.h
@@ -72,4 +72,73 @@ char *get_gnutls_cipher(gnutls_session_t session);
 #define gnutls_check_version_numeric gtls_ver
 #endif
 
+/**
+ * rcstring is a simple referenced counted string. This was added to
+ * simplify password passing and to reduce the number of times the
+ * password needs to be copied.
+ */
+
+typedef char rcstring;
+
+struct rcstring_st {
+       int refcount;
+       struct {
+               size_t len;
+               char data[1];
+       } str;
+};
+
+#define RCSTRING(p) \
+       ((struct rcstring_st *)((char *)(p) - offsetof(struct rcstring_st, str.    data)))
+
+const rcstring *rcstring_new_len(const char *s, size_t n);
+
+const rcstring *rcstring_new(const char *s);
+
+/**
+ * Acquire a reference to string
+ */
+static inline const char *
+rcstring_acquire(const rcstring *str)
+{
+       if (str == NULL) return NULL;
+       ++RCSTRING(str)->refcount;
+       return str;
+}
+/**
+ * Release a reference to the string
+ */
+void rcstring_release_zero(const rcstring *str,
+       void (*zero_func)(char *,size_t));
+
+static inline void
+rcstring_release(const rcstring *str)
+{
+       return rcstring_release_zero(str, NULL);
+}
+/**
+ * Length of string
+ */
+static inline size_t
+rcstring_length(const rcstring *str)
+{
+       if (str == NULL) return 0;
+       return RCSTRING(str)->str.len;
+}
+/**
+ * passwords are zeroed when the refcount <= 0
+ */
+#define password_new(s) rcstring_new(s)
+
+#define password_acquire(s) rcstring_acquire(s)
+
+void zero_password(char *s, size_t n);
+
+static inline void
+password_free(const rcstring **password)
+{
+       rcstring_release_zero(*password, zero_password);
+       *password = NULL;
+}
+
 #endif /* __OPENCONNECT_GNUTLS_H__ */