SilcBuffer silc_public_key_payload_encode(SilcPublicKey public_key) { SilcBuffer buffer; unsigned char *pk; SilcUInt32 pk_len; SilcPKCSType type; if (!public_key) return NULL; type = silc_pkcs_get_type(public_key); pk = silc_pkcs_public_key_encode(public_key, &pk_len); if (!pk) return NULL; buffer = silc_buffer_alloc_size(4 + pk_len); if (!buffer) { silc_free(pk); return NULL; } if (silc_buffer_format(buffer, SILC_STR_UI_SHORT(pk_len), SILC_STR_UI_SHORT(type), SILC_STR_DATA(pk, pk_len), SILC_STR_END) < 0) { silc_buffer_free(buffer); silc_free(pk); return NULL; } silc_free(pk); return buffer; }
SilcBool silc_public_key_payload_decode(unsigned char *data, SilcUInt32 data_len, SilcPublicKey *public_key) { SilcBufferStruct buf; SilcUInt16 pk_len, pk_type; unsigned char *pk; int ret; if (!public_key) return FALSE; silc_buffer_set(&buf, data, data_len); ret = silc_buffer_unformat(&buf, SILC_STR_ADVANCE, SILC_STR_UI_SHORT(&pk_len), SILC_STR_UI_SHORT(&pk_type), SILC_STR_END); if (ret < 0 || pk_len > data_len - 4) return FALSE; if (pk_type < SILC_PKCS_SILC || pk_type > SILC_PKCS_SPKI) return FALSE; ret = silc_buffer_unformat(&buf, SILC_STR_DATA(&pk, pk_len), SILC_STR_END); if (ret < 0) return FALSE; return silc_pkcs_public_key_alloc((SilcPKCSType)pk_type, pk, pk_len, public_key); }
SilcBuffer silc_notify_payload_encode_args(SilcNotifyType type, SilcUInt32 argc, SilcBuffer args) { SilcBuffer buffer; SilcUInt32 len; len = 5 + (args ? silc_buffer_len(args) : 0); buffer = silc_buffer_alloc_size(len); if (!buffer) return NULL; silc_buffer_format(buffer, SILC_STR_UI_SHORT(type), SILC_STR_UI_SHORT(len), SILC_STR_UI_CHAR(argc), SILC_STR_END); if (args) silc_buffer_format(buffer, SILC_STR_OFFSET(5), SILC_STR_DATA(args->data, silc_buffer_len(args)), SILC_STR_END); return buffer; }
void silcpurple_wb_send(PurpleWhiteboard *wb, GList *draw_list) { SilcPurpleWb wbs = wb->proto_data; SilcBuffer packet; GList *list; int len; PurpleConnection *gc; SilcPurple sg; g_return_if_fail(draw_list); gc = purple_account_get_connection(wb->account); g_return_if_fail(gc); sg = gc->proto_data; g_return_if_fail(sg); len = SILCPURPLE_WB_HEADER; for (list = draw_list; list; list = list->next) len += 4; packet = silc_buffer_alloc_size(len); if (!packet) return; /* Assmeble packet */ silc_buffer_format(packet, SILC_STR_UI32_STRING(SILCPURPLE_WB_MIME), SILC_STR_UI_CHAR(SILCPURPLE_WB_DRAW), SILC_STR_UI_SHORT(wbs->width), SILC_STR_UI_SHORT(wbs->height), SILC_STR_UI_INT(wbs->brush_color), SILC_STR_UI_SHORT(wbs->brush_size), SILC_STR_END); silc_buffer_pull(packet, SILCPURPLE_WB_HEADER); for (list = draw_list; list; list = list->next) { silc_buffer_format(packet, SILC_STR_UI_INT(GPOINTER_TO_INT(list->data)), SILC_STR_END); silc_buffer_pull(packet, 4); } /* Send the message */ if (wbs->type == 0) { /* Private message */ silc_client_send_private_message(sg->client, sg->conn, wbs->u.client, SILC_MESSAGE_FLAG_DATA, NULL, packet->head, len); } else if (wbs->type == 1) { /* Channel message. Channel private keys are not supported. */ silc_client_send_channel_message(sg->client, sg->conn, wbs->u.channel, NULL, SILC_MESSAGE_FLAG_DATA, NULL, packet->head, len); } silc_buffer_free(packet); }
static void silcpurple_wb_parse(SilcPurpleWb wbs, PurpleWhiteboard *wb, unsigned char *message, SilcUInt32 message_len) { SilcUInt8 command; SilcUInt16 width, height, brush_size; SilcUInt32 brush_color, x, y, dx, dy; SilcBufferStruct buf; int ret; /* Parse the packet */ silc_buffer_set(&buf, message, message_len); ret = silc_buffer_unformat(&buf, SILC_STR_UI_CHAR(&command), SILC_STR_UI_SHORT(&width), SILC_STR_UI_SHORT(&height), SILC_STR_UI_INT(&brush_color), SILC_STR_UI_SHORT(&brush_size), SILC_STR_END); if (ret < 0) return; silc_buffer_pull(&buf, ret); /* Update whiteboard if its dimensions changed */ if (width != wbs->width || height != wbs->height) silcpurple_wb_set_dimensions(wb, height, width); if (command == SILCPURPLE_WB_DRAW) { /* Parse data and draw it */ ret = silc_buffer_unformat(&buf, SILC_STR_UI_INT(&dx), SILC_STR_UI_INT(&dy), SILC_STR_END); if (ret < 0) return; silc_buffer_pull(&buf, 8); x = dx; y = dy; while (silc_buffer_len(&buf) > 0) { ret = silc_buffer_unformat(&buf, SILC_STR_UI_INT(&dx), SILC_STR_UI_INT(&dy), SILC_STR_END); if (ret < 0) return; silc_buffer_pull(&buf, 8); purple_whiteboard_draw_line(wb, x, y, x + dx, y + dy, brush_color, brush_size); x += dx; y += dy; } } if (command == SILCPURPLE_WB_CLEAR) purple_whiteboard_clear(wb); }
SilcCommandPayload silc_command_payload_parse(const unsigned char *payload, SilcUInt32 payload_len) { SilcBufferStruct buffer; SilcCommandPayload newp; unsigned char args_num; SilcUInt16 p_len; int ret; SILC_LOG_DEBUG(("Parsing command payload")); silc_buffer_set(&buffer, (unsigned char *)payload, payload_len); newp = silc_calloc(1, sizeof(*newp)); if (!newp) return NULL; /* Parse the Command Payload */ ret = silc_buffer_unformat(&buffer, SILC_STR_UI_SHORT(&p_len), SILC_STR_UI_CHAR(&newp->cmd), SILC_STR_UI_CHAR(&args_num), SILC_STR_UI_SHORT(&newp->ident), SILC_STR_END); if (ret == -1) { SILC_LOG_ERROR(("Incorrect command payload in packet")); silc_free(newp); return NULL; } if (p_len != silc_buffer_len(&buffer)) { SILC_LOG_ERROR(("Incorrect command payload in packet")); silc_free(newp); return NULL; } if (newp->cmd == 0) { SILC_LOG_ERROR(("Incorrect command type in command payload")); silc_free(newp); return NULL; } silc_buffer_pull(&buffer, SILC_COMMAND_PAYLOAD_LEN); if (args_num) { newp->args = silc_argument_payload_parse(buffer.data, silc_buffer_len(&buffer), args_num); if (!newp->args) { silc_free(newp); return NULL; } } silc_buffer_push(&buffer, SILC_COMMAND_PAYLOAD_LEN); return newp; }
SilcBuffer silc_attribute_payload_encode_data(SilcBuffer attrs, SilcAttribute attribute, SilcAttributeFlags flags, const unsigned char *data, SilcUInt32 data_len) { SilcBuffer buffer = attrs; SilcUInt32 len; len = 4 + (SilcUInt16)data_len; buffer = silc_buffer_realloc(buffer, (buffer ? silc_buffer_truelen(buffer) + len : len)); if (!buffer) return NULL; silc_buffer_pull(buffer, silc_buffer_len(buffer)); silc_buffer_pull_tail(buffer, len); silc_buffer_format(buffer, SILC_STR_UI_CHAR(attribute), SILC_STR_UI_CHAR(flags), SILC_STR_UI_SHORT((SilcUInt16)data_len), SILC_STR_UI_XNSTRING(data, (SilcUInt16)data_len), SILC_STR_END); silc_buffer_push(buffer, buffer->data - buffer->head); return buffer; }
SilcBuffer silc_command_payload_encode(SilcCommand cmd, SilcUInt32 argc, unsigned char **argv, SilcUInt32 *argv_lens, SilcUInt32 *argv_types, SilcUInt16 ident) { SilcBuffer buffer; SilcBuffer args = NULL; SilcUInt32 len = 0; SILC_LOG_DEBUG(("Encoding command payload")); if (argc) { args = silc_argument_payload_encode(argc, argv, argv_lens, argv_types); if (!args) return NULL; len = silc_buffer_len(args); } len += SILC_COMMAND_PAYLOAD_LEN; buffer = silc_buffer_alloc_size(len); if (!buffer) return NULL; /* Create Command payload */ silc_buffer_format(buffer, SILC_STR_UI_SHORT(len), SILC_STR_UI_CHAR(cmd), SILC_STR_UI_CHAR(argc), SILC_STR_UI_SHORT(ident), SILC_STR_END); /* Add arguments */ if (argc) { silc_buffer_pull(buffer, SILC_COMMAND_PAYLOAD_LEN); silc_buffer_format(buffer, SILC_STR_UI_XNSTRING(args->data, silc_buffer_len(args)), SILC_STR_END); silc_buffer_push(buffer, SILC_COMMAND_PAYLOAD_LEN); silc_buffer_free(args); } return buffer; }
void silcpurple_wb_clear(PurpleWhiteboard *wb) { SilcPurpleWb wbs = wb->proto_data; SilcBuffer packet; int len; PurpleConnection *gc; SilcPurple sg; gc = purple_account_get_connection(wb->account); g_return_if_fail(gc); sg = gc->proto_data; g_return_if_fail(sg); len = SILCPURPLE_WB_HEADER; packet = silc_buffer_alloc_size(len); if (!packet) return; /* Assmeble packet */ silc_buffer_format(packet, SILC_STR_UI32_STRING(SILCPURPLE_WB_MIME), SILC_STR_UI_CHAR(SILCPURPLE_WB_CLEAR), SILC_STR_UI_SHORT(wbs->width), SILC_STR_UI_SHORT(wbs->height), SILC_STR_UI_INT(wbs->brush_color), SILC_STR_UI_SHORT(wbs->brush_size), SILC_STR_END); /* Send the message */ if (wbs->type == 0) { /* Private message */ silc_client_send_private_message(sg->client, sg->conn, wbs->u.client, SILC_MESSAGE_FLAG_DATA, NULL, packet->head, len); } else if (wbs->type == 1) { /* Channel message */ silc_client_send_channel_message(sg->client, sg->conn, wbs->u.channel, NULL, SILC_MESSAGE_FLAG_DATA, NULL, packet->head, len); } silc_buffer_free(packet); }
SilcBuffer silc_command_payload_encode_payload(SilcCommandPayload payload) { SilcBuffer buffer; SilcBuffer args = NULL; SilcUInt32 len = 0; SilcUInt32 argc = 0; SILC_LOG_DEBUG(("Encoding command payload")); if (payload->args) { args = silc_argument_payload_encode_payload(payload->args); if (args) len = silc_buffer_len(args); argc = silc_argument_get_arg_num(payload->args); } len += SILC_COMMAND_PAYLOAD_LEN; buffer = silc_buffer_alloc_size(len); if (!buffer) { if (args) silc_buffer_free(args); return NULL; } /* Create Command payload */ silc_buffer_format(buffer, SILC_STR_UI_SHORT(len), SILC_STR_UI_CHAR(payload->cmd), SILC_STR_UI_CHAR(argc), SILC_STR_UI_SHORT(payload->ident), SILC_STR_END); /* Add arguments */ if (args) { silc_buffer_pull(buffer, SILC_COMMAND_PAYLOAD_LEN); silc_buffer_format(buffer, SILC_STR_UI_XNSTRING(args->data, silc_buffer_len(args)), SILC_STR_END); silc_buffer_push(buffer, SILC_COMMAND_PAYLOAD_LEN); silc_buffer_free(args); } return buffer; }
SilcNotifyPayload silc_notify_payload_parse(const unsigned char *payload, SilcUInt32 payload_len) { SilcBufferStruct buffer; SilcNotifyPayload newp; SilcUInt16 len; int ret; SILC_LOG_DEBUG(("Parsing Notify payload")); silc_buffer_set(&buffer, (unsigned char *)payload, payload_len); newp = silc_calloc(1, sizeof(*newp)); if (!newp) return NULL; ret = silc_buffer_unformat(&buffer, SILC_STR_UI_SHORT(&newp->type), SILC_STR_UI_SHORT(&len), SILC_STR_UI_CHAR(&newp->argc), SILC_STR_END); if (ret == -1) goto err; if (len > silc_buffer_len(&buffer)) goto err; if (newp->argc) { silc_buffer_pull(&buffer, 5); newp->args = silc_argument_payload_parse(buffer.data, silc_buffer_len(&buffer), newp->argc); if (!newp->args) goto err; silc_buffer_push(&buffer, 5); } return newp; err: silc_free(newp); return NULL; }
static SilcBool silc_client_send_private_message_key_request(SilcClient client, SilcClientConnection conn, SilcClientEntry client_entry) { const char *cipher, *hmac; SILC_LOG_DEBUG(("Sending private message key request")); cipher = silc_cipher_get_name(client_entry->internal.send_key); hmac = silc_hmac_get_name(client_entry->internal.hmac_send); /* Send the packet */ return silc_packet_send_va_ext(conn->stream, SILC_PACKET_PRIVATE_MESSAGE_KEY, 0, 0, NULL, SILC_ID_CLIENT, &client_entry->id, NULL, NULL, SILC_STR_UI_SHORT(strlen(cipher)), SILC_STR_DATA(cipher, strlen(cipher)), SILC_STR_UI_SHORT(strlen(hmac)), SILC_STR_DATA(hmac, strlen(hmac)), SILC_STR_END); }
unsigned char *silc_attribute_get_verify_data(SilcDList attrs, SilcBool server_verification, SilcUInt32 *data_len) { SilcAttributePayload attr; SilcBufferStruct buffer; unsigned char *data = NULL; SilcUInt32 len = 0; silc_dlist_start(attrs); while ((attr = silc_dlist_get(attrs)) != SILC_LIST_END) { switch (attr->attribute) { case SILC_ATTRIBUTE_SERVER_DIGITAL_SIGNATURE: /* Server signature is never part of the verification data */ break; case SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE: /* For user signature verification this is not part of the data */ if (!server_verification) break; /* Fallback, for server signature verification, user digital signature is part of verification data. */ default: /* All other data is part of the verification data */ data = silc_realloc(data, sizeof(*data) * (4 + attr->data_len + len)); if (!data) return NULL; silc_buffer_set(&buffer, data + len, 4 + attr->data_len); silc_buffer_format(&buffer, SILC_STR_UI_CHAR(attr->attribute), SILC_STR_UI_CHAR(attr->flags), SILC_STR_UI_SHORT(attr->data_len), SILC_STR_UI_XNSTRING(attr->data, attr->data_len), SILC_STR_END); len += 4 + attr->data_len; break; } } if (data_len) *data_len = len; return data; }
static unsigned char * silc_attribute_payload_encode_int(SilcAttribute attribute, SilcAttributeFlags flags, void *object, SilcUInt32 object_size, SilcUInt32 *ret_len) { SilcBuffer tmpbuf = NULL; unsigned char tmp[4], *str = NULL, *ret; SilcUInt32 len; /* Encode according to attribute type */ if (flags & SILC_ATTRIBUTE_FLAG_VALID) { if (!object && !object_size) return NULL; switch (attribute) { case SILC_ATTRIBUTE_USER_INFO: { SilcVCard vcard = object; if (object_size != sizeof(*vcard)) return NULL; str = silc_vcard_encode(vcard, &object_size); if (!str) return NULL; object = str; } break; case SILC_ATTRIBUTE_SERVICE: { SilcAttributeObjService *service = object; SilcUInt32 len2; if (object_size != sizeof(*service)) return NULL; len = strlen(service->address); len2 = strlen(service->signon); tmpbuf = silc_buffer_alloc_size(13 + len + len2); if (!tmpbuf) return NULL; silc_buffer_format(tmpbuf, SILC_STR_UI_INT(service->port), SILC_STR_UI_SHORT(len), SILC_STR_UI_XNSTRING(service->address, len), SILC_STR_UI_CHAR(service->status), SILC_STR_UI_SHORT(len2), SILC_STR_UI_XNSTRING(service->signon, len2), SILC_STR_UI_INT(service->idle), SILC_STR_END); object = tmpbuf->data; object_size = silc_buffer_len(tmpbuf); } break; case SILC_ATTRIBUTE_STATUS_MOOD: case SILC_ATTRIBUTE_PREFERRED_CONTACT: { SilcUInt32 mask = SILC_PTR_TO_32(object); if (object_size != sizeof(SilcUInt32)) return NULL; SILC_PUT32_MSB(mask, tmp); object = tmp; object_size = sizeof(SilcUInt32); } break; case SILC_ATTRIBUTE_STATUS_FREETEXT: case SILC_ATTRIBUTE_PREFERRED_LANGUAGE: case SILC_ATTRIBUTE_TIMEZONE: { unsigned char *string = object; str = silc_malloc(2 + object_size); if (!str) return NULL; SILC_PUT16_MSB(object_size, str); memcpy(str + 2, string, object_size); object = str; object_size += 2; } break; case SILC_ATTRIBUTE_STATUS_MESSAGE: case SILC_ATTRIBUTE_EXTENSION: case SILC_ATTRIBUTE_USER_ICON: { SilcMime mime = object; if (object_size != sizeof(*mime)) return NULL; str = silc_mime_encode(mime, &object_size); if (!str) return NULL; object = str; } break; case SILC_ATTRIBUTE_GEOLOCATION: { SilcAttributeObjGeo *geo = object; SilcUInt32 len1, len2, len3, len4; if (object_size != sizeof(*geo)) return NULL; len1 = (geo->longitude ? strlen(geo->longitude) : 0); len2 = (geo->latitude ? strlen(geo->latitude) : 0); len3 = (geo->altitude ? strlen(geo->altitude) : 0); len4 = (geo->accuracy ? strlen(geo->accuracy) : 0); if (len1 + len2 + len3 + len4 == 0) return NULL; len = len1 + len2 + len3 + len4; tmpbuf = silc_buffer_alloc_size(8 + len); if (!tmpbuf) return NULL; silc_buffer_format(tmpbuf, SILC_STR_UI_SHORT(len1), SILC_STR_UI16_STRING(len1 ? geo->longitude : ""), SILC_STR_UI_SHORT(len2), SILC_STR_UI16_STRING(len2 ? geo->latitude : ""), SILC_STR_UI_SHORT(len3), SILC_STR_UI16_STRING(len3 ? geo->altitude : ""), SILC_STR_UI_SHORT(len4), SILC_STR_UI16_STRING(len4 ? geo->accuracy : ""), SILC_STR_END); object = tmpbuf->data; object_size = silc_buffer_len(tmpbuf); } break; case SILC_ATTRIBUTE_DEVICE_INFO: { SilcAttributeObjDevice *dev = object; SilcUInt32 len1, len2, len3, len4; if (object_size != sizeof(*dev)) return NULL; len1 = (dev->manufacturer ? strlen(dev->manufacturer) : 0); len2 = (dev->version ? strlen(dev->version) : 0); len3 = (dev->model ? strlen(dev->model) : 0); len4 = (dev->language ? strlen(dev->language) : 0); if (len1 + len2 + len3 + len4 == 0) return NULL; len = len1 + len2 + len3 + len4; tmpbuf = silc_buffer_alloc_size(4 + 8 + len); if (!tmpbuf) return NULL; silc_buffer_format(tmpbuf, SILC_STR_UI_INT(dev->type), SILC_STR_UI_SHORT(len1), SILC_STR_UI16_STRING(len1 ? dev->manufacturer : ""), SILC_STR_UI_SHORT(len2), SILC_STR_UI16_STRING(len2 ? dev->version : ""), SILC_STR_UI_SHORT(len3), SILC_STR_UI16_STRING(len3 ? dev->model : ""), SILC_STR_UI_SHORT(len4), SILC_STR_UI16_STRING(len4 ? dev->language : ""), SILC_STR_END); object = tmpbuf->data; object_size = silc_buffer_len(tmpbuf); } break; case SILC_ATTRIBUTE_PHONE_NUMBER: { SilcAttributeObjPN *pn = object; if (object_size != sizeof(*pn)) return NULL; if (!pn->number || strlen(pn->number) < 5) return NULL; tmpbuf = silc_buffer_alloc(0); if (!tmpbuf) return NULL; if (silc_buffer_format(tmpbuf, SILC_STR_UI_INT(pn->format), SILC_STR_UI_SHORT(strlen(pn->number)), SILC_STR_UI16_STRING(pn->number), SILC_STR_END) < 0) return NULL; object = tmpbuf->data; object_size = silc_buffer_len(tmpbuf); } break; case SILC_ATTRIBUTE_USER_PUBLIC_KEY: case SILC_ATTRIBUTE_SERVER_PUBLIC_KEY: { SilcAttributeObjPk *pk = object; if (object_size != sizeof(*pk)) return NULL; len = (pk->type ? strlen(pk->type) : 0); tmpbuf = silc_buffer_alloc_size(2 + len + pk->data_len); if (!tmpbuf) return NULL; silc_buffer_format(tmpbuf, SILC_STR_UI_SHORT(len), SILC_STR_UI16_STRING(pk->type), SILC_STR_UI_XNSTRING(pk->data, pk->data_len), SILC_STR_END); object = tmpbuf->data; object_size = silc_buffer_len(tmpbuf); } break; case SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE: case SILC_ATTRIBUTE_SERVER_DIGITAL_SIGNATURE: { SilcAttributeObjPk *pk = object; if (object_size != sizeof(*pk)) return NULL; object = pk->data; object_size = pk->data_len; } break; default: return NULL; break; } ret = silc_memdup(object, object_size); if (tmpbuf) silc_buffer_free(tmpbuf); silc_free(str); if (ret_len) *ret_len = object_size; return ret; } return NULL; }
SilcBuffer silc_notify_payload_encode(SilcNotifyType type, SilcUInt32 argc, va_list ap) { SilcBuffer buffer; SilcBuffer args = NULL; unsigned char **argv; SilcUInt32 *argv_lens = NULL, *argv_types = NULL; unsigned char *x; SilcUInt32 x_len, len = 0; int i, k = 0; if (argc) { argv = silc_calloc(argc, sizeof(unsigned char *)); if (!argv) return NULL; argv_lens = silc_calloc(argc, sizeof(SilcUInt32)); if (!argv_lens) { silc_free(argv); return NULL; } argv_types = silc_calloc(argc, sizeof(SilcUInt32)); if (!argv_types) { silc_free(argv_lens); silc_free(argv); return NULL; } for (i = 0, k = 0; i < argc; i++) { x = va_arg(ap, unsigned char *); x_len = va_arg(ap, SilcUInt32); if (!x || !x_len) continue; argv[k] = silc_memdup(x, x_len); if (!argv[k]) return NULL; argv_lens[k] = x_len; argv_types[k] = i + 1; k++; } args = silc_argument_payload_encode(k, argv, argv_lens, argv_types); len = silc_buffer_len(args); for (i = 0; i < k; i++) silc_free(argv[i]); silc_free(argv); silc_free(argv_lens); silc_free(argv_types); } len += 5; buffer = silc_buffer_alloc_size(len); if (!buffer) return NULL; silc_buffer_format(buffer, SILC_STR_UI_SHORT(type), SILC_STR_UI_SHORT(len), SILC_STR_UI_CHAR(k), SILC_STR_END); if (k) { silc_buffer_format(buffer, SILC_STR_OFFSET(5), SILC_STR_DATA(args->data, silc_buffer_len(args)), SILC_STR_END); silc_buffer_free(args); } return buffer; }