~ubuntu-branches/ubuntu/trusty/libotr2/trusty

« back to all changes in this revision

Viewing changes to src/context.c

  • Committer: Package Import Robot
  • Author(s): Dmitrijs Ledkovs
  • Date: 2012-11-05 01:06:26 UTC
  • Revision ID: package-import@ubuntu.com-20121105010626-4m3hldpaz3jfr3wb
Tags: upstream-3.2.1
ImportĀ upstreamĀ versionĀ 3.2.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Off-the-Record Messaging library
 
3
 *  Copyright (C) 2004-2008  Ian Goldberg, Chris Alexander, Nikita Borisov
 
4
 *                           <otr@cypherpunks.ca>
 
5
 *
 
6
 *  This library is free software; you can redistribute it and/or
 
7
 *  modify it under the terms of version 2.1 of the GNU Lesser General
 
8
 *  Public License as published by the Free Software Foundation.
 
9
 *
 
10
 *  This library is distributed in the hope that it will be useful,
 
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
 *  Lesser General Public License for more details.
 
14
 *
 
15
 *  You should have received a copy of the GNU Lesser General Public
 
16
 *  License along with this library; if not, write to the Free Software
 
17
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
18
 */
 
19
 
 
20
/* system headers */
 
21
#include <stdlib.h>
 
22
#include <assert.h>
 
23
 
 
24
/* libgcrypt headers */
 
25
#include <gcrypt.h>
 
26
 
 
27
/* libotr headers */
 
28
#include "context.h"
 
29
 
 
30
/* Create a new connection context. */
 
31
static ConnContext * new_context(const char * user, const char * accountname,
 
32
        const char * protocol)
 
33
{
 
34
    ConnContext * context;
 
35
    OtrlSMState *smstate;
 
36
    context = malloc(sizeof(*context));
 
37
    assert(context != NULL);
 
38
    context->username = strdup(user);
 
39
    context->accountname = strdup(accountname);
 
40
    context->protocol = strdup(protocol);
 
41
    context->fragment = NULL;
 
42
    context->fragment_len = 0;
 
43
    context->fragment_n = 0;
 
44
    context->fragment_k = 0;
 
45
    context->msgstate = OTRL_MSGSTATE_PLAINTEXT;
 
46
    otrl_auth_new(&(context->auth));
 
47
 
 
48
    smstate = malloc(sizeof(OtrlSMState));
 
49
    assert(smstate != NULL);
 
50
    otrl_sm_state_new(smstate);
 
51
    context->smstate = smstate;
 
52
 
 
53
    context->fingerprint_root.fingerprint = NULL;
 
54
    context->fingerprint_root.context = context;
 
55
    context->fingerprint_root.next = NULL;
 
56
    context->fingerprint_root.tous = NULL;
 
57
    context->active_fingerprint = NULL;
 
58
    context->their_keyid = 0;
 
59
    context->their_y = NULL;
 
60
    context->their_old_y = NULL;
 
61
    context->our_keyid = 0;
 
62
    context->our_dh_key.groupid = 0;
 
63
    context->our_dh_key.priv = NULL;
 
64
    context->our_dh_key.pub = NULL;
 
65
    context->our_old_dh_key.groupid = 0;
 
66
    context->our_old_dh_key.priv = NULL;
 
67
    context->our_old_dh_key.pub = NULL;
 
68
    otrl_dh_session_blank(&(context->sesskeys[0][0]));
 
69
    otrl_dh_session_blank(&(context->sesskeys[0][1]));
 
70
    otrl_dh_session_blank(&(context->sesskeys[1][0]));
 
71
    otrl_dh_session_blank(&(context->sesskeys[1][1]));
 
72
    memset(context->sessionid, 0, 20);
 
73
    context->sessionid_len = 0;
 
74
    context->protocol_version = 0;
 
75
    context->numsavedkeys = 0;
 
76
    context->preshared_secret = NULL;
 
77
    context->preshared_secret_len = 0;
 
78
    context->saved_mac_keys = NULL;
 
79
    context->generation = 0;
 
80
    context->lastsent = 0;
 
81
    context->lastmessage = NULL;
 
82
    context->may_retransmit = 0;
 
83
    context->otr_offer = OFFER_NOT;
 
84
    context->app_data = NULL;
 
85
    context->app_data_free = NULL;
 
86
    context->next = NULL;
 
87
    return context;
 
88
}
 
89
 
 
90
/* Look up a connection context by name/account/protocol from the given
 
91
 * OtrlUserState.  If add_if_missing is true, allocate and return a new
 
92
 * context if one does not currently exist.  In that event, call
 
93
 * add_app_data(data, context) so that app_data and app_data_free can be
 
94
 * filled in by the application, and set *addedp to 1. */
 
95
ConnContext * otrl_context_find(OtrlUserState us, const char *user,
 
96
        const char *accountname, const char *protocol, int add_if_missing,
 
97
        int *addedp,
 
98
        void (*add_app_data)(void *data, ConnContext *context), void *data)
 
99
{
 
100
    ConnContext ** curp;
 
101
    int usercmp = 1, acctcmp = 1, protocmp = 1;
 
102
    if (addedp) *addedp = 0;
 
103
    if (!user || !accountname || !protocol) return NULL;
 
104
    for (curp = &(us->context_root); *curp; curp = &((*curp)->next)) {
 
105
        if ((usercmp = strcmp((*curp)->username, user)) > 0 ||
 
106
                (usercmp == 0 &&
 
107
                  (acctcmp = strcmp((*curp)->accountname, accountname)) > 0) ||
 
108
                (usercmp == 0 && acctcmp == 0 &&
 
109
                  (protocmp = strcmp((*curp)->protocol, protocol)) >= 0))
 
110
            /* We're at the right place in the list.  We've either found
 
111
             * it, or gone too far. */
 
112
            break;
 
113
    }
 
114
    if (usercmp == 0 && acctcmp == 0 && protocmp == 0) {
 
115
        /* Found it! */
 
116
        return *curp;
 
117
    }
 
118
    if (add_if_missing) {
 
119
        ConnContext *newctx;
 
120
        if (addedp) *addedp = 1;
 
121
        newctx = new_context(user, accountname, protocol);
 
122
        newctx->next = *curp;
 
123
        if (*curp) {
 
124
            (*curp)->tous = &(newctx->next);
 
125
        }
 
126
        *curp = newctx;
 
127
        newctx->tous = curp;
 
128
        if (add_app_data) {
 
129
            add_app_data(data, *curp);
 
130
        }
 
131
        return *curp;
 
132
    }
 
133
    return NULL;
 
134
}
 
135
 
 
136
/* Find a fingerprint in a given context, perhaps adding it if not
 
137
 * present. */
 
138
Fingerprint *otrl_context_find_fingerprint(ConnContext *context,
 
139
        unsigned char fingerprint[20], int add_if_missing, int *addedp)
 
140
{
 
141
    Fingerprint *f = context->fingerprint_root.next;
 
142
    if (addedp) *addedp = 0;
 
143
    while(f) {
 
144
        if (!memcmp(f->fingerprint, fingerprint, 20)) return f;
 
145
        f = f->next;
 
146
    }
 
147
    /* Didn't find it. */
 
148
    if (add_if_missing) {
 
149
        if (addedp) *addedp = 1;
 
150
        f = malloc(sizeof(*f));
 
151
        assert(f != NULL);
 
152
        f->fingerprint = malloc(20);
 
153
        assert(f->fingerprint != NULL);
 
154
        memmove(f->fingerprint, fingerprint, 20);
 
155
        f->context = context;
 
156
        f->trust = NULL;
 
157
        f->next = context->fingerprint_root.next;
 
158
        if (f->next) {
 
159
            f->next->tous = &(f->next);
 
160
        }
 
161
        context->fingerprint_root.next = f;
 
162
        f->tous = &(context->fingerprint_root.next);
 
163
        return f;
 
164
    }
 
165
    return NULL;
 
166
}
 
167
 
 
168
/* Set the trust level for a given fingerprint */
 
169
void otrl_context_set_trust(Fingerprint *fprint, const char *trust)
 
170
{
 
171
    if (fprint == NULL) return;
 
172
 
 
173
    free(fprint->trust);
 
174
    fprint->trust = trust ? strdup(trust) : NULL;
 
175
}
 
176
 
 
177
/* Set the preshared secret for a given fingerprint.  Note that this
 
178
 * currently only stores the secret in the ConnContext structure, but
 
179
 * doesn't yet do anything with it. */
 
180
void otrl_context_set_preshared_secret(ConnContext *context,
 
181
        const unsigned char *secret, size_t secret_len)
 
182
{
 
183
    free(context->preshared_secret);
 
184
    context->preshared_secret = NULL;
 
185
    context->preshared_secret_len = 0;
 
186
 
 
187
    if (secret_len) {
 
188
        context->preshared_secret = malloc(secret_len);
 
189
        if (context->preshared_secret) {
 
190
            memmove(context->preshared_secret, secret, secret_len);
 
191
            context->preshared_secret_len = secret_len;
 
192
        }
 
193
    }
 
194
}
 
195
 
 
196
/* Force a context into the OTRL_MSGSTATE_FINISHED state. */
 
197
void otrl_context_force_finished(ConnContext *context)
 
198
{
 
199
    context->msgstate = OTRL_MSGSTATE_FINISHED;
 
200
    otrl_auth_clear(&(context->auth));
 
201
    free(context->fragment);
 
202
    context->fragment = NULL;
 
203
    context->fragment_len = 0;
 
204
    context->fragment_n = 0;
 
205
    context->fragment_k = 0;
 
206
    context->active_fingerprint = NULL;
 
207
    context->their_keyid = 0;
 
208
    gcry_mpi_release(context->their_y);
 
209
    context->their_y = NULL;
 
210
    gcry_mpi_release(context->their_old_y);
 
211
    context->their_old_y = NULL;
 
212
    context->our_keyid = 0;
 
213
    otrl_dh_keypair_free(&(context->our_dh_key));
 
214
    otrl_dh_keypair_free(&(context->our_old_dh_key));
 
215
    otrl_dh_session_free(&(context->sesskeys[0][0]));
 
216
    otrl_dh_session_free(&(context->sesskeys[0][1]));
 
217
    otrl_dh_session_free(&(context->sesskeys[1][0]));
 
218
    otrl_dh_session_free(&(context->sesskeys[1][1]));
 
219
    memset(context->sessionid, 0, 20);
 
220
    context->sessionid_len = 0;
 
221
    free(context->preshared_secret);
 
222
    context->preshared_secret = NULL;
 
223
    context->preshared_secret_len = 0;
 
224
    context->protocol_version = 0;
 
225
    context->numsavedkeys = 0;
 
226
    free(context->saved_mac_keys);
 
227
    context->saved_mac_keys = NULL;
 
228
    gcry_free(context->lastmessage);
 
229
    context->lastmessage = NULL;
 
230
    context->may_retransmit = 0;
 
231
    otrl_sm_state_free(context->smstate);
 
232
}
 
233
 
 
234
/* Force a context into the OTRL_MSGSTATE_PLAINTEXT state. */
 
235
void otrl_context_force_plaintext(ConnContext *context)
 
236
{
 
237
    /* First clean up everything we'd need to do for the FINISHED state */
 
238
    otrl_context_force_finished(context);
 
239
 
 
240
    /* And just set the state properly */
 
241
    context->msgstate = OTRL_MSGSTATE_PLAINTEXT;
 
242
}
 
243
 
 
244
/* Forget a fingerprint (so long as it's not the active one.  If it's a
 
245
 * fingerprint_root, forget the whole context (as long as
 
246
 * and_maybe_context is set, and it's PLAINTEXT).  Also, if it's not
 
247
 * the fingerprint_root, but it's the only fingerprint, and we're
 
248
 * PLAINTEXT, forget the whole context if and_maybe_context is set. */
 
249
void otrl_context_forget_fingerprint(Fingerprint *fprint,
 
250
        int and_maybe_context)
 
251
{
 
252
    ConnContext *context = fprint->context;
 
253
    if (fprint == &(context->fingerprint_root)) {
 
254
        if (context->msgstate == OTRL_MSGSTATE_PLAINTEXT &&
 
255
                and_maybe_context) {
 
256
            otrl_context_forget(context);
 
257
        }
 
258
    } else {
 
259
        if (context->msgstate != OTRL_MSGSTATE_PLAINTEXT ||
 
260
                context->active_fingerprint != fprint) {
 
261
            free(fprint->fingerprint);
 
262
            free(fprint->trust);
 
263
            *(fprint->tous) = fprint->next;
 
264
            if (fprint->next) {
 
265
                fprint->next->tous = fprint->tous;
 
266
            }
 
267
            free(fprint);
 
268
            if (context->msgstate == OTRL_MSGSTATE_PLAINTEXT &&
 
269
                    context->fingerprint_root.next == NULL &&
 
270
                    and_maybe_context) {
 
271
                /* We just deleted the only fingerprint.  Forget the
 
272
                 * whole thing. */
 
273
                otrl_context_forget(context);
 
274
            }
 
275
        }
 
276
    }
 
277
}
 
278
 
 
279
/* Forget a whole context, so long as it's PLAINTEXT. */
 
280
void otrl_context_forget(ConnContext *context)
 
281
{
 
282
    if (context->msgstate != OTRL_MSGSTATE_PLAINTEXT) return;
 
283
 
 
284
    /* Just to be safe, force to plaintext.  This also frees any
 
285
     * extraneous data lying around. */
 
286
    otrl_context_force_plaintext(context);
 
287
 
 
288
    /* First free all the Fingerprints */
 
289
    while(context->fingerprint_root.next) {
 
290
        otrl_context_forget_fingerprint(context->fingerprint_root.next, 0);
 
291
    }
 
292
    /* Now free all the dynamic info here */
 
293
    free(context->username);
 
294
    free(context->accountname);
 
295
    free(context->protocol);
 
296
    free(context->smstate);
 
297
    context->username = NULL;
 
298
    context->accountname = NULL;
 
299
    context->protocol = NULL;
 
300
    context->smstate = NULL;
 
301
 
 
302
    /* Free the application data, if it exists */
 
303
    if (context->app_data && context->app_data_free) {
 
304
        (context->app_data_free)(context->app_data);
 
305
        context->app_data = NULL;
 
306
    }
 
307
 
 
308
    /* Fix the list linkages */
 
309
    *(context->tous) = context->next;
 
310
    if (context->next) {
 
311
        context->next->tous = context->tous;
 
312
    }
 
313
 
 
314
    free(context);
 
315
}
 
316
 
 
317
/* Forget all the contexts in a given OtrlUserState. */
 
318
void otrl_context_forget_all(OtrlUserState us)
 
319
{
 
320
    while (us->context_root) {
 
321
        otrl_context_force_plaintext(us->context_root);
 
322
        otrl_context_forget(us->context_root);
 
323
    }
 
324
}