Exemple #1
0
void qvd_set_cert_files(qvdclient *qvd, const char *client_cert, const char *client_key)
{
  if (client_cert == NULL || client_key == NULL)
    {
      qvd_printf("Disabling client certificate\n");
      qvd->use_client_cert = 0;
      return;
    }

  if (access(client_cert, R_OK) != 0)
    {
      qvd_error(qvd, "Cert file %s is not accessible: %s\n", client_cert, strerror(errno));
      qvd->use_client_cert = 0;
      return;
    }

  if (access(client_key, R_OK) != 0)
    {
      qvd_error(qvd, "Key file %s is not accessible: %s\n", client_key, strerror(errno));
      qvd->use_client_cert = 0;
      return;
    }

  strncpy(qvd->client_cert, client_cert, MAX_PATH_STRING);
  qvd->client_cert[MAX_PATH_STRING - 1] = '\0';

  strncpy(qvd->client_key, client_key, MAX_PATH_STRING);
  qvd->client_key[MAX_PATH_STRING - 1] = '\0';

  qvd->use_client_cert = 1;

  qvd_printf("Setting client_cert to <%s> and client_key to <%s> and enabling client certificate send", qvd->client_cert, qvd->client_key);

  return;
}
Exemple #2
0
int _qvd_verify_cert_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
{
  
  SSL    *ssl;
  SSL_CTX *sslctx;
  qvdclient *qvd ;

  ssl = X509_STORE_CTX_get_ex_data(x509_ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
  sslctx = SSL_get_SSL_CTX(ssl);
  qvd = SSL_CTX_get_ex_data(sslctx, _qvd_ssl_index); 
 
  X509 *cert = X509_STORE_CTX_get_current_cert(x509_ctx);
  int depth = X509_STORE_CTX_get_error_depth(x509_ctx);
  int err = X509_STORE_CTX_get_error(x509_ctx);

  /* save the certificate by incrementing the reference count and
   * keeping a pointer */
  if (depth < MAX_CERTS && !certificate[depth]) {
    certificate[depth] = cert;
    certificate_error[depth] = err;
    cert->references++;
  }

  /* See http://www.openssl.org/docs/ssl/SSL_CTX_set_verify.html# */
  if (preverify_ok)
    {
      qvd_printf("_qvd_verify_cert_callback: Certificate was validated\n");
      return preverify_ok;
    }
  if (qvd->ssl_verify_callback == NULL)
    {
      qvd_printf("_qvd_verify_cert_callback: No callback specified returning false (specify if you wissh callbacks for unknown certs with qvd_set_unknown_cert_callback)\n");
      return 0;
    }

  BIO *bio_out = BIO_new(BIO_s_mem());
  BUF_MEM *biomem;
  int result;
  PEM_write_bio_X509(bio_out, certificate[depth]);
  BIO_get_mem_ptr(bio_out, &biomem);
  char cert_info[1024];
  char issuer[256], subject[256];
  X509_NAME_oneline(X509_get_issuer_name(certificate[depth]), issuer, 256);
  X509_NAME_oneline(X509_get_subject_name(certificate[depth]), subject, 256);

  snprintf(cert_info, 1023, "Serial: %lu\n\nIssuer: %s\n\nValidity:\n\tNot before: %s\n\tNot after: %s\n\nSubject: %s\n",
	   ASN1_INTEGER_get(X509_get_serialNumber(certificate[depth])), issuer, 
	   X509_get_notBefore(certificate[depth])->data, X509_get_notAfter(cert)->data, subject);
  cert_info[1023] = '\0';
  result = qvd->ssl_verify_callback(qvd, cert_info, biomem->data);
  if (result)
    {
      _qvd_save_certificate(qvd, certificate[depth], depth, biomem);
    }

  BIO_free(bio_out);
  return result;
}
Exemple #3
0
void _qvd_print_environ()
{
  if (environ == NULL)
    qvd_printf("Environment variable not defined (NULL)");
  char **ptr;
  qvd_printf("Printing environment variables\n");
  for (ptr=environ; *ptr != NULL; ptr ++)
      qvd_printf("Environment var %s\n", *ptr);

}
Exemple #4
0
void QvdBufferReset(QvdBuffer *self)
{
#ifdef TRACE
  qvd_printf("QvdBufferReset offset=%d, size=%d\n", self->offset, self->size);
#endif
  self->offset = 0;
  self->size = 0;
#ifdef TRACE
  qvd_printf("QvdBufferReset offset=%d, size=%d\n", self->offset, self->size);
#endif
}
Exemple #5
0
int QvdBufferAppend(QvdBuffer *self, const char *data, size_t count)
{
#ifdef TRACE
  qvd_printf("QvdBufferAppend offset=%d, size=%d\n", self->offset, self->size);
#endif
  size_t bytes_to_copy = MIN(count, BUFFER_SIZE - self->size);
  memcpy(self->data+self->size, data, bytes_to_copy);
  self->size += count;
#ifdef TRACE
  qvd_printf("QvdBufferReset offset=%d, size=%d\n", self->offset, self->size);
#endif
  return bytes_to_copy;
}
Exemple #6
0
/* 
 * Returns 1 if client certificates are used and 0 otherwise
 */
int _qvd_use_client_cert(qvdclient *qvd)
{
  if (qvd->use_client_cert == 0)
    {
      qvd_printf("No client certificates used\n");
      return 0;
    }


  qvd_printf("Using client certificates cert: <%s>, key <%s>\n", qvd->client_cert, qvd->client_key);
  curl_easy_setopt(qvd->curl, CURLOPT_SSLCERT, qvd->client_cert);
  curl_easy_setopt(qvd->curl, CURLOPT_SSLKEY, qvd->client_key);
  /*  curl_easy_setopt(qvd->curl, CURLOPT_KEYPASSWD, "");*/
  return 1;
}
Exemple #7
0
int QvdBufferCanRead(QvdBuffer *self)
{
#ifdef TRACE
  qvd_printf("QvdBufferCanRead offset=%d, size=%d: %d\n", self->offset, self->size, self->size < BUFFER_SIZE);
#endif
  return self->size < BUFFER_SIZE;
}
Exemple #8
0
int QvdBufferCanWrite(QvdBuffer *self)
{
#ifdef TRACE
  qvd_printf("QvdBufferCanWrite offset=%d, size=%d: %d\n", self->offset, self->size, self->offset < self->size);
#endif
  return self->offset < self->size;
}
Exemple #9
0
void qvd_free(qvdclient *qvd) {
  qvd_printf("Calling qvd_free\n");
  curl_easy_cleanup(qvd->curl);
  QvdVmListFree(qvd->vmlist);
  /* nx_options should be null */
  free(qvd->nx_options);
  free(qvd);
}
Exemple #10
0
int _qvd_set_certdir(qvdclient *qvd)
{
  char *home = getenv(HOME_ENV);
  char *appdata = getenv(APPDATA_ENV);

  int result;
  if (home == NULL && appdata == NULL && !qvd->home && (*(qvd->home)) == '\0' && !_qvd_dir_exists(qvd, qvd->home)
      && _qvd_dir_exists(qvd, home) && !_qvd_dir_exists(qvd, appdata))
    {
      qvd_error(qvd, "Error %s and %s environment var were not defined, cannot save to $HOME/.qvd/certs, you can try to set also qvd_set_home", HOME_ENV, APPDATA_ENV);
      return 0;
    }

  if (qvd->home && (*(qvd->home)) && _qvd_dir_exists(qvd, qvd->home))
    {
      home = qvd->home;
    } else if (home != NULL && _qvd_dir_exists(qvd, home))
    {
      qvd_set_home(qvd, home);
      qvd_printf("using %s environment var", HOME_ENV);
    } else if (appdata != NULL && _qvd_dir_exists(qvd, appdata))
    {
      qvd_set_home(qvd, appdata);
      home = appdata;
      qvd_printf("%s was not defined using %s environment var", HOME_ENV, APPDATA_ENV);
    }

  /* Define .qvd/certs in qvdclient.h */
  if (!_qvd_create_dir(qvd, home, CONF_DIR))
    return 0;

  if (!_qvd_create_dir(qvd, home, CERT_DIR))
    return 0;

  snprintf(qvd->certpath, MAX_PATH_STRING, "%s/%s", home, CERT_DIR);
  qvd->certpath[MAX_PATH_STRING] = '\0';
  if (strlen(qvd->certpath) == MAX_PATH_STRING)
    {
      qvd_error(qvd, "Cert string too long (%d) recompile program. Path is %s", MAX_PATH_STRING, qvd->certpath);
      return 0;
    }
  qvd_printf("Setting cert path to %s\n", qvd->certpath);
  curl_easy_setopt(qvd->curl, CURLOPT_CAPATH, qvd->certpath);
  return 1;
}
Exemple #11
0
void QvdBufferInit(QvdBuffer *self)
{
  memset(self->data, 0, BUFFER_SIZE);
  self->offset = 0;
  self->size = 0;
#ifdef TRACE
  qvd_printf("QvdBufferInit offset=0, size=0\n");
#endif
}
/*
 * Sets callback to call the java method print_progress from the object
 * progressHandler of the class QvdClientWrapper
 */
int progress_callback(qvdclient *qvd, const char *message)
{
  /* TODO rename callbackhandler_environment_struct and reuse it for this case */
  jstring message_str;
  struct callbackhandler_environment_struct *callbackhandler_env;
  JNIEnv *env;
  jclass temp;

  qvd_printf("progress_callback\n");
  callbackhandler_env = (struct callbackhandler_environment_struct *) qvd->userdata;
  qvd_printf("progress_callback:progressHandler: %p, jvm: %p\n", callbackhandler_env->progressCallbackHandler, callbackhandler_env->jvm);
  (*(callbackhandler_env->jvm))->AttachCurrentThread(callbackhandler_env->jvm, (void **)&env, NULL);
  qvd_printf("progress_callback:progressHandler: %p, jvm: %p, env: %p\n", callbackhandler_env->progressCallbackHandler, callbackhandler_env->jvm, env);
  if (env == NULL)
    {
      qvd_error(qvd, "Error obtaining JNIEnv * from jvm\n");
      return 0;
    }

  /* Might be null if object is not defined */
  if (!callbackhandler_env->progressCallbackHandler)
    {
      qvd_printf("progressCallbackHandler object is null, returning 0\n");
      return 0;
    }
  qvd_printf("progressCallbackHandler is non null\n");

  message_str = (*env)->NewStringUTF(env, message);
  if (message_str == NULL)
    {
      qvd_error(qvd, "Error allocating memory for message_str\n");
      return 0;
    }
  qvd_printf("message_str is non null");

   temp = (*env)->GetObjectClass(env, callbackhandler_env->progressCallbackHandler);
   qvdprogresshandler_cls = (*env)->NewGlobalRef(env, temp);
   (*env)->DeleteLocalRef(env, temp);
   if (qvdprogresshandler_cls == NULL)
    {
      qvd_error(qvd, "Error finding class for QvdProgressHandler interface");
      return 0;
    }

   print_progress_mid = (*env)->GetMethodID(env, qvdprogresshandler_cls, "print_progress", "(Ljava/lang/String;)V");
  if (print_progress_mid == NULL)
    {
      qvd_error(qvd, "Error finding method for interface QvdProgressHandler print_progress\n");
      return 0;
    }

  (*env)->CallVoidMethod(env, callbackhandler_env->progressCallbackHandler, print_progress_mid, message_str);
  qvd_printf("After CallVoidMethod\n");
  (*env)->DeleteLocalRef(env, message_str);

  return 1;
}
Exemple #13
0
int QvdBufferRead(QvdBuffer *self, int fd)
{
  int ret;
  ret = read(fd, self->data+self->size, BUFFER_SIZE-self->size);
#ifdef TRACE
  qvd_printf("%d: read %d\n", fd, ret);
#endif
  if (ret >= 0)
    self->size += ret;
  return ret;
}
jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
    JNIEnv* env;
    jclass temp;

    if ((*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_6) != JNI_OK) {
      qvd_printf("Failed to get the environment using GetEnv\n");
      return -1;
    }

    // Get jclass with env->FindClass.
    if (initIds(env) < 0) {
      qvd_printf("Failed to register methods\n");
      return -1;
    }
    // Register methods with env->RegisterNatives.
    (*env)->RegisterNatives(env, qvdclientwrapper_cls, methods, sizeof(methods)/sizeof(methods[0]));

    return JNI_VERSION_1_6;
}
Exemple #15
0
int qvd_stop_vm(qvdclient *qvd, int vm) {
  char url[MAX_BASEURL];
  int i;
  long http_code = 0;
  json_error_t error;
  char *command = "/qvd/stop_vm";

  if (!_qvd_set_certdir(qvd)) {
    qvd_printf("Please set the cert dir");
    return 1;
  }

  if (snprintf(url, MAX_BASEURL, "%s%s", qvd->baseurl, command) >= MAX_BASEURL) {
    qvd_error(qvd, "Error initializing url in list_of_vm, length is longer than %d\n", MAX_BASEURL);
    return 2;
  }

  _qvd_use_client_cert(qvd);
  curl_easy_setopt(qvd->curl, CURLOPT_URL, url);
  /*  curl_easy_setopt(curl, CURLOPT_WRITEDATA, &jsonBuffer); */
  qvd->res = curl_easy_perform(qvd->curl);
  qvd_printf("After easy_perform: %ul\n", qvd->res);
  if (qvd->res)
    {
      qvd_printf("Error accessing url: <%s>, error code: %ul\n", url, qvd->res);
      qvd_error(qvd, "Error accessing list of VMs: %s\n", curl_easy_strerror(qvd->res));
      return 3;
    }
  
  curl_easy_getinfo (qvd->curl, CURLINFO_RESPONSE_CODE, &http_code);
  if (http_code == 401)
    {
      qvd_error(qvd, "Error authenticating user\n");
      return 4;
    }
  qvd_printf("No error and no auth error after curl_easy_perform\n");
  /*  QvdBufferInit(&(qvd->buffer)); */


   return 0;
}
Exemple #16
0
int qvd_connect_to_vm(qvdclient *qvd, int id)
{
  int result, proxyFd, fd;
  long curlsock;

  qvd_printf("qvd_connect_to_vm(%p,%d)", qvd, id);
  if (qvd->display && (*(qvd->display)) != '\0') {
    qvd_printf("Setting DISPLAY to %s\n", qvd->display);
    if (setenv(DISPLAY_ENV, qvd->display, 1)) {
      qvd_error(qvd, "Error setting DISPLAY to %s. errno: %d (%s)", qvd->display, errno, strerror(errno));
    }
  }
  if (qvd->home && (*(qvd->home)) != '\0') {
    qvd_printf("Setting NX_HOME to %s\n", qvd->home);
    if (setenv("NX_HOME", qvd->home, 1)) {
      qvd_error(qvd, "Error setting NX_HOME to %s. errno: %d (%s)", qvd->home, errno, strerror(errno));
    }
  }
  if (!_qvd_set_certdir(qvd)) {
    qvd_printf("Please set the cert dir");
    return 5;
  }

  qvd->end_connection = 0;

  result = _qvd_switch_protocols(qvd, id);
  _qvd_print_environ();
  /* if non zero return with error */
  if (result)
    return result;

  curl_easy_getinfo(qvd->curl, CURLINFO_LASTSOCKET, &curlsock);  
  fd = (int) curlsock;

  if ((proxyFd = _qvd_proxy_connect(qvd)) < 0)
    return 4;

  qvd_printf("Remote fd: %d Local fd: %d\n", fd, proxyFd);
  qvd_printf("Before _qvd_client_loop\n");
  result = _qvd_client_loop(qvd, fd, proxyFd);
  qvd_progress(qvd, "End of QVD connection");
  shutdown(proxyFd, 2);
  qvd_printf("before NXTransDestroy\n");
  NXTransDestroy(NX_FD_ANY);
  qvd_printf("after NXTransDestroy\n");

  if (result)
    return 6;

  return 0;
}
Exemple #17
0
int QvdBufferWrite(QvdBuffer *self, int fd)
{
  int ret;
  ret = write(fd, self->data+self->offset, self->size-self->offset);
#ifdef TRACE
  qvd_printf("%d: wrote %d\n", fd, ret);
#endif
  if (ret >= 0) {
    self->offset += ret;
    /* Write head has reached read head */
    if (self->offset >= self->size)
      QvdBufferReset(self);
  }
  return ret;
}
Exemple #18
0
CURLcode _qvd_sslctxfun(CURL *curl, SSL_CTX *sslctx, void *parm)
{

  qvdclient *qvd = (qvdclient *) parm;
  if (qvd->ssl_no_cert_check)
    {
      qvd_printf("No strict certificate checking. Accepting any server certificate\n");
      return CURLE_OK;
    }
  /* See SSL_set_ex_data and http://www.openssl.org/docs/ssl/SSL_get_ex_new_index.htm*/
  /* parm is qvdclient *qvd, the qvd object, set with  CURLOPT_SSL_CTX_DATA */
  SSL_CTX_set_ex_data(sslctx, _qvd_ssl_index, parm);

  SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER, _qvd_verify_cert_callback);

  return CURLE_OK;
} 
Exemple #19
0
int _qvd_set_base64_auth(qvdclient *qvd)
{
  CURLcode error;
  char *ptr = NULL, *content;
  size_t outlen;
  int result = 0;
  char *digest = NULL;
  BIO *bio, *b64;

  // Digest using the openssl BIO functionality
  b64 = BIO_new(BIO_f_base64());
  bio = BIO_new(BIO_s_mem());
  bio = BIO_push(b64, bio);
  BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
  BIO_write(b64, qvd->userpwd, strlen(qvd->userpwd));
  BIO_flush(b64);

  outlen = BIO_get_mem_data(bio, &ptr);

  if ( outlen >= MAX_AUTHDIGEST-1 )
    {
      qvd_error(qvd, "The authdigest string for %s is longer than %d\n", qvd->userpwd, MAX_AUTHDIGEST);
      result = 1;
    }
  else 
    {
      // The resulting digest isn't zero terminated
      memcpy(qvd->authdigest, ptr, outlen);
      qvd->authdigest[outlen] = '\0';

#ifdef TRACE
      qvd_printf("The conversion to base64 from <%s> is <%s>", qvd->userpwd, qvd->authdigest);
#endif
      result = 0;
    }

  BIO_free_all(bio);

  
  /* hack for base64 encode of "[email protected]:O3xTMCQ3" */
  /*  snprintf(qvd->authdigest, MAX_AUTHDIGEST, "%s", "bml0b0BkZWlyby5jb206TzN4VE1DUTM=");*/
  return result;
}
Exemple #20
0
int _qvd_save_certificate(qvdclient *qvd, X509 *cert, int depth, BUF_MEM *biomem)
{
  char path[MAX_PATH_STRING];

  int fd, result;
  snprintf(path, MAX_PATH_STRING - 1, "%s/%lx.%d", qvd->certpath, X509_subject_name_hash(cert), depth);
  path[MAX_PATH_STRING - 1] = '\0';
  if (strlen(path) == MAX_PATH_STRING)
    {
      qvd_error(qvd, "Cert string too long (%d) recompile program. Path is %s", MAX_PATH_STRING, path);
      return 0;
    }

  fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, 0644);
  if (fd == -1)
    {
      qvd_error(qvd, "Error creating file %s: %s", path, strerror(errno));
      return 0;
    }

  result = write(fd, biomem->data, strlen(biomem->data));
  if (result == -1)
    {
      qvd_error(qvd, "Error writing file %s: %s", path, strerror(errno));
      return 0;
	}
  if (result != strlen(biomem->data))
    {
      qvd_error(qvd, "Error writing file not enough bytes written in %s: %d vs %d", path, result, strlen(biomem->data));
      return 0;
    }

  result = close(fd);
  if (result == -1)
    {
	  qvd_error(qvd, "Error closing file %s: %s", path, strerror(errno));
	  return 0;
    }
  qvd_printf("Successfully saved cert in %s\n", path);
  return 1;
}
Exemple #21
0
int progress_callback(qvdclient *qvd, const char *message) {
  qvd_printf("Progress Callback: %s\n", message);
}
/*
 * Sets callback to call the java method certificate_verification from the object
 * certificateHandler of the class QvdClientWrapper
 * It gets from the qvd->userdata which points to a struct of callbackhandler_environment_struct
 * A pointer to the jvm and one to the QvdclientWrapper->unknowncertCallbackHandler object
 * From there we get the class of the certifcateHandler and the
 * method certificate_verification, which we invoke, and return the result.
 */
int accept_unknown_cert_callback(qvdclient *qvd, const char *cert_pem_str, const char *cert_pem_data)
{
  jstring jcert_pem_str, jcert_pem_data;
  jboolean response;
  struct callbackhandler_environment_struct *callbackhandler_env;
  JNIEnv *env;
  jclass temp;

  qvd_printf("accept_unknown_cert_callback\n");
  callbackhandler_env = (struct callbackhandler_environment_struct *) qvd->userdata;
  qvd_printf("accept_unknown_cert_callback:certificateHandler: %p, jvm: %p\n", callbackhandler_env->unknowncertCallbackHandler, callbackhandler_env->jvm);
  (*(callbackhandler_env->jvm))->AttachCurrentThread(callbackhandler_env->jvm, (void **)&env, NULL);
  qvd_printf("accept_unknown_cert_callback:certificateHandler: %p, jvm: %p, env: %p\n", callbackhandler_env->unknowncertCallbackHandler, callbackhandler_env->jvm, env);
  if (env == NULL)
    {
      qvd_error(qvd, "Error obtaining JNIEnv * from jvm\n");
      return 0;
    }

  /* Might be null if object is not defined */
  if (!callbackhandler_env->unknowncertCallbackHandler)
    {
      qvd_printf("certificateHandler object is null, returning false (certificate rejected)\n");
      return 0;
    }
  qvd_printf("certhandler is non null\n");

  jcert_pem_str = (*env)->NewStringUTF(env, cert_pem_str);
  if (jcert_pem_str == NULL)
    {
      qvd_error(qvd, "Error allocating memory for jcert_pem_str\n");
      return 0;
    }
  qvd_printf("jcert_pem_str is non null\n");

  jcert_pem_data = (*env)->NewStringUTF(env, cert_pem_data);
  if (jcert_pem_data == NULL)
    {
      qvd_error(qvd, "Error allocating memory for jcert_pem_data\n");
      return 0;
    }
  qvd_printf("jcert_pem_data is non null\n");


   temp = (*env)->GetObjectClass(env, callbackhandler_env->unknowncertCallbackHandler);
   qvdunknowncerthandler_cls = (*env)->NewGlobalRef(env, temp);
   (*env)->DeleteLocalRef(env, temp);
   if (qvdunknowncerthandler_cls == NULL)
    {
      qvd_error(qvd, "Error finding class for QvdUnknownCertificateHandler interface");
      return -1;
    }


  certificate_verification_mid = (*env)->GetMethodID(env, qvdunknowncerthandler_cls, "certificate_verification", "(Ljava/lang/String;Ljava/lang/String;)Z");
  if (certificate_verification_mid == NULL)
    {
      qvd_error(qvd, "Error finding method for interface QvdUnknownCertificateHandler certicate_verification\n");
      return 0;
    }

  response = (*env)->CallBooleanMethod(env, callbackhandler_env->unknowncertCallbackHandler, certificate_verification_mid, jcert_pem_str, jcert_pem_data);
  qvd_printf("After CallBooleanMethod\n");
  qvd_printf("After CallBooleanMethod response, %d\n", response);
  (*env)->DeleteLocalRef(env, jcert_pem_str);
  (*env)->DeleteLocalRef(env, jcert_pem_data);

  return response;

}
Exemple #23
0
vmlist *qvd_list_of_vm(qvdclient *qvd) {
  char url[MAX_BASEURL];
  int i;
  long http_code = 0;
  json_error_t error;
  char *command = "/qvd/list_of_vm";

  if (!_qvd_set_certdir(qvd)) {
    qvd_printf("Please set the cert dir");
    return NULL;
  }

  if (qvd->home && (*(qvd->home)) != '\0') {
    qvd_printf("Setting NX_HOME to %s\n", qvd->home);
    if (setenv("NX_HOME", qvd->home, 1)) {
      qvd_error(qvd, "Error setting NX_HOME to %s. errno: %d (%s)", qvd->home, errno, strerror(errno));
    }
  }

  if (snprintf(url, MAX_BASEURL, "%s%s", qvd->baseurl, command) >= MAX_BASEURL) {
    qvd_error(qvd, "Error initializing url in list_of_vm, length is longer than %d\n", MAX_BASEURL);
    return NULL;
  }

  _qvd_use_client_cert(qvd);
  curl_easy_setopt(qvd->curl, CURLOPT_URL, url);
  /*  curl_easy_setopt(curl, CURLOPT_WRITEDATA, &jsonBuffer); */
  qvd->res = curl_easy_perform(qvd->curl);
  qvd_printf("After easy_perform: %ul\n", qvd->res);
  if (qvd->res)
    {
      qvd_printf("Error accessing url: <%s>, error code: %ul\n", url, qvd->res);
      qvd_error(qvd, "Error accessing list of VMs: %s\n", curl_easy_strerror(qvd->res));
      return NULL;
    }
  
  curl_easy_getinfo (qvd->curl, CURLINFO_RESPONSE_CODE, &http_code);
  if (http_code == 401)
    {
      qvd_error(qvd, "Error authenticating user\n");
      return NULL;
    }
  qvd_printf("No error and no auth error after curl_easy_perform\n");
  /*  QvdBufferInit(&(qvd->buffer)); */

  json_t *vmList = json_loads(qvd->buffer.data, 0, &error);
  int arrayLength = json_array_size(vmList);
  qvd->numvms = arrayLength;
  qvd_printf("VMs available: %d\n", qvd->numvms);

  QvdVmListFree(qvd->vmlist);
  if (!(qvd->vmlist = malloc(sizeof(vmlist)))) {
    qvd_error(qvd, "Error allocating memory for vmlist");
    return NULL;
  }
  QvdVmListInit(qvd->vmlist);

  for (i = 0; i < arrayLength; i++) {
    json_t *obj = json_array_get(vmList, i);
    int id, blocked;
    char *name, *state;
    json_unpack(obj, "{s:i,s:s,s:i,s:s}", 
		"id", &id,
		"state", &state,
		"blocked", &blocked,
		"name", &name);
    qvd_printf("VM ID:%d NAME:%s STATE:%s BLOCKED:%d\n", 
	       id, name, state, blocked);
    QvdVmListAppendVm(qvd, qvd->vmlist, QvdVmNew(id, name, state, blocked));
  }
  /*  QvdBufferReset(&(qvd->buffer));*/
  if (qvd->numvms <= 0) {
    qvd_error(qvd, "No virtual machines available for user %s\n", qvd->username);
  } else {
    qvd_progress(qvd, "Returning list of vms");
  }
  return qvd->vmlist;
}
Exemple #24
0
void qvd_set_progress_callback(qvdclient *qvd, int (*progress_callback)(qvdclient *, const char *message))
{
  qvd_printf("Setting progress callback\n");
  qvd->progress_callback = progress_callback;
}
/*
 * Static method called once when the QvdclientWrapper class is loaded
 * It caches the fieldids and the class references
 */
