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; }
SilcSFTPPacket silc_sftp_packet_decode(SilcBuffer packet, unsigned char **payload, SilcUInt32 *payload_len) { SilcUInt32 len; SilcUInt8 type; int ret; ret = silc_buffer_unformat(packet, SILC_STR_UI_INT(&len), SILC_STR_UI_CHAR(&type), SILC_STR_END); if (ret < 0) return 0; if (type < SILC_SFTP_INIT || type > SILC_SFTP_EXTENDED_REPLY) return 0; if (len > (silc_buffer_len(packet) - 5)) return -1; silc_buffer_pull(packet, 5); ret = silc_buffer_unformat(packet, SILC_STR_UI_XNSTRING(payload, len), SILC_STR_END); if (ret < 0) return 0; silc_buffer_push(packet, 5); *payload_len = len; return (SilcSFTPPacket)type; }
static void silc_sftp_server_handle(SilcSFTP sftp, SilcSFTPStatus status, SilcSFTPHandle handle, void *context) { SilcSFTPServer server = (SilcSFTPServer)sftp; SilcUInt32 id = SILC_PTR_TO_32(context); unsigned char *hdata; SilcUInt32 hdata_len; SILC_LOG_DEBUG(("Handle callback")); SILC_LOG_DEBUG(("Request ID: %d", id)); if (status != SILC_SFTP_STATUS_OK) { silc_sftp_send_error(server, status, id); return; } hdata = server->fs->fs->sftp_encode_handle(server->fs->fs_context, sftp, handle, &hdata_len); if (!hdata) { silc_sftp_send_error(server, SILC_SFTP_STATUS_FAILURE, id); return; } silc_sftp_send_packet(server, SILC_SFTP_HANDLE, 8 + hdata_len, SILC_STR_UI_INT(id), SILC_STR_UI_INT(hdata_len), SILC_STR_UI_XNSTRING(hdata, hdata_len), SILC_STR_END); }
static SilcBool silc_connauth_get_signature(SilcConnAuth connauth, unsigned char **auth_data, SilcUInt32 *auth_data_len) { int len; SilcSKE ske; SilcPrivateKey private_key; SilcBuffer auth; SILC_LOG_DEBUG(("Compute signature")); ske = connauth->ske; private_key = connauth->auth_data; /* Make the authentication data. Protocol says it is HASH plus KE Start Payload. */ len = ske->hash_len + silc_buffer_len(ske->start_payload_copy); auth = silc_buffer_alloc_size(len); if (!auth) return FALSE; silc_buffer_format(auth, SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len), SILC_STR_UI_XNSTRING( ske->start_payload_copy->data, silc_buffer_len(ske->start_payload_copy)), SILC_STR_END); len = ((silc_pkcs_private_key_get_len(private_key) + 7) / 8) + 1; *auth_data = silc_calloc(len, sizeof(**auth_data)); if (*auth_data == NULL) { silc_buffer_free(auth); return FALSE; } /* Compute signature */ if (!silc_pkcs_sign(private_key, auth->data, silc_buffer_len(auth), *auth_data, len, auth_data_len, TRUE, ske->prop->hash)) { silc_free(*auth_data); silc_buffer_free(auth); return FALSE; } silc_buffer_free(auth); return TRUE; }
static SilcBool silc_connauth_verify_signature(SilcConnAuth connauth, SilcPublicKey pub_key, unsigned char *sign, SilcUInt32 sign_len) { int len; SilcBuffer auth; SilcSKE ske = connauth->ske; if (!pub_key || !sign) return FALSE; /* Make the authentication data. Protocol says it is HASH plus KE Start Payload. */ len = ske->hash_len + silc_buffer_len(ske->start_payload_copy); auth = silc_buffer_alloc_size(len); if (!auth) return FALSE; silc_buffer_format(auth, SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len), SILC_STR_UI_XNSTRING( ske->start_payload_copy->data, silc_buffer_len(ske->start_payload_copy)), SILC_STR_END); /* Verify signature */ if (!silc_pkcs_verify(pub_key, sign, sign_len, auth->data, silc_buffer_len(auth), ske->prop->hash)) { silc_buffer_free(auth); return FALSE; } silc_buffer_free(auth); return TRUE; }
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; }
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; }
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; }
static void silc_sftp_server_extended(SilcSFTP sftp, SilcSFTPStatus status, const unsigned char *data, SilcUInt32 data_len, void *context) { SilcSFTPServer server = (SilcSFTPServer)sftp; SilcUInt32 id = SILC_PTR_TO_32(context); SILC_LOG_DEBUG(("Extended callback")); SILC_LOG_DEBUG(("Request ID: %d", id)); if (status != SILC_SFTP_STATUS_OK) { silc_sftp_send_error(server, status, id); return; } silc_sftp_send_packet(server, SILC_SFTP_EXTENDED, 4 + data_len, SILC_STR_UI_INT(id), SILC_STR_UI_XNSTRING(data, data_len), SILC_STR_END); }
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; }