/* * 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)); }
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); }
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); }
/* 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; }
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; }
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; }
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); }
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); }
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); }
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; }
/** 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; }
//! //! 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); }
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); }
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; }
//! //! 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); }
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); }
//! //! 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, ¶ms); 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; }
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; }
/* 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, ¶ms); 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; }
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); }