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); } }
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; }
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); }
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; }
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); }
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); }
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); }
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); }
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); }