/*
 * Generate the base64 encoded sha1 hash of the string in str. This is used
 * to generate unique names for files based on whatever the caller adds to
 * the incoming string.
 */
static char *get_sha1_b64(void *ctx, const char *str)
{
	uint8_t sha1_buf[SHA_DIGEST_LENGTH];

	SHA1(str, strlen(str), sha1_buf);

	return base64_enc(ctx, sha1_buf, sizeof(sha1_buf));
}
Esempio n. 2
0
static void apple_challenge(int fd, rtsp_message *req, rtsp_message *resp) {
    char *hdr = msg_get_header(req, "Apple-Challenge");
    if (!hdr)
        return;

    SOCKADDR fdsa;
    socklen_t sa_len = sizeof(fdsa);
    getsockname(fd, (struct sockaddr*)&fdsa, &sa_len);

    int chall_len;
    uint8_t *chall = base64_dec(hdr, &chall_len);
    uint8_t buf[48], *bp = buf;
    int i;
    memset(buf, 0, sizeof(buf));

    if (chall_len > 16) {
        warn("oversized Apple-Challenge!");
        free(chall);
        return;
    }
    memcpy(bp, chall, chall_len);
    free(chall);
    bp += chall_len;

#ifdef AF_INET6
    if (fdsa.SAFAMILY == AF_INET6) {
        struct sockaddr_in6 *sa6 = (struct sockaddr_in6*)(&fdsa);
        memcpy(bp, sa6->sin6_addr.s6_addr, 16);
        bp += 16;
    } else
#endif
    {
        struct sockaddr_in *sa = (struct sockaddr_in*)(&fdsa);
        memcpy(bp, &sa->sin_addr.s_addr, 4);
        bp += 4;
    }

    for (i=0; i<6; i++)
        *bp++ = config.hw_addr[i];

    int buflen, resplen;
    buflen = bp-buf;
    if (buflen < 0x20)
        buflen = 0x20;

    uint8_t *challresp = rsa_apply(buf, buflen, &resplen, RSA_MODE_AUTH);
    char *encoded = base64_enc(challresp, resplen);

    // strip the padding.
    char *padding = strchr(encoded, '=');
    if (padding)
        *padding = 0;

    msg_add_header(resp, "Apple-Response", encoded);
    free(challresp);
    free(encoded);
}
Esempio n. 3
0
static char *make_nonce(void) {
    uint8_t random[8];
    int fd = open("/dev/random", O_RDONLY);
    if (fd < 0)
        die("could not open /dev/random!");
    read(fd, random, sizeof(random));
    close(fd);
    return base64_enc(random, 8);
}
Esempio n. 4
0
/* caller must free the returned string */
char * euca_sign_url (const char * verb, const char * date, const char * url)
{
	if (!initialized) euca_init_cert ();
		
    char * sig_str = NULL;
    RSA * rsa = NULL;
    FILE * fp = NULL;

    if ( verb==NULL || date==NULL || url==NULL ) return NULL;

    if ( ( rsa = RSA_new() ) == NULL ) {
      logprintfl (EUCAERROR, "error: RSA_new() failed\n");
    } else if ( ( fp = fopen (pk_file, "r") ) == NULL) {
      logprintfl (EUCAERROR, "error: failed to open private key file %s\n", pk_file);
      RSA_free (rsa);
    } else {
      logprintfl (EUCADEBUG2, "euca_sign_url(): reading private key file %s\n", pk_file);
      PEM_read_RSAPrivateKey(fp, &rsa, NULL, NULL); /* read the PEM-encoded file into rsa struct */
      if ( rsa==NULL ) {
	logprintfl (EUCAERROR, "error: failed to read private key file %s\n", pk_file);
      } else {
	unsigned char * sig;
        
	// RSA_print_fp (stdout, rsa, 0); /* (for debugging) */
	if ( (sig = malloc(RSA_size(rsa))) == NULL) {
	  logprintfl (EUCAERROR, "error: out of memory (for RSA key)\n");
	} else {
	  unsigned char sha1 [SHA_DIGEST_LENGTH];
#define BUFSIZE 2024
	  char input [BUFSIZE];
	  unsigned int siglen;
	  int ret;
	  
	  /* finally, SHA1 and sign with PK */
	  assert ((strlen(verb)+strlen(date)+strlen(url)+4)<=BUFSIZE);
	  snprintf (input, BUFSIZE, "%s\n%s\n%s\n", verb, date, url);
	  logprintfl (EUCADEBUG2, "euca_sign_url(): signing input %s\n", get_string_stats(input));	
	  SHA1 ((unsigned char *)input, strlen(input), sha1);
	  if ((ret = RSA_sign (NID_sha1, sha1, SHA_DIGEST_LENGTH, sig, &siglen, rsa))!=1) {
	    logprintfl (EUCAERROR, "error: RSA_sign() failed\n");
	  } else {
	    logprintfl (EUCADEBUG2, "euca_sign_url(): signing output %d\n", sig[siglen-1]);	
	    sig_str = base64_enc (sig, siglen);
	    logprintfl (EUCADEBUG2, "euca_sign_url(): base64 signature %s\n", get_string_stats((char *)sig_str));	
	  }
	  free (sig);
	}
	RSA_free (rsa);
      }            
      fclose(fp);
    }
    
    return sig_str;
}
Esempio n. 5
0
static int w_crypto_aes_encrypt(sip_msg_t* msg, char* inb, char* keyb, char* outb)
{
	str ins;
	str keys;
	pv_spec_t *dst;
	pv_value_t val;
	EVP_CIPHER_CTX en;
	str etext;

	if (fixup_get_svalue(msg, (gparam_t*)inb, &ins) != 0) {
		LM_ERR("cannot get input value\n");
		return -1;
	}
	if (fixup_get_svalue(msg, (gparam_t*)keyb, &keys) != 0) {
		LM_ERR("cannot get key value\n");
		return -1;
	}
	dst = (pv_spec_t*)outb;

	/* gen key and iv. init the cipher ctx object */
	if (crypto_aes_init((unsigned char *)keys.s, keys.len,
				(unsigned char*)((_crypto_salt_param)?_crypto_salt:0), &en, NULL)) {
		LM_ERR("couldn't initialize AES cipher\n");
		return -1;
	}
	etext.len = ins.len;
	etext.s = (char *)crypto_aes_encrypt(&en, (unsigned char *)ins.s, &etext.len);
	if(etext.s==NULL) {
		LM_ERR("AES encryption failed\n");
		return -1;
	}

	memset(&val, 0, sizeof(pv_value_t));
	val.rs.s = pv_get_buffer();
	val.rs.len = base64_enc((unsigned char *)etext.s, etext.len,
					(unsigned char *)val.rs.s, pv_get_buffer_size()-1);
	if (val.rs.len < 0) {
		LM_ERR("base64 output of encrypted value is too large (need %d)\n",
				-val.rs.len);
		goto error;
	}
	LM_DBG("base64 encrypted result: [%.*s]\n", val.rs.len, val.rs.s);
	val.flags = PV_VAL_STR;
	dst->setf(msg, &dst->pvp, (int)EQ_T, &val);

	free(etext.s);
	EVP_CIPHER_CTX_cleanup(&en);
	return 1;

error:
	free(etext.s);
	EVP_CIPHER_CTX_cleanup(&en);
	return -1;
}
Esempio n. 6
0
char * zauthToken(unsigned long int gid, unsigned long int zid,time_t exp_time)
{
        char str[MAX],str_final[MAX],temp[MAX],str_sig[MAX];
         int len,len1;
        char *ret = (char *) malloc(1024 * sizeof(char *));
        sprintf(str, "%lu:%lu.%lu.AAAAAA==",gid,zid,(unsigned long int)exp_time);
        unsigned char *ptr = HMAC(EVP_sha256(),my.secret,strlen(my.secret),str,strlen(str),str_final,&len); // hmac--sha256 before base64 encoding....

        base64_enc(str_final,len,1,str_sig);                                                                    //base64 encoding to get signature
        sprintf(ret, "%s|%s\n",str,str_sig);
	return ret;
}
Esempio n. 7
0
END_TEST

START_TEST(base64_enc_06)
{
	char *buf;
	size_t sz;

	buf = base64_enc((unsigned char *)"", 0, &sz);
	fail_unless(!!buf, "no buffer returned");
	fail_unless(!sz, "length not 0");
	fail_unless(!buf[0], "not empty string");
	free(buf);
}
Esempio n. 8
0
END_TEST

