?? encrypt.c
字號:
/* Gaim encryption plugin *//* Copyright (C) 2001-2003 William Tompkins *//* This plugin is free software, distributed under the GNU General Public *//* License. *//* Please see the file "COPYING" distributed with the Gaim source code *//* for more details *//* *//* *//* This software 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 *//* General Public License for more details. *//* To compile and use: *//* See INSTALL file. */#include "gaim-encryption-config.h"#include <gdk/gdk.h>#include <gtk/gtkplug.h>#include <config.h>#include <debug.h>#include <gaim.h>#include <core.h>#include <gtkutils.h>#include <gtkplugin.h>#include <gtkconv.h>#include <gtkdialogs.h>#include <gtkprefs.h>#include <blist.h>#include <gtkblist.h>#include <signals.h>#include <util.h>#include <version.h>#include <internal.h>#include "cryptproto.h"#include "cryptutil.h"#include "state.h"#include "state_ui.h"#include "keys.h"#include "nonce.h"#include "prefs.h"#include "config_ui.h"#include "ge_blist.h"#include "encrypt.h"#include "nls.h"#include <time.h>#include <sys/types.h>#include <sys/time.h>#include <string.h>#include <unistd.h>#include <math.h>#include <ctype.h>#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <errno.h>#ifdef HAVE_ALLOCA_H#include <alloca.h>#endif#ifdef _WIN32#include "win32dep.h"#endif/* from Gaim's internal.h, but it isn't critical that it is in sync: *//* #define BUF_LONG 4096 */G_MODULE_IMPORT GSList *gaim_accounts;G_MODULE_IMPORT guint im_options;#define ENCRYPT_PLUGIN_ID "gtk-obobo-gaim-encryption"/* Types */struct msg_node { char who[64]; time_t time; GaimConnection* gc; struct msg_node* next; unsigned char msg[1];};typedef struct msg_node msg_node;GaimPlugin *GE_plugin_handle;/* Outgoing message queue (waiting on a public key to encrypt) */static msg_node* first_out_msg = 0;static msg_node* last_out_msg = 0;/* Incoming message queue (waiting on a public key to verify) */static msg_node* first_inc_msg = 0;static msg_node* last_inc_msg = 0;static int GE_get_msg_size_limit(GaimAccount*);static void GE_send_key(GaimAccount *, const char *name, int, char*);static crypt_key * GE_get_key(GaimConnection *, const char *name);static int decrypt_msg(unsigned char **decrypted, unsigned char *msg, const unsigned char *name, crypt_key *, crypt_key *);static void GE_store_msg(const char *name, GaimConnection*, char *, msg_node**, msg_node**);static void got_encrypted_msg(GaimConnection *, const char *name, char **);static void reap_all_sent_messages(GaimConversation*);static void reap_old_sent_messages(GaimConversation*);/* Function pointers exported to Gaim */static gboolean GE_got_msg_cb(GaimAccount *, char **, char **, GaimConvImFlags flags, void *);static void GE_send_msg_cb(GaimAccount *, char *, char **, void *);static void GE_new_conv_cb(GaimConversation *, void *);static void GE_del_conv_cb(GaimConversation *, void *);static GHashTable *header_table, *footer_table, *notify_table;static gchar* header_default;/* #define CRYPT_HEADER "*** Encrypted with the Gaim-Encryption plugin <A HREF=\"" *//* #define CRYPT_FOOTER "\"></A>" *//* #define CRYPT_NOTIFY_HEADER "<A HREF=\"Gaim-Encryption Capable\"></A>" */// Jabber seems to turn our double quotes into single quotes at times, so define// the same headers, only with single quotes. Lengths MUST be the same as above/* #define CRYPT_HEADER_MANGLED "*** Encrypted with the Gaim-Encryption plugin <A HREF='" *//* #define CRYPT_NOTIFY_HEADER_MANGLED "<A HREF='Gaim-Encryption Capable'></A>" *//* Send key to other side. If msg_id is non-null, we include a request to re-send *//* a certain message, as well. */static void GE_send_key(GaimAccount *acct, const char *name, int asError, gchar *msg_id) { /* load key somehow */ char *msg; GString *key_str; crypt_key *pub_key; GaimConversation *conv; int header_size, footer_size; const gchar* header = g_hash_table_lookup(header_table, gaim_account_get_protocol_id(acct)); const gchar* footer = g_hash_table_lookup(footer_table, gaim_account_get_protocol_id(acct)); if (!header) header = header_default; if (!footer) footer = ""; header_size = strlen(header); footer_size = strlen(footer); gaim_debug(GAIM_DEBUG_INFO, "gaim-encryption", "send_key: %s\n", acct->username); conv = gaim_find_conversation_with_account(name, acct); gaim_debug(GAIM_DEBUG_INFO, "gaim-encryption", "send_key: %s, %p, %s\n", name, conv, acct->username); pub_key = GE_find_own_key_by_name(&GE_my_pub_ring, acct->username, acct, conv); gaim_debug(GAIM_DEBUG_INFO, "gaim-encryption", "send_key2: %s\n", acct->username); if (!pub_key) return; key_str = GE_make_sendable_key(pub_key, name); gaim_debug(GAIM_DEBUG_INFO, "gaim-encryption", "send_key3: %s\n", acct->username); msg = alloca(header_size + footer_size + key_str->len + 100); if (msg == 0) return; if (asError) { if (msg_id) { sprintf(msg, "%s: ErrKey: Prot %s: Len %d:%sResend:%s:%s", header, pub_key->proto->name, (int)key_str->len, key_str->str, msg_id, footer); } else { sprintf(msg, "%s: ErrKey: Prot %s: Len %d:%s%s", header, pub_key->proto->name, (int)key_str->len, key_str->str, footer); } } else { sprintf(msg, "%s: Key: Prot %s: Len %d:%s%s", header, pub_key->proto->name, (int)key_str->len, key_str->str, footer); } if (strlen(msg) > GE_get_msg_size_limit(acct)) { g_free(msg); gaim_debug(GAIM_DEBUG_MISC, "gaim-encryption", "Key too big to send in message\n"); conv = gaim_find_conversation_with_account(name, acct); if (conv == NULL) { conv = gaim_conversation_new(GAIM_CONV_IM, acct, name); } gaim_conversation_write(conv, 0, _("This account key is too large for this protocol. " "Unable to send."), GAIM_MESSAGE_SYSTEM, time((time_t)NULL)); return; } serv_send_im(acct->gc, name, msg, GAIM_CONNECTION_AUTO_RESP); g_string_free(key_str, TRUE);}static crypt_key *GE_get_key(GaimConnection *gc, const char *name) { crypt_key *bkey; unsigned char* tmpmsg; int header_size, footer_size; const gchar* header = g_hash_table_lookup(header_table, gaim_account_get_protocol_id(gc->account)); const gchar* footer = g_hash_table_lookup(footer_table, gaim_account_get_protocol_id(gc->account)); if (!header) header = header_default; if (!footer) footer = ""; header_size = strlen(header); footer_size = strlen(footer); gaim_debug(GAIM_DEBUG_INFO, "gaim-encryption", "get_key: %s\n", name); bkey = GE_find_key_by_name(GE_buddy_ring, name, gc->account); gaim_debug(GAIM_DEBUG_INFO, "gaim-encryption", "got key: %p\n", bkey); if( bkey == 0 ) { tmpmsg = alloca(header_size + footer_size + sizeof (": Send Key")); // sizeof() gets the trailing null too sprintf(tmpmsg, "%s%s%s", header, ": Send Key", footer); gaim_debug(GAIM_DEBUG_MISC, "gaim-encryption", "Sending: %s\n", tmpmsg); serv_send_im(gc, name, tmpmsg, GAIM_CONNECTION_AUTO_RESP); return 0; } return bkey;}static int decrypt_msg(unsigned char **decrypted, unsigned char *msg, const unsigned char *name, crypt_key *priv_key, crypt_key *pub_key) { int realstart = 0; unsigned int length; int retval; gaim_debug(GAIM_DEBUG_INFO, "gaim-encryption", "decrypt_msg\n"); if ( (sscanf(msg, ": Len %u:%n", &length, &realstart) < 1) || (realstart == 0)) { gaim_debug(GAIM_DEBUG_ERROR, "gaim-encryption", "Garbled length in decrypt\n"); return -1; } msg += realstart; if (strlen(msg) < length) { gaim_debug(GAIM_DEBUG_ERROR, "gaim-encryption", "Length doesn't match in decrypt\n"); return -1; } msg[length] = 0; retval = GE_decrypt_signed(decrypted, msg, priv_key, pub_key, name); return retval;}static void GE_store_msg(const char *who, GaimConnection *gc, char *msg, msg_node** first_node, msg_node** last_node) { msg_node* newnode; newnode = g_malloc(sizeof(msg_node) + strlen(msg)); gaim_debug(GAIM_DEBUG_INFO, "gaim-encryption", "store_msg: %p : %s\n", newnode, who); strncpy(newnode->who, gaim_normalize(gc->account, who), sizeof(newnode->who)); newnode->who[sizeof(newnode->who)-1] = 0; newnode->gc = gc; newnode->time = time((time_t)NULL); strcpy(newnode->msg, msg); newnode->next = 0; if (*first_node == 0) { *last_node = newnode; *first_node = newnode; } else { (*last_node)->next = newnode; *last_node = newnode; } for (newnode = *first_node; newnode != *last_node; newnode = newnode->next) { gaim_debug(GAIM_DEBUG_INFO, "gaim-encryption", " In store stack: %p\n", newnode, newnode->who); } gaim_debug(GAIM_DEBUG_INFO, "gaim-encryption", " In store stack: %p\n", *last_node, (*last_node)->who);}void GE_send_stored_msgs(GaimAccount* acct, const char* who) { msg_node* node = first_out_msg; msg_node* prev = 0; char *tmp_msg; gaim_debug(GAIM_DEBUG_INFO, "gaim-encryption", "send_stored_msgs\n"); while (node != 0) { gaim_debug(GAIM_DEBUG_INFO, "gaim-encryption", "Looking for stored msg:%s:%s\n",node->who, who); if ((strcmp(node->who, who) == 0) && (node->gc->account == acct)) { tmp_msg = g_strdup(node->msg);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -