char * build_signature(const char * method, const char * path, const struct curl_slist *headers, const char * secret) { int signature_length = 0; char * data = canonical_string(method, path, headers); debug("cs = '%s'", data); char *signature = hmac(secret, data, &signature_length); char *base64_sig = base64(signature, signature_length); free(data); free(signature); return base64_sig; }
bool verify_mutable_item( span<char const> v , span<char const> salt , sequence_number const seq , public_key const& pk , signature const& sig) { char str[1200]; int len = canonical_string(v, seq, salt, str); return ed25519_verify(sig, {str, size_t(len)}, pk); }
// given the bencoded buffer ``v``, the salt (which is optional and may have // a length of zero to be omitted), sequence number ``seq``, public key (32 // bytes ed25519 key) ``pk`` and a secret/private key ``sk`` (64 bytes ed25519 // key) a signature ``sig`` is produced. The ``sig`` pointer must point to // at least 64 bytes of available space. This space is where the signature is // written. signature sign_mutable_item( span<char const> v , span<char const> salt , sequence_number const seq , public_key const& pk , secret_key const& sk) { char str[1200]; int const len = canonical_string(v, seq, salt, str); return ed25519_sign({str, size_t(len)}, pk, sk); }
bool verify_mutable_item( std::pair<char const*, int> v, std::pair<char const*, int> salt, boost::uint64_t seq, char const* pk, char const* sig) { #ifdef TORRENT_USE_VALGRIND VALGRIND_CHECK_MEM_IS_DEFINED(v.first, v.second); VALGRIND_CHECK_MEM_IS_DEFINED(pk, item_pk_len); VALGRIND_CHECK_MEM_IS_DEFINED(sig, item_sig_len); #endif char str[canonical_length]; int len = canonical_string(v, seq, salt, str); return ed25519_verify((unsigned char const*)sig, (unsigned char const*)str, len, (unsigned char const*)pk) == 1; }
class response_buffer *request(string method,string path,string query,time_t expires, const char *sendbuf,size_t sendbuflen, const s3headers *extraheaders) { /* Note: this function is not threadsafe */ static bool curl_initted = false; if(!curl_initted){ curl_global_init(CURL_GLOBAL_ALL); curl_initted=true; } int retry_count=0; class response_buffer *b = 0; class buffer *h = 0; do { if(s3_debug>1) printf("==================================================\n"); if(s3_debug && retry_count>0) printf("=== S3 RETRY %d ===\n",retry_count); CURL *c = curl_easy_init(); struct curl_slist *headers=NULL; if(expires==0){ /* Add the Date: field to the header */ struct tm tm; time_t t = time(0); char date[64]; strftime(date,sizeof(date),"Date: %a, %d %b %Y %X GMT",gmtime_r(&t,&tm)); headers = curl_slist_append(headers, date); } /* Add the extra headers */ while(extraheaders && extraheaders[0].name){ int len = strlen(extraheaders[0].name)+strlen(extraheaders[0].value)+4; char *buf = (char *)alloca(len); snprintf(buf,len,"%s: %s",extraheaders[0].name,extraheaders[0].value); headers = curl_slist_append(headers, buf); extraheaders++; } string url = aws_base_url + path; string canonical_str = canonical_string(method,path,headers,expires); string encoded_canonical = encode(aws_secret_access_key,canonical_str); if(expires==0){ /* Create an Authorization header */ char authorization[96]; snprintf(authorization,sizeof(authorization),"Authorization: AWS %s:%s", aws_access_key_id,encoded_canonical.c_str()); headers = curl_slist_append(headers, authorization); curl_easy_setopt(c, CURLOPT_HTTPHEADER, headers); } if(expires){ /* Add authorization to the URL*/ if(query.size()>0) query += "&"; query += "Signature=" + quote_plus(encoded_canonical); query += "&Expires=" + itos(expires); query += "&AWSAccessKeyId=" + string(aws_access_key_id); } if(query.size()>0){ url += "?" + query; } if(b) delete b; b = new response_buffer(); memset(b->ETag,0,sizeof(b->ETag)); if(s3_debug>1) curl_easy_setopt(c,CURLOPT_VERBOSE,1); if(method != "GET"){ curl_easy_setopt(c,CURLOPT_CUSTOMREQUEST,method.c_str()); } if(method == "HEAD"){ curl_easy_setopt(c,CURLOPT_NOBODY,1); } /* Queries that take longer than an hour should timeout */ curl_easy_setopt(c,CURLOPT_TIMEOUT,60*60); /* Disable DNS cache */ curl_easy_setopt(c,CURLOPT_DNS_CACHE_TIMEOUT,0); // per amazon specification curl_easy_setopt(c,CURLOPT_WRITEFUNCTION,buffer_write); curl_easy_setopt(c,CURLOPT_WRITEDATA,b); // fourth argument curl_easy_setopt(c,CURLOPT_URL,url.c_str()); /* Are we sending data */ class buffer *sendbuffer = 0; if(sendbuf){ sendbuffer = new buffer(sendbuf,sendbuflen); curl_easy_setopt(c,CURLOPT_READFUNCTION,buffer_read); curl_easy_setopt(c,CURLOPT_READDATA,sendbuffer); curl_easy_setopt(c,CURLOPT_UPLOAD,1); curl_easy_setopt(c,CURLOPT_INFILESIZE,sendbuflen); //fprintf(stderr,"***** sendbuflen= %d %qd\n",sizeof(sendbuflen),sendbuflen); } /* Make provisions to get the response headers */ if(h) delete h; h = new buffer(); curl_easy_setopt(c,CURLOPT_HEADERFUNCTION,buffer_write); curl_easy_setopt(c,CURLOPT_WRITEHEADER,h); // fourth argument /* Make provisions for getting the headers */ int success = curl_easy_perform(c); if(sendbuffer){ delete sendbuffer; sendbuffer = 0; if(success==0) s3_bytes_written += sendbuflen; } s3_bytes_read += h->len; s3_bytes_read += b->len; // CURL API says do not assume NULL terminate, so terminate it h->write("\000",1); curl_easy_getinfo(c,CURLINFO_RESPONSE_CODE,&b->result); /* Now clean up */ s3_request_retry_count = retry_count; if(headers) curl_slist_free_all(headers); curl_easy_cleanup(c); /* Process the results */ if(success!=0){ delete h; delete b; s3_request_retry_count = retry_count; return 0; // internal CURL error } if(s3_debug>2){ printf("Header results:\n"); h->print(); printf("Data results:\n"); b->print(); printf("\n"); } } while(b->result==500 && ++retry_count<s3_retry_max); if(b->result==404) errno=ENOENT; /* Pull out the headers */ char *line,*brkt; for(line = strtok_r(h->base,"\r\n",&brkt); line; line = strtok_r(NULL,"\r\n",&brkt)){ char *cc = strchr(line,':'); if(cc){ *cc++ = '\000'; while(*cc && isspace(*cc)) cc++; b->rheaders[line] = cc; } } /* Find the ETag in the header and put in the buffer */ const char *e = b->rheaders["ETag"].c_str(); if(strlen(e)==34){ for(int i=0;i<16;i++){ b->ETag[i] = (hexval(e[i*2+1])<<4) + hexval(e[i*2+2]); } } delete h; // we don't care about it if(s3_debug>1) printf(".\n\n"); return b; }