Ejemplo n.º 1
0
static int psync_p2p_get_download_token(psync_fileid_t fileid, const unsigned char *filehashhex, uint64_t fsize, unsigned char **token, size_t *tlen){
  binparam params[]={P_STR("auth", psync_my_auth), P_NUM("fileid", fileid), P_NUM("filesize", fsize),
                     P_LSTR(PSYNC_CHECKSUM, filehashhex, PSYNC_HASH_DIGEST_HEXLEN),
                     P_LSTR("keydata", psync_rsa_public_bin->data, psync_rsa_public_bin->datalen)};
  psync_socket *api;
  binresult *res;
  const binresult *ctoken;
  *token=NULL; /* especially for gcc */
  *tlen=0;
  api=psync_apipool_get();
  if (unlikely_log(!api))
    return PSYNC_NET_TEMPFAIL;
  res=send_command(api, "getfileownershiptoken", params);
  if (unlikely_log(!res)){
    psync_apipool_release_bad(api);
    return PSYNC_NET_TEMPFAIL;
  }
  psync_apipool_release(api);
  if (unlikely_log(psync_find_result(res, "result", PARAM_NUM)->num!=0)){
    psync_free(res);
    return PSYNC_NET_PERMFAIL;
  }
  ctoken=psync_find_result(res, "token", PARAM_STR);
  *token=psync_malloc(ctoken->length+1);
  memcpy(*token, ctoken->str, ctoken->length+1);
  *tlen=ctoken->length;
  psync_free(res);
  return PSYNC_NET_OK;
}
Ejemplo n.º 2
0
static void psync_notifications_download_thumb(const binresult *thumb, const char *thumbpath){
  const char *path, *filename, *host;
  char *filepath, *tmpfilepath, *buff;
  char cookie[128];
  psync_http_socket *sock;
  psync_stat_t st;
  psync_file_t fd;
  int rd;
  rd=-1;
  path=psync_find_result(thumb, "path", PARAM_STR)->str;
  filename=strrchr(path, '/');
  if (unlikely_log(!filename++))
    return;
  filepath=psync_strcat(thumbpath, PSYNC_DIRECTORY_SEPARATOR, filename, NULL);
  if (!psync_stat(filepath, &st)){
    debug(D_NOTICE, "skipping download of %s as it already exists", filename);
    goto err0;
  }
  tmpfilepath=psync_strcat(filepath, ".part", NULL);
  debug(D_NOTICE, "downloading thumbnail %s", filename);
  if (unlikely_log((fd=psync_file_open(tmpfilepath, P_O_WRONLY, P_O_CREAT|P_O_TRUNC))==INVALID_HANDLE_VALUE))
    goto err1;
  sock=psync_http_connect_multihost(psync_find_result(thumb, "hosts", PARAM_ARRAY), &host);
  if (unlikely_log(!sock))
    goto err2;
  psync_slprintf(cookie, sizeof(cookie), "Cookie: dwltag=%s\015\012", psync_find_result(thumb, "dwltag", PARAM_STR)->str);
  if (unlikely_log(psync_http_request(sock, host, path, 0, 0, cookie)))
    goto err3;
  if (unlikely_log(psync_http_next_request(sock)))
    goto err3;
  buff=(char *)psync_malloc(PSYNC_COPY_BUFFER_SIZE);
  while (1){
    rd=psync_http_request_readall(sock, buff, PSYNC_COPY_BUFFER_SIZE);
    if (rd<=0)
      break;
    if (psync_file_write(fd, buff, rd)!=rd)
      break;
  }
  psync_free(buff);
err3:
  psync_http_close(sock);
err2:
  psync_file_close(fd);
err1:
  if (rd==0 && !psync_file_rename_overwrite(tmpfilepath, filepath))
    debug(D_NOTICE, "downloaded thumbnail %s", filename);
  else
    debug(D_WARNING, "downloading of thumbnail %s failed", filename);
  psync_free(tmpfilepath);
err0:
  psync_free(filepath);
}
Ejemplo n.º 3
0
static int check_token(char *token, uint32_t tlen, unsigned char *key, uint32_t keylen, unsigned char *hashhex){
  binparam params[]={P_LSTR(PSYNC_CHECKSUM, hashhex, PSYNC_HASH_DIGEST_HEXLEN),
                     P_LSTR("keydata", key, keylen), P_LSTR("token", token, tlen)};
  psync_socket *api;
  binresult *res;
  uint64_t result;
  api=psync_apipool_get();
  if (unlikely_log(!api))
    return 0;
  res=send_command(api, "checkfileownershiptoken", params);
  if (unlikely_log(!res)){
    psync_apipool_release_bad(api);
    return 0;
  }
  psync_apipool_release(api);
  result=psync_find_result(res, "result", PARAM_NUM)->num;
  psync_free(res);
  return result?0:1;
}
Ejemplo n.º 4
0
void psync_send_event_by_id(psync_eventtype_t eventid, psync_syncid_t syncid, const char *localpath, psync_fileorfolderid_t remoteid){
  if (eventthreadrunning){
    char *remotepath;
    if (eventid&PEVENT_TYPE_FOLDER)
      remotepath=psync_get_path_by_folderid(remoteid, NULL);
    else
      remotepath=psync_get_path_by_fileid(remoteid, NULL);
    if (unlikely_log(!remotepath))
      return;
    psync_send_event_by_path(eventid, syncid, localpath, remoteid, remotepath);
    psync_free(remotepath);
  }
}
Ejemplo n.º 5
0
static void psync_p2p_wake(){
  psync_socket_t sock;
  struct sockaddr_in addr;
  packet_type_t pack;
  sock=psync_create_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  if (unlikely_log(sock==INVALID_SOCKET))
    return;
  memset(&addr, 0, sizeof(addr));
  addr.sin_family=AF_INET;
  addr.sin_port=htons(PSYNC_P2P_PORT);
  addr.sin_addr.s_addr=htonl(0x7f000001UL);
  pack=P2P_WAKE;
  if (connect(sock, (struct sockaddr *)&addr, sizeof(addr))!=SOCKET_ERROR)
    assertw(psync_write_socket(sock, &pack, sizeof(pack))==sizeof(pack));
  psync_close_socket(sock);
}
Ejemplo n.º 6
0
static void psync_sync_newsyncedfolder(psync_syncid_t syncid){
  psync_sql_res *res;
  psync_uint_row row;
  uint64_t folderid;
  psync_synctype_t synctype;
  psync_sql_start_transaction();
  res=psync_sql_query("SELECT folderid, synctype FROM syncfolder WHERE id=? AND flags=0");
  psync_sql_bind_uint(res, 1, syncid);
  row=psync_sql_fetch_rowint(res);
  if (unlikely_log(!row)){
    psync_sql_free_result(res);
    psync_sql_rollback_transaction();
    return;
  }
  folderid=row[0];
  synctype=row[1];
  psync_sql_free_result(res);
  if (synctype&PSYNC_DOWNLOAD_ONLY){
    psync_add_folder_for_downloadsync(syncid, synctype, folderid, 0);
  }
  else {
    res=psync_sql_prep_statement("REPLACE INTO syncedfolder (syncid, folderid, localfolderid, synctype) VALUES (?, ?, 0, ?)");
    psync_sql_bind_uint(res, 1, syncid);
    psync_sql_bind_uint(res, 2, folderid);
    psync_sql_bind_uint(res, 3, synctype);
    psync_sql_run_free(res);
  }
  res=psync_sql_prep_statement("UPDATE syncfolder SET flags=1 WHERE flags=0 AND id=?");
  psync_sql_bind_uint(res, 1, syncid);
  psync_sql_run_free(res);
  if (likely_log(psync_sql_affected_rows())){
    if (!psync_sql_commit_transaction()){
      if (synctype&PSYNC_UPLOAD_ONLY)
        psync_wake_localscan();
      if (synctype&PSYNC_DOWNLOAD_ONLY){
        psync_status_recalc_to_download();
        psync_send_status_update();
        psync_wake_download();
      }
      psync_localnotify_add_sync(syncid);
    }
  }
  else
    psync_sql_rollback_transaction();
}
Ejemplo n.º 7
0
static int psync_p2p_check_rsa(){
  static pthread_mutex_t rsa_lock=PTHREAD_MUTEX_INITIALIZER;
  pthread_mutex_lock(&rsa_lock);
  if (psync_rsa_private==PSYNC_INVALID_RSA){
    psync_rsa_t rsa;
    psync_rsa_privatekey_t rsapriv;
    psync_rsa_publickey_t rsapub;
    psync_binary_rsa_key_t rsapubbin;
    debug(D_NOTICE, "generating %ubit RSA key", PSYNC_P2P_RSA_SIZE);
    rsa=psync_ssl_gen_rsa(PSYNC_P2P_RSA_SIZE);
    debug(D_NOTICE, "key generated");
    if (unlikely_log(rsa==PSYNC_INVALID_RSA))
      goto rete;
    rsapriv=psync_ssl_rsa_get_private(rsa);
    rsapub=psync_ssl_rsa_get_public(rsa);
    if (likely_log(rsapub!=PSYNC_INVALID_RSA))
      rsapubbin=psync_ssl_rsa_public_to_binary(rsapub);
    else
      rsapubbin=PSYNC_INVALID_BIN_RSA;
    psync_ssl_free_rsa(rsa);
    if (likely_log(rsapriv!=PSYNC_INVALID_RSA && rsapub!=PSYNC_INVALID_RSA && rsapubbin!=PSYNC_INVALID_BIN_RSA)){
      psync_rsa_private=rsapriv;
      psync_rsa_public=rsapub;
      psync_rsa_public_bin=rsapubbin;
      goto ret0;
    }
    else{
      if (rsapriv!=PSYNC_INVALID_RSA)
        psync_ssl_rsa_free_private(rsapriv);
      if (rsapub!=PSYNC_INVALID_RSA)
        psync_ssl_rsa_free_public(rsapub);
      if (rsapubbin!=PSYNC_INVALID_BIN_RSA)
        psync_ssl_rsa_free_binary(rsapubbin);
      goto rete;
    }
  }
ret0:
  pthread_mutex_unlock(&rsa_lock);
  return 0;
rete:
  pthread_mutex_unlock(&rsa_lock);
  return -1;
}
Ejemplo n.º 8
0
int psync_p2p_check_download(psync_fileid_t fileid, const unsigned char *filehashhex, uint64_t fsize, const char *filename){
  struct sockaddr_in6 addr;
  fd_set rfds;
  packet_check pct1;
  packet_get pct2;
  packet_check_resp resp;
  struct timeval tv;
  psync_interface_list_t *il;
  psync_socket_t *sockets;
  size_t i, tlen;
  psync_socket_t sock, msock;
  packet_resp_t bresp;
  unsigned char hashsource[PSYNC_HASH_BLOCK_SIZE], hashbin[PSYNC_HASH_DIGEST_LEN], hashhex[PSYNC_HASH_DIGEST_HEXLEN];
  unsigned char *token;
  socklen_t slen;
  int sret;
  if (!psync_setting_get_bool(_PS(p2psync)))
    return PSYNC_NET_PERMFAIL;
  debug(D_NOTICE, "sending P2P_CHECK for file with hash %."NTO_STR(PSYNC_HASH_DIGEST_HEXLEN)"s", filehashhex);
  pct1.type=P2P_CHECK;
  memcpy(pct1.hashstart, filehashhex, PSYNC_P2P_HEXHASH_BYTES);
  pct1.filesize=fsize;
  psync_ssl_rand_weak(pct1.rand, sizeof(pct1.rand));
  memcpy(hashsource, filehashhex, PSYNC_HASH_DIGEST_HEXLEN);
  memcpy(hashsource+PSYNC_HASH_DIGEST_HEXLEN, pct1.rand, sizeof(pct1.rand));
  psync_hash(hashsource, PSYNC_HASH_BLOCK_SIZE, hashbin);
  psync_binhex(pct1.genhash, hashbin, PSYNC_HASH_DIGEST_LEN);
  memcpy(pct1.computername, computername, PSYNC_HASH_DIGEST_HEXLEN);
  il=psync_list_ip_adapters();
  sockets=psync_new_cnt(psync_socket_t, il->interfacecnt);
  FD_ZERO(&rfds);
  msock=0;
  for (i=0; i<il->interfacecnt; i++){
    sockets[i]=INVALID_SOCKET;
    sock=psync_create_socket(il->interfaces[i].address.ss_family, SOCK_DGRAM, IPPROTO_UDP);
    if (unlikely(sock==INVALID_SOCKET)){
      debug(D_NOTICE, "could not create a socket for address family %u", (unsigned)il->interfaces[i].address.ss_family);
      continue;
    }
    setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on));
    setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (const char *)&on, sizeof(on));
    if (unlikely_log(bind(sock, (struct sockaddr *)&il->interfaces[i].address, il->interfaces[i].addrsize)==SOCKET_ERROR)){
      psync_close_socket(sock);
      continue;
    }
    if (il->interfaces[i].broadcast.ss_family==AF_INET)
      ((struct sockaddr_in *)(&il->interfaces[i].broadcast))->sin_port=htons(PSYNC_P2P_PORT);
    else if (il->interfaces[i].broadcast.ss_family==AF_INET6)
      ((struct sockaddr_in6 *)(&il->interfaces[i].broadcast))->sin6_port=htons(PSYNC_P2P_PORT);
    if (sendto(sock, (const char *)&pct1, sizeof(pct1), 0, (struct sockaddr *)&il->interfaces[i].broadcast, il->interfaces[i].addrsize)!=SOCKET_ERROR){
      sockets[i]=sock;
      FD_SET(sock, &rfds);
      if (sock>=msock)
        msock=sock+1;
    }
    else
      psync_close_socket(sock);
  }
  if (unlikely_log(!msock))
    goto err_perm;
  tv.tv_sec=PSYNC_P2P_INITIAL_TIMEOUT/1000;
  tv.tv_usec=(PSYNC_P2P_INITIAL_TIMEOUT%1000)*1000;
  sret=select(msock, &rfds, NULL, NULL, &tv);
  if (sret==0 || unlikely_log(sret==SOCKET_ERROR))
    goto err_perm;
  bresp=P2P_RESP_NOPE;
  for (i=0; i<il->interfacecnt; i++)
    if (sockets[i]!=INVALID_SOCKET && FD_ISSET(sockets[i], &rfds)){
      slen=sizeof(addr);
      sret=recvfrom(sockets[i], (char *)&resp, sizeof(resp), 0, (struct sockaddr *)&addr, &slen);
      if (unlikely_log(sret==SOCKET_ERROR) || unlikely_log(sret<sizeof(resp)))
        continue;
      if (!memcmp(pct1.rand, resp.rand, sizeof(resp.rand))){
        debug(D_WARNING, "clients are supposed to generate random data, not to reuse mine");
        continue;
      }
      memcpy(hashsource, filehashhex, PSYNC_HASH_DIGEST_HEXLEN);
      memcpy(hashsource+PSYNC_HASH_DIGEST_HEXLEN, resp.rand, sizeof(resp.rand));
      psync_hash(hashsource, PSYNC_HASH_BLOCK_SIZE, hashbin);
      psync_binhex(hashhex, hashbin, PSYNC_HASH_DIGEST_LEN);
      if (unlikely_log(memcmp(hashhex, resp.genhash, PSYNC_HASH_DIGEST_HEXLEN)))
        continue;
      if (resp.type==P2P_RESP_HAVEIT){
        debug(D_NOTICE, "got P2P_RESP_HAVEIT");
        bresp=P2P_RESP_HAVEIT;
        break;
      }
      else if (resp.type==P2P_RESP_WAIT && bresp==P2P_RESP_NOPE)
        bresp=P2P_RESP_WAIT;
    }
  for (i=0; i<il->interfacecnt; i++)
    if (sockets[i]!=INVALID_SOCKET)
      psync_close_socket(sockets[i]);
  psync_free(il);
  psync_free(sockets);
  if (bresp==P2P_RESP_NOPE)
    goto err_perm2;
  else if (bresp==P2P_RESP_WAIT){
    psync_milisleep(PSYNC_P2P_SLEEP_WAIT_DOWNLOAD);
    goto err_temp2;
  }
  if (psync_p2p_check_rsa())
    goto err_perm2;
  sret=psync_p2p_get_download_token(fileid, filehashhex, fsize, &token, &tlen);
  debug(D_NOTICE, "got token");
  if (unlikely_log(sret!=PSYNC_NET_OK)){
    if (sret==PSYNC_NET_TEMPFAIL)
      goto err_temp2;
    else
      goto err_perm2;
  }
  if (addr.sin6_family==AF_INET6){
    sock=psync_create_socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
    addr.sin6_port=htons(resp.port);
  }
  else if (addr.sin6_family==AF_INET){
    sock=psync_create_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    ((struct sockaddr_in *)&addr)->sin_port=htons(resp.port);
  }
  else{
    debug(D_ERROR, "unknown address family %u", (unsigned)addr.sin6_family);
    goto err_perm2;
  }
  if (unlikely_log(sock==INVALID_SOCKET))
    goto err_perm3;
  if (unlikely(connect(sock, (struct sockaddr *)&addr, slen)==SOCKET_ERROR)){
    debug(D_WARNING, "could not connect to %s port %u", p2p_get_address(&addr), (unsigned)resp.port);
    goto err_perm3;
  }
  debug(D_NOTICE, "connected to peer");
  pct2.type=P2P_GET;
  memcpy(pct2.hashstart, filehashhex, PSYNC_P2P_HEXHASH_BYTES);
  pct2.filesize=fsize;
  pct2.keylen=psync_rsa_public_bin->datalen;
  pct2.tokenlen=tlen;
  memcpy(pct2.rand, pct1.rand, sizeof(pct1.rand));
  memcpy(pct2.genhash, pct1.genhash, sizeof(pct1.genhash));
  memcpy(pct2.computername, computername, PSYNC_HASH_DIGEST_HEXLEN);
  if (socket_write_all(sock, &pct2, sizeof(pct2)) ||
      socket_write_all(sock, psync_rsa_public_bin->data, psync_rsa_public_bin->datalen) ||
      socket_write_all(sock, token, tlen)){
    debug(D_WARNING, "writing to socket failed");
    goto err_temp3;
  }
  psync_free(token);
  sret=psync_p2p_download(sock, fileid, filehashhex, fsize, filename);
  psync_close_socket(sock);
  return sret;
