[Pkg-privacy-commits] [libotr] 56/225: * configure.ac: Update libtool version to match 4.0.0.

Ximin Luo infinity0 at moszumanska.debian.org
Sat Aug 22 12:44:53 UTC 2015


This is an automated email from the git hooks/post-receive script.

infinity0 pushed a commit to branch master
in repository libotr.

commit a98cd1259f992b866d73e8160847991e5530b350
Author: cypherpunk <cypherpunk>
Date:   Sun Jul 6 22:03:30 2008 +0000

    	* configure.ac: Update libtool version to match 4.0.0.
    
    	* src/privkey-t.h:
    	* src/privkey.c:
    	* src/privkey.h:
    	* src/userstate.c:
    	* src/userstate.h: Support for generating privkeys in a
    	background thread.
---
 ChangeLog       |  11 +++
 configure.ac    |   4 +-
 src/privkey-t.h |  10 +++
 src/privkey.c   | 269 ++++++++++++++++++++++++++++++++++++++++++++++----------
 src/privkey.h   |  29 ++++++
 src/userstate.c |   2 +
 src/userstate.h |   1 +
 7 files changed, 276 insertions(+), 50 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index de9902d..0e61469 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2008-07-06:
+
+	* configure.ac: Update libtool version to match 4.0.0.
+
+	* src/privkey-t.h:
+	* src/privkey.c:
+	* src/privkey.h:
+	* src/userstate.c:
+	* src/userstate.h: Support for generating privkeys in a
+	background thread.
+
 2008-07-02:
 
 	* version.h: Change version number to 4.0.0 (but still far from
diff --git a/configure.ac b/configure.ac
index 51d83a9..9d17372 100644
--- a/configure.ac
+++ b/configure.ac
@@ -16,8 +16,8 @@ dnl   For a backwards-incompatible API change (e.g. changing data structures):
 dnl     Change the libotr package version from a.b.c to (a+1).0.0
 dnl     Change the libotr libtool version from x:y:z to (x+1):0:0
 
-AM_INIT_AUTOMAKE(libotr, 3.2.0)
-LIBOTR_LIBTOOL_VERSION="4:0:2"
+AM_INIT_AUTOMAKE(libotr, 4.0.0)
+LIBOTR_LIBTOOL_VERSION="5:0:0"
 
 AC_SUBST(LIBOTR_LIBTOOL_VERSION)
 
diff --git a/src/privkey-t.h b/src/privkey-t.h
index 3421b8b..92f23e6 100644
--- a/src/privkey-t.h
+++ b/src/privkey-t.h
@@ -36,4 +36,14 @@ typedef struct s_OtrlPrivKey {
 
 #define OTRL_PUBKEY_TYPE_DSA 0x0000
 
+/* The list of privkeys currently being constructed, possibly in a
+ * background thread */
+typedef struct s_OtrlPendingPrivKey {
+    struct s_OtrlPendingPrivKey *next;
+    struct s_OtrlPendingPrivKey **tous;
+
+    char *accountname;
+    char *protocol;
+} OtrlPendingPrivKey;
+
 #endif
diff --git a/src/privkey.c b/src/privkey.c
index cfb7f42..68ee51c 100644
--- a/src/privkey.c
+++ b/src/privkey.c
@@ -342,6 +342,76 @@ gcry_error_t otrl_privkey_read_FILEp(OtrlUserState us, FILE *privf)
     return gcry_error(GPG_ERR_NO_ERROR);
 }
 
+static OtrlPendingPrivKey *pending_find(OtrlUserState us,
+	const char *accountname, const char *protocol)
+{
+    OtrlPendingPrivKey *search = us->pending_root;
+
+    while (search) {
+	if (!strcmp(search->accountname, accountname) &&
+		!strcmp(search->protocol, protocol)) {
+	    /* Found it */
+	    return search;
+	}
+	search = search->next;
+    }
+    return NULL;
+}
+
+/* Insert an account/protocol pair into the pending privkey list of the
+ * given OtrlUserState and return a pointer to the new
+ * OtrlPendingPrivKey, or return NULL if it's already there. */
+static OtrlPendingPrivKey *pending_insert(OtrlUserState us,
+	const char *accountname, const char *protocol)
+{
+    /* See if it's already there */
+    OtrlPendingPrivKey *search = pending_find(us, accountname, protocol);
+
+    if (search) {
+	/* It is */
+	return NULL;
+    }
+
+    /* We'll insert it at the beginning of the list */
+    search = malloc(sizeof(*search));
+    if (!search) return NULL;
+
+    search->accountname = strdup(accountname);
+    search->protocol = strdup(protocol);
+
+    search->next = us->pending_root;
+    us->pending_root = search;
+    if (search->next) {
+	search->next->tous = &(search->next);
+    }
+    search->tous = &(us->pending_root);
+    return search;
+}
+
+static void pending_forget(OtrlPendingPrivKey *ppk)
+{
+    if (ppk) {
+	free(ppk->accountname);
+	free(ppk->protocol);
+
+	/* Re-link the list */
+	*(ppk->tous) = ppk->next;
+	if (ppk->next) {
+	    ppk->next->tous = ppk->tous;
+	}
+
+	free(ppk);
+    }
+}
+
+/* Free the memory associated with the pending privkey list */
+void otrl_privkey_pending_forget_all(OtrlUserState us)
+{
+    while(us->pending_root) {
+	pending_forget(us->pending_root);
+    }
+}
+
 static gcry_error_t sexp_write(FILE *privf, gcry_sexp_t sexp)
 {
     size_t buflen;
@@ -385,13 +455,75 @@ static gcry_error_t account_write(FILE *privf, const char *accountname,
     return err;
 }
 
-/* Generate a private DSA key for a given account, storing it into a
- * file on disk, and loading it into the given OtrlUserState.  Overwrite any
- * previously generated keys for that account in that OtrlUserState. */
-gcry_error_t otrl_privkey_generate(OtrlUserState us, const char *filename,
-	const char *accountname, const char *protocol)
+struct s_pending_privkey_calc {
+    char *accountname;
+    char *protocol;
+    gcry_sexp_t privkey;
+};
+
+/* Begin a private key generation that will potentially take place in
+ * a background thread.  This routine must be called from the main
+ * thread.  It will set *newkeyp, which you can pass to
+ * otrl_privkey_generate_calculate in a background thread.  If it
+ * returns gcry_error(GPG_ERR_EEXIST), then a privkey creation for
+ * this accountname/protocol is already in progress, and *newkeyp will
+ * be set to NULL. */
+gcry_error_t otrl_privkey_generate_start(OtrlUserState us,
+	const char *accountname, const char *protocol, void **newkeyp)
 {
+    OtrlPendingPrivKey *found = pending_find(us, accountname, protocol);
+    struct s_pending_privkey_calc *ppc;
+
+    if (found) {
+	if (newkeyp) *newkeyp = NULL;
+	return gcry_error(GPG_ERR_EEXIST);
+    }
+
+    /* We're not already creating this key.  Mark it as in progress. */
+    pending_insert(us, accountname, protocol);
+
+    /* Allocate the working structure */
+    ppc = malloc(sizeof(*ppc));
+    ppc->accountname = strdup(accountname);
+    ppc->protocol = strdup(protocol);
+    ppc->privkey = NULL;
+
+    *newkeyp = ppc;
+
+    return gcry_error(GPG_ERR_NO_ERROR);
+}
+
+/* Do the private key generation calculation.  You may call this from a
+ * background thread.  When it completes, call
+ * otrl_privkey_generate_finish from the _main_ thread. */
+gcry_error_t otrl_privkey_generate_calculate(void *newkey)
+{
+    struct s_pending_privkey_calc *ppc =
+	(struct s_pending_privkey_calc *)newkey;
     gcry_error_t err;
+    gcry_sexp_t key, parms;
+    static const char *parmstr = "(genkey (dsa (nbits 4:1024)))";
+
+    /* Create a DSA key */
+    err = gcry_sexp_new(&parms, parmstr, strlen(parmstr), 0);
+    if (err) {
+	return err;
+    }
+    err = gcry_pk_genkey(&key, parms);
+    gcry_sexp_release(parms);
+    if (err) {
+	return err;
+    }
+
+    /* Extract the privkey */
+    ppc->privkey = gcry_sexp_find_token(key, "private-key", 0);
+    gcry_sexp_release(key);
+
+    return gcry_error(GPG_ERR_NO_ERROR);
+}
+
+static FILE* privkey_fopen(const char *filename, gcry_error_t *errp)
+{
     FILE *privf;
 #ifndef WIN32
     mode_t oldmask;
@@ -401,71 +533,112 @@ gcry_error_t otrl_privkey_generate(OtrlUserState us, const char *filename,
     oldmask = umask(077);
 #endif
     privf = fopen(filename, "w+b");
-    if (!privf) {
+    if (!privf && errp) {
+	*errp = gcry_error_from_errno(errno);
+    }
 #ifndef WIN32
-	umask(oldmask);
+    umask(oldmask);
 #endif
-	err = gcry_error_from_errno(errno);
+    return privf;
+}
+
+/* Call this from the main thread only.  It will write the newly created
+ * private key into the given file and store it in the OtrlUserState. */
+gcry_error_t otrl_privkey_generate_finish(OtrlUserState us,
+	void *newkey, const char *filename)
+{
+    gcry_error_t err;
+    FILE *privf = privkey_fopen(filename, &err);
+    if (!privf) {
 	return err;
     }
 
-    err = otrl_privkey_generate_FILEp(us, privf, accountname, protocol);
+    err = otrl_privkey_generate_finish_FILEp(us, newkey, privf);
 
     fclose(privf);
-#ifndef WIN32
-    umask(oldmask);
-#endif
     return err;
 }
 
-/* Generate a private DSA key for a given account, storing it into a
- * FILE*, and loading it into the given OtrlUserState.  Overwrite any
- * previously generated keys for that account in that OtrlUserState.
- * The FILE* must be open for reading and writing. */
-gcry_error_t otrl_privkey_generate_FILEp(OtrlUserState us, FILE *privf,
-	const char *accountname, const char *protocol)
+/* Call this from the main thread only.  It will write the newly created
+ * private key into the given FILE* (which must be open for reading and
+ * writing) and store it in the OtrlUserState. */
+gcry_error_t otrl_privkey_generate_finish_FILEp(OtrlUserState us,
+	void *newkey, FILE *privf)
 {
-    gcry_error_t err;
-    gcry_sexp_t key, parms, privkey;
-    static const char *parmstr = "(genkey (dsa (nbits 4:1024)))";
-    OtrlPrivKey *p;
+    struct s_pending_privkey_calc *ppc =
+	(struct s_pending_privkey_calc *)newkey;
+    gcry_error_t ret = gcry_error(GPG_ERR_INV_VALUE);
 
-    if (!privf) return gcry_error(GPG_ERR_NO_ERROR);
+    if (ppc && us && privf) {
+	OtrlPrivKey *p;
 
-    /* Create a DSA key */
-    err = gcry_sexp_new(&parms, parmstr, strlen(parmstr), 0);
-    if (err) {
-	return err;
+	/* Output the other keys we know */
+	fprintf(privf, "(privkeys\n");
+
+	for (p=us->privkey_root; p; p=p->next) {
+	    /* Skip this one if our new key replaces it */
+	    if (!strcmp(p->accountname, ppc->accountname) &&
+		    !strcmp(p->protocol, ppc->protocol)) {
+		continue;
+	    }
+
+	    account_write(privf, p->accountname, p->protocol, p->privkey);
+	}
+	account_write(privf, ppc->accountname, ppc->protocol, ppc->privkey);
+	fprintf(privf, ")\n");
+
+	fseek(privf, 0, SEEK_SET);
+
+	ret = otrl_privkey_read_FILEp(us, privf);
+
+	/* Remove our entry from the pending list */
+	pending_forget(pending_find(us, ppc->accountname, ppc->protocol));
     }
-    err = gcry_pk_genkey(&key, parms);
-    gcry_sexp_release(parms);
-    if (err) {
+
+    /* Deallocate ppc */
+    free(ppc->accountname);
+    free(ppc->protocol);
+    gcry_sexp_release(ppc->privkey);
+    free(ppc);
+
+    return ret;
+}
+
+/* Generate a private DSA key for a given account, storing it into a
+ * file on disk, and loading it into the given OtrlUserState.  Overwrite any
+ * previously generated keys for that account in that OtrlUserState. */
+gcry_error_t otrl_privkey_generate(OtrlUserState us, const char *filename,
+	const char *accountname, const char *protocol)
+{
+    gcry_error_t err;
+    FILE *privf = privkey_fopen(filename, &err);
+    if (!privf) {
 	return err;
     }
 
-    /* Extract the privkey */
-    privkey = gcry_sexp_find_token(key, "private-key", 0);
-    gcry_sexp_release(key);
+    err = otrl_privkey_generate_FILEp(us, privf, accountname, protocol);
 
-    /* Output the other keys we know */
-    fprintf(privf, "(privkeys\n");
+    fclose(privf);
+    return err;
+}
 
-    for (p=us->privkey_root; p; p=p->next) {
-	/* Skip this one if our new key replaces it */
-	if (!strcmp(p->accountname, accountname) &&
-		!strcmp(p->protocol, protocol)) {
-	    continue;
-	}
+/* Generate a private DSA key for a given account, storing it into a
+ * FILE*, and loading it into the given OtrlUserState.  Overwrite any
+ * previously generated keys for that account in that OtrlUserState.
+ * The FILE* must be open for reading and writing. */
+gcry_error_t otrl_privkey_generate_FILEp(OtrlUserState us, FILE *privf,
+	const char *accountname, const char *protocol)
+{
+    void *newkey = NULL;
+    gcry_error_t err;
 
-	account_write(privf, p->accountname, p->protocol, p->privkey);
+    err = otrl_privkey_generate_start(us, accountname, protocol, &newkey);
+    if (newkey) {
+	otrl_privkey_generate_calculate(newkey);
+	err = otrl_privkey_generate_finish_FILEp(us, newkey, privf);
     }
-    account_write(privf, accountname, protocol, privkey);
-    gcry_sexp_release(privkey);
-    fprintf(privf, ")\n");
 
-    fseek(privf, 0, SEEK_SET);
-
-    return otrl_privkey_read_FILEp(us, privf);
+    return err;
 }
 
 /* Convert a hex character to a value */
diff --git a/src/privkey.h b/src/privkey.h
index 83e7d48..efe025a 100644
--- a/src/privkey.h
+++ b/src/privkey.h
@@ -47,6 +47,35 @@ gcry_error_t otrl_privkey_read(OtrlUserState us, const char *filename);
  * OtrlUserState.  The FILE* must be open for reading. */
 gcry_error_t otrl_privkey_read_FILEp(OtrlUserState us, FILE *privf);
 
+/* Free the memory associated with the pending privkey list */
+void otrl_privkey_pending_forget_all(OtrlUserState us);
+
+/* Begin a private key generation that will potentially take place in
+ * a background thread.  This routine must be called from the main
+ * thread.  It will set *newkeyp, which you can pass to
+ * otrl_privkey_generate_calculate in a background thread.  If it
+ * returns gcry_error(GPG_ERR_EEXIST), then a privkey creation for
+ * this accountname/protocol is already in progress, and *newkeyp will
+ * be set to NULL. */
+gcry_error_t otrl_privkey_generate_start(OtrlUserState us,
+	const char *accountname, const char *protocol, void **newkeyp);
+
+/* Do the private key generation calculation.  You may call this from a
+ * background thread.  When it completes, call
+ * otrl_privkey_generate_finish from the _main_ thread. */
+gcry_error_t otrl_privkey_generate_calculate(void *newkey);
+
+/* Call this from the main thread only.  It will write the newly created
+ * private key into the given file and store it in the OtrlUserState. */
+gcry_error_t otrl_privkey_generate_finish(OtrlUserState us,
+	void *newkey, const char *filename);
+
+/* Call this from the main thread only.  It will write the newly created
+ * private key into the given FILE* (which must be open for reading and
+ * writing) and store it in the OtrlUserState. */
+gcry_error_t otrl_privkey_generate_finish_FILEp(OtrlUserState us,
+	void *newkey, FILE *privf);
+
 /* Generate a private DSA key for a given account, storing it into a
  * file on disk, and loading it into the given OtrlUserState.  Overwrite any
  * previously generated keys for that account in that OtrlUserState. */
diff --git a/src/userstate.c b/src/userstate.c
index 6de95b8..5ce5f5a 100644
--- a/src/userstate.c
+++ b/src/userstate.c
@@ -38,6 +38,7 @@ OtrlUserState otrl_userstate_create(void)
     if (!us) return NULL;
     us->context_root = NULL;
     us->privkey_root = NULL;
+    us->pending_root = NULL;
 
     return us;
 }
@@ -47,5 +48,6 @@ void otrl_userstate_free(OtrlUserState us)
 {
     otrl_context_forget_all(us);
     otrl_privkey_forget_all(us);
+    otrl_privkey_pending_forget_all(us);
     free(us);
 }
diff --git a/src/userstate.h b/src/userstate.h
index 8525df0..9815714 100644
--- a/src/userstate.h
+++ b/src/userstate.h
@@ -28,6 +28,7 @@ typedef struct s_OtrlUserState* OtrlUserState;
 struct s_OtrlUserState {
     ConnContext *context_root;
     OtrlPrivKey *privkey_root;
+    OtrlPendingPrivKey *pending_root;
 };
 
 /* Create a new OtrlUserState.  Most clients will only need one of

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-privacy/packages/libotr.git



More information about the Pkg-privacy-commits mailing list