5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2002 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.
21 #include "silcincludes.h"
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)(SilcUInt32)key;
35 SilcAttributePayload attr = context;
36 SilcAttrForeach *f = user_context;
37 const unsigned char *data;
41 SILC_LOG_DEBUG(("Attribute %d was not set", attribute));
43 /* USER_PUBLIC_KEY we have set earlier */
44 if (attribute == SILC_ATTRIBUTE_USER_PUBLIC_KEY)
47 /* The requested attribute was not found */
48 f->buffer = silc_attribute_payload_encode(f->buffer, attribute,
49 SILC_ATTRIBUTE_FLAG_INVALID,
54 SILC_LOG_DEBUG(("Attribute %d found", attribute));
55 data = silc_attribute_get_data(attr, &data_len);
57 /* We replace the TIMEZONE with valid value here */
58 if (attribute == SILC_ATTRIBUTE_TIMEZONE) {
59 data = (const unsigned char *)silc_get_time(0);
60 data_len = strlen(data);
61 f->buffer = silc_attribute_payload_encode(f->buffer, attribute,
62 SILC_ATTRIBUTE_FLAG_VALID,
63 (void *)data, data_len);
67 f->buffer = silc_attribute_payload_encode_data(f->buffer, attribute,
68 SILC_ATTRIBUTE_FLAG_VALID,
72 /* Process list of attributes. Returns reply to the requested attributes. */
74 SilcBuffer silc_client_attributes_process(SilcClient client,
75 SilcSocketConnection sock,
78 SilcClientConnection conn = sock->user_data;
79 SilcBuffer buffer = NULL;
81 SilcAttribute attribute;
82 SilcAttributePayload attr;
83 SilcAttributeObjPk pk;
84 unsigned char sign[2048 + 1];
87 SILC_LOG_DEBUG(("Process Requested Attributes"));
89 /* If nothing is set by application assume that we don't want to use
90 attributes, ignore the request. */
91 if (!conn->internal->attrs)
94 /* Always put our public key. */
96 pk.data = silc_pkcs_public_key_encode(client->public_key, &pk.data_len);
97 buffer = silc_attribute_payload_encode(buffer,
98 SILC_ATTRIBUTE_USER_PUBLIC_KEY,
99 pk.data ? SILC_ATTRIBUTE_FLAG_VALID :
100 SILC_ATTRIBUTE_FLAG_INVALID,
104 /* Go through all requested attributes */
106 silc_dlist_start(attrs);
107 while ((attr = silc_dlist_get(attrs)) != SILC_LIST_END) {
108 /* Put all attributes of this type */
109 attribute = silc_attribute_get_attribute(attr);
111 /* Ignore signature since we will compute it later */
112 if (attribute == SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE)
115 silc_hash_table_find_foreach(conn->internal->attrs,
116 (void *)(SilcUInt32)attribute,
117 silc_client_attributes_process_foreach,
122 /* Finally compute the digital signature of all the data we provided. */
123 if (silc_pkcs_sign_with_hash(client->pkcs, client->sha1hash,
124 buffer->data, buffer->len,
128 pk.data_len = sign_len;
130 silc_attribute_payload_encode(buffer,
131 SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE,
132 SILC_ATTRIBUTE_FLAG_VALID,
139 static void silc_client_attribute_destruct(void *key, void *context,
142 silc_attribute_payload_free(context);
145 /* Add new attribute */
147 SilcAttributePayload silc_client_attribute_add(SilcClient client,
148 SilcClientConnection conn,
149 SilcAttribute attribute,
151 SilcUInt32 object_size)
153 SilcAttributePayload attr;
155 attr = silc_attribute_payload_alloc(attribute, SILC_ATTRIBUTE_FLAG_VALID,
156 object, object_size);
160 if (!conn->internal->attrs)
161 conn->internal->attrs =
162 silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL,
163 NULL, silc_client_attribute_destruct,
165 silc_hash_table_add(conn->internal->attrs,
166 (void *)(SilcUInt32)attribute, attr);
170 static void silc_client_attribute_del_foreach(void *key, void *context,
173 SilcClientConnection conn = user_context;
174 SilcAttributePayload attr = context;
175 SilcAttribute attribute;
178 attribute = silc_attribute_get_attribute(attr);
179 silc_hash_table_del_by_context(conn->internal->attrs,
180 (void *)(SilcUInt32)attribute, attr);
183 /* Delete one attribute */
185 bool silc_client_attribute_del(SilcClient client,
186 SilcClientConnection conn,
187 SilcAttribute attribute,
188 SilcAttributePayload attr)
192 if (!conn->internal->attrs)
196 attribute = silc_attribute_get_attribute(attr);
197 ret = silc_hash_table_del_by_context(conn->internal->attrs,
198 (void *)(SilcUInt32)attribute, attr);
199 } else if (attribute) {
200 silc_hash_table_find_foreach(conn->internal->attrs,
201 (void *)(SilcUInt32)attribute,
202 silc_client_attribute_del_foreach, conn);
209 if (!silc_hash_table_count(conn->internal->attrs)) {
210 silc_hash_table_free(conn->internal->attrs);
211 conn->internal->attrs = NULL;
217 /* Return all attributes */
219 const SilcHashTable silc_client_attributes_get(SilcClient client,
220 SilcClientConnection conn)
222 return (const SilcHashTable)conn->internal->attrs;
225 /* Construct a Requested Attributes buffer. If the `attribute' is zero (0)
226 then all attributes are requested. Additionally `attribute' and
227 all variable arguments can be one requested attribute. Always set
228 the last requested attribute to zero (0) to complete list of
229 requested attribute. */
231 SilcBuffer silc_client_attributes_request(SilcAttribute attribute, ...)
234 SilcBuffer buffer = NULL;
237 return silc_client_attributes_request(SILC_ATTRIBUTE_USER_INFO,
238 SILC_ATTRIBUTE_SERVICE,
239 SILC_ATTRIBUTE_STATUS_MOOD,
240 SILC_ATTRIBUTE_STATUS_FREETEXT,
241 SILC_ATTRIBUTE_STATUS_MESSAGE,
242 SILC_ATTRIBUTE_PREFERRED_LANGUAGE,
243 SILC_ATTRIBUTE_PREFERRED_CONTACT,
244 SILC_ATTRIBUTE_TIMEZONE,
245 SILC_ATTRIBUTE_GEOLOCATION,
246 SILC_ATTRIBUTE_DEVICE_INFO,
247 SILC_ATTRIBUTE_USER_PUBLIC_KEY, 0);
249 va_start(va, attribute);
251 buffer = silc_attribute_payload_encode(buffer, attribute, 0, NULL, 0);
252 attribute = (SilcAttribute)va_arg(va, SilcUInt32);