int initIds(JNIEnv *env) {
  jclass temp;

  temp = (*env)->FindClass(env, "com/theqvd/client/jni/QvdclientWrapper");
  qvdclientwrapper_cls = (*env)->NewGlobalRef(env, temp);
  (*env)->DeleteLocalRef(env, temp);
  if (qvdclientwrapper_cls == NULL)
    {
      qvd_printf("Error finding class for QvdclientWrapper");
      return -1;
    }

  temp = (*env)->FindClass(env, "com/theqvd/client/jni/Qvdclient");
  qvdclient_cls = (*env)->NewGlobalRef(env, temp);
  (*env)->DeleteLocalRef(env, temp);
  if (qvdclient_cls == NULL)
    {
      qvd_printf("Error finding class for Qvdclient");
      return -1;
    }

  temp = (*env)->FindClass(env, "com/theqvd/client/jni/Vm");
  vm_cls = (*env)->NewGlobalRef(env, temp);
  (*env)->DeleteLocalRef(env, temp);
   if (vm_cls == NULL)
     {
       qvd_printf("Error finding class for Vm");
       return -1;
     }

   temp = (*env)->FindClass(env, "[Lcom/theqvd/client/jni/Vm;");
   vm_array_cls = (*env)->NewGlobalRef(env, temp);
   (*env)->DeleteLocalRef(env, temp);
   if (vm_array_cls == NULL)
    {
      qvd_printf("Error finding class for Vm array");
      return -1;
    }

   host_fid = (*env)->GetFieldID(env, qvdclient_cls, "host", "Ljava/lang/String;");
   if (host_fid == NULL)
     {
       qvd_printf("Error finding field id for host in class Qvdclient");
       return -1;
     }

   qvdclient_fid = (*env)->GetFieldID(env, qvdclientwrapper_cls, "qvdclient", "Lcom/theqvd/client/jni/Qvdclient;");
   if (qvdclient_fid == NULL)
     {
       qvd_printf("Error finding field id for qvdclient member of class QvdclientWrapper");
       return -1;
     }
   certificatehandler_fid = (*env)->GetFieldID(env, qvdclientwrapper_cls, "certificateHandler", "Lcom/theqvd/client/jni/QvdUnknownCertificateHandler;");
   if (certificatehandler_fid == NULL)
     {
       qvd_printf("Error finding field id for interface QvdUnknownCertificateHandler");
       return -1;
     }
   qvd_printf("certificatehandler_fid: %p\n", certificatehandler_fid);

   progresshandler_fid = (*env)->GetFieldID(env, qvdclientwrapper_cls, "progressHandler", "Lcom/theqvd/client/jni/QvdProgressHandler;");
   if (progresshandler_fid == NULL)
     {
       qvd_printf("Error finding field id for interface QvdProgressHandler");
       return -1;
     }
   qvd_printf("progresshandler_fid: %p\n", progresshandler_fid);


   port_fid = (*env)->GetFieldID(env, qvdclient_cls, "port", "I");
   if (port_fid == NULL)
     {
       qvd_printf("Error finding field id for port in class Qvdclient");
       return -1;
     }

   username_fid = (*env)->GetFieldID(env, qvdclient_cls, "username", "Ljava/lang/String;");
   if (username_fid == NULL)
     {
       qvd_printf("Error finding field id for username in class Qvdclient");
       return -1;
     }

   password_fid = (*env)->GetFieldID(env, qvdclient_cls, "password", "Ljava/lang/String;");
   if (password_fid == NULL)
     {
       qvd_printf("Error finding field id for password in class Qvdclient");
       return -1;
     }

   vm_id_fid = (*env)->GetFieldID(env, vm_cls, "id", "I");
   if (vm_id_fid == NULL)
     {
       qvd_printf("Error finding field id in class Vm");
       return -1;
     }

   vm_name_fid = (*env)->GetFieldID(env, vm_cls, "name", "Ljava/lang/String;");
   if (vm_name_fid == NULL)
     {
       qvd_printf("Error finding field id for name in class Vm");
       return -1;
     }

   vm_state_fid = (*env)->GetFieldID(env, vm_cls, "state", "Ljava/lang/String;");
   if (vm_state_fid == NULL)
     {
       qvd_printf("Error finding field id for state in class Vm");
       return -1;
     }

   vm_blocked_fid = (*env)->GetFieldID(env, vm_cls, "blocked", "I");
   if (vm_blocked_fid == NULL)
     {
      qvd_printf("Error finding field blocked in class Vm");
      return -1;
     }

   vm_constructor_mid = (*env)->GetMethodID(env, vm_cls, "<init>", "(ILjava/lang/String;Ljava/lang/String;I)V");
   if (vm_constructor_mid == NULL)
     {
       qvd_printf("Error finding constructor for class Vm");
       return -1;
     }

   return 0;
}
Exemple #26
0
/*
 * _qvd_client_loop
 *            --------------------
 *            |                  |
 * proxyFd ---| _qvd_client_loop |---connFd            
 * (X display)|                  | (curl to remote host)
 *            --------------------
 * 
 *       -----   proxyRead  ---->
 *      <-----   proxyWrite ----
 *
 * We read from proxyFd and store it in the proxyRead buffer and then write it into connFd (curl)
 * We read from connFd and store it in the proxyWrite buffer and then write it ingo proxyFd (NX)
 *
 */
int _qvd_client_loop(qvdclient *qvd, int connFd, int proxyFd)
{
  qvd_printf("_qvd_client_loop\n");
  size_t read = 0, written = 0;
  struct timeval timeout;
  fd_set rfds, wfds;
  int ret, res, err, maxfds, numunsupportedprotocolerrs = 0, result = 0, i;

  QvdBuffer proxyWrite, proxyRead;
  qvd_printf("_qvd_client_loop(%p, %d, %d)\n", qvd, connFd, proxyFd);
  QvdBufferInit(&proxyWrite);
  QvdBufferInit(&proxyRead);
  do
    {
      ret = 0;
      timeout.tv_sec = QVDLOOP_TIMEOUT_SEC;
      timeout.tv_usec = QVDLOOP_TIMEOUT_USEC;
      maxfds = 1+MAX(connFd, proxyFd);
      FD_ZERO(&rfds);
      FD_ZERO(&wfds);
      if (proxyFd > 0 && QvdBufferCanRead(&proxyRead))
	  FD_SET(proxyFd, &rfds);

      if (connFd > 0 && QvdBufferCanRead(&proxyWrite))
	FD_SET(connFd, &rfds);

      if (NXTransPrepare(&maxfds, &rfds, &wfds, &timeout))
	{
#ifdef TRACE
	  qvd_printf("_qvd_client_loop: executing select()\n");
#endif
	  NXTransSelect(&ret, &err, &maxfds, &rfds, &wfds, &timeout);
	  NXTransExecute(&ret, &err, &maxfds, &rfds, &wfds, &timeout);
	}
      if (ret == -1 && errno == EINTR)
	continue;

      if (ret < 0)
	{
	  qvd_error(qvd, "Error in _qvd_client_loop: select() %s\n", strerror(errno));
	  return 1;
	}
      if (qvd->end_connection)
	{
	  qvd_printf("Connection ended with qvd_end_connection().");
	  qvd_progress(qvd, "Connection ended with qvd_end_connection().");
	  return 0;
	}
#ifdef TRACE
      qvd_printf("isset proxyfd read: %d; connfd read: %d\n",
		   FD_ISSET(proxyFd, &rfds), FD_ISSET(connFd, &rfds));
#endif
      /* Read from curl socket and store in proxyWrite buffer */
      if (connFd > 0 && FD_ISSET(connFd, &rfds))
	{
	  read = 0; /* handle case of CURLE_UNSUPPORTED_PROTOCOL where read does not gets modified */
	  res = curl_easy_recv(qvd->curl, proxyWrite.data+proxyWrite.offset,
			       BUFFER_SIZE-proxyWrite.size, &read);

	  switch (res)
	    {
	    case CURLE_OK:
#ifdef TRACE
	      qvd_printf("curl: recv'd %ld\n", read);
#endif
	      proxyWrite.size += read;
	      if (read == 0)
		{
		  qvd_printf("Setting connFd to 0, End of stream\n");
		  connFd = -1; 
		}
	      numunsupportedprotocolerrs = 0;
	      break;
	    case CURLE_AGAIN:
	      qvd_printf("Nothing read. receiving curl_easy_recv: %d CURLE_AGAIN, read %d\n", res, read);
	      break;
	    case CURLE_UNSUPPORTED_PROTOCOL:
	      numunsupportedprotocolerrs++;
	      qvd_printf("Unsupported protocol. receiving curl_easy_recv: %d CURLE_UNSUPPORTED_PROTOCOL (wait for next iteration), read %d, number of sequential errors=%d\n", res, read, numunsupportedprotocolerrs);
	      qvd_printf("Error buffer: %s", qvd->error_buffer);
#ifdef TRACE
	      qvd_printf("curle_unsupported_protocol string size");
	      for (i=0; i < read; i++)
		qvd_printf("%x %c ",proxyWrite.data[i], proxyWrite.data[i]);
	      qvd_printf("\n");
#endif
# define MAX_CURLE_UNSUPPORTED_PROTOCOL 1
	      if (numunsupportedprotocolerrs >= MAX_CURLE_UNSUPPORTED_PROTOCOL) {
		qvd_error(qvd, "Unsupported protocol received %d times. receiving curl_easy_recv: %d CURLE_UNSUPPORTED_PROTOCOL (wait for next iteration), read %d, number of sequential errors=%d\n", MAX_CURLE_UNSUPPORTED_PROTOCOL, res, read, numunsupportedprotocolerrs);
		/* An error we need to finish the connection */
		connFd = -1;
		/*		  proxyFd = -1;  */
		result = 0;
	      }
	      break;
	    default:
	      qvd_error(qvd, "Error receiving curl_easy_recv: %d\n", res);
	      connFd = -1;
	      /* proxyFd = -1; */
	      result = -1;
	    }
	}
      /* Read from NX and store in proxyRead buffer */
      if (proxyFd > 0 && FD_ISSET(proxyFd, &rfds))
	{
	  ret = QvdBufferRead(&proxyRead, proxyFd);
	  if (ret == 0)
	    {
	      qvd_printf("No more bytes to read from proxyFd ending\n");
	      proxyFd = -1;
	    }
	  if (ret < 0)
	    {
	      qvd_error(qvd, "Error proxyFd read error: %s\n", strerror(errno));
	      proxyFd = -1;
	    }
	}
      if (proxyFd > 0 && QvdBufferCanWrite(&proxyWrite))
	{
	  ret = QvdBufferWrite(&proxyWrite, proxyFd);
	  if (ret < 0 && errno != EINTR) {
	    qvd_error(qvd, "Error reading from proxyFd: %d %s\n", errno, strerror(errno));
	    proxyFd = -1;
	  }
	}
      if (connFd > 0 && QvdBufferCanWrite(&proxyRead))
	{
	  /*QvdBufferWrite(&proxyRead, connFd);*/
	  res = curl_easy_send(qvd->curl, proxyRead.data+proxyRead.offset,
			       proxyRead.size-proxyRead.offset, &written);
	  switch (res)
	    {
	    case CURLE_OK:
	      proxyRead.offset += written;
#ifdef TRACE
	      qvd_printf("curl: send'd %ld\n", written);
#endif
	      if (proxyRead.offset >= proxyRead.size)
		QvdBufferReset(&proxyRead);
	      numunsupportedprotocolerrs = 0;
	      break;
	    case CURLE_AGAIN:
	      qvd_printf("Nothing written, wait for next iteration. curl_easy_send: %d CURLE_AGAIN, written %d\n", res, written);
	      break;
	    case CURLE_UNSUPPORTED_PROTOCOL:
	      numunsupportedprotocolerrs++;
	      qvd_printf("Unsupported protocol sent %d times. sending curl_easy_sendv: %d CURLE_UNSUPPORTED_PROTOCOL (wait for next iteration), written %d, number of sequential errors=%d\n", MAX_CURLE_UNSUPPORTED_PROTOCOL, res, written, numunsupportedprotocolerrs);
	      qvd_printf("Error buffer: %s", qvd->error_buffer);

#ifdef TRACE
	      qvd_printf("curle_unsupported_protocol string size");
	      for (i=0; i < written; i++)
		qvd_printf("%x %c ",proxyWrite.data[i], proxyWrite.data[i]);
	      qvd_printf("\n");
#endif
	      if (numunsupportedprotocolerrs >= MAX_CURLE_UNSUPPORTED_PROTOCOL) {
		qvd_error(qvd, "Unsupported protocol sent %d times. sending curl_easy_sendv: %d CURLE_UNSUPPORTED_PROTOCOL (wait for next iteration), written %d, number of sequential errors=%d\n", MAX_CURLE_UNSUPPORTED_PROTOCOL, res, written, numunsupportedprotocolerrs);
		/* An error we need to finish the connection */
		/* TODO only finish connFd */
		connFd = -1;
		/*		  proxyFd = -1; */
		result = 0;
	      }
	      break;
	    default:
	      qvd_error(qvd, "Error sending curl_easy_send: %d", res);
	      connFd = -1;
	    }
	}
    } while (connFd > 0 && proxyFd > 0);
  
  return result;
}
Exemple #27
0
/* Init and free functions */
qvdclient *qvd_init(const char *hostname, const int port, const char *username, const char *password) {
  qvdclient *qvd;
  qvd_printf("Starting qvd_init. %s", qvd_get_version_text);
  if (strlen(username) + strlen(password) + 2 > MAX_USERPWD) {
    qvd_error(qvd, "Length of username and password + 2 is longer than %d\n", MAX_USERPWD);
    return NULL;
  }

  if (strlen(hostname) + 6 + strlen("https:///") + 2 > MAX_BASEURL) {
    qvd_error(qvd, "Length of hostname and port + scheme  + 2 is longer than %d\n", MAX_BASEURL);
    return NULL;
  }

  if (! (qvd = (qvdclient *) malloc(sizeof(qvdclient)))) {
    qvd_error(qvd, "Error allocating memory: %s", strerror(errno));
    return NULL;
  }
  
  if (snprintf(qvd->userpwd, MAX_USERPWD, "%s:%s", username, password) >= MAX_USERPWD) {
    qvd_error(qvd, "Error initializing userpwd (string too long)\n");
    free(qvd);
    return NULL;
  }
  if (_qvd_set_base64_auth(qvd)) {
    qvd_error(qvd, "Error initializing authdigest\n");
    free(qvd);
    return NULL;
    }

  if (snprintf(qvd->baseurl, MAX_BASEURL, "https://%s:%d", hostname, port) >= MAX_BASEURL) {
    qvd_error(qvd, "Error initializing baseurl(string too long)\n");
    free(qvd);
    return NULL;
  }

  if (snprintf(qvd->useragent, MAX_USERAGENT, "%s %s", DEFAULT_USERAGENT_PRODUCT, curl_version()) >= MAX_USERAGENT) {
    qvd_error(qvd, "Error initializing useragent (string too long)\n");
    free(qvd);
    return NULL;
  }

  qvd->curl = curl_easy_init();
  if (!qvd->curl) {
    qvd_error(qvd, "Error initializing curl\n");
    free(qvd);
    return NULL;
  }
  qvd_printf("Curl pointer is %p", qvd->curl);
  if (get_debug_level()) {
    curl_easy_setopt(qvd->curl, CURLOPT_VERBOSE, 1L);
    curl_easy_setopt(qvd->curl, CURLOPT_DEBUGFUNCTION, qvd_curl_debug_callback);
  }

  curl_easy_setopt(qvd->curl, CURLOPT_ERRORBUFFER, qvd->error_buffer);  /* curl_easy_setopt(qvd->curl, CURLOPT_SSL_VERIFYPEER, 1L); */
  /* curl_easy_setopt(qvd->curl, CURLOPT_SSL_VERIFYHOST, 2L); */
  curl_easy_setopt(qvd->curl, CURLOPT_CERTINFO, 1L);
  curl_easy_setopt(qvd->curl, CURLOPT_CAPATH, qvd->certpath);
  curl_easy_setopt(qvd->curl, CURLOPT_SSL_CTX_FUNCTION, _qvd_sslctxfun);
  curl_easy_setopt(qvd->curl, CURLOPT_SSL_CTX_DATA, (void *)qvd);
  /*  curl_easy_setopt(qvd->curl, CURLOPT_CAINFO, NULL);*/
  _qvd_ssl_index = SSL_CTX_get_ex_new_index(0, (void *)qvd, NULL, NULL, NULL);
  curl_easy_setopt(qvd->curl, CURLOPT_SSL_VERIFYPEER, 0L);
  curl_easy_setopt(qvd->curl, CURLOPT_SSL_VERIFYHOST, 0L);
  curl_easy_setopt(qvd->curl, CURLOPT_TCP_NODELAY, 1L);
  /*  curl_easy_setopt(qvd->curl, CURLOPT_FAILONERROR, 1L);*/
  curl_easy_setopt(qvd->curl, CURLOPT_HTTPAUTH, (long)CURLAUTH_BASIC);
  curl_easy_setopt(qvd->curl, CURLOPT_USERPWD, qvd->userpwd);
  curl_easy_setopt(qvd->curl, CURLOPT_WRITEFUNCTION, _qvd_write_buffer_callback);
  curl_easy_setopt(qvd->curl, CURLOPT_WRITEDATA, &(qvd->buffer));
  curl_easy_setopt(qvd->curl, CURLOPT_USERAGENT, qvd->useragent);
  /* If client certificate CURLOPT_SSLCERT , CURLOPT_SSLKEY, CURLOPT_SSLCERTTYPE "PEM" */
  /* Copy parameters */
  strncpy(qvd->hostname, hostname, MAX_BASEURL);
  qvd->hostname[MAX_BASEURL - 1] = '\0';
  qvd->port = port;
  strncpy(qvd->username, username, MAX_USERPWD);
  qvd->username[MAX_USERPWD - 1] = '\0';
  strncpy(qvd->password, password, MAX_USERPWD);
  qvd->password[MAX_USERPWD - 1] = '\0';
  strncpy(qvd->client_cert, "", MAX_PATH_STRING);
  strncpy(qvd->client_key, "", MAX_PATH_STRING);
  qvd->use_client_cert = 0;
  qvd->numvms = 0;
  qvd_set_link(qvd, DEFAULT_LINK);
  qvd_set_geometry(qvd, DEFAULT_GEOMETRY);
  qvd_set_os(qvd, DEFAULT_OS);
  qvd->keyboard = "pc%2F105";
  qvd->fullscreen = 0;
  qvd->print_enabled = 0;
  qvd->ssl_no_cert_check = 0;
  qvd->ssl_verify_callback = NULL;
  qvd->progress_callback = NULL;
  qvd->userdata = NULL;
  qvd->nx_options = NULL;

  *(qvd->display) = '\0';
  *(qvd->home) = '\0';
  strcpy(qvd->error_buffer, "");
  QvdBufferInit(&(qvd->buffer));

  if (!(qvd->vmlist = malloc(sizeof(vmlist)))) {
    free(qvd);
    return NULL;
  }
  QvdVmListInit(qvd->vmlist);
  
  return qvd;
}
Exemple #28
0
int _qvd_switch_protocols(qvdclient *qvd, int id)
{
  fd_set myset, zero;
  size_t bytes_sent, bytes_received, bytes_received_total;
  int socket, i, content_length, content_size_parsed;
  char url[MAX_BASEURL];
  char base64auth[MAX_PARAM];
  char *ptr, *content;

  _qvd_use_client_cert(qvd);
  curl_easy_setopt(qvd->curl, CURLOPT_URL, qvd->baseurl);
  curl_easy_setopt(qvd->curl, CURLOPT_CONNECT_ONLY, 1L);
  curl_easy_perform(qvd->curl);
  curl_easy_getinfo(qvd->curl, CURLINFO_LASTSOCKET, &socket);

  /*  if (snprintf(url, MAX_BASEURL, "GET /qvd/connect_to_vm?id=%d&qvd.client.os=%s&qvd.client.fullscreen=%d&qvd.client.geometry=%s&qvd.client.link=%s&qvd.client.keyboard=%s&qvd.client.printing.enabled=%d HTTP/1.1\nAuthorization: Basic %s\nConnection: Upgrade\nUpgrade: QVD/1.0\n\n", id, qvd->os, qvd->fullscreen, qvd->geometry, qvd->link, qvd->keyboard, qvd->print_enabled, qvd->authdigest) >= MAX_BASEURL) { */
  if (snprintf(url, MAX_BASEURL, "GET /qvd/connect_to_vm?id=%d&qvd.client.os=%s&qvd.client.geometry=%s&qvd.client.link=%s&qvd.client.keyboard=%s&qvd.client.fullscreen=%d HTTP/1.1\nAuthorization: Basic %s\nConnection: Upgrade\nUpgrade: QVD/1.0\n\n", id, qvd->os, qvd->geometry, qvd->link, qvd->keyboard, qvd->fullscreen, qvd->authdigest) >= MAX_BASEURL) {
    qvd_error(qvd, "Error initializing authdigest\n");
    return 1;
  }
  qvd_printf("Switch protocols the url is: <%s>\n", url);

  /*  char *url = "GET /qvd/connect_to_vm?id=1&qvd.client.os=linux&qvd.client.fullscreen=&qvd.client.geometry=800x600&qvd.client.link=local&qvd.client.keyboard=pc105%2Fus&qvd.client.printing.enabled=0 HTTP/1.1\nAuthorization: Basic bml0bzpuaXRv\nConnection: Upgrade\nUpgrade: QVD/1.0\n\n"; */
  if ((qvd->res = curl_easy_send(qvd->curl, url, strlen(url) , &bytes_sent )) != CURLE_OK ) {
    qvd_error(qvd, "An error ocurred in first curl_easy_send: %ul <%s>\n", qvd->res, curl_easy_strerror(qvd->res));
    return 1;
  }

  /* TODO perhaps put this in another func ??? */

  FD_ZERO(&myset);
  FD_ZERO(&zero);
  FD_SET(socket, &myset);
  qvd_printf("Before select on send socket is: %d\n", socket);
  for (i=0; i<MAX_HTTP_RESPONSES_FOR_UPGRADE; ++i) {
    /* TODO define timeouts perhaps in qvd_init */
    select(socket+1, &myset, &zero, &zero, NULL);
    if ((qvd->res = curl_easy_recv(qvd->curl, qvd->buffer.data, BUFFER_SIZE, &bytes_received)) != CURLE_OK ) {
      qvd_error(qvd, "An error ocurred in curl_easy_recv: %ul <%s>\n", qvd->res, curl_easy_strerror(qvd->res));
      return 2;
    }
    qvd->buffer.data[bytes_received] = 0;
    qvd_printf("%d input received was <%s>\n", i, qvd->buffer.data);
    /* TODO what happens if  for other strings
V/qvd     ( 7551): Before select on send socket is: 43
V/qvd     ( 7551): 0 input received was <HTTP/1.1 403 Forbidden
V/qvd     ( 7551): Content-Type: text/plain
V/qvd     ( 7551): Content-Length: 56
V/qvd     ( 7551): 
V/qvd     ( 7551): >
V/qvd     ( 7551): 1 input received was <The requested virtual machine is offline for maintenance>

 */


    if (strstr(qvd->buffer.data, "HTTP/1.1 101")) {
      qvd_printf("Upgrade of protocol was done\n");
      break;
    }

#define PROGRESSINFO "\r\nX-QVD-VM-Info: "
    if (strstr(qvd->buffer.data, "HTTP/1.1 102")) {
      qvd_printf("Progress message");
      if ((ptr = strcasestr(qvd->buffer.data, PROGRESSINFO)) != NULL) {
#ifdef TRACE
	qvd_printf("ptr is %s and size is %d", ptr, strlen(PROGRESSINFO));
#endif
	ptr += strlen(PROGRESSINFO);
	qvd_progress(qvd, ptr);
      }
#ifdef TRACE
      else {
	qvd_printf("Pointer finding %s is null", PROGRESSINFO);
      }
#endif
    }

    /* TODO cleanup printf */
    if (strstr(qvd->buffer.data, "HTTP/1.1 2")
	|| strstr(qvd->buffer.data, "HTTP/1.1 3")
	|| strstr(qvd->buffer.data, "HTTP/1.1 4")
	|| strstr(qvd->buffer.data, "HTTP/1.1 5")) {
      bytes_received_total = 0;
#define CONTENT_LENGTH "\r\nContent-Length: "
      if ((ptr = strcasestr(qvd->buffer.data, CONTENT_LENGTH)) != NULL) {
	ptr += strlen(CONTENT_LENGTH);
#ifdef TRACE
	qvd_printf("Parsing content length from <%s> and starting in <%s>", qvd->buffer.data, ptr);
#endif
	content_length = -1;
	if (sscanf(ptr, "%d", &content_length) != 1) {
	  qvd_printf("Error parsing content-length setting to -1: %d", content_length);
	  content_length = -1;	  
	}
      }
      while (bytes_received < BUFFER_SIZE) {
	qvd_printf("Waiting for extra data after found 2xx, 3xx, 4xx or 5xx code <%s>", qvd->buffer.data);
	select(socket+1, &myset, &zero, &zero, NULL);
       
	ptr = qvd->buffer.data;
	ptr += bytes_received;
	/* TODO implement callback for info */
	if ((qvd->res = curl_easy_recv(qvd->curl, ptr, BUFFER_SIZE, &bytes_received_total)) != CURLE_OK ) {
	  ptr = strstr(qvd->buffer.data, "\r\n\r\n");
	  qvd_error(qvd, "Error received in qvd_curl_easy_recv: %d. <%s>", qvd->res, ptr);
	  return 7;
	}
	bytes_received += bytes_received_total;
#define DOUBLENEWLINE "\r\n\r\n"
	content = strstr(qvd->buffer.data, DOUBLENEWLINE);
	content_size_parsed = content != NULL ? strlen(content): -1;
#ifdef TRACE
	qvd_printf("The bytes received were: %d, and curle code was: %d, content: <%s>, size of content: %d", bytes_received_total, qvd->res, content, content_size_parsed);
#endif
	if (bytes_received == 0 || content_size_parsed >= content_length) {
	  content += strlen(DOUBLENEWLINE);
	  qvd_error(qvd, "Error: <%s>", content);
	  return 8;
	}
     
      }
    }

  }
  if (i >=10 ) {
    qvd_error(qvd, "Error not received response for protocol upgrade in %d tries http/1.1\n", i);
    return 3;
  }

  return 0;
}