START_TEST(base64_enc_04)
{
	char *buf;
	size_t sz;

	buf = base64_enc((unsigned char *)plain04, strlen(plain04), &sz);
	fail_unless(!!buf, "no buffer returned");
	fail_unless(sz == strlen(coded04), "wrong length");
	fail_unless(!memcmp(coded04, buf, sz), "wrong data");
	free(buf);
}
/*
 * Generate the base64 encoded hmac sha1 hash of string str using the secret 
 * key in the amazon_context_struct pointed to in request.
 */
static char *get_hmac_sha1_b64(struct s3_request_struct *req, const char *str)
{
	uint8_t hmac_sha1_buf[EVP_MAX_MD_SIZE];
	unsigned int hmac_sha1_len = 0;

	HMAC(EVP_sha1(), 
	     req->amz_ctx->secret_key,
	     strlen(req->amz_ctx->secret_key),
	     str,
	     strlen(str),
	     hmac_sha1_buf,
	     &hmac_sha1_len);

	return base64_enc(get_tmp_context(req), hmac_sha1_buf, hmac_sha1_len);
}
Esempio n. 10
0
string cipher::encrypt(string const &plain,time_t timeout)
{
	size_t block_size=(plain.size() + 15) / 16 * 16;

	vector<unsigned char> data(sizeof(aes_hdr)+sizeof(info)+block_size,0);
	copy(plain.begin(),plain.end(),data.begin() + sizeof(aes_hdr)+sizeof(info));
	aes_hdr &aes_header=*(aes_hdr*)(&data.front());
	info &header=*(info *)(&data.front()+sizeof(aes_hdr));
	header.timeout=timeout;
	header.size=plain.size();
	memset(&aes_header,0,16);

	gcry_md_hash_buffer(GCRY_MD_MD5,&aes_header.md5,&header,block_size+sizeof(info));
	gcry_cipher_encrypt(hd_out,&data.front(),data.size(),NULL,0);

	return base64_enc(data);
}
Esempio n. 11
0
static inline int get_pass(str *_username, str *_secret, str *_password)
{
	unsigned int hmac_len = SHA_DIGEST_LENGTH;
	unsigned char hmac_sha1[hmac_len];

	if (HMAC(EVP_sha1(), _secret->s, _secret->len,
			(unsigned char *) _username->s,
			_username->len, hmac_sha1, &hmac_len) == NULL)
	{
		LM_ERR("HMAC-SHA1 failed\n");
		return -1;
	}

	_password->len = base64_enc(hmac_sha1, hmac_len,
					(unsigned char *) _password->s,
					base64_enc_len(hmac_len));
	LM_DBG("calculated password: %.*s\n", _password->len, _password->s);

	return 0;
}
Esempio n. 12
0
/** Calculates the nonce string for RFC2617 digest authentication.
 * This function creates the nonce string as it will be sent to the
 * user agent in digest challenge. The format of the nonce string
 * depends on the value of three module parameters, auth_checks_register,
 * auth_checks_no_dlg, and auth_checks_in_dlg. These module parameters
 * control the amount of information from the SIP requst that will be
 * stored in the nonce string for verification purposes.
 *
 * If all three parameters contain zero then the nonce string consists
 * of time in seconds since 1.1. 1970 and a secret phrase:
 * <expire_time> <valid_since> MD5(<expire_time>, <valid_since>, secret)
 * If any of the parameters is not zero (some optional checks are enabled
 * then the nonce string will also contain MD5 hash of selected parts
 * of the SIP request:
 * <expire_time> <valid_since> MD5(<expire_time>, <valid_since>, secret1) MD5(<extra_checks>, secret2)
 * @param nonce  Pointer to a buffer of *nonce_len. It must have enough
 *               space to hold the nonce. MAX_NONCE_LEN should be always 
 *               safe.
 * @param nonce_len A value/result parameter. Initially it contains the
 *                  nonce buffer length. If the length is too small, it 
 *                  will be set to the needed length and the function will 
 *                  return error immediately. After a succesfull call it will 
 *                  contain the size of nonce written into the buffer, 
 *                  without the terminating 0.
 * @param cfg This is the value of one of the tree module parameters that
 *            control which optional checks are enabled/disabled and which
 *            parts of the message will be included in the nonce string.
 * @param since Time when nonce was created, i.e. nonce is valid since <valid_since> up to <expires>
 * @param expires Time in seconds after which the nonce will be considered 
 *                stale.
 * @param n_id    Nounce count and/or one-time nonce index value
 *                (32 bit counter)
 * @param pf      First 2 bits are flags, the rest is the index pool number
 *                 used if nonce counts or one-time nonces are enabled.
 *                The possible flags values are: NF_VALID_NC_ID which means
 *                the nonce-count support is enabled and NF_VALID_OT_ID 
 *                which means the one-time nonces support is enabled.
 *                The pool number can be obtained by and-ing with
 *                NF_POOL_NO_MASK
 * @param secret1 A secret used for the nonce expires integrity check:
 *                MD5(<expire_time>, <valid_since>, secret1).
 * @param secret2 A secret used for integrity check of the message parts 
 *                selected by auth_extra_checks (if any):
 *                MD5(<msg_parts(auth_extra_checks)>, secret2).
 * @param msg     The message for which the nonce is computed. If 
 *                auth_extra_checks is set, the MD5 of some fields of the
 *                message will be included in the  generated nonce.
 * @return 0 on success and -1 on error
 */
int calc_nonce(char* nonce, int *nonce_len, int cfg, int since, int expires,
#if defined USE_NC || defined USE_OT_NONCE
					unsigned int n_id, unsigned char pf,
#endif /* USE_NC || USE_OT_NONCE */
					str* secret1, str* secret2,
					struct sip_msg* msg)
{
	union bin_nonce b_nonce;
	int len;
	if (unlikely(*nonce_len < MAX_NONCE_LEN)) {
		len=get_nonce_len(cfg, pf & NF_VALID_NC_ID);
		if (unlikely(*nonce_len<len)){
			*nonce_len=len;
			return -1;
		}
	}