err_perm3:
  psync_free(token);
  goto err_perm2;
err_perm:
  for (i=0; i<il->interfacecnt; i++)
    if (sockets[i]!=INVALID_SOCKET)
      psync_close_socket(sockets[i]);
  psync_free(il);
  psync_free(sockets);
err_perm2:
  return PSYNC_NET_PERMFAIL;
err_temp3:
  psync_close_socket(sock);
  psync_free(token);
err_temp2:
  return PSYNC_NET_TEMPFAIL;
}
Ejemplo n.º 9
0
static int psync_p2p_download(psync_socket_t sock, psync_fileid_t fileid, const unsigned char *filehashhex, uint64_t fsize, const char *filename){
  uint32_t keylen, enctype;
  psync_symmetric_key_t key;
  psync_encrypted_symmetric_key_t ekey;
  psync_crypto_aes256_ctr_encoder_decoder_t decoder;
  psync_hash_ctx hashctx;
  uint64_t off;
  size_t rd;
  psync_file_t fd;
  unsigned char buff[4096];
  unsigned char hashbin[PSYNC_HASH_DIGEST_LEN], hashhex[PSYNC_HASH_DIGEST_HEXLEN];
  if (unlikely_log(socket_read_all(sock, &keylen, sizeof(keylen)) || socket_read_all(sock, &enctype, sizeof(enctype))))
    return PSYNC_NET_TEMPFAIL;
  if (enctype!=P2P_ENCTYPE_RSA_AES){
    debug(D_ERROR, "unknown encryption type %u", (unsigned)enctype);
    return PSYNC_NET_PERMFAIL;
  }
  if (keylen>PSYNC_P2P_RSA_SIZE/8*2){ /* PSYNC_P2P_RSA_SIZE/8 is enough actually */
    debug(D_ERROR, "too long key - %u bytes", (unsigned)keylen);
    return PSYNC_NET_PERMFAIL;
  }
  ekey=psync_ssl_alloc_encrypted_symmetric_key(keylen);
  if (unlikely_log(socket_read_all(sock, ekey->data, keylen)) ||
      unlikely_log((key=psync_ssl_rsa_decrypt_symmetric_key(psync_rsa_private, ekey))==PSYNC_INVALID_SYM_KEY)){
    psync_free(ekey);
    return PSYNC_NET_TEMPFAIL;
  }
  psync_free(ekey);
  decoder=psync_crypto_aes256_ctr_encoder_decoder_create(key);
  psync_ssl_free_symmetric_key(key);
  if (decoder==PSYNC_CRYPTO_INVALID_ENCODER)
    return PSYNC_NET_PERMFAIL;
  fd=psync_file_open(filename, P_O_WRONLY, P_O_CREAT|P_O_TRUNC);
  if (unlikely(fd==INVALID_HANDLE_VALUE)){
    psync_crypto_aes256_ctr_encoder_decoder_free(decoder);
    debug(D_ERROR, "could not open %s", filename);
    return PSYNC_NET_PERMFAIL;
  }
  off=0;
  psync_hash_init(&hashctx);
  while (off<fsize){
    if (fsize-off>sizeof(buff))
      rd=sizeof(buff);
    else
      rd=fsize-off;
    if (unlikely_log(socket_read_all(sock, buff, rd)))
      goto err0;
    psync_crypto_aes256_ctr_encode_decode_inplace(decoder, buff, rd, off);
    if (unlikely_log(psync_file_write(fd, buff, rd)!=rd))
      goto err0;
    psync_hash_update(&hashctx, buff, rd);
    off+=rd;
  }
  psync_crypto_aes256_ctr_encoder_decoder_free(decoder);
  psync_file_close(fd);
  psync_hash_final(hashbin, &hashctx);
  psync_binhex(hashhex, hashbin, PSYNC_HASH_DIGEST_LEN);
  debug(D_NOTICE, "downloaded file %s from peer", filename);
  if (memcmp(hashhex, filehashhex, PSYNC_HASH_DIGEST_HEXLEN)){
    /* it is better to return permanent fail and let the block checksum algo to find bad blocks */
    debug(D_WARNING, "got bad checksum for file %s", filename);
    return PSYNC_NET_PERMFAIL;
  }
  else
    return PSYNC_NET_OK;
err0:
  psync_crypto_aes256_ctr_encoder_decoder_free(decoder);
  psync_file_close(fd);
  psync_hash_final(hashbin, &hashctx);
  return PSYNC_NET_TEMPFAIL;
}
Ejemplo n.º 10
0
static void psync_p2p_thread(){
  ssize_t ret;
  char buff[2048];
/*  struct sockaddr_in6 addr; */
  struct sockaddr_in addr4;
  psync_socket_t tcpsock, socks[2], *inconn;
  socklen_t sl;
  int sret;
  psync_wait_statuses_array(requiredstatuses, ARRAY_SIZE(requiredstatuses));
  tcpsock=INVALID_SOCKET;
/*  udpsock=psync_create_socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
  if (unlikely_log(udpsock==INVALID_SOCKET)){*/
    udpsock=psync_create_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (unlikely_log(udpsock==INVALID_SOCKET))
      goto ex;
    setsockopt(udpsock, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on));
    memset(&addr4, 0, sizeof(addr4));
    addr4.sin_family=AF_INET;
    addr4.sin_port  =htons(PSYNC_P2P_PORT);
    addr4.sin_addr.s_addr=INADDR_ANY;
    if (unlikely_log(bind(udpsock, (struct sockaddr *)&addr4, sizeof(addr4))==SOCKET_ERROR))
      goto ex;
