SilcBuffer silc_client_attributes_request(SilcAttribute attribute, ...) { va_list va; SilcBuffer buffer = NULL; if (!attribute) return silc_client_attributes_request(SILC_ATTRIBUTE_USER_INFO, SILC_ATTRIBUTE_USER_ICON, SILC_ATTRIBUTE_SERVICE, SILC_ATTRIBUTE_STATUS_MOOD, SILC_ATTRIBUTE_STATUS_FREETEXT, SILC_ATTRIBUTE_STATUS_MESSAGE, SILC_ATTRIBUTE_PREFERRED_LANGUAGE, SILC_ATTRIBUTE_PREFERRED_CONTACT, SILC_ATTRIBUTE_TIMEZONE, SILC_ATTRIBUTE_GEOLOCATION, SILC_ATTRIBUTE_DEVICE_INFO, SILC_ATTRIBUTE_USER_PUBLIC_KEY, 0); va_start(va, attribute); while (attribute) { buffer = silc_attribute_payload_encode(buffer, attribute, 0, NULL, 0); attribute = (SilcAttribute)va_arg(va, SilcUInt32); } va_end(va); return buffer; }
static void silc_client_attributes_process_foreach(void *key, void *context, void *user_context) { SilcAttribute attribute = (SilcAttribute)SILC_PTR_TO_32(key); SilcAttributePayload attr = context; SilcAttrForeach *f = user_context; const unsigned char *data; unsigned char tmp[32]; SilcUInt32 data_len; if (!context) { SILC_LOG_DEBUG(("Attribute %d was not set", attribute)); /* USER_PUBLIC_KEY we have set earlier */ if (attribute == SILC_ATTRIBUTE_USER_PUBLIC_KEY) return; /* The requested attribute was not found */ f->buffer = silc_attribute_payload_encode(f->buffer, attribute, SILC_ATTRIBUTE_FLAG_INVALID, NULL, 0); return; } SILC_LOG_DEBUG(("Attribute %d found", attribute)); data = silc_attribute_get_data(attr, &data_len); /* We replace the TIMEZONE with valid value here */ if (attribute == SILC_ATTRIBUTE_TIMEZONE) { if (silc_timezone(tmp, sizeof(tmp))) { data = tmp; data_len = strlen(tmp); f->buffer = silc_attribute_payload_encode(f->buffer, attribute, SILC_ATTRIBUTE_FLAG_VALID, (void *)data, data_len); } return; } f->buffer = silc_attribute_payload_encode_data(f->buffer, attribute, SILC_ATTRIBUTE_FLAG_VALID, data, data_len); }
static void silcpurple_add_buddy_i(PurpleConnection *gc, PurpleBuddy *b, gboolean init) { SilcPurple sg = gc->proto_data; SilcClient client = sg->client; SilcClientConnection conn = sg->conn; SilcPurpleBuddyRes r; SilcBuffer attrs; const char *filename, *name = b->name; r = silc_calloc(1, sizeof(*r)); if (!r) return; r->client = client; r->conn = conn; r->b = b; r->init = init; /* 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) { SilcPublicKey public_key; SilcAttributeObjPk userpk; if (!silc_pkcs_load_public_key(filename, &public_key, SILC_PKCS_FILE_PEM) && !silc_pkcs_load_public_key(filename, &public_key, SILC_PKCS_FILE_BIN)) return; /* Get all attributes, and use the public key to search user */ name = NULL; attrs = silc_client_attributes_request(SILC_ATTRIBUTE_USER_INFO, SILC_ATTRIBUTE_SERVICE, SILC_ATTRIBUTE_STATUS_MOOD, SILC_ATTRIBUTE_STATUS_FREETEXT, SILC_ATTRIBUTE_STATUS_MESSAGE, SILC_ATTRIBUTE_PREFERRED_LANGUAGE, SILC_ATTRIBUTE_PREFERRED_CONTACT, SILC_ATTRIBUTE_TIMEZONE, SILC_ATTRIBUTE_GEOLOCATION, #ifdef SILC_ATTRIBUTE_USER_ICON SILC_ATTRIBUTE_USER_ICON, #endif SILC_ATTRIBUTE_DEVICE_INFO, 0); userpk.type = "silc-rsa"; userpk.data = silc_pkcs_public_key_encode(public_key, &userpk.data_len); attrs = silc_attribute_payload_encode(attrs, SILC_ATTRIBUTE_USER_PUBLIC_KEY, SILC_ATTRIBUTE_FLAG_VALID, &userpk, sizeof(userpk)); silc_free(userpk.data); silc_pkcs_public_key_free(public_key); r->pubkey_search = TRUE; } else { /* Get all attributes */ attrs = silc_client_attributes_request(0); } /* Resolve */ silc_client_get_clients_whois(client, conn, name, NULL, attrs, silcpurple_add_buddy_resolved, r); silc_buffer_free(attrs); }
SilcBuffer silc_client_attributes_process(SilcClient client, SilcClientConnection conn, SilcDList attrs) { SilcBuffer buffer = NULL; SilcAttrForeach f; SilcAttribute attribute; SilcAttributePayload attr; SilcAttributeObjPk pk; unsigned char sign[2048 + 1]; SilcUInt32 sign_len; SILC_LOG_DEBUG(("Process Requested Attributes")); /* If nothing is set by application assume that we don't want to use attributes, ignore the request. */ if (!conn->internal->attrs) { SILC_LOG_DEBUG(("User has not set any attributes")); return NULL; } /* Always put our public key. */ pk.type = "silc-rsa"; pk.data = silc_pkcs_public_key_encode(conn->public_key, &pk.data_len); buffer = silc_attribute_payload_encode(buffer, SILC_ATTRIBUTE_USER_PUBLIC_KEY, pk.data ? SILC_ATTRIBUTE_FLAG_VALID : SILC_ATTRIBUTE_FLAG_INVALID, &pk, sizeof(pk)); silc_free(pk.data); /* Go through all requested attributes */ f.buffer = buffer; silc_dlist_start(attrs); while ((attr = silc_dlist_get(attrs)) != SILC_LIST_END) { /* Put all attributes of this type */ attribute = silc_attribute_get_attribute(attr); /* Ignore signature since we will compute it later */ if (attribute == SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE) continue; silc_hash_table_find_foreach(conn->internal->attrs, SILC_32_TO_PTR(attribute), silc_client_attributes_process_foreach, &f); } buffer = f.buffer; /* Finally compute the digital signature of all the data we provided. */ if (silc_pkcs_sign(conn->private_key, silc_buffer_data(buffer), silc_buffer_len(buffer), sign, sizeof(sign), &sign_len, TRUE, conn->internal->sha1hash)) { pk.type = NULL; pk.data = sign; pk.data_len = sign_len; buffer = silc_attribute_payload_encode(buffer, SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE, SILC_ATTRIBUTE_FLAG_VALID, &pk, sizeof(pk)); } return buffer; }