	BIN_NONCE_PREPARE(&b_nonce, expires, since, n_id, pf, cfg, msg);
	len=calc_bin_nonce_md5(&b_nonce, cfg, secret1, secret2, msg);
	*nonce_len=base64_enc(&b_nonce.raw[0], len, 
							(unsigned char*)nonce, *nonce_len);
	assert(*nonce_len>=0); /*FIXME*/
	return 0;
}
Esempio n. 13
0
//!
//! Handles the console output retrieval request.
//!
//! @param[in]  nc a pointer to the NC state structure to initialize
//! @param[in]  pMeta a pointer to the node controller (NC) metadata structure
//! @param[in]  instanceId the instance identifier string (i-XXXXXXXX)
//! @param[out] consoleOutput a pointer to the unallocated string that will contain the output
//!
//! @return EUCA_OK on success or EUCA_ERROR and EUCA_NOT_FOUND_ERROR on failure.
//!
static int doGetConsoleOutput(struct nc_state_t *nc, ncMetadata * pMeta, char *instanceId, char **consoleOutput)
{
    int rc = 0;
    int fd = 0;
    int ret = EUCA_OK;
    int readsize = 0;
    char *console_output = NULL;
    char *console_append = NULL;
    char *console_main = NULL;
    char console_file[MAX_PATH] = "";
    char userId[48] = "";
    ncInstance *instance = NULL;
    struct stat statbuf = { 0 };

    *consoleOutput = NULL;
    readsize = 64 * 1024;

    // find the instance record
    sem_p(inst_sem);
    {
        if ((instance = find_instance(&global_instances, instanceId)) != NULL) {
            snprintf(console_file, 1024, "%s/console.append.log", instance->instancePath);
            snprintf(userId, 48, "%s", instance->userId);
        }
    }
    sem_v(inst_sem);

    if (!instance) {
        logprintfl(EUCAERROR, "[%s] cannot locate instance\n", instanceId);
        return (EUCA_NOT_FOUND_ERROR);
    }
    // read from console.append.log if it exists into dynamically allocated 4K console_append buffer
    if ((rc = stat(console_file, &statbuf)) >= 0) {
        if (diskutil_ch(console_file, nc->admin_user_id, nc->admin_user_id, 0) != EUCA_OK) {
            logprintfl(EUCAERROR, "[%s] failed to change ownership of %s\n", instanceId, console_file);
            return (EUCA_ERROR);
        }

        if ((fd = open(console_file, O_RDONLY)) >= 0) {
            if ((console_append = EUCA_ZALLOC(4096, sizeof(char))) != NULL) {
                rc = read(fd, console_append, (4096) - 1);
            }
            close(fd);
        }
    }

    sem_p(inst_sem);
    {
        snprintf(console_file, MAX_PATH, "%s/console.log", instance->instancePath);
    }
    sem_v(inst_sem);

    // read the last 64K from console.log or the whole file, if smaller, into dynamically allocated 64K console_main buffer
    if ((rc = stat(console_file, &statbuf)) >= 0) {
        if (diskutil_ch(console_file, nc->admin_user_id, nc->admin_user_id, 0) != EUCA_OK) {
            logprintfl(EUCAERROR, "[%s] failed to change ownership of %s\n", instanceId, console_file);
            EUCA_FREE(console_append);
            return (EUCA_ERROR);
        }

        if ((fd = open(console_file, O_RDONLY)) >= 0) {
            if ((rc = lseek(fd, (off_t) (-1 * readsize), SEEK_END)) < 0) {
                if ((rc = lseek(fd, (off_t) 0, SEEK_SET)) < 0) {
                    logprintfl(EUCAERROR, "[%s] cannot seek to beginning of file\n", instanceId);
                    if (console_append)
                        EUCA_FREE(console_append);
                    close(fd);
                    return (EUCA_ERROR);
                }
            }

            if ((console_main = EUCA_ZALLOC(readsize, sizeof(char))) != NULL) {
                rc = read(fd, console_main, (readsize) - 1);
            }
            close(fd);
        } else {
            logprintfl(EUCAERROR, "[%s] cannot open '%s' read-only\n", instanceId, console_file);
        }
    } else {
        logprintfl(EUCAERROR, "[%s] cannot stat console_output file '%s'\n", instanceId, console_file);
    }

    // concatenate console_append with console_main, base64-encode this, and put into dynamically allocated buffer consoleOutput
    ret = EUCA_ERROR;
    if ((console_output = EUCA_ZALLOC((readsize) + 4096, sizeof(char))) != NULL) {
        if (console_append) {
            strncat(console_output, console_append, 4096);
        }

        if (console_main) {
            strncat(console_output, console_main, readsize);
        }

        *consoleOutput = base64_enc((unsigned char *)console_output, strlen(console_output));
        ret = EUCA_OK;
    }

    EUCA_FREE(console_append);
    EUCA_FREE(console_main);
    EUCA_FREE(console_output);
    return (ret);
}
Esempio n. 14
0
static int
doGetConsoleOutput(	struct nc_state_t *nc,
			ncMetadata *meta,
			char *instanceId,
			char **consoleOutput) {

  char *console_output=NULL, *console_append=NULL, *console_main=NULL;
  char console_file[MAX_PATH], userId[48];
  int rc, fd, ret, readsize;
  struct stat statbuf;
  ncInstance *instance=NULL;

  *consoleOutput = NULL;
  readsize = 64 * 1024;

  // find the instance record
  sem_p (inst_sem); 
  instance = find_instance(&global_instances, instanceId);
  if (instance) {
          snprintf(console_file, 1024, "%s/console.append.log", instance->instancePath);
          snprintf(userId, 48, "%s", instance->userId);
  }
  sem_v (inst_sem);

  if (!instance) {
    logprintfl(EUCAERROR, "doGetConsoleOutput(): cannot locate instance with instanceId=%s\n", instanceId);
    return(1);
  }

  // read from console.append.log if it exists into dynamically allocated 4K console_append buffer
  rc = stat(console_file, &statbuf);
  if (rc >= 0) {
      if (diskutil_ch (console_file, nc->admin_user_id, nc->admin_user_id, 0) != OK) {
          logprintfl (EUCAERROR, "doGetConsoleOutput(): failed to change ownership of %s\n", console_file);
          return (1);
      }
    fd = open(console_file, O_RDONLY);
    if (fd >= 0) {
      console_append = malloc(4096);
      if (console_append) {
	bzero(console_append, 4096);
	rc = read(fd, console_append, (4096)-1);
	close(fd);          
      }
    }
  }
  
  sem_p (inst_sem); 
  snprintf(console_file, MAX_PATH, "%s/console.log", instance->instancePath);
  sem_v (inst_sem);

  // read the last 64K from console.log or the whole file, if smaller, into dynamically allocated 64K console_main buffer
  rc = stat(console_file, &statbuf);
  if (rc >= 0) {
      if (diskutil_ch (console_file, nc->admin_user_id, nc->admin_user_id, 0) != OK) {
          logprintfl (EUCAERROR, "doGetConsoleOutput(): failed to change ownership of %s\n", console_file);
          if (console_append) 
              free(console_append);
          return (1);
      }
    fd = open(console_file, O_RDONLY);
    if (fd >= 0) {
      rc = lseek(fd, (off_t)(-1 * readsize), SEEK_END);
      if (rc < 0) {
	rc = lseek(fd, (off_t)0, SEEK_SET);
	if (rc < 0) {
	  logprintfl(EUCAERROR, "cannot seek to beginning of file\n");
	  if (console_append) free(console_append);
	  close(fd);
	  return(1);
	}
      }
      console_main = malloc(readsize);
      if (console_main) {
	bzero(console_main, readsize);
	rc = read(fd, console_main, (readsize)-1);
	close(fd);
      }
    } else {
      logprintfl(EUCAERROR, "cannot open '%s' read-only\n", console_file);
    }
  } else {
    logprintfl(EUCAERROR, "cannot stat console_output file '%s'\n", console_file);
  }
  
  // concatenate console_append with console_main, base64-encode this, and put into dynamically allocated buffer consoleOutput
  ret = 1;
  console_output = malloc( (readsize) + 4096 );
  if (console_output) {
    bzero(console_output, (readsize) + 4096 );
    if (console_append) {
      strncat(console_output, console_append, 4096);
    }
    if (console_main) {
      strncat(console_output, console_main, readsize);
    }
    *consoleOutput = base64_enc((unsigned char *)console_output, strlen(console_output));
    ret = 0;
  }

  if (console_append) free(console_append);
  if (console_main) free(console_main);
  if (console_output) free(console_output);

  return(ret);
}
Esempio n. 15
0
static inline int get_pass(str *_username, str *_secret, str *_password)
{
	unsigned int hmac_len = SHA_DIGEST_LENGTH;
	unsigned char hmac_sha1[512];

	switch(autheph_sha_alg) {
		case AUTHEPH_SHA1:
			hmac_len = SHA_DIGEST_LENGTH;
			if (HMAC(EVP_sha1(), _secret->s, _secret->len,
					(unsigned char *) _username->s,
					_username->len, hmac_sha1, &hmac_len) == NULL)
			{
				LM_ERR("HMAC-SHA1 failed\n");
				return -1;
			}
			break;
		case AUTHEPH_SHA256:
			hmac_len = SHA256_DIGEST_LENGTH;
			if (HMAC(EVP_sha256(), _secret->s, _secret->len,
					(unsigned char *) _username->s,
					_username->len, hmac_sha1, &hmac_len) == NULL)
			{
				LM_ERR("HMAC-SHA256 failed\n");
				return -1;
			}
			break;
		case AUTHEPH_SHA384:
			hmac_len = SHA384_DIGEST_LENGTH;
			if (HMAC(EVP_sha256(), _secret->s, _secret->len,
					(unsigned char *) _username->s,
					_username->len, hmac_sha1, &hmac_len) == NULL)
			{
				LM_ERR("HMAC-SHA256 failed\n");
				return -1;
			}
			break;
		case AUTHEPH_SHA512:
			hmac_len = SHA512_DIGEST_LENGTH;
			if (HMAC(EVP_sha512(), _secret->s, _secret->len,
					(unsigned char *) _username->s,
					_username->len, hmac_sha1, &hmac_len) == NULL)
			{
				LM_ERR("HMAC-SHA512 failed\n");
				return -1;
			}
			break;
		default:
			LM_ERR("Inavlid SHA Algorithm\n");
			return -1;

	}

	LM_DBG("HMAC-Len (%i)\n", hmac_len);


	_password->len = base64_enc(hmac_sha1, hmac_len,
					(unsigned char *) _password->s,
					base64_enc_len(hmac_len));
	LM_DBG("calculated password: %.*s (%i)\n", _password->len, _password->s, _password->len);

	return 0;
}
Esempio n. 16
0
//!
//! Handles the get keys service request.
//!
//! @param[in]  service service name identifier
//! @param[out] outCCCert output CC Certificate
//! @param[out] outNCCert output NC certificate
//!
//! @return EUCA_OK on success or the following error codes:
//!         \li EUCA_MEMORY_ERROR: if we fail to allocate memory
//!         \li EUCA_INVALID_ERROR: if any parameter does not meet the preconditions
//!
//! @pre All parameters must be non-NULLs.
//!
//! @post On success, the outCCCert, outNCCert parameters are set appropriately.
//!
int doGetKeys(char *service, char **outCCCert, char **outNCCert)
{
    int fd = -1;
    int rc = 0;
    int bufsize = 0;
    int pid = 0;
    int filedes[2] = { 0 };
    int status = 0;
    char *tmp = NULL;
    char *buf = NULL;
    char *home = NULL;
    char *ccert = NULL;
    char *ncert = NULL;
    char file[MAX_PATH] = { 0 };
    axutil_env_t *env = NULL;
    axis2_char_t *client_home = NULL;
    axis2_stub_t *stub = NULL;

    if (!service || !outCCCert || !outNCCert) {
        printf("ERROR: Invalid params: service=%s, outCCCert=%p, outNCCert=%p\n", service, outCCCert, outNCCert);
        return (EUCA_INVALID_ERROR);
    }

    *outCCCert = *outNCCert = NULL;

    bufsize = 1000 * 1024;
    if ((buf = EUCA_ALLOC(bufsize, sizeof(char))) == NULL) {
        printf("ERROR: Out of memory!\n");
        return (EUCA_MEMORY_ERROR);
    }

    if (!strcmp(service, "self")) {
        home = NULL;
        if ((tmp = getenv("EUCALYPTUS")) != NULL)
            home = strdup(tmp);

        if (!home)
            home = strdup("");

        if (!home) {
            printf("ERROR: Out of memory!\n");
            EUCA_FREE(buf);
            return (EUCA_MEMORY_ERROR);
        }

        snprintf(file, MAX_PATH, EUCALYPTUS_KEYS_DIR "/cluster-cert.pem", home);
        if ((fd = open(file, O_RDONLY)) >= 0) {
            bzero(buf, bufsize);
            lseek(fd, -1 * bufsize, SEEK_END);
            if ((rc = read(fd, buf, bufsize)) > 0) {
                *outCCCert = base64_enc(((unsigned char *)buf), strlen(buf));
            }
            close(fd);
        }

        snprintf(file, MAX_PATH, EUCALYPTUS_KEYS_DIR "/node-cert.pem", home);
        if ((fd = open(file, O_RDONLY)) >= 0) {
            bzero(buf, bufsize);
            lseek(fd, -1 * bufsize, SEEK_END);
            // make sure that buf is NULL terminated
            if ((rc = read(fd, buf, bufsize - 1)) > 0) {
                *outNCCert = base64_enc(((unsigned char *)buf), strlen(buf));
            }
            close(fd);
        }

        EUCA_FREE(home);
    } else {
        if (pipe(filedes) == 0) {
            pid = fork();
            if (pid == 0) {
                close(filedes[0]);

                env = axutil_env_create_all(NULL, 0);
                if ((client_home = AXIS2_GETENV("AXIS2C_HOME")) == NULL) {
                    printf("ERROR: cannot retrieve AXIS2_HOME environment variable.\n");
                    exit(1);
                } else {
                    if ((stub = axis2_stub_create_EucalyptusGL(env, client_home, service)) == NULL) {
                        printf("ERROR: cannot retrieve AXIS2 stub.\n");
                        exit(1);
                    }

                    ccert = ncert = NULL;
                    if ((rc = gl_getKeys("self", &ccert, &ncert, env, stub)) == EUCA_OK) {
                        bzero(buf, bufsize);
                        if (ccert)
                            snprintf(buf, bufsize, "%s", ccert);
                        rc = write(filedes[1], buf, bufsize);

                        bzero(buf, bufsize);
                        if (ncert)
                            snprintf(buf, bufsize, "%s", ncert);
                        rc = write(filedes[1], buf, bufsize);
                    }
                }
                close(filedes[1]);
                exit(0);
            } else {
                close(filedes[1]);

                rc = read(filedes[0], buf, bufsize - 1);
                if (rc) {
                    *outCCCert = strdup(buf);
                }

                rc = read(filedes[0], buf, bufsize - 1);
                if (rc) {
                    *outNCCert = strdup(buf);
                }

                close(filedes[0]);
                wait(&status);
            }
        }
    }

    EUCA_FREE(buf);
    return (EUCA_OK);
}
Esempio n. 17
0
static int
doGetConsoleOutput(	struct nc_state_t *nc,
			ncMetadata *meta,
			char *instanceId,
			char **consoleOutput) {

  char *console_output=NULL, *console_append=NULL, *console_main=NULL;
  char console_file[MAX_PATH];
  int rc, fd, ret;
  struct stat statbuf;

  int bufsize, pid, status;

  *consoleOutput = NULL;

  snprintf(console_file, 1024, "%s/%s/%s/console.append.log", scGetInstancePath(), meta->userId, instanceId);
  rc = stat(console_file, &statbuf);
  if (rc >= 0) {
    fd = open(console_file, O_RDONLY);
    if (fd >= 0) {
      console_append = malloc(4096);
      if (console_append) {
	bzero(console_append, 4096);
	rc = read(fd, console_append, (4096)-1);
	close(fd);          
      }
    }
  }


  if (getuid() != 0) {
    console_main = strdup("NOT SUPPORTED");
    if (!console_main) {
      fprintf(stderr, "strdup failed (out of memory?)\n");
      if (console_append) free(console_append);
      return 1;
    }
  } else {

  bufsize = sizeof(char) * 1024 * 64;
  console_main = malloc(bufsize);
  if (!console_main) {
    logprintfl(EUCAERROR, "doGetConsoleOutput(): out of memory!\n");
    if (console_append) free(console_append);
    return(1);
  }
  bzero(console_main, bufsize);

  snprintf(console_file, MAX_PATH, "/tmp/consoleOutput.%s", instanceId);
  
  pid = fork();
  if (pid == 0) {
    int fd;
    fd = open(console_file, O_WRONLY | O_TRUNC | O_CREAT, 0644);
    if (fd < 0) {
      // error
    } else {
      dup2(fd, 2);
      dup2(2, 1);
      close(0);
      // TODO: test virsh console:
      // rc = execl(rootwrap_command_path, rootwrap_command_path, "virsh", "console", instanceId, NULL);
      rc = execl("/usr/sbin/xm", "/usr/sbin/xm", "console", instanceId, NULL);
      fprintf(stderr, "execl() failed\n");
      close(fd);
    }
    exit(0);
  } else {
    int count;
    fd_set rfds;
    struct timeval tv;
    struct stat statbuf;
    
    count=0;
    while(count < 10000 && stat(console_file, &statbuf) < 0) {count++;}
    fd = open(console_file, O_RDONLY);
    if (fd < 0) {
      logprintfl (EUCAERROR, "ERROR: could not open consoleOutput file %s for reading\n", console_file);
    } else {
      FD_ZERO(&rfds);
      FD_SET(fd, &rfds);
      tv.tv_sec = 0;
      tv.tv_usec = 500000;
      rc = select(1, &rfds, NULL, NULL, &tv);
      bzero(console_main, bufsize);
      
      count = 0;
      rc = 1;
      while(rc && count < 1000) {
	rc = read(fd, console_main, bufsize-1);
	count++;
      }
      close(fd);
    }
    kill(pid, 9);
    wait(&status);
  }
  
  unlink(console_file);
  }
  
  ret = 1;
  console_output = malloc( (64*1024) + 4096 );
  if (console_output) {
    bzero(console_output, (64*1024) + 4096 );
    if (console_append) {
      strncat(console_output, console_append, 4096);
    }
    if (console_main) {
      strncat(console_output, console_main, 1024*64);
    }
    *consoleOutput = base64_enc((unsigned char *)console_output, strlen(console_output));
    ret = 0;
  }

  if (console_append) free(console_append);
  if (console_main) free(console_main);
  if (console_output) free(console_output);

  return(ret);
}
Esempio n. 18
0
//!
//! downloads a decrypted image from Walrus based on the manifest URL,
//! saves it to outfile
//!
//! @param[in] walrus_op
//! @param[in] verb
//! @param[in] requested_url
//! @param[in] outfile
//! @param[in] do_compress
//! @param[in] connect_timeout
//! @param[in] total_timeout
//!
//! @return EUCA_OK on success or proper error code. Known error code returned include: EUCA_ERROR.
//!
static int walrus_request_timeout(const char *walrus_op, const char *verb, const char *requested_url, const char *outfile, const int do_compress,
                                  int connect_timeout, int total_timeout)
{
    int code = EUCA_ERROR;
    char url[BUFSIZE];

    pthread_mutex_lock(&wreq_mutex);    /* lock for curl construction */

    euca_strncpy(url, requested_url, BUFSIZE);
#if defined(CAN_GZIP)
    if (do_compress)
        snprintf(url, BUFSIZE, "%s%s", requested_url, "?IsCompressed=true");
#endif /* CAN_GZIP */

    /* isolate the PATH in the URL as it will be needed for signing */
    char *url_path;
    if (strncasecmp(url, "http://", 7) != 0 && strncasecmp(url, "https://", 8) != 0) {
        logprintfl(EUCAERROR, "Walrus URL must start with http(s)://...\n");
        pthread_mutex_unlock(&wreq_mutex);
        return code;
    }
    if ((url_path = strchr(url + 8, '/')) == NULL) {    /* find first '/' after hostname */
        logprintfl(EUCAERROR, "Walrus URL has no path\n");
        pthread_mutex_unlock(&wreq_mutex);
        return code;
    }

    if (euca_init_cert()) {
        logprintfl(EUCAERROR, "failed to initialize certificate for Walrus request\n");
        pthread_mutex_unlock(&wreq_mutex);
        return code;
    }

    int fd = open(outfile, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);  // we do not truncate the file
    if (fd == -1 || lseek(fd, 0, SEEK_SET) == -1) {
        logprintfl(EUCAERROR, "failed to open %s for writing Walrus request\n", outfile);
        pthread_mutex_unlock(&wreq_mutex);
        if (fd >= 0)
            close(fd);
        return code;
    }

    logprintfl(EUCADEBUG, "will use URL: %s\n", url);

    CURL *curl;
    CURLcode result;
    curl = curl_easy_init();
    if (curl == NULL) {
        logprintfl(EUCAERROR, "could not initialize libcurl for Walrus request\n");
        close(fd);
        pthread_mutex_unlock(&wreq_mutex);
        return code;
    }

    char error_msg[CURL_ERROR_SIZE];
    curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error_msg);
    curl_easy_setopt(curl, CURLOPT_URL, url);
    curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, write_header);
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); //! @todo make this optional?
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
    curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, 360L);  // must have at least a 360 baud modem
    curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, 10L);    // abort if below speed limit for this many seconds
    // curl_easy_setopt (curl, CURLOPT_FOLLOWLOCATION, 1); //! @todo remove the comment once we want to follow redirects (e.g., on HTTP 407)

    if (strncmp(verb, "GET", 4) == 0) {
        curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L);
    } else if (strncmp(verb, "HEAD", 5) == 0) {
        //! @todo HEAD isn't very useful atm since we don't look at headers
        curl_easy_setopt(curl, CURLOPT_NOBODY, 1L);
    } else {
        close(fd);
        logprintfl(EUCAERROR, "invalid HTTP verb %s in Walrus request\n", verb);
        pthread_mutex_unlock(&wreq_mutex);
        return EUCA_ERROR;      //! @todo dealloc structs before returning!
    }

    if (connect_timeout > 0) {
        curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, connect_timeout);
    }
    if (total_timeout > 0) {
        curl_easy_setopt(curl, CURLOPT_TIMEOUT, total_timeout);
    }

    /* set up the default write function, but possibly override
     * it below, if compression is desired and possible */
    struct request params;
    params.fd = fd;
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &params);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
#if defined(CAN_GZIP)
    if (do_compress) {
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data_zlib);
    }