/*  }
  else{
    setsockopt(udpsock, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on));
    memset(&addr, 0, sizeof(addr));
    addr.sin6_family=AF_INET6;
    addr.sin6_port  =htons(PSYNC_P2P_PORT);
    addr.sin6_addr  =in6addr_any;
    if (unlikely_log(bind(udpsock, (struct sockaddr *)&addr, sizeof(addr))==SOCKET_ERROR))
      goto ex;
  }
  tcpsock=psync_create_socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
  if (unlikely_log(tcpsock==INVALID_SOCKET)){*/
    tcpsock=psync_create_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (unlikely_log(tcpsock==INVALID_SOCKET))
      goto ex;
    setsockopt(tcpsock, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on));
    memset(&addr4, 0, sizeof(addr4));
    addr4.sin_family=AF_INET;
    addr4.sin_port  =htons(0);
    addr4.sin_addr.s_addr=INADDR_ANY;
    if (unlikely_log(bind(tcpsock, (struct sockaddr *)&addr4, sizeof(addr4))==SOCKET_ERROR))
      goto ex;
    sl=sizeof(addr4);
    if (unlikely_log(getsockname(tcpsock, (struct sockaddr *)&addr4, &sl)==SOCKET_ERROR))
      goto ex;
    tcpport=ntohs(addr4.sin_port);
/*  }
  else{
    setsockopt(tcpsock, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on));
    memset(&addr, 0, sizeof(addr));
    addr.sin6_family=AF_INET6;
    addr.sin6_port  =htons(0);
    addr.sin6_addr  =in6addr_any;
    if (unlikely_log(bind(tcpsock, (struct sockaddr *)&addr, sizeof(addr))==SOCKET_ERROR))
      goto ex;
    sl=sizeof(addr);
    if (unlikely_log(getsockname(tcpsock, (struct sockaddr *)&addr, &sl)==SOCKET_ERROR))
      goto ex;
    tcpport=ntohs(addr.sin6_port);
  }*/
  if (unlikely_log(listen(tcpsock, 2)))
    goto ex;
  socks[0]=udpsock;
  socks[1]=tcpsock;
  while (psync_do_run){
    if (unlikely(!psync_setting_get_bool(_PS(p2psync)))){
      pthread_mutex_lock(&p2pmutex);
      if (!psync_setting_get_bool(_PS(p2psync))){
        running=0;
        psync_close_socket(tcpsock);
        psync_close_socket(udpsock);
        pthread_mutex_unlock(&p2pmutex);
        return;
      }
      pthread_mutex_unlock(&p2pmutex);
    }
    psync_wait_statuses_array(requiredstatuses, ARRAY_SIZE(requiredstatuses));
    sret=psync_select_in(socks, 2, -1);
    if (unlikely_log(sret==-1)){
      psync_milisleep(1);
      continue;
    }
    if (sret==0){
      paddrlen=sizeof(paddr);
      ret=recvfrom(udpsock, buff, sizeof(buff), 0, (struct sockaddr *)&paddr, &paddrlen);
      if (likely_log(ret!=SOCKET_ERROR))
        psync_p2p_process_packet(buff, ret);
      else
        psync_milisleep(1);
    }
    else if (sret==1){
      inconn=psync_new(psync_socket_t);
      *inconn=accept(tcpsock, NULL, NULL);
      if (unlikely_log(*inconn==INVALID_SOCKET))
        psync_free(inconn);
      else
        psync_run_thread1("p2p tcp", psync_p2p_tcphandler, inconn);
    }
  }
ex:
  pthread_mutex_lock(&p2pmutex);
  running=0;
  psync_close_socket(tcpsock);
  psync_close_socket(udpsock);
  pthread_mutex_unlock(&p2pmutex);
}
Ejemplo n.º 11
0
static void psync_p2p_tcphandler(void *ptr){
  packet_get packet;
  psync_fileid_t localfileid;
  psync_binary_rsa_key_t binpubrsa;
  psync_rsa_publickey_t pubrsa;
  psync_symmetric_key_t aeskey;
  psync_encrypted_symmetric_key_t encaeskey;
  psync_crypto_aes256_ctr_encoder_decoder_t encoder;
  char *token, *localpath;
  uint64_t off;
  size_t rd;
  psync_socket_t sock;
  psync_file_t fd;
  uint32_t keylen, enctype;
  unsigned char hashhex[PSYNC_HASH_DIGEST_HEXLEN], buff[4096];
  sock=*((psync_socket_t *)ptr);
  psync_free(ptr);
  debug(D_NOTICE, "got tcp connection");
  if (unlikely_log(socket_read_all(sock, &packet, sizeof(packet))))
    goto err0;
  if (unlikely_log(packet.keylen>PSYNC_P2P_RSA_SIZE) || unlikely_log(packet.tokenlen>512)) /* lets allow 8 times larger keys than we use */
    goto err0;
  localfileid=psync_p2p_has_file(packet.hashstart, packet.genhash, packet.rand, packet.filesize, hashhex);
  if (!localfileid){
    debug(D_WARNING, "got request for file that we do not have");
    goto err0;
  }
  binpubrsa=psync_ssl_alloc_binary_rsa(packet.keylen);
  if (unlikely_log(socket_read_all(sock, binpubrsa->data, binpubrsa->datalen))){
    psync_free(binpubrsa);
    goto err0;
  }
  token=psync_new_cnt(char, packet.tokenlen);
  if (unlikely_log(socket_read_all(sock, token, packet.tokenlen)) ||
      unlikely_log(!check_token(token, packet.tokenlen, binpubrsa->data, packet.keylen, hashhex))){
    psync_free(binpubrsa);
    psync_free(token);
    goto err0;
  }
  psync_free(token);
  pubrsa=psync_ssl_rsa_binary_to_public(binpubrsa);
  psync_free(binpubrsa);
  if (unlikely_log(pubrsa==PSYNC_INVALID_RSA))
    goto err0;
  localpath=psync_local_path_for_local_file(localfileid, NULL);
  if (unlikely_log(!localpath))
    goto err0;
  fd=psync_file_open(localpath, P_O_RDONLY, 0);
  debug(D_NOTICE, "sending file %s to peer", localpath);
  psync_free(localpath);
  if (fd==INVALID_HANDLE_VALUE){
    debug(D_WARNING, "could not open local file %lu", (unsigned long)localfileid);
    goto err0;
  }
  aeskey=psync_crypto_aes256_ctr_gen_key();
  encaeskey=psync_ssl_rsa_encrypt_symmetric_key(pubrsa, aeskey);
  encoder=psync_crypto_aes256_ctr_encoder_decoder_create(aeskey);
  psync_ssl_free_symmetric_key(aeskey);
  keylen=encaeskey->datalen;
  enctype=P2P_ENCTYPE_RSA_AES;
  if (unlikely_log(encaeskey==PSYNC_INVALID_ENC_SYM_KEY) || unlikely_log(encoder==PSYNC_CRYPTO_INVALID_ENCODER) ||
      unlikely_log(socket_write_all(sock, &keylen, sizeof(keylen)) || socket_write_all(sock, &enctype, sizeof(enctype)) ||
                   socket_write_all(sock, encaeskey->data, encaeskey->datalen))){
    if (encaeskey!=PSYNC_INVALID_ENC_SYM_KEY)
      psync_free(encaeskey);
    if (encoder!=PSYNC_CRYPTO_INVALID_ENCODER)
      psync_crypto_aes256_ctr_encoder_decoder_free(encoder);
    psync_file_close(fd);
    goto err0;
  }
  psync_free(encaeskey);
  off=0;
  while (off<packet.filesize){
    if (packet.filesize-off<sizeof(buff))
      rd=packet.filesize-off;
    else
      rd=sizeof(buff);
    if (unlikely_log(psync_file_read(fd, buff, rd)!=rd))
      break;
    psync_crypto_aes256_ctr_encode_decode_inplace(encoder, buff, rd, off);
    if (unlikely_log(socket_write_all(sock, buff, rd)))
      break;
    off+=rd;
  }
  psync_crypto_aes256_ctr_encoder_decoder_free(encoder);
  psync_file_close(fd);
  debug(D_NOTICE, "file sent successfuly");
err0:
  psync_close_socket(sock);
}
Ejemplo n.º 12
0
void psync_syncer_check_delayed_syncs(){
  psync_stat_t st;
  psync_sql_res *res, *res2, *stmt;
  psync_variant_row row;
  psync_uint_row urow;
  psync_str_row srow;
  char *localpath, *remotepath;
  uint64_t id, synctype;
  int64_t syncid;
  psync_folderid_t folderid;
  int unsigned md;
re:
  res=psync_sql_query("SELECT id, localpath, remotepath, synctype FROM syncfolderdelayed");
  while ((row=psync_sql_fetch_row(res))){
    id=psync_get_number(row[0]);
    localpath=(char *)psync_get_string(row[1]);
    remotepath=(char *)psync_get_string(row[2]);
    synctype=psync_get_number(row[3]);
    if (synctype&PSYNC_DOWNLOAD_ONLY)
      md=7;
    else
      md=5;
    if (unlikely_log(psync_stat(localpath, &st)) || unlikely_log(!psync_stat_isfolder(&st)) || unlikely_log(!psync_stat_mode_ok(&st, md))){
      debug(D_WARNING, "ignoring delayed sync id %"P_PRI_U64" for local path %s", id, localpath);
      delete_delayed_sync(id);
      continue;
    }
    md=0;
    res2=psync_sql_query("SELECT localpath FROM syncfolder");
    while ((srow=psync_sql_fetch_rowstr(res2)))
      if (psync_str_is_prefix(srow[0], localpath)){
        debug(D_WARNING, "skipping localfolder %s, remote %s, because of same parent to %s", localpath, remotepath, srow[0]);
        md=1;
      }
      else if (!psync_filename_cmp(srow[0], localpath)){
        debug(D_WARNING, "skipping localfolder %s, remote %s, because of same dir to %s", localpath, remotepath, srow[0]);
        md=1;
      }
    psync_sql_free_result(res2);
    if (md){
      delete_delayed_sync(id);
      continue;
    }

    localpath=psync_strdup(localpath);
    remotepath=psync_strdup(remotepath);
    psync_sql_free_result(res);

    folderid=psync_get_folderid_by_path_or_create(remotepath);
    if (unlikely(folderid==PSYNC_INVALID_FOLDERID)){
      debug(D_WARNING, "could not get folderid/create folder %s", remotepath);
      psync_free(localpath);
      psync_free(remotepath);
      if (psync_error!=PERROR_OFFLINE){
        delete_delayed_sync(id);
        goto re;
      }
      else
        return;
    }
    psync_sql_start_transaction();
    delete_delayed_sync(id);
    stmt=psync_sql_query_nolock("SELECT id FROM folder WHERE id=?");
    psync_sql_bind_uint(stmt, 1, folderid);
    urow=psync_sql_fetch_rowint(stmt);
    psync_sql_free_result(stmt);
    if (!urow){
      psync_sql_commit_transaction();
      psync_free(localpath);
      psync_free(remotepath);
      goto re;
    }
    stmt=psync_sql_prep_statement("INSERT OR IGNORE INTO syncfolder (folderid, localpath, synctype, flags, inode, deviceid) VALUES (?, ?, ?, 0, ?, ?)");
    psync_sql_bind_uint(stmt, 1, folderid);
    psync_sql_bind_string(stmt, 2, localpath);
    psync_sql_bind_uint(stmt, 3, synctype);
    psync_sql_bind_uint(stmt, 4, psync_stat_inode(&st));
    psync_sql_bind_uint(stmt, 5, psync_stat_device(&st));
    psync_sql_run(stmt);
    if (likely_log(psync_sql_affected_rows()))
      syncid=psync_sql_insertid();
    else
      syncid=-1;
    psync_sql_free_result(stmt);
    psync_free(localpath);
    psync_free(remotepath);
    if (!psync_sql_commit_transaction() && syncid!=-1) {
      psync_path_status_reload_syncs();
      psync_syncer_new(syncid);
      goto re;
    }
    return;
  }
  psync_sql_free_result(res);
}