📄 buddy.c
字号:
default: break; } } } /* Verify the attribute signatures */ if (usersign.data) { SilcPKCS pkcs; unsigned char *verifyd; SilcUInt32 verify_len; silc_pkcs_alloc((unsigned char*)"rsa", &pkcs); verifyd = silc_attribute_get_verify_data(client_entry->attrs, FALSE, &verify_len); if (verifyd && silc_pkcs_public_key_set(pkcs, client_entry->public_key)){ if (!silc_pkcs_verify_with_hash(pkcs, client->sha1hash, usersign.data, usersign.data_len, verifyd, verify_len)) usign_success = FALSE; } silc_free(verifyd); } if (serversign.data && !strcmp(serverpk.type, "silc-rsa")) { SilcPublicKey public_key; SilcPKCS pkcs; unsigned char *verifyd; SilcUInt32 verify_len; if (silc_pkcs_public_key_decode(serverpk.data, serverpk.data_len, &public_key)) { silc_pkcs_alloc((unsigned char *)"rsa", &pkcs); verifyd = silc_attribute_get_verify_data(client_entry->attrs, TRUE, &verify_len); if (verifyd && silc_pkcs_public_key_set(pkcs, public_key)) { if (!silc_pkcs_verify_with_hash(pkcs, client->sha1hash, serversign.data, serversign.data_len, verifyd, verify_len)) ssign_success = FALSE; } silc_pkcs_public_key_free(public_key); silc_free(verifyd); } } fingerprint = silc_fingerprint(client_entry->fingerprint, client_entry->fingerprint_len); for (i = 0; i < strlen(fingerprint); i++) if (fingerprint[i] == ' ') fingerprint[i] = '_'; if (usign_success || ssign_success) { struct passwd *pw; struct stat st; memset(filename2, 0, sizeof(filename2)); /* Filename for dir */ tmp = fingerprint + strlen(fingerprint) - 9; g_snprintf(filename, sizeof(filename) - 1, "%s" G_DIR_SEPARATOR_S "friends" G_DIR_SEPARATOR_S "%s", silcpurple_silcdir(), tmp); pw = getpwuid(getuid()); if (!pw) return; /* Create dir if it doesn't exist */ if ((g_stat(filename, &st)) == -1) { if (errno == ENOENT) { if (pw->pw_uid == geteuid()) g_mkdir(filename, 0755); } } /* Save VCard */ g_snprintf(filename2, sizeof(filename2) - 1, "%s" G_DIR_SEPARATOR_S "vcard", filename); if (vcard.full_name) { tmp = (char *)silc_vcard_encode(&vcard, &len); silc_file_writefile(filename2, tmp, len); silc_free(tmp); } /* Save status message */ if (message.mime) { memset(filename2, 0, sizeof(filename2)); g_snprintf(filename2, sizeof(filename2) - 1, "%s" G_DIR_SEPARATOR_S "status_message.mime", filename); silc_file_writefile(filename2, (char *)message.mime, message.mime_len); } /* Save extension data */ if (extension.mime) { memset(filename2, 0, sizeof(filename2)); g_snprintf(filename2, sizeof(filename2) - 1, "%s" G_DIR_SEPARATOR_S "extension.mime", filename); silc_file_writefile(filename2, (char *)extension.mime, extension.mime_len); }#ifdef SILC_ATTRIBUTE_USER_ICON /* Save user icon */ if (usericon.mime) { SilcMime m = silc_mime_decode(usericon.mime, usericon.mime_len); if (m) { const char *type = silc_mime_get_field(m, "Content-Type"); if (!strcmp(type, "image/jpeg") || !strcmp(type, "image/gif") || !strcmp(type, "image/bmp") || !strcmp(type, "image/png")) { const unsigned char *data; SilcUInt32 data_len; data = silc_mime_get_data(m, &data_len); if (data) { /* TODO: Check if SILC gives us something to use as the checksum instead */ purple_buddy_icons_set_for_user(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), g_memdup(data, data_len), data_len, NULL); } } silc_mime_free(m); } }#endif } /* Save the public key path to buddy properties, as it is used to identify the buddy in the network (and not the nickname). */ memset(filename, 0, sizeof(filename)); g_snprintf(filename, sizeof(filename) - 1, "%s" G_DIR_SEPARATOR_S "clientkeys" G_DIR_SEPARATOR_S "clientkey_%s.pub", silcpurple_silcdir(), fingerprint); purple_blist_node_set_string((PurpleBlistNode *)b, "public-key", filename); /* Update online status */ purple_prpl_got_user_status(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), SILCPURPLE_STATUS_ID_AVAILABLE, NULL); /* Finally, start watching this user so we receive its status changes from the server */ g_snprintf(filename2, sizeof(filename2) - 1, "+%s", filename); silc_client_command_call(r->client, r->conn, NULL, "WATCH", "-pubkey", filename2, NULL); silc_free(fingerprint); silc_free(r);}static voidsilcpurple_add_buddy_ask_import(void *user_data, const char *name){ SilcPurpleBuddyRes r = (SilcPurpleBuddyRes)user_data; SilcPublicKey public_key; /* Load the public key */ if (!silc_pkcs_load_public_key(name, &public_key, SILC_PKCS_FILE_PEM) && !silc_pkcs_load_public_key(name, &public_key, SILC_PKCS_FILE_BIN)) { silcpurple_add_buddy_ask_pk_cb(r, 0); purple_notify_error(r->client->application, _("Add Buddy"), _("Could not load public key"), NULL); return; } /* Now verify the public key */ r->offline_pk = silc_pkcs_public_key_encode(public_key, &r->offline_pk_len); silcpurple_verify_public_key(r->client, r->conn, r->b->name, SILC_SOCKET_TYPE_CLIENT, r->offline_pk, r->offline_pk_len, SILC_SKE_PK_TYPE_SILC, silcpurple_add_buddy_save, r);}static voidsilcpurple_add_buddy_ask_pk_cancel(void *user_data, const char *name){ SilcPurpleBuddyRes r = (SilcPurpleBuddyRes)user_data; /* The user did not import public key. The buddy is unusable. */ silcpurple_add_buddy_pk_no(r); silc_free(r);}static voidsilcpurple_add_buddy_ask_pk_cb(SilcPurpleBuddyRes r, gint id){ if (id != 0) { /* The user did not import public key. The buddy is unusable. */ silcpurple_add_buddy_pk_no(r); silc_free(r); return; } /* Open file selector to select the public key. */ purple_request_file(r->client->application, _("Open..."), NULL, FALSE, G_CALLBACK(silcpurple_add_buddy_ask_import), G_CALLBACK(silcpurple_add_buddy_ask_pk_cancel), purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, r);}static voidsilcpurple_add_buddy_ask_pk(SilcPurpleBuddyRes r){ char tmp[512]; g_snprintf(tmp, sizeof(tmp), _("The %s buddy is not present in the network"), r->b->name); purple_request_action(r->client->application, _("Add Buddy"), tmp, _("To add the buddy you must import his/her public key. " "Press Import to import a public key."), 0, purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, r, 2, _("Cancel"), G_CALLBACK(silcpurple_add_buddy_ask_pk_cb), _("_Import..."), G_CALLBACK(silcpurple_add_buddy_ask_pk_cb));}static voidsilcpurple_add_buddy_getkey_cb(SilcPurpleBuddyRes r, SilcClientCommandReplyContext cmd){ SilcClientEntry client_entry; unsigned char *pk; SilcUInt32 pk_len; /* Get the client entry. */ client_entry = silc_client_get_client_by_id(r->client, r->conn, &r->client_id); if (!client_entry || !client_entry->public_key) { /* The buddy is offline/nonexistent. We will require user to associate a public key with the buddy or the buddy cannot be added. */ r->offline = TRUE; silcpurple_add_buddy_ask_pk(r); return; } /* Now verify the public key */ pk = silc_pkcs_public_key_encode(client_entry->public_key, &pk_len); silcpurple_verify_public_key(r->client, r->conn, client_entry->nickname, SILC_SOCKET_TYPE_CLIENT, pk, pk_len, SILC_SKE_PK_TYPE_SILC, silcpurple_add_buddy_save, r); silc_free(pk);}static voidsilcpurple_add_buddy_select_cb(SilcPurpleBuddyRes r, PurpleRequestFields *fields){ PurpleRequestField *f; const GList *list; SilcClientEntry client_entry; f = purple_request_fields_get_field(fields, "list"); list = purple_request_field_list_get_selected(f); if (!list) { /* The user did not select any user. */ silcpurple_add_buddy_pk_no(r); silc_free(r); return; } client_entry = purple_request_field_list_get_data(f, list->data); silcpurple_add_buddy_resolved(r->client, r->conn, &client_entry, 1, r);}static voidsilcpurple_add_buddy_select_cancel(SilcPurpleBuddyRes r, PurpleRequestFields *fields){ /* The user did not select any user. */ silcpurple_add_buddy_pk_no(r); silc_free(r);}static voidsilcpurple_add_buddy_select(SilcPurpleBuddyRes r, SilcClientEntry *clients, SilcUInt32 clients_count){ PurpleRequestFields *fields; PurpleRequestFieldGroup *g; PurpleRequestField *f; char tmp[512], tmp2[128]; int i; char *fingerprint; fields = purple_request_fields_new(); g = purple_request_field_group_new(NULL); f = purple_request_field_list_new("list", NULL); purple_request_field_group_add_field(g, f); purple_request_field_list_set_multi_select(f, FALSE); purple_request_fields_add_group(fields, g); for (i = 0; i < clients_count; i++) { fingerprint = NULL; if (clients[i]->fingerprint) { fingerprint = silc_fingerprint(clients[i]->fingerprint, clients[i]->fingerprint_len); g_snprintf(tmp2, sizeof(tmp2), "\n%s", fingerprint); } g_snprintf(tmp, sizeof(tmp), "%s - %s (%s@%s)%s", clients[i]->realname, clients[i]->nickname, clients[i]->username, clients[i]->hostname ? clients[i]->hostname : "", fingerprint ? tmp2 : ""); purple_request_field_list_add(f, tmp, clients[i]); silc_free(fingerprint); } purple_request_fields(r->client->application, _("Add Buddy"), _("Select correct user"), r->pubkey_search ? _("More than one user was found with the same public key. Select " "the correct user from the list to add to the buddy list.") : _("More than one user was found with the same name. Select " "the correct user from the list to add to the buddy list."), fields, _("OK"), G_CALLBACK(silcpurple_add_buddy_select_cb), _("Cancel"), G_CALLBACK(silcpurple_add_buddy_select_cancel), purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, r);}static voidsilcpurple_add_buddy_resolved(SilcClient client, SilcClientConnection conn, SilcClientEntry *clients, SilcUInt32 clients_count, void *context){ SilcPurpleBuddyRes r = context; PurpleBuddy *b = r->b; SilcAttributePayload pub; SilcAttributeObjPk userpk; unsigned char *pk; SilcUInt32 pk_len; const char *filename; filename = purple_blist_node_get_string((PurpleBlistNode *)b, "public-key"); /* If the buddy is offline/nonexistent, we will require user to associate a public key with the buddy or the buddy cannot be added. */ if (!clients_count) { if (r->init) { silc_free(r); return; } r->offline = TRUE; /* If the user has already associated a public key, try loading it * before prompting the user to load it again */ if (filename != NULL) silcpurple_add_buddy_ask_import(r, filename); else silcpurple_add_buddy_ask_pk(r); return; } /* If more than one client was found with nickname, we need to verify from user which one is the correct. */ if (clients_count > 1 && !r->pubkey_search) { if (r->init) { silc_free(r); return; } silcpurple_add_buddy_select(r, clients, clients_count); return; } /* If we searched using public keys and more than one entry was found the same person is logged on multiple times. */ if (clients_count > 1 && r->pubkey_search && b->name) { if (r->init) { /* Find the entry that closest matches to the buddy nickname. */ int i; for (i = 0; i < clients_count; i++) { if (!strncasecmp(b->name, clients[i]->nickname, strlen(b->name))) { clients[0] = clients[i]; break; } } } else { /* Verify from user which one is correct */ silcpurple_add_buddy_select(r, clients, clients_count); return; } } /* The client was found. Now get its public key and verify that before adding the buddy. */ memset(&userpk, 0, sizeof(userpk)); b->proto_data = silc_memdup(clients[0]->id, sizeof(*clients[0]->id)); r->client_id = *clients[0]->id; /* Get the public key from attributes, if not present then resolve it with GETKEY unless we have it cached already. */ if (clients[0]->attrs && !clients[0]->public_key) { pub = silcpurple_get_attr(clients[0]->attrs, SILC_ATTRIBUTE_USER_PUBLIC_KEY); if (!pub || !silc_attribute_get_object(pub, (void *)&userpk, sizeof(userpk))) { /* Get public key with GETKEY */ silc_client_command_call(client, conn, NULL, "GETKEY", clients[0]->nickname, NULL); silc_client_command_pending(conn, SILC_COMMAND_GETKEY, conn->cmd_ident, (SilcCommandCb)silcpurple_add_buddy_getkey_cb, r); return; } if (!silc_pkcs_public_key_decode(userpk.data, userpk.data_len, &clients[0]->public_key)) return; silc_free(userpk.data); } else if (filename && !clients[0]->public_key) { if (!silc_pkcs_load_public_key(filename, &clients[0]->public_key, SILC_PKCS_FILE_PEM) && !silc_pkcs_load_public_key(filename, &clients[0]->public_key, SILC_PKCS_FILE_BIN)) { /* Get public key with GETKEY */ silc_client_command_call(client, conn, NULL, "GETKEY", clients[0]->nickname, NULL); silc_client_command_pending(conn, SILC_COMMAND_GETKEY, conn->cmd_ident, (SilcCommandCb)silcpurple_add_buddy_getkey_cb, r);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -