示例#1
0
// write_error: queues a KSSL error message for sending.
void write_error(connection_state *state, DWORD id, BYTE error)
{
  int size = 0;
  BYTE *resp = NULL;

  kssl_error_code err = kssl_error(id, error, &resp, &size);
  log_error(id, error);
  if (err != KSSL_ERROR_INTERNAL) {
    queue_write(state, resp, size);
  }
}
示例#2
0
// kssl_operate: create a serialized response from a KSSL request
// header and payload
kssl_error_code kssl_operate(kssl_header *header,
                             BYTE *payload,
                             pk_list privates,
                             BYTE **out_response,
                             int *out_response_len) {
  kssl_error_code err = KSSL_ERROR_NONE;
  BYTE *local_resp = NULL;
  int local_resp_len = 0;

  // Parse the indices of the items out of the payload
  kssl_header out_header;
  kssl_operation request;
  kssl_operation response;
  BYTE *out_payload = NULL;
  zero_operation(&request);
  zero_operation(&response);

  *out_response = 0;
  *out_response_len = 0;

  // Extract the items from the payload
  err = parse_message_payload(payload, header->length, &request);
  if (err != KSSL_ERROR_NONE) {
    goto exit;
  }

  if (silent == 0) {
    log_operation(header, &request);
  }

  switch (request.opcode) {
    // Other side sent response, error or pong: unexpected
    case KSSL_OP_RESPONSE:
    case KSSL_OP_ERROR:
    case KSSL_OP_PONG:
    {
      err = KSSL_ERROR_UNEXPECTED_OPCODE;
      break;
    }

    // Echo is trivial, it just echos the complete state->header back
    // including the payload item
    case KSSL_OP_PING:
    {
      response.is_payload_set = 1;
      response.payload = request.payload;
      response.payload_len = request.payload_len;
      response.is_opcode_set = 1;
      response.opcode = KSSL_OP_PONG;

      break;
    }

    // Decrypt or sign the payload using the private key
    case KSSL_OP_RSA_DECRYPT:
    case KSSL_OP_RSA_SIGN_MD5SHA1:
    case KSSL_OP_RSA_SIGN_SHA1:
    case KSSL_OP_RSA_SIGN_SHA224:
    case KSSL_OP_RSA_SIGN_SHA256:
    case KSSL_OP_RSA_SIGN_SHA384:
    case KSSL_OP_RSA_SIGN_SHA512:
    {
      unsigned int payload_size;
      int max_payload_size;
      int key_id;

      if (request.is_digest_set == 0) {
        err = KSSL_ERROR_FORMAT;
        break;
      }

      // Identify private key from request digest
      key_id = find_private_key(privates, request.digest);
      if (key_id < 0) {
        err = KSSL_ERROR_KEY_NOT_FOUND;
        break;
      }

      // Allocate buffer to hold output of private key operation
      max_payload_size = key_size(privates, key_id);
      out_payload = malloc(max_payload_size);
      if (out_payload == NULL) {
        err = KSSL_ERROR_INTERNAL;
        break;
      }

      // Operate on payload
      err = private_key_operation(privates, key_id, request.opcode,
          request.payload_len, request.payload, out_payload,
          &payload_size);
      if (err != KSSL_ERROR_NONE) {
        err = KSSL_ERROR_CRYPTO_FAILED;
        break;
      }

      response.is_payload_set = 1;
      response.payload        = out_payload;
      response.payload_len    = payload_size;
      response.is_opcode_set  = 1;
      response.opcode         = KSSL_OP_RESPONSE;

      break;
    }

    // This should not occur
  default:
    {
      err = KSSL_ERROR_BAD_OPCODE;
      break;
    }
  }

exit:
  if (err != KSSL_ERROR_NONE) {
    err = kssl_error(header->id, err, &local_resp, &local_resp_len);
  } else {

    // Create output header

    out_header.version_maj = KSSL_VERSION_MAJ;
    out_header.version_min = KSSL_VERSION_MIN;
    out_header.id          = header->id;

    // Note that the response in &local_resp is dynamically allocated
    // and needs to be freed

    err = flatten_operation(&out_header, &response, &local_resp,
        &local_resp_len);
  }

  if (out_payload != NULL) {
    free(out_payload);
  }

  if (err == KSSL_ERROR_NONE) {
    *out_response = local_resp;
    *out_response_len = local_resp_len;
  }

  return err;
}