#endif /* CAN_GZIP */

    struct curl_slist *headers = NULL;  /* beginning of a DLL with headers */
    headers = curl_slist_append(headers, "Authorization: Euca");

    char op_hdr[STRSIZE];
    if (walrus_op != NULL) {
        snprintf(op_hdr, STRSIZE, "EucaOperation: %s", walrus_op);
        headers = curl_slist_append(headers, op_hdr);
    }

    time_t t = time(NULL);
    char date_str[26];
    if (ctime_r(&t, date_str) == NULL) {
        close(fd);
        pthread_mutex_unlock(&wreq_mutex);
        return EUCA_ERROR;
    }
    assert(strlen(date_str) + 7 <= STRSIZE);
    char *newline = strchr(date_str, '\n');
    if (newline != NULL) {
        *newline = '\0';
    }                           // remove newline that terminates asctime() output
    char date_hdr[STRSIZE];
    snprintf(date_hdr, STRSIZE, "Date: %s", date_str);
    headers = curl_slist_append(headers, date_hdr);

    char *cert_str = euca_get_cert(0);  /* read the cloud-wide cert */
    if (cert_str == NULL) {
        close(fd);
        pthread_mutex_unlock(&wreq_mutex);
        return EUCA_ERROR;
    }
    char *cert64_str = base64_enc((unsigned char *)cert_str, strlen(cert_str));
    assert(strlen(cert64_str) + 11 <= BUFSIZE);
    char cert_hdr[BUFSIZE];
    snprintf(cert_hdr, BUFSIZE, "EucaCert: %s", cert64_str);
    logprintfl(EUCATRACE, "base64 certificate: %s\n", get_string_stats(cert64_str));
    headers = curl_slist_append(headers, cert_hdr);
    EUCA_FREE(cert64_str);
    EUCA_FREE(cert_str);

    char *sig_str = euca_sign_url(verb, date_str, url_path);    /* create Walrus-compliant sig */
    if (sig_str == NULL) {
        close(fd);
        pthread_mutex_unlock(&wreq_mutex);
        return EUCA_ERROR;
    }
    assert(strlen(sig_str) + 16 <= BUFSIZE);
    char sig_hdr[BUFSIZE];
    snprintf(sig_hdr, BUFSIZE, "EucaSignature: %s", sig_str);
    headers = curl_slist_append(headers, sig_hdr);

    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);    /* register headers */
    if (walrus_op) {
        logprintfl(EUCADEBUG, "writing %s/%s output\n", verb, walrus_op);
        logprintfl(EUCADEBUG, "        from %s\n", url);
        logprintfl(EUCADEBUG, "        to %s\n", outfile);
    } else {
        logprintfl(EUCADEBUG, "writing %s output to %s\n", verb, outfile);
    }
    int retries = TOTAL_RETRIES;
    int timeout = FIRST_TIMEOUT;
    do {
        params.total_wrote = 0L;
        params.total_calls = 0L;
#if defined(CAN_GZIP)
        if (do_compress) {
            /* allocate zlib inflate state */
            params.strm.zalloc = Z_NULL;
            params.strm.zfree = Z_NULL;
            params.strm.opaque = Z_NULL;
            params.strm.avail_in = 0;
            params.strm.next_in = Z_NULL;
            params.ret = inflateInit2(&(params.strm), 31);
            if (params.ret != Z_OK) {
                zerr(params.ret, "walrus_request");
                break;
            }
        }
#endif /* CAN_GZIP */

        //! @todo There used to be a 'pthread_mutex_unlock(&wreq_mutex)' before curl invocation
        //! and a 'lock' after it, but under heavy load we were seeing failures inside
        //! libcurl code that would propagate to NC, implying lack of thread safety in
        //! the library. For now, we will serialize all curl operations, but in the future
        //! an approach to parallelizing Walrus downloads is necessary
        result = curl_easy_perform(curl);   /* do it */
        logprintfl(EUCADEBUG, "wrote %lld byte(s) in %lld write(s)\n", params.total_wrote, params.total_calls);

#if defined(CAN_GZIP)
        if (do_compress) {
            inflateEnd(&(params.strm));
            if (params.ret != Z_STREAM_END) {
                zerr(params.ret, "walrus_request");
            }
        }
#endif /* CAN_GZIP */

        if (result) {           // curl error (connection or transfer failed)
            logprintfl(EUCAERROR, "curl error: %s (%d)\n", error_msg, result);

        } else {
            long httpcode;
            curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpcode);
            //! @todo pull out response message, too

            switch (httpcode) {
            case 200L:         /* all good */
                logprintfl(EUCAINFO, "downloaded %s\n", outfile);
                code = EUCA_OK;
                break;
            case 408L:         /* timeout, retry */
                logprintfl(EUCAWARN, "server responded with HTTP code %ld (timeout) for %s\n", httpcode, url);
                //logcat (EUCADEBUG, outfile); /* dump the error from outfile into the log */
                break;
            default:           /* some kind of error */
                logprintfl(EUCAERROR, "server responded with HTTP code %ld for %s\n", httpcode, url);
                //logcat (EUCADEBUG, outfile); /* dump the error from outfile into the log */
                retries = 0;
                break;
            }
        }

        if (code != EUCA_OK && retries > 0) {
            logprintfl(EUCAWARN, "download retry %d of %d will commence in %d sec for %s\n", retries, TOTAL_RETRIES, timeout, url);
            sleep(timeout);
            lseek(fd, 0L, SEEK_SET);
            timeout <<= 1;
            if (timeout > MAX_TIMEOUT)
                timeout = MAX_TIMEOUT;
        }

        retries--;
    } while (code != EUCA_OK && retries > 0);
    close(fd);

    if (code != EUCA_OK) {
        logprintfl(EUCAWARN, "removing %s\n", outfile);
        remove(outfile);
    }

    EUCA_FREE(sig_str);
    curl_slist_free_all(headers);
    curl_easy_cleanup(curl);
    pthread_mutex_unlock(&wreq_mutex);
    return code;
}
Esempio n. 19
0
int ws_handle_handshake(struct sip_msg *msg)
{
	str key = {0, 0}, headers = {0, 0}, reply_key = {0, 0}, origin = {0, 0};
	unsigned char sha1[SHA_DIGEST_LENGTH];
	unsigned int hdr_flags = 0, sub_protocol = 0;
	int version = 0;
	struct hdr_field *hdr = msg->headers;
	struct tcp_connection *con;
	ws_connection_t *wsc;

	/* Make sure that the connection is closed after the response _and_
	   the existing connection (from the request) is reused for the
	   response.  The close flag will be unset later if the handshake is
	   successful. */
	msg->rpl_send_flags.f |= SND_F_CON_CLOSE;
	msg->rpl_send_flags.f |= SND_F_FORCE_CON_REUSE;

	if (cfg_get(websocket, ws_cfg, enabled) == 0)
	{
		LM_INFO("disabled: bouncing handshake\n");
		ws_send_reply(msg, 503, &str_status_service_unavailable,
				NULL);
		return 0;
	}

	/* Retrieve TCP/TLS connection */
	if ((con = tcpconn_get(msg->rcv.proto_reserved1, 0, 0, 0, 0)) == NULL)
	{
		LM_ERR("retrieving connection\n");
		ws_send_reply(msg, 500, &str_status_internal_server_error,
				NULL);
		return 0;
	}

	if (con->type != PROTO_TCP && con->type != PROTO_TLS)
	{
		LM_ERR("unsupported transport: %d", con->type);
		goto end;
	}

	if (parse_headers(msg, HDR_EOH_F, 0) < 0)
	{
		LM_ERR("error parsing headers\n");
		ws_send_reply(msg, 500, &str_status_internal_server_error,
				NULL);
		goto end;
	}

	/* Process HTTP headers */
	while (hdr != NULL)
	{
		/* Decode and validate Connection */
		if (cmp_hdrname_strzn(&hdr->name,
				str_hdr_connection.s,
				str_hdr_connection.len) == 0)
		{
			strlower(&hdr->body);
			if (str_search(&hdr->body, &str_upgrade) != NULL)
			{
				LM_DBG("found %.*s: %.*s\n",

					hdr->name.len, hdr->name.s,
					hdr->body.len, hdr->body.s);
				hdr_flags |= CONNECTION;
			}
		}
		/* Decode and validate Upgrade */
		else if (cmp_hdrname_strzn(&hdr->name,
				str_hdr_upgrade.s,
				str_hdr_upgrade.len) == 0)
		{
			strlower(&hdr->body);
			if (str_search(&hdr->body, &str_websocket) != NULL)
			{
				LM_DBG("found %.*s: %.*s\n",
					hdr->name.len, hdr->name.s,
					hdr->body.len, hdr->body.s);
				hdr_flags |= UPGRADE;
			}
		}
		/* Decode and validate Sec-WebSocket-Key */
		else if (cmp_hdrname_strzn(&hdr->name,
				str_hdr_sec_websocket_key.s, 
				str_hdr_sec_websocket_key.len) == 0) 
		{
			if (hdr_flags & SEC_WEBSOCKET_KEY)
			{
				LM_WARN("%.*s found multiple times\n",
					hdr->name.len, hdr->name.s);
				ws_send_reply(msg, 400,
						&str_status_bad_request,
						NULL);
				goto end;
			}

			LM_DBG("found %.*s: %.*s\n",
				hdr->name.len, hdr->name.s,
				hdr->body.len, hdr->body.s);
			key = hdr->body;
			hdr_flags |= SEC_WEBSOCKET_KEY;
		}
		/* Decode and validate Sec-WebSocket-Protocol */
		else if (cmp_hdrname_strzn(&hdr->name,
				str_hdr_sec_websocket_protocol.s,
				str_hdr_sec_websocket_protocol.len) == 0)
		{
			strlower(&hdr->body);
			if (str_search(&hdr->body, &str_sip) != NULL)
			{
				LM_DBG("found %.*s: %.*s\n",
					hdr->name.len, hdr->name.s,
					hdr->body.len, hdr->body.s);
				hdr_flags |= SEC_WEBSOCKET_PROTOCOL;
				sub_protocol |= SUB_PROTOCOL_SIP;
			}
			if (str_search(&hdr->body, &str_msrp) != NULL)
			{
				LM_DBG("found %.*s: %.*s\n",
					hdr->name.len, hdr->name.s,
					hdr->body.len, hdr->body.s);
				hdr_flags |= SEC_WEBSOCKET_PROTOCOL;
				sub_protocol |= SUB_PROTOCOL_MSRP;
			}
		}
		/* Decode and validate Sec-WebSocket-Version */
		else if (cmp_hdrname_strzn(&hdr->name,
				str_hdr_sec_websocket_version.s,
				str_hdr_sec_websocket_version.len) == 0)
		{
			if (hdr_flags & SEC_WEBSOCKET_VERSION)
			{
				LM_WARN("%.*s found multiple times\n",
					hdr->name.len, hdr->name.s);
				ws_send_reply(msg, 400,
						&str_status_bad_request,
						NULL);
				goto end;
			}

			str2sint(&hdr->body, &version);

			if (version != WS_VERSION)
			{
				LM_WARN("Unsupported protocol version %.*s\n",
					hdr->body.len, hdr->body.s);
				headers.s = headers_buf;
				headers.len = snprintf(headers.s, HDR_BUF_LEN,
					"%.*s: %d\r\n",
					str_hdr_sec_websocket_version.len,
					str_hdr_sec_websocket_version.s,
					WS_VERSION);
				ws_send_reply(msg, 426,
						&str_status_upgrade_required,
						&headers);
				goto end;
			}

			LM_DBG("found %.*s: %.*s\n",
				hdr->name.len, hdr->name.s,
				hdr->body.len, hdr->body.s);
			hdr_flags |= SEC_WEBSOCKET_VERSION;
		}
		/* Decode Origin */
		else if (cmp_hdrname_strzn(&hdr->name,
				str_hdr_origin.s,
				str_hdr_origin.len) == 0)
		{
			if (hdr_flags & ORIGIN)
			{
				LM_WARN("%.*s found multiple times\n",
					hdr->name.len, hdr->name.s);
				ws_send_reply(msg, 400,
						&str_status_bad_request,
						NULL);
				goto end;
			}

			LM_DBG("found %.*s: %.*s\n",
				hdr->name.len, hdr->name.s,
				hdr->body.len, hdr->body.s);
			origin = hdr->body;
			hdr_flags |= ORIGIN;
		}

		hdr = hdr->next;
	}

	/* Final check that all required headers/values were found */
	sub_protocol &= ws_sub_protocols;
	if ((hdr_flags & REQUIRED_HEADERS) != REQUIRED_HEADERS
			|| sub_protocol == 0)
	{

		LM_WARN("required headers not present\n");
		headers.s = headers_buf;
		headers.len = 0;

		if (ws_sub_protocols & SUB_PROTOCOL_SIP)
			headers.len += snprintf(headers.s + headers.len,
						HDR_BUF_LEN - headers.len,
						"%.*s: %.*s\r\n",
					str_hdr_sec_websocket_protocol.len,
					str_hdr_sec_websocket_protocol.s,
					str_sip.len, str_sip.s);

		if (ws_sub_protocols & SUB_PROTOCOL_MSRP)
			headers.len += snprintf(headers.s + headers.len,
						HDR_BUF_LEN - headers.len,
						"%.*s: %.*s\r\n",
					str_hdr_sec_websocket_protocol.len,
					str_hdr_sec_websocket_protocol.s,
					str_msrp.len, str_msrp.s);

		headers.len += snprintf(headers.s + headers.len,
					HDR_BUF_LEN - headers.len,
					"%.*s: %d\r\n",
					str_hdr_sec_websocket_version.len,
					str_hdr_sec_websocket_version.s,
					WS_VERSION);
		ws_send_reply(msg, 400, &str_status_bad_request, &headers);
		goto end;
	}

	/* Construct reply_key */
	reply_key.s = (char *) pkg_malloc(
				(key.len + str_ws_guid.len) * sizeof(char)); 
	if (reply_key.s == NULL)
	{
		LM_ERR("allocating pkg memory\n");
		ws_send_reply(msg, 500, &str_status_internal_server_error,
				NULL);
		goto end;
	}
	memcpy(reply_key.s, key.s, key.len);
	memcpy(reply_key.s + key.len, str_ws_guid.s, str_ws_guid.len);
	reply_key.len = key.len + str_ws_guid.len;
	SHA1((const unsigned char *) reply_key.s, reply_key.len, sha1);
	pkg_free(reply_key.s);
	reply_key.s = key_buf;
	reply_key.len = base64_enc(sha1, SHA_DIGEST_LENGTH,
				(unsigned char *) reply_key.s,
				base64_enc_len(SHA_DIGEST_LENGTH));

	/* Add the connection to the WebSocket connection table */
	wsconn_add(msg->rcv, sub_protocol);

	/* Make sure Kamailio core sends future messages on this connection
	   directly to this module */
	if (con->type == PROTO_TLS)
		con->type = con->rcv.proto = PROTO_WSS;
	else
		con->type = con->rcv.proto = PROTO_WS;

	/* Now Kamailio is ready to receive WebSocket frames build and send a
	   101 reply */
	headers.s = headers_buf;
	headers.len = 0;

	if (ws_cors_mode == CORS_MODE_ANY)
		headers.len += snprintf(headers.s + headers.len,
					HDR_BUF_LEN - headers.len,
					"%.*s: *\r\n",
					str_hdr_access_control_allow_origin.len,
					str_hdr_access_control_allow_origin.s);
	else if (ws_cors_mode == CORS_MODE_ORIGIN && origin.len > 0)
		headers.len += snprintf(headers.s + headers.len,
					HDR_BUF_LEN - headers.len,
					"%.*s: %.*s\r\n",
					str_hdr_access_control_allow_origin.len,
					str_hdr_access_control_allow_origin.s,
					origin.len,
					origin.s);

	if (sub_protocol & SUB_PROTOCOL_SIP)
		headers.len += snprintf(headers.s + headers.len,
					HDR_BUF_LEN - headers.len,
					"%.*s: %.*s\r\n",
					str_hdr_sec_websocket_protocol.len,
					str_hdr_sec_websocket_protocol.s,
					str_sip.len, str_sip.s);
	else if (sub_protocol & SUB_PROTOCOL_MSRP)
		headers.len += snprintf(headers.s + headers.len,
					HDR_BUF_LEN - headers.len,
					"%.*s: %.*s\r\n",
					str_hdr_sec_websocket_protocol.len,
					str_hdr_sec_websocket_protocol.s,
					str_msrp.len, str_msrp.s);

	headers.len += snprintf(headers.s + headers.len,
				HDR_BUF_LEN - headers.len,
				"%.*s: %.*s\r\n"
				"%.*s: %.*s\r\n"
				"%.*s: %.*s\r\n",
				str_hdr_upgrade.len, str_hdr_upgrade.s,
				str_websocket.len, str_websocket.s,
				str_hdr_connection.len, str_hdr_connection.s,
				str_upgrade.len, str_upgrade.s,
				str_hdr_sec_websocket_accept.len,
				str_hdr_sec_websocket_accept.s, reply_key.len,
				reply_key.s);
	msg->rpl_send_flags.f &= ~SND_F_CON_CLOSE;
	if (ws_send_reply(msg, 101, &str_status_switching_protocols,
				&headers) < 0)
	{
		if ((wsc = wsconn_get(msg->rcv.proto_reserved1)) != NULL)
			wsconn_rm(wsc, WSCONN_EVENTROUTE_NO);

		goto end;
	}
	else
	{
		if (sub_protocol & SUB_PROTOCOL_SIP)
			update_stat(ws_sip_successful_handshakes, 1);
		else if (sub_protocol & SUB_PROTOCOL_MSRP)
			update_stat(ws_msrp_successful_handshakes, 1);
	}

	tcpconn_put(con);
	return 1;
end:
	if (con)
		tcpconn_put(con);
	return 0;
}
Esempio n. 20
0
/* downloads a decrypted image from Walrus based on the manifest URL,
 * saves it to outfile */
static int walrus_request (const char * walrus_op, const char * verb, const char * requested_url, const char * outfile, const int do_compress)
{
	int code = ERROR;
	char url [BUFSIZE];

    strncpy (url, requested_url, BUFSIZE);
#if defined(CAN_GZIP)
    if (do_compress)
        snprintf (url, BUFSIZE, "%s%s", requested_url, "?IsCompressed=true");
#endif
    logprintfl (EUCAINFO, "walrus_request(): downloading %s\n", outfile);
    logprintfl (EUCAINFO, "                  from %s\n", url);

	/* isolate the PATH in the URL as it will be needed for signing */
	char * url_path; 
	if (strncasecmp (url, "http://", 7)!=0) {
		logprintfl (EUCAERROR, "walrus_request(): URL must start with http://...\n");
		return code;
	}
	if ((url_path=strchr(url+7, '/'))==NULL) { /* find first '/' after hostname */
		logprintfl (EUCAERROR, "walrus_request(): URL has no path\n");
		return code;
	}
	
	if (euca_init_cert()) {
		logprintfl (EUCAERROR, "walrus_request(): failed to initialize certificate\n");
		return code;
	} 

	FILE * fp = fopen64 (outfile, "w");
	if (fp==NULL) {
		logprintfl (EUCAERROR, "walrus_request(): failed to open %s for writing\n", outfile);
		return code;
	}

	CURL * curl;
	CURLcode result;
	curl = curl_easy_init ();
	if (curl==NULL) {
		logprintfl (EUCAERROR, "walrus_request(): could not initialize libcurl\n");
		fclose(fp);
		return code;
	}

	char error_msg [CURL_ERROR_SIZE];
	curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, error_msg);
	curl_easy_setopt (curl, CURLOPT_URL, url); 
	curl_easy_setopt (curl, CURLOPT_HEADERFUNCTION, write_header);

    if (strncmp (verb, "GET", 4)==0) {
        curl_easy_setopt (curl, CURLOPT_HTTPGET, 1L);
    } else if (strncmp (verb, "HEAD", 5)==0) {
        /* TODO: HEAD isn't very useful atm since we don't look at headers */
        curl_easy_setopt (curl, CURLOPT_NOBODY, 1L);
    } else {
	fclose(fp);
        logprintfl (EUCAERROR, "walrus_request(): invalid HTTP verb %s\n", verb);
        return ERROR; /* TODO: dealloc structs before returning! */
    }
	
	/* set up the default write function, but possibly override
     * it below, if compression is desired and possible */
	struct request params;
    params.fp = fp;
    curl_easy_setopt (curl, CURLOPT_WRITEDATA, &params);
    curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, write_data);
#if defined(CAN_GZIP)
	if (do_compress) {
		curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, write_data_zlib);
	}
#endif

	struct curl_slist * headers = NULL; /* beginning of a DLL with headers */
	headers = curl_slist_append (headers, "Authorization: Euca");

	char op_hdr [STRSIZE];
	if(walrus_op != NULL) {
	    snprintf (op_hdr, STRSIZE, "EucaOperation: %s", walrus_op);
	    headers = curl_slist_append (headers, op_hdr);
	}

	time_t t = time(NULL);
	char * date_str = asctime(localtime(&t)); /* points to a static area */
	if (date_str==NULL) {
	       fclose(fp);
       	       return ERROR;
	}
	assert (strlen(date_str)+7<=STRSIZE);
	date_str [strlen(date_str)-1] = '\0'; /* trim off the newline */
	char date_hdr [STRSIZE];
	snprintf (date_hdr, STRSIZE, "Date: %s", date_str);
	headers = curl_slist_append (headers, date_hdr);

	char * cert_str = euca_get_cert (0); /* read the cloud-wide cert */
	if (cert_str==NULL) {
	       fclose(fp);
       	       return ERROR;
	}
	char * cert64_str = base64_enc ((unsigned char *)cert_str, strlen(cert_str));
	assert (strlen(cert64_str)+11<=BUFSIZE);
	char cert_hdr [BUFSIZE];
	snprintf (cert_hdr, BUFSIZE, "EucaCert: %s", cert64_str);
    logprintfl (EUCADEBUG2, "walrus_request(): base64 certificate, %s\n", get_string_stats(cert64_str));
	headers = curl_slist_append (headers, cert_hdr);
	free (cert64_str);
	free (cert_str);

	char * sig_str = euca_sign_url (verb, date_str, url_path); /* create Walrus-compliant sig */
	if (sig_str==NULL) {
	       fclose(fp);
       	       return ERROR;
	}
	assert (strlen(sig_str)+16<=BUFSIZE);
	char sig_hdr [BUFSIZE];
	snprintf (sig_hdr, BUFSIZE, "EucaSignature: %s", sig_str);
	headers = curl_slist_append (headers, sig_hdr);

	curl_easy_setopt (curl, CURLOPT_HTTPHEADER, headers); /* register headers */
    if (walrus_op) {
        logprintfl (EUCADEBUG, "walrus_request(): writing %s/%s output to %s\n", verb, walrus_op, outfile);
    } else {
        logprintfl (EUCADEBUG, "walrus_request(): writing %s output to %s\n", verb, outfile);
	}
    int retries = TOTAL_RETRIES;
    int timeout = FIRST_TIMEOUT;
    do {
        params.total_wrote = 0L;
        params.total_calls = 0L;
#if defined(CAN_GZIP)
        if (do_compress) {
            /* allocate zlib inflate state */
            params.strm.zalloc = Z_NULL;
            params.strm.zfree = Z_NULL;
            params.strm.opaque = Z_NULL;
            params.strm.avail_in = 0;
            params.strm.next_in = Z_NULL;
            params.ret = inflateInit2 (&(params.strm), 31);
            if (params.ret != Z_OK) {
                zerr (params.ret, "walrus_request");
                break;
            }
        }
#endif

        result = curl_easy_perform (curl); /* do it */
        logprintfl (EUCADEBUG, "walrus_request(): wrote %ld bytes in %ld writes\n", params.total_wrote, params.total_calls);

#if defined(CAN_GZIP)
        if (do_compress) {
            inflateEnd(&(params.strm));
            if (params.ret != Z_STREAM_END) {
                zerr (params.ret, "walrus_request");
            }
        }
#endif

        if (result) { // curl error (connection or transfer failed)
            logprintfl (EUCAERROR,     "walrus_request(): %s (%d)\n", error_msg, result);
            if (retries > 0) {
                logprintfl (EUCAERROR, "                  download retry %d of %d will commence in %d seconds\n", retries, TOTAL_RETRIES, timeout);
            }
            sleep (timeout);
            fseek (fp, 0L, SEEK_SET);
            timeout <<= 1;
            retries--;

        } else {
            long httpcode;
            curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &httpcode);
            /* TODO: pull out response message, too */

            switch (httpcode) {
            case 200L: /* all good */
                logprintfl (EUCAINFO, "walrus_request(): saved image in %s\n", outfile);
                code = OK;
		retries = 0;
                break;
	    case 408L: /* timeout, retry */
	      logprintfl (EUCAWARN, "walrus_request(): server responded with HTTP code %ld (timeout), retrying\n", httpcode);
	      logcat (EUCADEBUG, outfile); /* dump the error from outfile into the log */
	      break;
            default: /* some kind of error */
                logprintfl (EUCAERROR, "walrus_request(): server responded with HTTP code %ld, retrying\n", httpcode);
                logcat (EUCADEBUG, outfile); /* dump the error from outfile into the log */
            }
        }
    } while (code!=OK && retries>0);
    fclose (fp);

    if ( code != OK ) {
        logprintfl (EUCAINFO, "walrus_request(): due to error, removing %s\n", outfile);
        remove (outfile);
    }

	free (sig_str);
	curl_slist_free_all (headers);
	curl_easy_cleanup (curl);
	return code;
}
Esempio n. 21
0
static int
doGetConsoleOutput(	struct nc_state_t *nc,
			ncMetadata *meta,
			char *instanceId,
			char **consoleOutput) {

  char *console_output=NULL, *console_append=NULL, *console_main=NULL, *tmp=NULL;
  char console_file[MAX_PATH], dest_file[MAX_PATH], cmd[MAX_PATH];
  char userId[48];
  int rc, fd, ret;
  struct stat statbuf;
  ncInstance *instance=NULL;

  int bufsize, pid, status;

  *consoleOutput = NULL;

  // find the instance record
  sem_p (inst_sem); 
  instance = find_instance(&global_instances, instanceId);
  if (instance) {
    snprintf(userId, 48, "%s", instance->userId);
  	snprintf(console_file, 1024, "%s/console.append.log", instance->instancePath);
  }
  sem_v (inst_sem);
  if (!instance) {
    logprintfl(EUCAERROR, "[%s] cannot locate instance\n", instanceId);
    return(1);
  }
  rc = stat(console_file, &statbuf);
  if (rc >= 0) {
    fd = open(console_file, O_RDONLY);
    if (fd >= 0) {
      console_append = malloc(4096);
      if (console_append) {
	bzero(console_append, 4096);
	rc = read(fd, console_append, (4096)-1);
      }
      close(fd);
    }
  }


  bufsize = sizeof(char) * 1024 * 64;
  console_main = malloc(bufsize);
  if (!console_main) {
    logprintfl(EUCAERROR, "[%s] out of memory!\n", instanceId);
    if (console_append) free(console_append);
    return(1);
  }
  bzero(console_main, bufsize);

  if (getuid() != 0) {
    snprintf(console_file, MAX_PATH, "/var/log/xen/console/guest-%s.log", instanceId);
    snprintf(dest_file, MAX_PATH, "%s/console.log", instance->instancePath);
    snprintf(cmd, MAX_PATH, "%s cp %s %s", nc->rootwrap_cmd_path, console_file, dest_file);
    rc = system(cmd);
    if (!rc) {
      // was able to copy xen guest console file, read it
      snprintf(cmd, MAX_PATH, "%s chown %s:%s %s", nc->rootwrap_cmd_path, nc->admin_user_id, nc->admin_user_id, dest_file);
      rc = system(cmd);
      if (!rc) {
	tmp = file2str_seek(dest_file, bufsize, 1);
	if (tmp) {
	  snprintf(console_main, bufsize, "%s", tmp);
	  free(tmp);
	} else {
	  snprintf(console_main, bufsize, "NOT SUPPORTED");
	}
      } else {
	snprintf(console_main, bufsize, "NOT SUPPORTED");
      }
    } else {
      snprintf(console_main, bufsize, "NOT SUPPORTED");
    }
  } else {

    snprintf(console_file, MAX_PATH, "/tmp/consoleOutput.%s", instanceId);
    
    pid = fork();
    if (pid == 0) {
      int fd;
      fd = open(console_file, O_WRONLY | O_TRUNC | O_CREAT, 0644);
      if (fd < 0) {
	// error
      } else {
	dup2(fd, 2);
	dup2(2, 1);
	close(0);
	// TODO: test virsh console:
	// rc = execl(rootwrap_command_path, rootwrap_command_path, "virsh", "console", instanceId, NULL);
	rc = execl("/usr/sbin/xm", "/usr/sbin/xm", "console", instanceId, NULL);
	fprintf(stderr, "execl() failed\n");
	close(fd);
      }
      exit(0);
    } else {
      int count;
      fd_set rfds;
      struct timeval tv;
      struct stat statbuf;
      
      count=0;
      while(count < 10000 && stat(console_file, &statbuf) < 0) {count++;}
      fd = open(console_file, O_RDONLY);
      if (fd < 0) {
	logprintfl (EUCAERROR, "[%s] could not open consoleOutput file %s for reading\n", instanceId, console_file);
      } else {
	FD_ZERO(&rfds);
	FD_SET(fd, &rfds);
	tv.tv_sec = 0;
	tv.tv_usec = 500000;
	rc = select(1, &rfds, NULL, NULL, &tv);
	bzero(console_main, bufsize);
	
	count = 0;
	rc = 1;
	while(rc && count < 1000) {
	  rc = read(fd, console_main, bufsize-1);
	  count++;
	}
	close(fd);
      }
      kill(pid, 9);
      wait(&status);
    }
    
    unlink(console_file);
  }
  
  ret = 1;
  console_output = malloc( (64*1024) + 4096 );
  if (console_output) {
    bzero(console_output, (64*1024) + 4096 );
    if (console_append) {
      strncat(console_output, console_append, 4096);
    }
    if (console_main) {
      strncat(console_output, console_main, 1024*64);
    }
    *consoleOutput = base64_enc((unsigned char *)console_output, strlen(console_output));
    ret = 0;
  }
  
  if (console_append) free(console_append);
  if (console_main) free(console_main);
  if (console_output) free(console_output);
  
  return(ret);
}