⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 buddy.c

📁 Linux下的多协议即时通讯程序源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	}	/* Verify the attribute signatures */	silc_hash_alloc((const unsigned char *)"sha1", &hash);	if (usersign.data) {		unsigned char *verifyd;		SilcUInt32 verify_len;		verifyd = silc_attribute_get_verify_data(client_entry->attrs,							 FALSE, &verify_len);		if (verifyd && !silc_pkcs_verify(client_entry->public_key,						 usersign.data,						 usersign.data_len,						 verifyd, verify_len, hash))			usign_success = FALSE;		silc_free(verifyd);	}	if (serversign.data) {		SilcPublicKey public_key;		SilcPKCSType type = 0;		unsigned char *verifyd;		SilcUInt32 verify_len;		if (!strcmp(serverpk.type, "silc-rsa"))		  type = SILC_PKCS_SILC;		else if (!strcmp(serverpk.type, "ssh-rsa"))		  type = SILC_PKCS_SSH2;		else if (!strcmp(serverpk.type, "x509v3-sign-rsa"))		  type = SILC_PKCS_X509V3;		else if (!strcmp(serverpk.type, "pgp-sign-rsa"))		  type = SILC_PKCS_OPENPGP;		if (silc_pkcs_public_key_alloc(type, serverpk.data,					       serverpk.data_len,					       &public_key)) {			verifyd = silc_attribute_get_verify_data(client_entry->attrs,								 TRUE, &verify_len);			if (verifyd && !silc_pkcs_verify(public_key,							 serversign.data,							 serversign.data_len,							 verifyd, verify_len,							 hash))				ssign_success = FALSE;			silc_pkcs_public_key_free(public_key);			silc_free(verifyd);		}	}	fingerprint = silc_fingerprint(client_entry->fingerprint, 20);	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) {			memset(filename2, 0, sizeof(filename2));			g_snprintf(filename2, sizeof(filename2) - 1,				   "%s" G_DIR_SEPARATOR_S "status_message.mime",				   filename);			tmp = (char *)silc_mime_get_data(message, &len);			silc_file_writefile(filename2, tmp, len);			silc_mime_free(message);		}		/* Save extension data */		if (extension) {			memset(filename2, 0, sizeof(filename2));			g_snprintf(filename2, sizeof(filename2) - 1,				   "%s" G_DIR_SEPARATOR_S "extension.mime",				   filename);			tmp = (char *)silc_mime_get_data(extension, &len);			silc_file_writefile(filename2, tmp, len);			silc_mime_free(extension);		}		/* Save user icon */		if (usericon) {			const char *type = silc_mime_get_field(usericon, "Content-Type");			if (type &&			    (!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(usericon, &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(usericon);		}	}	/* 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_hash_free(hash);	silc_free(fingerprint);	silc_free(r->offline_pk);	if (r->public_key)	  silc_pkcs_public_key_free(r->public_key);	silc_free(r);}static voidsilcpurple_add_buddy_ask_import(void *user_data, const char *name){	SilcPurpleBuddyRes r = (SilcPurpleBuddyRes)user_data;	/* Load the public key */	if (!silc_pkcs_load_public_key(name, &r->public_key)) {		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(r->public_key, &r->offline_pk_len);	silcpurple_verify_public_key(r->client, r->conn, r->b->name,				     SILC_CONN_CLIENT, r->public_key,				     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 SilcBoolsilcpurple_add_buddy_getkey_cb(SilcClient client, SilcClientConnection conn,			       SilcCommand command, SilcStatus status,			       SilcStatus error, void *context, va_list ap){	SilcPurpleBuddyRes r = context;	SilcClientEntry client_entry;	if (status != SILC_STATUS_OK) {		/* 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 FALSE;	}	/* 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 FALSE;	}	/* Now verify the public key */	silcpurple_verify_public_key(r->client, r->conn, client_entry->nickname,				     SILC_CONN_CLIENT, client_entry->public_key,				     silcpurple_add_buddy_save, r);	return TRUE;}static voidsilcpurple_add_buddy_select_cb(SilcPurpleBuddyRes r, PurpleRequestFields *fields){	PurpleRequestField *f;	const GList *list;	SilcClientEntry client_entry;	SilcDList clients;	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);	clients = silc_dlist_init();	silc_dlist_add(clients, client_entry);	silcpurple_add_buddy_resolved(r->client, r->conn, SILC_STATUS_OK,				      clients, r);	silc_dlist_uninit(clients);}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, SilcDList clients){	PurpleRequestFields *fields;	PurpleRequestFieldGroup *g;	PurpleRequestField *f;	char tmp[512], tmp2[128];	char *fingerprint;	SilcClientEntry client_entry;	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);	silc_dlist_start(clients);	while ((client_entry = silc_dlist_get(clients))) {		fingerprint = NULL;		if (*client_entry->fingerprint) {			fingerprint = silc_fingerprint(client_entry->fingerprint, 20);			g_snprintf(tmp2, sizeof(tmp2), "\n%s", fingerprint);		}		g_snprintf(tmp, sizeof(tmp), "%s - %s (%s@%s)%s",			   client_entry->realname, client_entry->nickname,			   client_entry->username, *client_entry->hostname ?			   client_entry->hostname : "",			   fingerprint ? tmp2 : "");		purple_request_field_list_add(f, tmp, client_entry);		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,			      SilcStatus status,			      SilcDList clients,			      void *context){	SilcPurpleBuddyRes r = context;	PurpleBuddy *b = r->b;	SilcAttributePayload pub;	SilcAttributeObjPk userpk;	const char *filename;	SilcClientEntry client_entry = NULL;	SilcUInt16 cmd_ident;	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) {		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 (silc_dlist_count(clients) > 1 && !r->pubkey_search) {		if (r->init) {			silc_free(r);			return;		}		silcpurple_add_buddy_select(r, clients);		return;	}	silc_dlist_start(clients);	client_entry = silc_dlist_get(clients);	/* If we searched using public keys and more than one entry was found	   the same person is logged on multiple times. */	if (silc_dlist_count(clients) > 1 && r->pubkey_search && b->name) {		if (r->init) {			/* Find the entry that closest matches to the			   buddy nickname. */			SilcClientEntry entry;			silc_dlist_start(clients);			while ((entry = silc_dlist_get(clients))) {				if (!strncasecmp(b->name, entry->nickname,						 strlen(b->name))) {					client_entry = entry;					break;				}			}		} else {			/* Verify from user which one is correct */			silcpurple_add_buddy_select(r, clients);			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(&client_entry->id, sizeof(client_entry->id));	r->client_id = client_entry->id;	/* Get the public key from attributes, if not present then	   resolve it with GETKEY unless we have it cached already. */	if (client_entry->attrs && !client_entry->public_key) {		pub = silcpurple_get_attr(client_entry->attrs,					  SILC_ATTRIBUTE_USER_PUBLIC_KEY);		if (!pub || !silc_attribute_get_object(pub, (void *)&userpk,						       sizeof(userpk))) {			/* Get public key with GETKEY */			cmd_ident =			  silc_client_command_call(client, conn, NULL,						   "GETKEY", client_entry->nickname, NULL);			silc_client_command_pending(conn, SILC_COMMAND_GETKEY,						    cmd_ident,						    silcpurple_add_buddy_getkey_cb,						    r);			return;		}		if (!silc_pkcs_public_key_alloc(SILC_PKCS_SILC,						userpk.data, userpk.data_len,						&client_entry->public_key))

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -