5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2002 - 2007 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
22 #include "silcclient.h"
23 #include "client_internal.h"
29 /* Add one attribute that was found from hash table */
31 static void silc_client_attributes_process_foreach(void *key, void *context,
34 SilcAttribute attribute = (SilcAttribute)SILC_PTR_TO_32(key);
35 SilcAttributePayload attr = context;
36 SilcAttrForeach *f = user_context;
37 const unsigned char *data;
38 unsigned char tmp[32];
42 SILC_LOG_DEBUG(("Attribute %d was not set", attribute));
44 /* USER_PUBLIC_KEY we have set earlier */
45 if (attribute == SILC_ATTRIBUTE_USER_PUBLIC_KEY)
48 /* The requested attribute was not found */
49 f->buffer = silc_attribute_payload_encode(f->buffer, attribute,
50 SILC_ATTRIBUTE_FLAG_INVALID,
55 SILC_LOG_DEBUG(("Attribute %d found", attribute));
56 data = silc_attribute_get_data(attr, &data_len);
58 /* We replace the TIMEZONE with valid value here */
59 if (attribute == SILC_ATTRIBUTE_TIMEZONE) {
60 if (silc_timezone(tmp, sizeof(tmp))) {
62 data_len = strlen(tmp);
63 f->buffer = silc_attribute_payload_encode(f->buffer, attribute,
64 SILC_ATTRIBUTE_FLAG_VALID,
65 (void *)data, data_len);
70 f->buffer = silc_attribute_payload_encode_data(f->buffer, attribute,
71 SILC_ATTRIBUTE_FLAG_VALID,
75 /* Process list of attributes. Returns reply to the requested attributes. */
77 SilcBuffer silc_client_attributes_process(SilcClient client,
78 SilcClientConnection conn,
81 SilcBuffer buffer = NULL;
83 SilcAttribute attribute;
84 SilcAttributePayload attr;
85 SilcAttributeObjPk pk;
86 unsigned char sign[2048 + 1];
89 SILC_LOG_DEBUG(("Process Requested Attributes"));
91 /* If nothing is set by application assume that we don't want to use
92 attributes, ignore the request. */
93 if (!conn->internal->attrs) {
94 SILC_LOG_DEBUG(("User has not set any attributes"));
98 /* Always put our public key. */
100 pk.data = silc_pkcs_public_key_encode(conn->public_key, &pk.data_len);
101 buffer = silc_attribute_payload_encode(buffer,
102 SILC_ATTRIBUTE_USER_PUBLIC_KEY,
103 pk.data ? SILC_ATTRIBUTE_FLAG_VALID :
104 SILC_ATTRIBUTE_FLAG_INVALID,
108 /* Go through all requested attributes */
110 silc_dlist_start(attrs);
111 while ((attr = silc_dlist_get(attrs)) != SILC_LIST_END) {
112 /* Put all attributes of this type */
113 attribute = silc_attribute_get_attribute(attr);
115 /* Ignore signature since we will compute it later */
116 if (attribute == SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE)
119 silc_hash_table_find_foreach(conn->internal->attrs,
120 SILC_32_TO_PTR(attribute),
121 silc_client_attributes_process_foreach,
126 /* Finally compute the digital signature of all the data we provided. */
127 if (silc_pkcs_sign(conn->private_key, silc_buffer_data(buffer),
128 silc_buffer_len(buffer), sign, sizeof(sign), &sign_len,
129 TRUE, conn->internal->sha1hash)) {
132 pk.data_len = sign_len;
134 silc_attribute_payload_encode(buffer,
135 SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE,
136 SILC_ATTRIBUTE_FLAG_VALID,
143 static void silc_client_attribute_destruct(void *key, void *context,
146 silc_attribute_payload_free(context);
149 /* Add new attribute */
151 SilcAttributePayload silc_client_attribute_add(SilcClient client,
152 SilcClientConnection conn,
153 SilcAttribute attribute,
155 SilcUInt32 object_size)
157 SilcAttributePayload attr;
159 attr = silc_attribute_payload_alloc(attribute, SILC_ATTRIBUTE_FLAG_VALID,
160 object, object_size);
164 if (!conn->internal->attrs)
165 conn->internal->attrs =
166 silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL,
167 NULL, silc_client_attribute_destruct,
169 silc_hash_table_add(conn->internal->attrs,
170 SILC_32_TO_PTR(attribute), attr);
174 static void silc_client_attribute_del_foreach(void *key, void *context,
177 SilcClientConnection conn = user_context;
178 SilcAttributePayload attr = context;
179 SilcAttribute attribute;
182 attribute = silc_attribute_get_attribute(attr);
183 silc_hash_table_del_by_context(conn->internal->attrs,
184 SILC_32_TO_PTR(attribute), attr);
187 /* Delete one attribute */
189 SilcBool silc_client_attribute_del(SilcClient client,
190 SilcClientConnection conn,
191 SilcAttribute attribute,
192 SilcAttributePayload attr)
196 if (!conn->internal->attrs)
200 attribute = silc_attribute_get_attribute(attr);
201 ret = silc_hash_table_del_by_context(conn->internal->attrs,
202 SILC_32_TO_PTR(attribute), attr);
203 } else if (attribute) {
204 silc_hash_table_find_foreach(conn->internal->attrs,
205 SILC_32_TO_PTR(attribute),
206 silc_client_attribute_del_foreach, conn);
213 if (!silc_hash_table_count(conn->internal->attrs)) {
214 silc_hash_table_free(conn->internal->attrs);
215 conn->internal->attrs = NULL;
221 /* Return all attributes */
223 SilcHashTable silc_client_attributes_get(SilcClient client,
224 SilcClientConnection conn)
226 return conn->internal->attrs;
229 /* Construct a Requested Attributes buffer. If the `attribute' is zero (0)
230 then all attributes are requested. Additionally `attribute' and
231 all variable arguments can be one requested attribute. Always set
232 the last requested attribute to zero (0) to complete list of
233 requested attribute. */
235 SilcBuffer silc_client_attributes_request(SilcAttribute attribute, ...)
238 SilcBuffer buffer = NULL;
241 return silc_client_attributes_request(SILC_ATTRIBUTE_USER_INFO,
242 SILC_ATTRIBUTE_USER_ICON,
243 SILC_ATTRIBUTE_SERVICE,
244 SILC_ATTRIBUTE_STATUS_MOOD,
245 SILC_ATTRIBUTE_STATUS_FREETEXT,
246 SILC_ATTRIBUTE_STATUS_MESSAGE,
247 SILC_ATTRIBUTE_PREFERRED_LANGUAGE,
248 SILC_ATTRIBUTE_PREFERRED_CONTACT,
249 SILC_ATTRIBUTE_TIMEZONE,
250 SILC_ATTRIBUTE_GEOLOCATION,
251 SILC_ATTRIBUTE_DEVICE_INFO,
252 SILC_ATTRIBUTE_USER_PUBLIC_KEY, 0);
254 va_start(va, attribute);
256 buffer = silc_attribute_payload_encode(buffer, attribute, 0, NULL, 0);
257 attribute = (SilcAttribute)va_arg(va, SilcUInt32);