Пример #1
0
void silcpurple_get_info(PurpleConnection *gc, const char *who)
{
	SilcPurple sg = gc->proto_data;
	SilcClient client = sg->client;
	SilcClientConnection conn = sg->conn;
	SilcClientEntry client_entry;
	PurpleBuddy *b;
	const char *filename, *nick = who;
	char tmp[256];

	if (!who)
		return;
	if (strlen(who) > 1 && who[0] == '@')
		nick = who + 1;
	if (strlen(who) > 1 && who[0] == '*')
		nick = who + 1;
	if (strlen(who) > 2 && who[0] == '*' && who[1] == '@')
		nick = who + 2;

	b = purple_find_buddy(gc->account, nick);
	if (b) {
		/* See if we have this buddy's public key.  If we do use that
		   to search the details. */
		filename = purple_blist_node_get_string((PurpleBlistNode *)b, "public-key");
		if (filename) {
			/* Call WHOIS.  The user info is displayed in the WHOIS
			   command reply. */
			silc_client_command_call(client, conn, NULL, "WHOIS",
						 "-details", "-pubkey", filename, NULL);
			return;
		}

		if (!b->proto_data) {
			g_snprintf(tmp, sizeof(tmp),
				   _("User %s is not present in the network"), b->name);
			purple_notify_error(gc, _("User Information"),
					  _("Cannot get user information"), tmp);
			return;
		}

		client_entry = silc_client_get_client_by_id(client, conn, b->proto_data);
		if (client_entry) {
			/* Call WHOIS.  The user info is displayed in the WHOIS
			   command reply. */
			silc_client_command_call(client, conn, NULL, "WHOIS",
						 client_entry->nickname, "-details", NULL);
		}
	} else {
		/* Call WHOIS just with nickname. */
		silc_client_command_call(client, conn, NULL, "WHOIS", nick, NULL);
	}
}
Пример #2
0
int command_silc_join(void *data, struct t_gui_buffer *buffer, int argc, char **argv, char **argv_eol) {
    SilcPluginServerList server;
    char *channelname;
    char *command;
    size_t command_length;

    if (argc < 3) {
        weechat_printf(buffer, "you need to specify a channel to join");
        return WEECHAT_RC_ERROR;
    }

    channelname = argv[2];
    command_length = strlen(channelname) + 6;
    command = malloc(command_length);
    memset(command, 0, command_length);
    snprintf(command, command_length, "JOIN %s", channelname);

    server = find_server_for_buffer(buffer);
    if (server == NULL) {
        weechat_printf(buffer, "%sCurrent buffer is not a SILC buffer", weechat_prefix("error"));
        return WEECHAT_RC_OK;
    }

    // Join here
    silc_client_command_call(silc_plugin->client, server->connection, command);
    return WEECHAT_RC_OK;
}
Пример #3
0
static void
silc_connected(SilcClient client, SilcClientConnection conn,
	       SilcClientConnectionStatus status,
	       SilcStatus error, const char *message,
	       void *context)
{
  MyBot mybot = client->application;

  if (status == SILC_CLIENT_CONN_DISCONNECTED) {
    SILC_LOG_DEBUG(("Disconnected %s", message ? message : ""));
    silc_client_stop(client, silc_stopped, mybot);
    return;
  }

  if (status != SILC_CLIENT_CONN_SUCCESS &&
      status != SILC_CLIENT_CONN_SUCCESS_RESUME) {
    SILC_LOG_DEBUG(("Error connecting to server %d", status));
    silc_client_stop(client, silc_stopped, mybot);
    return;
  }

  fprintf(stdout, "\nMyBot: Connected to server\n\n");

  /* Now that we have connected to server, let's join a channel named
     "mybot". */
  silc_client_command_call(client, conn, "JOIN mybot");

  /* Save the connection context */
  mybot->conn = conn;
}
void i_silc_channel_change_request(struct channel_connection *chconn,
								struct event *event,
								async_change_request_callback_t *cb,
								struct client_async_cmd_context *context)
{
	const char *new_topic = event_get(event, "topic");
	struct i_silc_channel_connection *silc_chconn =
					(struct i_silc_channel_connection *)chconn;
	struct i_silc_gateway_connection *silc_gwconn =
					(struct i_silc_gateway_connection *)chconn->gwconn;
	bool ret;
	SilcChannelEntry ch = silc_chconn->channel_entry;
	SilcClient client;
	SilcClientConnection conn;

	if( *new_topic == '\0' ) {
		cb(CLIENT_CMDERR_ARGS, context);
		return;
	}

	client = silc_gwconn->client;
	conn = silc_gwconn->conn;

	ret = silc_client_command_call(client, conn, NULL, "TOPIC", ch->channel_name,
									new_topic, NULL);

	if( !ret )
		cb(CLIENT_CMDERR_SILC_CANTSEND, context);
}
Пример #5
0
int command_silc_disconnect(void *data, struct t_gui_buffer *buffer, int argc, char **argv, char **argv_eol) {
    SilcPluginServerList server;

    server = find_server_for_buffer(buffer);
    if (server == NULL) {
        weechat_printf(buffer, "%sCurrent buffer is not a SILC buffer", weechat_prefix("error"));
        return WEECHAT_RC_OK;
    }

    silc_client_command_call(silc_plugin->client, server->connection, "QUIT");
    return WEECHAT_RC_OK;
}
Пример #6
0
static PyObject *pysilc_client_command_call(PyObject *self, PyObject *args, PyObject *kwds)
{
    char *message;
    int result;
    PySilcClient *pyclient = (PySilcClient *)self;

    if (!pyclient || !pyclient->silcobj) {
       PyErr_SetString(PyExc_RuntimeError, "SILC Client Not Initialised");
       return NULL;
    }

    if (!PyArg_ParseTuple(args, "s", &message))
        return NULL;

    result = silc_client_command_call(pyclient->silcobj, pyclient->silcconn, message);
    return PyInt_FromLong(result);
}
Пример #7
0
static void
silcpurple_buddy_kill(PurpleBlistNode *node, gpointer data)
{
	PurpleBuddy *b;
	PurpleConnection *gc;
	SilcPurple sg;

	g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));

	b = (PurpleBuddy *) node;
	gc = purple_account_get_connection(b->account);
	sg = gc->proto_data;

	/* Call KILL */
	silc_client_command_call(sg->client, sg->conn, NULL, "KILL",
				 b->name, "Killed by operator", NULL);
}
Пример #8
0
static void
silcpurple_buddy_getkey(PurpleConnection *gc, const char *name)
{
	SilcPurple sg = gc->proto_data;
	SilcClient client = sg->client;
	SilcClientConnection conn = sg->conn;
	SilcClientEntry *clients;
	SilcUInt32 clients_count;
	SilcPurpleBuddyGetkey g;
	char *nickname;

	if (!name)
		return;

	if (!silc_parse_userfqdn(name, &nickname, NULL))
		return;

	/* Find client entry */
	clients = silc_client_get_clients_local(client, conn, nickname, name,
						&clients_count);
	if (!clients) {
		silc_client_get_clients(client, conn, nickname, NULL,
					silcpurple_buddy_getkey_resolved,
					g_strdup(name));
		silc_free(nickname);
		return;
	}

	/* Call GETKEY */
	g = silc_calloc(1, sizeof(*g));
	if (!g)
		return;
	g->client = client;
	g->conn = conn;
	g->client_id = *clients[0]->id;
	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_buddy_getkey_cb, g);
	silc_free(clients);
	silc_free(nickname);
}
static void silc_cmd_channel_part(struct event *event)
{
	const char *channel_name = event_get(event, EVENT_KEY_CHANNEL_NAME);
	struct presence *presence;
	struct channel_connection *chconn;
	struct i_silc_gateway_connection *silc_gwconn;

	if( !client_command_get_presence(event, &presence))
		return;

	silc_gwconn = (struct i_silc_gateway_connection *)presence->gwconn;
	chconn = channel_connection_lookup(presence->gwconn, channel_name);
	if( !IS_SILC_CHCONN(chconn) )
		return;

	if( chconn->joined == TRUE )
		silc_client_command_call(silc_gwconn->client, silc_gwconn->conn,
				NULL, "LEAVE", channel_name, NULL);
}
void event_channel_connection_init(struct event *event)
{
	struct channel_connection *chconn = event_get_control(event, channel_conn);

	if( !IS_SILC_CHCONN(chconn) )
		return;

	SilcBuffer idp;
	struct i_silc_gateway_connection *silc_gwconn =
		(struct i_silc_gateway_connection *)chconn->gwconn;
	const char *channel_str = chconn->channel->name;

	idp = silc_id_payload_encode(silc_gwconn->conn->local_id,
			SILC_ID_CLIENT);

	i_assert(idp != NULL);

	silc_client_command_call(silc_gwconn->client, silc_gwconn->conn,
			"JOIN", channel_str);
//	silc_client_command_send(silc_gwconn->client, silc_gwconn->conn,
//			SILC_COMMAND_JOIN, 0, 2, 1, channel_str,
//			strlen(channel_str), 2, silc_buffer_len(idp), idp->len);
}
Пример #11
0
static void
silcpurple_add_buddy_save(bool success, void *context)
{
	SilcPurpleBuddyRes r = context;
	PurpleBuddy *b = r->b;
	SilcClient client = r->client;
	SilcClientEntry client_entry;
	SilcAttributePayload attr;
	SilcAttribute attribute;
	SilcVCardStruct vcard;
	SilcAttributeObjMime message, extension;
#ifdef SILC_ATTRIBUTE_USER_ICON
	SilcAttributeObjMime usericon;
#endif
	SilcAttributeObjPk serverpk, usersign, serversign;
	gboolean usign_success = TRUE, ssign_success = TRUE;
	char filename[512], filename2[512], *fingerprint = NULL, *tmp;
	SilcUInt32 len;
	int i;

	if (!success) {
		/* The user did not trust the public key. */
		silcpurple_add_buddy_pk_no(r);
		silc_free(r);
		return;
	}

	if (r->offline) {
		/* User is offline.  Associate the imported public key with
		   this user. */
		fingerprint = silc_hash_fingerprint(NULL, r->offline_pk,
						    r->offline_pk_len);
		for (i = 0; i < strlen(fingerprint); i++)
			if (fingerprint[i] == ' ')
				fingerprint[i] = '_';
		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);
		purple_prpl_got_user_status(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), SILCPURPLE_STATUS_ID_OFFLINE, NULL);
		silc_free(fingerprint);
		silc_free(r->offline_pk);
		silc_free(r);
		return;
	}

	/* Get the client entry. */
	client_entry = silc_client_get_client_by_id(r->client, r->conn,
						    &r->client_id);
	if (!client_entry) {
		silc_free(r);
		return;
	}

	memset(&vcard, 0, sizeof(vcard));
	memset(&message, 0, sizeof(message));
	memset(&extension, 0, sizeof(extension));
#ifdef SILC_ATTRIBUTE_USER_ICON
	memset(&usericon, 0, sizeof(usericon));
#endif
	memset(&serverpk, 0, sizeof(serverpk));
	memset(&usersign, 0, sizeof(usersign));
	memset(&serversign, 0, sizeof(serversign));

	/* Now that we have the public key and we trust it now we
	   save the attributes of the buddy and update its status. */

	if (client_entry->attrs) {
		silc_dlist_start(client_entry->attrs);
		while ((attr = silc_dlist_get(client_entry->attrs))
		       != SILC_LIST_END) {
			attribute = silc_attribute_get_attribute(attr);

			switch (attribute) {
			case SILC_ATTRIBUTE_USER_INFO:
				if (!silc_attribute_get_object(attr, (void *)&vcard,
							       sizeof(vcard)))
					continue;
				break;

			case SILC_ATTRIBUTE_STATUS_MESSAGE:
				if (!silc_attribute_get_object(attr, (void *)&message,
							       sizeof(message)))
					continue;
				break;

			case SILC_ATTRIBUTE_EXTENSION:
				if (!silc_attribute_get_object(attr, (void *)&extension,
							       sizeof(extension)))
					continue;
				break;

#ifdef SILC_ATTRIBUTE_USER_ICON
			case SILC_ATTRIBUTE_USER_ICON:
				if (!silc_attribute_get_object(attr, (void *)&usericon,
							       sizeof(usericon)))
					continue;
				break;
#endif

			case SILC_ATTRIBUTE_SERVER_PUBLIC_KEY:
				if (serverpk.type)
					continue;
				if (!silc_attribute_get_object(attr, (void *)&serverpk,
							       sizeof(serverpk)))
					continue;
				break;

			case SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE:
				if (usersign.data)
					continue;
				if (!silc_attribute_get_object(attr, (void *)&usersign,
							       sizeof(usersign)))
					continue;
				break;

			case SILC_ATTRIBUTE_SERVER_DIGITAL_SIGNATURE:
				if (serversign.data)
					continue;
				if (!silc_attribute_get_object(attr, (void *)&serversign,
							       sizeof(serversign)))
					continue;
				break;

			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 && purple_strequal(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()) {
					int ret = g_mkdir(filename, 0755);
					if (ret < 0)
						return;
				}
			}
		}

		/* 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 (purple_strequal(type, "image/jpeg") ||
				    purple_strequal(type, "image/gif") ||
				    purple_strequal(type, "image/bmp") ||
				    purple_strequal(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);
}
Пример #12
0
static void
silcpurple_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 (!g_ascii_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);
			return;
		}
	} else if (!clients[0]->public_key) {
		/* 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;
	}

	/* We have the public key, verify it. */
	pk = silc_pkcs_public_key_encode(clients[0]->public_key, &pk_len);
	silcpurple_verify_public_key(client, conn, clients[0]->nickname,
				   SILC_SOCKET_TYPE_CLIENT,
				   pk, pk_len, SILC_SKE_PK_TYPE_SILC,
				   silcpurple_add_buddy_save, r);
	silc_free(pk);
}