1 | /* |
2 | * Off-the-Record Messaging library |
3 | * Copyright (C) 2004-2012 Ian Goldberg, Rob Smits, Chris Alexander, |
4 | * Willy Lew, Lisa Du, Nikita Borisov |
5 | * <otr@cypherpunks.ca> |
6 | * |
7 | * This library is free software; you can redistribute it and/or |
8 | * modify it under the terms of version 2.1 of the GNU Lesser General |
9 | * Public License as published by the Free Software Foundation. |
10 | * |
11 | * This library is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | * Lesser General Public License for more details. |
15 | * |
16 | * You should have received a copy of the GNU Lesser General Public |
17 | * License along with this library; if not, write to the Free Software |
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
19 | */ |
20 | |
21 | #ifndef __MESSAGE_H__ |
22 | #define __MESSAGE_H__ |
23 | |
24 | #define OTR_ERROR_PREFIX "?OTR Error: " |
25 | |
26 | typedef enum { |
27 | OTRL_ERRCODE_NONE, |
28 | OTRL_ERRCODE_ENCRYPTION_ERROR, |
29 | OTRL_ERRCODE_MSG_NOT_IN_PRIVATE, |
30 | OTRL_ERRCODE_MSG_UNREADABLE, |
31 | OTRL_ERRCODE_MSG_MALFORMED, |
32 | } OtrlErrorCode; |
33 | |
34 | /* These define the events used to indicate status of SMP to the UI */ |
35 | typedef enum { |
36 | OTRL_SMPEVENT_NONE, |
37 | OTRL_SMPEVENT_ERROR, |
38 | OTRL_SMPEVENT_ABORT, |
39 | OTRL_SMPEVENT_CHEATED, |
40 | OTRL_SMPEVENT_ASK_FOR_ANSWER, |
41 | OTRL_SMPEVENT_ASK_FOR_SECRET, |
42 | OTRL_SMPEVENT_IN_PROGRESS, |
43 | OTRL_SMPEVENT_SUCCESS, |
44 | OTRL_SMPEVENT_FAILURE |
45 | } OtrlSMPEvent; |
46 | |
47 | /* These define the events used to indicate the messages that need |
48 | * to be sent */ |
49 | typedef enum { |
50 | OTRL_MSGEVENT_NONE, |
51 | OTRL_MSGEVENT_ENCRYPTION_REQUIRED, |
52 | OTRL_MSGEVENT_ENCRYPTION_ERROR, |
53 | OTRL_MSGEVENT_CONNECTION_ENDED, |
54 | OTRL_MSGEVENT_SETUP_ERROR, |
55 | OTRL_MSGEVENT_MSG_REFLECTED, |
56 | OTRL_MSGEVENT_MSG_RESENT, |
57 | OTRL_MSGEVENT_RCVDMSG_NOT_IN_PRIVATE, |
58 | OTRL_MSGEVENT_RCVDMSG_UNREADABLE, |
59 | OTRL_MSGEVENT_RCVDMSG_MALFORMED, |
60 | OTRL_MSGEVENT_LOG_HEARTBEAT_RCVD, |
61 | OTRL_MSGEVENT_LOG_HEARTBEAT_SENT, |
62 | OTRL_MSGEVENT_RCVDMSG_GENERAL_ERR, |
63 | OTRL_MSGEVENT_RCVDMSG_UNENCRYPTED, |
64 | OTRL_MSGEVENT_RCVDMSG_UNRECOGNIZED, |
65 | OTRL_MSGEVENT_RCVDMSG_FOR_OTHER_INSTANCE |
66 | } OtrlMessageEvent; |
67 | |
68 | typedef enum { |
69 | OTRL_NOTIFY_ERROR, |
70 | OTRL_NOTIFY_WARNING, |
71 | OTRL_NOTIFY_INFO |
72 | } OtrlNotifyLevel; |
73 | |
74 | typedef enum { |
75 | OTRL_CONVERT_SENDING, |
76 | OTRL_CONVERT_RECEIVING |
77 | } OtrlConvertType; |
78 | |
79 | typedef struct s_OtrlMessageAppOps { |
80 | /* Return the OTR policy for the given context. */ |
81 | OtrlPolicy (*policy)(void *opdata, ConnContext *context); |
82 | |
83 | /* Create a private key for the given accountname/protocol if |
84 | * desired. */ |
85 | void (*create_privkey)(void *opdata, const char *accountname, |
86 | const char *protocol); |
87 | |
88 | /* Report whether you think the given user is online. Return 1 if |
89 | * you think he is, 0 if you think he isn't, -1 if you're not sure. |
90 | * |
91 | * If you return 1, messages such as heartbeats or other |
92 | * notifications may be sent to the user, which could result in "not |
93 | * logged in" errors if you're wrong. */ |
94 | int (*is_logged_in)(void *opdata, const char *accountname, |
95 | const char *protocol, const char *recipient); |
96 | |
97 | /* Send the given IM to the given recipient from the given |
98 | * accountname/protocol. */ |
99 | void (*inject_message)(void *opdata, const char *accountname, |
100 | const char *protocol, const char *recipient, const char *message); |
101 | |
102 | /* When the list of ConnContexts changes (including a change in |
103 | * state), this is called so the UI can be updated. */ |
104 | void (*update_context_list)(void *opdata); |
105 | |
106 | /* A new fingerprint for the given user has been received. */ |
107 | void (*new_fingerprint)(void *opdata, OtrlUserState us, |
108 | const char *accountname, const char *protocol, |
109 | const char *username, unsigned char fingerprint[20]); |
110 | |
111 | /* The list of known fingerprints has changed. Write them to disk. */ |
112 | void (*write_fingerprints)(void *opdata); |
113 | |
114 | /* A ConnContext has entered a secure state. */ |
115 | void (*gone_secure)(void *opdata, ConnContext *context); |
116 | |
117 | /* A ConnContext has left a secure state. */ |
118 | void (*gone_insecure)(void *opdata, ConnContext *context); |
119 | |
120 | /* We have completed an authentication, using the D-H keys we |
121 | * already knew. is_reply indicates whether we initiated the AKE. */ |
122 | void (*still_secure)(void *opdata, ConnContext *context, int is_reply); |
123 | |
124 | /* Find the maximum message size supported by this protocol. */ |
125 | int (*max_message_size)(void *opdata, ConnContext *context); |
126 | |
127 | /* Return a newly allocated string containing a human-friendly |
128 | * representation for the given account */ |
129 | const char *(*account_name)(void *opdata, const char *account, |
130 | const char *protocol); |
131 | |
132 | /* Deallocate a string returned by account_name */ |
133 | void (*account_name_free)(void *opdata, const char *account_name); |
134 | |
135 | /* We received a request from the buddy to use the current "extra" |
136 | * symmetric key. The key will be passed in symkey, of length |
137 | * OTRL_EXTRAKEY_BYTES. The requested use, as well as use-specific |
138 | * data will be passed so that the applications can communicate other |
139 | * information (some id for the data transfer, for example). */ |
140 | void (*received_symkey)(void *opdata, ConnContext *context, |
141 | unsigned int use, const unsigned char *usedata, |
142 | size_t usedatalen, const unsigned char *symkey); |
143 | |
144 | /* Return a string according to the error event. This string will then |
145 | * be concatenated to an OTR header to produce an OTR protocol error |
146 | * message. The following are the possible error events: |
147 | * - OTRL_ERRCODE_ENCRYPTION_ERROR |
148 | * occured while encrypting a message |
149 | * - OTRL_ERRCODE_MSG_NOT_IN_PRIVATE |
150 | * sent encrypted message to somebody who is not in |
151 | * a mutual OTR session |
152 | * - OTRL_ERRCODE_MSG_UNREADABLE |
153 | * sent an unreadable encrypted message |
154 | * - OTRL_ERRCODE_MSG_MALFORMED |
155 | * message sent is malformed */ |
156 | const char *(*otr_error_message)(void *opdata, ConnContext *context, |
157 | OtrlErrorCode err_code); |
158 | |
159 | /* Deallocate a string returned by otr_error_message */ |
160 | void (*otr_error_message_free)(void *opdata, const char *err_msg); |
161 | |
162 | /* Return a string that will be prefixed to any resent message. If this |
163 | * function is not provided by the application then the default prefix, |
164 | * "[resent]", will be used. |
165 | * */ |
166 | const char *(*resent_msg_prefix)(void *opdata, ConnContext *context); |
167 | |
168 | /* Deallocate a string returned by resent_msg_prefix */ |
169 | void (*resent_msg_prefix_free)(void *opdata, const char *prefix); |
170 | |
171 | /* Update the authentication UI with respect to SMP events |
172 | * These are the possible events: |
173 | * - OTRL_SMPEVENT_ASK_FOR_SECRET |
174 | * prompt the user to enter a shared secret. The sender application |
175 | * should call otrl_message_initiate_smp, passing NULL as the question. |
176 | * When the receiver application resumes the SM protocol by calling |
177 | * otrl_message_respond_smp with the secret answer. |
178 | * - OTRL_SMPEVENT_ASK_FOR_ANSWER |
179 | * (same as OTRL_SMPEVENT_ASK_FOR_SECRET but sender calls |
180 | * otrl_message_initiate_smp_q instead) |
181 | * - OTRL_SMPEVENT_CHEATED |
182 | * abort the current auth and update the auth progress dialog |
183 | * with progress_percent. otrl_message_abort_smp should be called to |
184 | * stop the SM protocol. |
185 | * - OTRL_SMPEVENT_INPROGRESS and |
186 | * OTRL_SMPEVENT_SUCCESS and |
187 | * OTRL_SMPEVENT_FAILURE and |
188 | * OTRL_SMPEVENT_ABORT |
189 | * update the auth progress dialog with progress_percent |
190 | * - OTRL_SMPEVENT_ERROR |
191 | * (same as OTRL_SMPEVENT_CHEATED) |
192 | * */ |
193 | void (*handle_smp_event)(void *opdata, OtrlSMPEvent smp_event, |
194 | ConnContext *context, unsigned short progress_percent, |
195 | char *question); |
196 | |
197 | /* Handle and send the appropriate message(s) to the sender/recipient |
198 | * depending on the message events. All the events only require an opdata, |
199 | * the event, and the context. The message and err will be NULL except for |
200 | * some events (see below). The possible events are: |
201 | * - OTRL_MSGEVENT_ENCRYPTION_REQUIRED |
202 | * Our policy requires encryption but we are trying to send |
203 | * an unencrypted message out. |
204 | * - OTRL_MSGEVENT_ENCRYPTION_ERROR |
205 | * An error occured while encrypting a message and the message |
206 | * was not sent. |
207 | * - OTRL_MSGEVENT_CONNECTION_ENDED |
208 | * Message has not been sent because our buddy has ended the |
209 | * private conversation. We should either close the connection, |
210 | * or refresh it. |
211 | * - OTRL_MSGEVENT_SETUP_ERROR |
212 | * A private conversation could not be set up. A gcry_error_t |
213 | * will be passed. |
214 | * - OTRL_MSGEVENT_MSG_REFLECTED |
215 | * Received our own OTR messages. |
216 | * - OTRL_MSGEVENT_MSG_RESENT |
217 | * The previous message was resent. |
218 | * - OTRL_MSGEVENT_RCVDMSG_NOT_IN_PRIVATE |
219 | * Received an encrypted message but cannot read |
220 | * it because no private connection is established yet. |
221 | * - OTRL_MSGEVENT_RCVDMSG_UNREADABLE |
222 | * Cannot read the received message. |
223 | * - OTRL_MSGEVENT_RCVDMSG_MALFORMED |
224 | * The message received contains malformed data. |
225 | * - OTRL_MSGEVENT_LOG_HEARTBEAT_RCVD |
226 | * Received a heartbeat. |
227 | * - OTRL_MSGEVENT_LOG_HEARTBEAT_SENT |
228 | * Sent a heartbeat. |
229 | * - OTRL_MSGEVENT_RCVDMSG_GENERAL_ERR |
230 | * Received a general OTR error. The argument 'message' will |
231 | * also be passed and it will contain the OTR error message. |
232 | * - OTRL_MSGEVENT_RCVDMSG_UNENCRYPTED |
233 | * Received an unencrypted message. The argument 'smessage' will |
234 | * also be passed and it will contain the plaintext message. |
235 | * - OTRL_MSGEVENT_RCVDMSG_UNRECOGNIZED |
236 | * Cannot recognize the type of OTR message received. |
237 | * - OTRL_MSGEVENT_RCVDMSG_FOR_OTHER_INSTANCE |
238 | * Received and discarded a message intended for another instance. */ |
239 | void (*handle_msg_event)(void *opdata, OtrlMessageEvent msg_event, |
240 | ConnContext *context, const char *message, |
241 | gcry_error_t err); |
242 | |
243 | /* Create a instance tag for the given accountname/protocol if |
244 | * desired. */ |
245 | void (*create_instag)(void *opdata, const char *accountname, |
246 | const char *protocol); |
247 | |
248 | /* Called immediately before a data message is encrypted, and after a data |
249 | * message is decrypted. The OtrlConvertType parameter has the value |
250 | * OTRL_CONVERT_SENDING or OTRL_CONVERT_RECEIVING to differentiate these |
251 | * cases. */ |
252 | void (*convert_msg)(void *opdata, ConnContext *context, |
253 | OtrlConvertType convert_type, char ** dest, const char *src); |
254 | |
255 | /* Deallocate a string returned by convert_msg. */ |
256 | void (*convert_free)(void *opdata, ConnContext *context, char *dest); |
257 | |
258 | /* When timer_control is called, turn off any existing periodic |
259 | * timer. |
260 | * |
261 | * Additionally, if interval > 0, set a new periodic timer |
262 | * to go off every interval seconds. When that timer fires, you |
263 | * must call otrl_message_poll(userstate, uiops, uiopdata); from the |
264 | * main libotr thread. |
265 | * |
266 | * The timing does not have to be exact; this timer is used to |
267 | * provide forward secrecy by cleaning up stale private state that |
268 | * may otherwise stick around in memory. Note that the |
269 | * timer_control callback may be invoked from otrl_message_poll |
270 | * itself, possibly to indicate that interval == 0 (that is, that |
271 | * there's no more periodic work to be done at this time). |
272 | * |
273 | * If you set this callback to NULL, then you must ensure that your |
274 | * application calls otrl_message_poll(userstate, uiops, uiopdata); |
275 | * from the main libotr thread every definterval seconds (where |
276 | * definterval can be obtained by calling |
277 | * definterval = otrl_message_poll_get_default_interval(userstate); |
278 | * right after creating the userstate). The advantage of |
279 | * implementing the timer_control callback is that the timer can be |
280 | * turned on by libotr only when it's needed. |
281 | * |
282 | * It is not a problem (except for a minor performance hit) to call |
283 | * otrl_message_poll more often than requested, whether |
284 | * timer_control is implemented or not. |
285 | * |
286 | * If you fail to implement the timer_control callback, and also |
287 | * fail to periodically call otrl_message_poll, then you open your |
288 | * users to a possible forward secrecy violation: an attacker that |
289 | * compromises the user's computer may be able to decrypt a handful |
290 | * of long-past messages (the first messages of an OTR |
291 | * conversation). |
292 | */ |
293 | void (*timer_control)(void *opdata, unsigned int interval); |
294 | |
295 | } OtrlMessageAppOps; |
296 | |
297 | /* Deallocate a message allocated by other otrl_message_* routines. */ |
298 | void otrl_message_free(char *message); |
299 | |
300 | /* Handle a message about to be sent to the network. It is safe to pass |
301 | * all messages about to be sent to this routine. add_appdata is a |
302 | * function that will be called in the event that a new ConnContext is |
303 | * created. It will be passed the data that you supplied, as well as a |
304 | * pointer to the new ConnContext. You can use this to add |
305 | * application-specific information to the ConnContext using the |
306 | * "context->app" field, for example. If you don't need to do this, you |
307 | * can pass NULL for the last two arguments of otrl_message_sending. |
308 | * |
309 | * tlvs is a chain of OtrlTLVs to append to the private message. It is |
310 | * usually correct to just pass NULL here. |
311 | * |
312 | * If non-NULL, ops->convert_msg will be called just before encrypting a |
313 | * message. |
314 | * |
315 | * "instag" specifies the instance tag of the buddy (protocol version 3 only). |
316 | * Meta-instances may also be specified (e.g., OTRL_INSTAG_MOST_SECURE). |
317 | * If "contextp" is not NULL, it will be set to the ConnContext used for |
318 | * sending the message. |
319 | * |
320 | * If no fragmentation or msg injection is wanted, use OTRL_FRAGMENT_SEND_SKIP |
321 | * as the OtrlFragmentPolicy. In this case, this function will assign *messagep |
322 | * with the encrypted msg. If the routine returns non-zero, then the library |
323 | * tried to encrypt the message, but for some reason failed. DO NOT send the |
324 | * message in the clear in that case. If *messagep gets set by the call to |
325 | * something non-NULL, then you should replace your message with the contents |
326 | * of *messagep, and send that instead. |
327 | * |
328 | * Other fragmentation policies are OTRL_FRAGMENT_SEND_ALL, |
329 | * OTRL_FRAGMENT_SEND_ALL_BUT_LAST, or OTRL_FRAGMENT_SEND_ALL_BUT_FIRST. In |
330 | * these cases, the appropriate fragments will be automatically sent. For the |
331 | * last two policies, the remaining fragment will be passed in *original_msg. |
332 | * |
333 | * Call otrl_message_free(*messagep) if you don't need *messagep or when you're |
334 | * done with it. */ |
335 | gcry_error_t otrl_message_sending(OtrlUserState us, |
336 | const OtrlMessageAppOps *ops, |
337 | void *opdata, const char *accountname, const char *protocol, |
338 | const char *recipient, otrl_instag_t instag, const char *original_msg, |
339 | OtrlTLV *tlvs, char **messagep, OtrlFragmentPolicy fragPolicy, |
340 | ConnContext **contextp, |
341 | void (*add_appdata)(void *data, ConnContext *context), |
342 | void *data); |
343 | |
344 | /* Handle a message just received from the network. It is safe to pass |
345 | * all received messages to this routine. add_appdata is a function |
346 | * that will be called in the event that a new ConnContext is created. |
347 | * It will be passed the data that you supplied, as well as |
348 | * a pointer to the new ConnContext. You can use this to add |
349 | * application-specific information to the ConnContext using the |
350 | * "context->app" field, for example. If you don't need to do this, you |
351 | * can pass NULL for the last two arguments of otrl_message_receiving. |
352 | * |
353 | * If non-NULL, ops->convert_msg will be called after a data message is |
354 | * decrypted. |
355 | * |
356 | * If "contextp" is not NULL, it will be set to the ConnContext used for |
357 | * receiving the message. |
358 | * |
359 | * If otrl_message_receiving returns 1, then the message you received |
360 | * was an internal protocol message, and no message should be delivered |
361 | * to the user. |
362 | * |
363 | * If it returns 0, then check if *messagep was set to non-NULL. If |
364 | * so, replace the received message with the contents of *messagep, and |
365 | * deliver that to the user instead. You must call |
366 | * otrl_message_free(*messagep) when you're done with it. If tlvsp is |
367 | * non-NULL, *tlvsp will be set to a chain of any TLVs that were |
368 | * transmitted along with this message. You must call |
369 | * otrl_tlv_free(*tlvsp) when you're done with those. |
370 | * |
371 | * If otrl_message_receiving returns 0 and *messagep is NULL, then this |
372 | * was an ordinary, non-OTR message, which should just be delivered to |
373 | * the user without modification. */ |
374 | int otrl_message_receiving(OtrlUserState us, const OtrlMessageAppOps *ops, |
375 | void *opdata, const char *accountname, const char *protocol, |
376 | const char *sender, const char *message, char **newmessagep, |
377 | OtrlTLV **tlvsp, ConnContext **contextp, |
378 | void (*add_appdata)(void *data, ConnContext *context), |
379 | void *data); |
380 | |
381 | /* Put a connection into the PLAINTEXT state, first sending the |
382 | * other side a notice that we're doing so if we're currently ENCRYPTED, |
383 | * and we think he's logged in. Affects only the specified instance. */ |
384 | void otrl_message_disconnect(OtrlUserState us, const OtrlMessageAppOps *ops, |
385 | void *opdata, const char *accountname, const char *protocol, |
386 | const char *username, otrl_instag_t instance); |
387 | |
388 | /* Put a connection into the PLAINTEXT state, first sending the |
389 | * other side a notice that we're doing so if we're currently ENCRYPTED, |
390 | * and we think he's logged in. Affects all matching instances. */ |
391 | void otrl_message_disconnect_all_instances(OtrlUserState us, |
392 | const OtrlMessageAppOps *ops, void *opdata, const char *accountname, |
393 | const char *protocol, const char *username); |
394 | |
395 | /* Initiate the Socialist Millionaires' Protocol */ |
396 | void otrl_message_initiate_smp(OtrlUserState us, const OtrlMessageAppOps *ops, |
397 | void *opdata, ConnContext *context, const unsigned char *secret, |
398 | size_t secretlen); |
399 | |
400 | /* Initiate the Socialist Millionaires' Protocol and send a prompt |
401 | * question to the buddy */ |
402 | void otrl_message_initiate_smp_q(OtrlUserState us, |
403 | const OtrlMessageAppOps *ops, void *opdata, ConnContext *context, |
404 | const char *question, const unsigned char *secret, size_t secretlen); |
405 | |
406 | /* Respond to a buddy initiating the Socialist Millionaires' Protocol */ |
407 | void otrl_message_respond_smp(OtrlUserState us, const OtrlMessageAppOps *ops, |
408 | void *opdata, ConnContext *context, const unsigned char *secret, |
409 | size_t secretlen); |
410 | |
411 | /* Abort the SMP. Called when an unexpected SMP message breaks the |
412 | * normal flow. */ |
413 | void otrl_message_abort_smp(OtrlUserState us, const OtrlMessageAppOps *ops, |
414 | void *opdata, ConnContext *context); |
415 | |
416 | /* Get the current extra symmetric key (of size OTRL_EXTRAKEY_BYTES |
417 | * bytes) and let the other side know what we're going to use it for. |
418 | * The key is stored in symkey, which must already be allocated |
419 | * and OTRL_EXTRAKEY_BYTES bytes long. */ |
420 | gcry_error_t otrl_message_symkey(OtrlUserState us, |
421 | const OtrlMessageAppOps *ops, void *opdata, ConnContext *context, |
422 | unsigned int use, const unsigned char *usedata, size_t usedatalen, |
423 | unsigned char *symkey); |
424 | |
425 | /* If you do _not_ define a timer_control callback function, set a timer |
426 | * to go off every definterval = |
427 | * otrl_message_poll_get_default_interval(userstate) seconds, and call |
428 | * otrl_message_poll every time the timer goes off. */ |
429 | unsigned int otrl_message_poll_get_default_interval(OtrlUserState us); |
430 | |
431 | /* Call this function every so often, either as directed by the |
432 | * timer_control callback, or every definterval = |
433 | * otrl_message_poll_get_default_interval(userstate) seconds if you have |
434 | * no timer_control callback. This function must be called from the |
435 | * main libotr thread.*/ |
436 | void otrl_message_poll(OtrlUserState us, const OtrlMessageAppOps *ops, |
437 | void *opdata); |
438 | |
439 | #endif |
440 | |