if (!tmp)
continue;
- id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
- if (!id) {
+ id = silc_id_payload_parse_id(tmp, tmp_len, &id_type);
+ if (!id || id_type != SILC_ID_CLIENT) {
silc_server_query_add_error(server, query, TRUE, i + 4,
SILC_STATUS_ERR_BAD_CLIENT_ID);
continue;
for (i = 0; i < query->ids_count; i++)
silc_free(query->ids[i].id);
silc_free(query->ids);
+ query->ids = NULL;
+ query->ids_count = 0;
silc_free(id);
return;
}
/* Get requested attributes if set */
tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
- if (tmp)
+ if (tmp && tmp_len <= SILC_ATTRIBUTE_MAX_REQUEST_LEN) {
query->attrs = silc_attribute_payload_parse(tmp, tmp_len);
+
+ /* When Requested Attributes is present we will assure that this
+ client cannot execute the WHOIS command too fast. This would be
+ same as having SILC_CF_LAG_STRICT. */
+ if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
+ cmd->sock->user_data)
+ ((SilcClientEntry)cmd->sock->user_data)->fast_command = 6;
+ }
break;
case SILC_COMMAND_WHOWAS:
/* Normal server must check whether this ID exist, and if not then
send the query to router, unless done so already */
if (server->server_type == SILC_SERVER && !query->resolved) {
- if (!silc_idlist_find_client_by_id(server->local_list,
- id, TRUE, NULL)) {
- if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT ||
- !silc_idlist_find_client_by_id(server->global_list,
+ if (id_type == SILC_ID_CLIENT) {
+ if (!silc_idlist_find_client_by_id(server->local_list,
id, TRUE, NULL)) {
- silc_server_query_send_router(server, query);
- for (i = 0; i < query->ids_count; i++)
- silc_free(query->ids[i].id);
- silc_free(query->ids);
- silc_free(id);
- return;
+ if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT ||
+ !silc_idlist_find_client_by_id(server->global_list,
+ id, TRUE, NULL)) {
+ silc_server_query_send_router(server, query);
+ for (i = 0; i < query->ids_count; i++)
+ silc_free(query->ids[i].id);
+ silc_free(query->ids);
+ query->ids = NULL;
+ query->ids_count = 0;
+ silc_free(id);
+ return;
+ }
}
+ } else {
+ /* For now all other ID's except Client ID's are explicitly
+ sent to router for resolving. */
+ silc_server_query_send_router(server, query);
+ for (i = 0; i < query->ids_count; i++)
+ silc_free(query->ids[i].id);
+ silc_free(query->ids);
+ query->ids = NULL;
+ query->ids_count = 0;
+ silc_free(id);
+ return;
}
}
}
}
+ /* Remove the NOATTR status periodically */
+ if (client_entry->data.status & SILC_IDLIST_STATUS_NOATTR &&
+ client_entry->updated + 600 < time(NULL))
+ client_entry->data.status &= ~SILC_IDLIST_STATUS_NOATTR;
+
/* When requested attributes is present and local client is detached
we cannot send the command to the client, we'll reply on behalf of
the client instead. */
for (i = 0; i < query->querylist_count; i++) {
r = &query->querylist[i];
+ /* If Requested Attributes were present put them to this resolving */
+ if (query->attrs && query->querycmd == SILC_COMMAND_WHOIS) {
+ len = r->argc + 1;
+ r->arg = silc_realloc(r->arg, sizeof(*r->arg) * len);
+ r->arg_lens = silc_realloc(r->arg_lens, sizeof(*r->arg_lens) * len);
+ r->arg_types = silc_realloc(r->arg_types, sizeof(*r->arg_types) * len);
+
+ tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
+ if (tmp)
+ r->arg[r->argc] = silc_memdup(tmp, len);
+ r->arg_lens[r->argc] = len;
+ r->arg_types[r->argc] = 3;
+ r->argc++;
+ }
+
/* Send WHOIS command */
res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
r->argc, r->arg, r->arg_lens,
case SILC_COMMAND_WHOIS:
case SILC_COMMAND_IDENTIFY:
/* Take existing query context if exist for this connection */
- for (i = 0; i < query->queries_count; i++)
+ for (i = 0; i < query->querylist_count; i++)
if (query->querylist[i].sock == sock) {
r = &query->querylist[i];
break;
r->timeout = 3;
}
- /* If Requested Attributes were present put them to this resolving */
- if (query->attrs && query->querycmd == SILC_COMMAND_WHOIS) {
- len = r->argc + 1;
- r->arg = silc_realloc(r->arg, sizeof(*r->arg) * len);
- r->arg_lens = silc_realloc(r->arg_lens, sizeof(*r->arg_lens) * len);
- r->arg_types = silc_realloc(r->arg_types, sizeof(*r->arg_types) * len);
-
- tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
- if (tmp)
- r->arg[r->argc] = silc_memdup(tmp, len);
- r->arg_lens[r->argc] = len;
- r->arg_types[r->argc] = 3;
- r->argc++;
- }
-
len = r->argc + 1;
r->arg = silc_realloc(r->arg, sizeof(*r->arg) * len);
r->arg_lens = silc_realloc(r->arg_lens, sizeof(*r->arg_lens) * len);
client_entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
client_entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
client_entry->resolve_cmd_ident = ident;
+ client_entry->updated = time(NULL);
/* Save the queried ID, which we will reprocess after we get this and
all other queries back. */
attributes we will reply to them on behalf of the client. */
len = 0;
if (query->attrs) {
- if (!entry->attrs) {
+ if (!entry->attrs && SILC_IS_LOCAL(entry)) {
tmpattrs = silc_server_query_reply_attrs(server, query, entry);
entry->attrs = silc_memdup(tmpattrs->data, tmpattrs->len);
entry->attrs_len = tmpattrs->len;
SilcAttributeObjPk pk;
SilcAttributeObjService service;
unsigned char *tmp;
- unsigned char sign[2048];
+ unsigned char sign[2048 + 1];
SilcUInt32 sign_len;
SILC_LOG_DEBUG(("Constructing Requested Attributes"));
silc_strncat(service.address, sizeof(service.address),
server->server_name, strlen(server->server_name));
service.status = !(client_entry->mode & SILC_UMODE_DETACHED);
+ if (client_entry->connection)
+ service.idle = time(NULL) - client_entry->data.last_receive;
buffer = silc_attribute_payload_encode(buffer, attribute,
SILC_ATTRIBUTE_FLAG_VALID,
&service, sizeof(service));
+ if (!buffer)
+ return NULL;
break;
case SILC_ATTRIBUTE_STATUS_MOOD:
(void *)
SILC_ATTRIBUTE_MOOD_NORMAL,
sizeof(SilcUInt32));
+ if (!buffer)
+ return NULL;
break;
case SILC_ATTRIBUTE_STATUS_FREETEXT:
buffer = silc_attribute_payload_encode(buffer, attribute,
SILC_ATTRIBUTE_FLAG_VALID,
tmp, strlen(tmp));
+ if (!buffer)
+ return NULL;
break;
case SILC_ATTRIBUTE_PREFERRED_CONTACT:
(void *)
SILC_ATTRIBUTE_CONTACT_CHAT,
sizeof(SilcUInt32));
+ if (!buffer)
+ return NULL;
break;
case SILC_ATTRIBUTE_USER_PUBLIC_KEY:
SILC_ATTRIBUTE_FLAG_INVALID,
&pk, sizeof(pk));
silc_free(pk.data);
+ if (!buffer)
+ return NULL;
break;
}
buffer = silc_attribute_payload_encode(buffer, attribute,
SILC_ATTRIBUTE_FLAG_INVALID,
NULL, 0);
+ if (!buffer)
+ return NULL;
break;
default:
buffer = silc_attribute_payload_encode(buffer, attribute,
SILC_ATTRIBUTE_FLAG_INVALID,
NULL, 0);
+ if (!buffer)
+ return NULL;
break;
}
}
SILC_ATTRIBUTE_FLAG_INVALID,
&pk, sizeof(pk));
silc_free(pk.data);
+ if (!buffer)
+ return NULL;
/* Finally compute the digital signature of all the data we provided
as an indication that we provided rightfull information, and this
SILC_ATTRIBUTE_FLAG_VALID,
&pk, sizeof(pk));
}
+ if (!buffer)
+ return NULL;
return buffer;
}