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"
27 SilcPKCSSignCb sign_cb;
35 /* Add one attribute that was found from hash table */
37 static void silc_client_attributes_process_foreach(void *key, void *context,
40 SilcAttribute attribute = (SilcAttribute)SILC_PTR_TO_32(key);
41 SilcAttributePayload attr = context;
42 SilcAttrForeach *f = user_context;
43 const unsigned char *data;
44 unsigned char tmp[32];
48 SILC_LOG_DEBUG(("Attribute %d was not set", attribute));
50 /* USER_PUBLIC_KEY we have set earlier */
51 if (attribute == SILC_ATTRIBUTE_USER_PUBLIC_KEY)
54 /* The requested attribute was not found */
55 f->buffer = silc_attribute_payload_encode(f->buffer, attribute,
56 SILC_ATTRIBUTE_FLAG_INVALID,
61 SILC_LOG_DEBUG(("Attribute %d found", attribute));
62 data = silc_attribute_get_data(attr, &data_len);
64 /* We replace the TIMEZONE with valid value here */
65 if (attribute == SILC_ATTRIBUTE_TIMEZONE) {
66 if (silc_timezone(tmp, sizeof(tmp))) {
68 data_len = strlen(tmp);
69 f->buffer = silc_attribute_payload_encode(f->buffer, attribute,
70 SILC_ATTRIBUTE_FLAG_VALID,
71 (void *)data, data_len);
76 f->buffer = silc_attribute_payload_encode_data(f->buffer, attribute,
77 SILC_ATTRIBUTE_FLAG_VALID,
81 /* Attribute signature callback */
84 silc_client_attributes_process_signed(SilcBool success,
85 const unsigned char *signature,
86 SilcUInt32 signature_len,
89 SilcAttrSign s = context;
90 SilcAttributeObjPk pk;
94 pk.data = (unsigned char *)signature;
95 pk.data_len = signature_len;
97 silc_attribute_payload_encode(s->buffer,
98 SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE,
99 SILC_ATTRIBUTE_FLAG_VALID,
103 s->sign_cb(TRUE, silc_buffer_data(s->buffer), silc_buffer_len(s->buffer),
106 silc_buffer_free(s->buffer);
110 /* Process list of attributes. Returns reply to the requested attributes. */
112 void silc_client_attributes_process(SilcClient client,
113 SilcClientConnection conn,
115 SilcPKCSSignCb sign_cb,
119 SilcBuffer buffer = NULL;
121 SilcAttribute attribute;
122 SilcAttributePayload attr;
123 SilcAttributeObjPk pk;
125 SILC_LOG_DEBUG(("Process Requested Attributes"));
127 /* If nothing is set by application assume that we don't want to use
128 attributes, ignore the request. */
129 if (!conn->internal->attrs) {
130 SILC_LOG_DEBUG(("User has not set any attributes"));
131 sign_cb(FALSE, NULL, 0, context);
135 /* Always put our public key. */
136 pk.type = "silc-rsa";
137 pk.data = silc_pkcs_public_key_encode(NULL, conn->public_key, &pk.data_len);
138 buffer = silc_attribute_payload_encode(buffer,
139 SILC_ATTRIBUTE_USER_PUBLIC_KEY,
140 pk.data ? SILC_ATTRIBUTE_FLAG_VALID :
141 SILC_ATTRIBUTE_FLAG_INVALID,
145 /* Go through all requested attributes */
147 silc_dlist_start(attrs);
148 while ((attr = silc_dlist_get(attrs)) != SILC_LIST_END) {
149 /* Put all attributes of this type */
150 attribute = silc_attribute_get_attribute(attr);
152 /* Ignore signature since we will compute it later */
153 if (attribute == SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE)
156 silc_hash_table_find_foreach(conn->internal->attrs,
157 SILC_32_TO_PTR(attribute),
158 silc_client_attributes_process_foreach,
163 s = silc_calloc(1, sizeof(*s));
165 sign_cb(FALSE, NULL, 0, context);
168 s->sign_cb = sign_cb;
169 s->context = context;
172 /* Finally compute the digital signature of all the data we provided. */
173 silc_pkcs_sign(conn->private_key, silc_buffer_data(buffer),
174 silc_buffer_len(buffer), TRUE, conn->internal->sha1hash,
175 client->rng, silc_client_attributes_process_signed, s);
178 static void silc_client_attribute_destruct(void *key, void *context,
181 silc_attribute_payload_free(context);
184 /* Add new attribute */
186 SilcAttributePayload silc_client_attribute_add(SilcClient client,
187 SilcClientConnection conn,
188 SilcAttribute attribute,
190 SilcUInt32 object_size)
192 SilcAttributePayload attr;
194 attr = silc_attribute_payload_alloc(attribute, SILC_ATTRIBUTE_FLAG_VALID,
195 object, object_size);
199 if (!conn->internal->attrs)
200 conn->internal->attrs =
201 silc_hash_table_alloc(NULL, 0, silc_hash_ptr, NULL, NULL,
202 NULL, silc_client_attribute_destruct,
204 silc_hash_table_add(conn->internal->attrs,
205 SILC_32_TO_PTR(attribute), attr);
209 static void silc_client_attribute_del_foreach(void *key, void *context,
212 SilcClientConnection conn = user_context;
213 SilcAttributePayload attr = context;
214 SilcAttribute attribute;
217 attribute = silc_attribute_get_attribute(attr);
218 silc_hash_table_del_by_context(conn->internal->attrs,
219 SILC_32_TO_PTR(attribute), attr);
222 /* Delete one attribute */
224 SilcBool silc_client_attribute_del(SilcClient client,
225 SilcClientConnection conn,
226 SilcAttribute attribute,
227 SilcAttributePayload attr)
231 if (!conn->internal->attrs)
235 attribute = silc_attribute_get_attribute(attr);
236 ret = silc_hash_table_del_by_context(conn->internal->attrs,
237 SILC_32_TO_PTR(attribute), attr);
238 } else if (attribute) {
239 silc_hash_table_find_foreach(conn->internal->attrs,
240 SILC_32_TO_PTR(attribute),
241 silc_client_attribute_del_foreach, conn);
248 if (!silc_hash_table_count(conn->internal->attrs)) {
249 silc_hash_table_free(conn->internal->attrs);
250 conn->internal->attrs = NULL;
256 /* Return all attributes */
258 SilcHashTable silc_client_attributes_get(SilcClient client,
259 SilcClientConnection conn)
261 return conn->internal->attrs;
264 /* Construct a Requested Attributes buffer. If the `attribute' is zero (0)
265 then all attributes are requested. Additionally `attribute' and
266 all variable arguments can be one requested attribute. Always set
267 the last requested attribute to zero (0) to complete list of
268 requested attribute. */
270 SilcBuffer silc_client_attributes_request(SilcAttribute attribute, ...)
273 SilcBuffer buffer = NULL;
276 return silc_client_attributes_request(SILC_ATTRIBUTE_USER_INFO,
277 SILC_ATTRIBUTE_USER_ICON,
278 SILC_ATTRIBUTE_SERVICE,
279 SILC_ATTRIBUTE_STATUS_MOOD,
280 SILC_ATTRIBUTE_STATUS_FREETEXT,
281 SILC_ATTRIBUTE_STATUS_MESSAGE,
282 SILC_ATTRIBUTE_PREFERRED_LANGUAGE,
283 SILC_ATTRIBUTE_PREFERRED_CONTACT,
284 SILC_ATTRIBUTE_TIMEZONE,
285 SILC_ATTRIBUTE_GEOLOCATION,
286 SILC_ATTRIBUTE_DEVICE_INFO,
287 SILC_ATTRIBUTE_USER_PUBLIC_KEY, 0);
289 va_start(va, attribute);
291 buffer = silc_attribute_payload_encode(buffer, attribute, 0, NULL, 0);
292 attribute = (SilcAttribute)va_arg(va, SilcUInt32);