summaryrefslogtreecommitdiff
path: root/plugins/MirOTR/libotr-3.2.0/src/context.c
diff options
context:
space:
mode:
authorKirill Volinsky <mataes2007@gmail.com>2012-05-19 18:01:32 +0000
committerKirill Volinsky <mataes2007@gmail.com>2012-05-19 18:01:32 +0000
commitb1509f22892dc98057c750e7fae39ded5cea3b09 (patch)
tree6bdcc9379ae86339a67022b758575729d1304074 /plugins/MirOTR/libotr-3.2.0/src/context.c
parente7a776a6f5ab323cd9dd824e815846ef268fa7f1 (diff)
added MirOTR
git-svn-id: http://svn.miranda-ng.org/main/trunk@83 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/MirOTR/libotr-3.2.0/src/context.c')
-rw-r--r--plugins/MirOTR/libotr-3.2.0/src/context.c330
1 files changed, 330 insertions, 0 deletions
diff --git a/plugins/MirOTR/libotr-3.2.0/src/context.c b/plugins/MirOTR/libotr-3.2.0/src/context.c
new file mode 100644
index 0000000000..8807b89145
--- /dev/null
+++ b/plugins/MirOTR/libotr-3.2.0/src/context.c
@@ -0,0 +1,330 @@
+/*
+ * Off-the-Record Messaging library
+ * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov
+ * <otr@cypherpunks.ca>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General
+ * Public License as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* system headers */
+#include <stdlib.h>
+#include <assert.h>
+
+/* libgcrypt headers */
+#include <gcrypt.h>
+
+/* libotr headers */
+#include "context.h"
+
+/* Create a new connection context. */
+static ConnContext * new_context(const char * user, const char * accountname,
+ const char * protocol)
+{
+ ConnContext * context;
+ OtrlSMState *smstate;
+ context = malloc(sizeof(*context));
+ assert(context != NULL);
+ context->username = _strdup(user);
+ context->accountname = _strdup(accountname);
+ context->protocol = _strdup(protocol);
+ context->fragment = NULL;
+ context->fragment_len = 0;
+ context->fragment_n = 0;
+ context->fragment_k = 0;
+ context->msgstate = OTRL_MSGSTATE_PLAINTEXT;
+ otrl_auth_new(&(context->auth));
+
+ smstate = malloc(sizeof(OtrlSMState));
+ assert(smstate != NULL);
+ otrl_sm_state_new(smstate);
+ context->smstate = smstate;
+
+ context->fingerprint_root.fingerprint = NULL;
+ context->fingerprint_root.context = context;
+ context->fingerprint_root.next = NULL;
+ context->fingerprint_root.tous = NULL;
+ context->active_fingerprint = NULL;
+ context->their_keyid = 0;
+ context->their_y = NULL;
+ context->their_old_y = NULL;
+ context->our_keyid = 0;
+ context->our_dh_key.groupid = 0;
+ context->our_dh_key.priv = NULL;
+ context->our_dh_key.pub = NULL;
+ context->our_old_dh_key.groupid = 0;
+ context->our_old_dh_key.priv = NULL;
+ context->our_old_dh_key.pub = NULL;
+ otrl_dh_session_blank(&(context->sesskeys[0][0]));
+ otrl_dh_session_blank(&(context->sesskeys[0][1]));
+ otrl_dh_session_blank(&(context->sesskeys[1][0]));
+ otrl_dh_session_blank(&(context->sesskeys[1][1]));
+ memset(context->sessionid, 0, 20);
+ context->sessionid_len = 0;
+ context->protocol_version = 0;
+ context->numsavedkeys = 0;
+ context->preshared_secret = NULL;
+ context->preshared_secret_len = 0;
+ context->saved_mac_keys = NULL;
+ context->generation = 0;
+ context->lastsent = 0;
+ context->lastmessage = NULL;
+ context->may_retransmit = 0;
+ context->otr_offer = OFFER_NOT;
+ context->app_data = NULL;
+ context->app_data_free = NULL;
+ context->next = NULL;
+ return context;
+}
+
+ConnContext * otrl_context_new(const char * user, const char * accountname,
+ const char * protocol)
+{
+ return new_context(user, accountname, protocol);
+}
+
+/* Look up a connection context by name/account/protocol from the given
+ * OtrlUserState. If add_if_missing is true, allocate and return a new
+ * context if one does not currently exist. In that event, call
+ * add_app_data(data, context) so that app_data and app_data_free can be
+ * filled in by the application, and set *addedp to 1. */
+ConnContext * otrl_context_find(OtrlUserState us, const char *user,
+ const char *accountname, const char *protocol, int add_if_missing,
+ int *addedp,
+ void (*add_app_data)(void *data, ConnContext *context), void *data)
+{
+ ConnContext ** curp;
+ int usercmp = 1, acctcmp = 1, protocmp = 1;
+ if (addedp) *addedp = 0;
+ if (!user || !accountname || !protocol) return NULL;
+ for (curp = &(us->context_root); *curp; curp = &((*curp)->next)) {
+ if ((usercmp = strcmp((*curp)->username, user)) > 0 ||
+ (usercmp == 0 &&
+ (acctcmp = strcmp((*curp)->accountname, accountname)) > 0) ||
+ (usercmp == 0 && acctcmp == 0 &&
+ (protocmp = strcmp((*curp)->protocol, protocol)) >= 0))
+ /* We're at the right place in the list. We've either found
+ * it, or gone too far. */
+ break;
+ }
+ if (usercmp == 0 && acctcmp == 0 && protocmp == 0) {
+ /* Found it! */
+ return *curp;
+ }
+ if (add_if_missing) {
+ ConnContext *newctx;
+ if (addedp) *addedp = 1;
+ newctx = new_context(user, accountname, protocol);
+ newctx->next = *curp;
+ if (*curp) {
+ (*curp)->tous = &(newctx->next);
+ }
+ *curp = newctx;
+ newctx->tous = curp;
+ if (add_app_data) {
+ add_app_data(data, *curp);
+ }
+ return *curp;
+ }
+ return NULL;
+}
+
+/* Find a fingerprint in a given context, perhaps adding it if not
+ * present. */
+Fingerprint *otrl_context_find_fingerprint(ConnContext *context,
+ unsigned char fingerprint[20], int add_if_missing, int *addedp)
+{
+ Fingerprint *f = context->fingerprint_root.next;
+ if (addedp) *addedp = 0;
+ while(f) {
+ if (!memcmp(f->fingerprint, fingerprint, 20)) return f;
+ f = f->next;
+ }
+ /* Didn't find it. */
+ if (add_if_missing) {
+ if (addedp) *addedp = 1;
+ f = malloc(sizeof(*f));
+ assert(f != NULL);
+ f->fingerprint = malloc(20);
+ assert(f->fingerprint != NULL);
+ memmove(f->fingerprint, fingerprint, 20);
+ f->context = context;
+ f->trust = NULL;
+ f->next = context->fingerprint_root.next;
+ if (f->next) {
+ f->next->tous = &(f->next);
+ }
+ context->fingerprint_root.next = f;
+ f->tous = &(context->fingerprint_root.next);
+ return f;
+ }
+ return NULL;
+}
+
+/* Set the trust level for a given fingerprint */
+void otrl_context_set_trust(Fingerprint *fprint, const char *trust)
+{
+ if (fprint == NULL) return;
+
+ free(fprint->trust);
+ fprint->trust = trust ? _strdup(trust) : NULL;
+}
+
+/* Set the preshared secret for a given fingerprint. Note that this
+ * currently only stores the secret in the ConnContext structure, but
+ * doesn't yet do anything with it. */
+void otrl_context_set_preshared_secret(ConnContext *context,
+ const unsigned char *secret, size_t secret_len)
+{
+ free(context->preshared_secret);
+ context->preshared_secret = NULL;
+ context->preshared_secret_len = 0;
+
+ if (secret_len) {
+ context->preshared_secret = malloc(secret_len);
+ if (context->preshared_secret) {
+ memmove(context->preshared_secret, secret, secret_len);
+ context->preshared_secret_len = secret_len;
+ }
+ }
+}
+
+/* Force a context into the OTRL_MSGSTATE_FINISHED state. */
+void otrl_context_force_finished(ConnContext *context)
+{
+ context->msgstate = OTRL_MSGSTATE_FINISHED;
+ otrl_auth_clear(&(context->auth));
+ free(context->fragment);
+ context->fragment = NULL;
+ context->fragment_len = 0;
+ context->fragment_n = 0;
+ context->fragment_k = 0;
+ context->active_fingerprint = NULL;
+ context->their_keyid = 0;
+ gcry_mpi_release(context->their_y);
+ context->their_y = NULL;
+ gcry_mpi_release(context->their_old_y);
+ context->their_old_y = NULL;
+ context->our_keyid = 0;
+ otrl_dh_keypair_free(&(context->our_dh_key));
+ otrl_dh_keypair_free(&(context->our_old_dh_key));
+ otrl_dh_session_free(&(context->sesskeys[0][0]));
+ otrl_dh_session_free(&(context->sesskeys[0][1]));
+ otrl_dh_session_free(&(context->sesskeys[1][0]));
+ otrl_dh_session_free(&(context->sesskeys[1][1]));
+ memset(context->sessionid, 0, 20);
+ context->sessionid_len = 0;
+ free(context->preshared_secret);
+ context->preshared_secret = NULL;
+ context->preshared_secret_len = 0;
+ context->protocol_version = 0;
+ context->numsavedkeys = 0;
+ free(context->saved_mac_keys);
+ context->saved_mac_keys = NULL;
+ gcry_free(context->lastmessage);
+ context->lastmessage = NULL;
+ context->may_retransmit = 0;
+ otrl_sm_state_free(context->smstate);
+}
+
+/* Force a context into the OTRL_MSGSTATE_PLAINTEXT state. */
+void otrl_context_force_plaintext(ConnContext *context)
+{
+ /* First clean up everything we'd need to do for the FINISHED state */
+ otrl_context_force_finished(context);
+
+ /* And just set the state properly */
+ context->msgstate = OTRL_MSGSTATE_PLAINTEXT;
+}
+
+/* Forget a fingerprint (so long as it's not the active one. If it's a
+ * fingerprint_root, forget the whole context (as long as
+ * and_maybe_context is set, and it's PLAINTEXT). Also, if it's not
+ * the fingerprint_root, but it's the only fingerprint, and we're
+ * PLAINTEXT, forget the whole context if and_maybe_context is set. */
+void otrl_context_forget_fingerprint(Fingerprint *fprint,
+ int and_maybe_context)
+{
+ ConnContext *context = fprint->context;
+ if (fprint == &(context->fingerprint_root)) {
+ if (context->msgstate == OTRL_MSGSTATE_PLAINTEXT &&
+ and_maybe_context) {
+ otrl_context_forget(context);
+ }
+ } else {
+ if (context->msgstate != OTRL_MSGSTATE_PLAINTEXT ||
+ context->active_fingerprint != fprint) {
+ free(fprint->fingerprint);
+ free(fprint->trust);
+ *(fprint->tous) = fprint->next;
+ if (fprint->next) {
+ fprint->next->tous = fprint->tous;
+ }
+ free(fprint);
+ if (context->msgstate == OTRL_MSGSTATE_PLAINTEXT &&
+ context->fingerprint_root.next == NULL &&
+ and_maybe_context) {
+ /* We just deleted the only fingerprint. Forget the
+ * whole thing. */
+ otrl_context_forget(context);
+ }
+ }
+ }
+}
+
+/* Forget a whole context, so long as it's PLAINTEXT. */
+void otrl_context_forget(ConnContext *context)
+{
+ if (context->msgstate != OTRL_MSGSTATE_PLAINTEXT) return;
+
+ /* Just to be safe, force to plaintext. This also frees any
+ * extraneous data lying around. */
+ otrl_context_force_plaintext(context);
+
+ /* First free all the Fingerprints */
+ while(context->fingerprint_root.next) {
+ otrl_context_forget_fingerprint(context->fingerprint_root.next, 0);
+ }
+ /* Now free all the dynamic info here */
+ free(context->username);
+ free(context->accountname);
+ free(context->protocol);
+ free(context->smstate);
+ context->username = NULL;
+ context->accountname = NULL;
+ context->protocol = NULL;
+ context->smstate = NULL;
+
+ /* Free the application data, if it exists */
+ if (context->app_data && context->app_data_free) {
+ (context->app_data_free)(context->app_data);
+ context->app_data = NULL;
+ }
+
+ /* Fix the list linkages */
+ *(context->tous) = context->next;
+ if (context->next) {
+ context->next->tous = context->tous;
+ }
+
+ free(context);
+}
+
+/* Forget all the contexts in a given OtrlUserState. */
+void otrl_context_forget_all(OtrlUserState us)
+{
+ while (us->context_root) {
+ otrl_context_force_plaintext(us->context_root);
+ otrl_context_forget(us->context_root);
+ }
+}