[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