Example #1
0
static int rhizome_sync_with_peers(int mode, int peer_count, const struct config_rhizome_peer *const *peers)
{

  /* Get iterator capable of 64KB buffering.
     In future we should parse the sync URL and base the buffer size on the
     transport and allowable traffic volumes. */
  rhizome_direct_transport_state_http *state = emalloc_zero(sizeof(rhizome_direct_transport_state_http));
  /* XXX This code runs each sync in series, when we can probably do them in
     parallel.  But we can't really do them in parallel until we make the
     synchronisation process fully asynchronous, which probably won't happen
     for a while yet.
     Also, we don't currently parse the URI protocol field fully. */
  int peer_number;
  for (peer_number = 0; peer_number < peer_count; ++peer_number) {
    const struct config_rhizome_peer *peer = peers[peer_number];
    if (strcasecmp(peer->protocol, "http") != 0)
      return WHYF("Unsupported Rhizome Direct protocol %s", alloca_str_toprint(peer->protocol));
    strbuf h = strbuf_local(state->host, sizeof state->host);
    strbuf_puts(h, peer->host);
    if (strbuf_overrun(h))
      return WHYF("Rhizome Direct host name too long: %s", alloca_str_toprint(peer->host));
    state->port = peer->port;
    DEBUGF("Rhizome direct peer is %s://%s:%d", peer->protocol, state->host, state->port);
    rhizome_direct_sync_request *s = rhizome_direct_new_sync_request(rhizome_direct_http_dispatch, 65536, 0, mode, state);
    rhizome_direct_start_sync_request(s);
    if (rd_sync_handle_count > 0)
      while (fd_poll() && rd_sync_handle_count > 0)
	;
  }
  return 0;
}
Example #2
0
int rhizome_manifest_check_sanity(rhizome_manifest *m_in)
{
  /* Ensure manifest meets basic sanity checks. */
  const char *service = rhizome_manifest_get(m_in, "service", NULL, 0);
  const char *sender = rhizome_manifest_get(m_in, "sender", NULL, 0);
  const char *recipient = rhizome_manifest_get(m_in, "recipient", NULL, 0);
  
  if (service == NULL || !service[0])
      return WHY("Manifest missing 'service' field");
  if (rhizome_manifest_get_ll(m_in, "date") == -1)
      return WHY("Manifest missing 'date' field");
  if (strcasecmp(service, RHIZOME_SERVICE_FILE) == 0) {
    const char *name = rhizome_manifest_get(m_in, "name", NULL, 0);
    if (name == NULL)
      return WHY("Manifest missing 'name' field");
  } else if (strcasecmp(service, RHIZOME_SERVICE_MESHMS) == 0) {
    if (sender == NULL || !sender[0])
      return WHY("MeshMS Manifest missing 'sender' field");
    if (!str_is_subscriber_id(sender))
      return WHYF("MeshMS Manifest contains invalid 'sender' field: %s", sender);
    if (recipient == NULL || !recipient[0])
      return WHY("MeshMS Manifest missing 'recipient' field");
    if (!str_is_subscriber_id(recipient))
      return WHYF("MeshMS Manifest contains invalid 'recipient' field: %s", recipient);
  } else {
    return WHY("Invalid service type");
  }
  if (debug & DEBUG_RHIZOME)
    DEBUGF("sender='%s'", sender ? sender : "(null)");

  /* passes all sanity checks */
  return 0;
}
Example #3
0
int rhizome_manifest_check_file(rhizome_manifest *m_in)
{
  long long gotfile = 0;
  if (sqlite_exec_int64(&gotfile, "SELECT COUNT(*) FROM FILES WHERE ID='%s' and datavalid=1;", m_in->fileHexHash) != 1) {
    WHYF("Failed to count files");
    return 0;
  }
  if (gotfile) {
    DEBUGF("Skipping file checks for bundle, as file is already in the database");
    return 0;
  }

  /* Find out whether the payload is expected to be encrypted or not */
  m_in->payloadEncryption=rhizome_manifest_get_ll(m_in, "crypt");
  
  /* Check payload file is accessible and discover its length, then check that it matches
     the file size stored in the manifest */
  long long mfilesize = rhizome_manifest_get_ll(m_in, "filesize");
  m_in->fileLength = 0;
  if (m_in->dataFileName[0]) {
    struct stat stat;
    if (lstat(m_in->dataFileName,&stat) == -1) {
      if (errno != ENOENT || mfilesize != 0)
	return WHYF_perror("stat(%s)", m_in->dataFileName);
    } else {
      m_in->fileLength = stat.st_size;
    }
  }
  if (debug & DEBUG_RHIZOME)
    DEBUGF("filename=%s, fileLength=%lld", m_in->dataFileName, m_in->fileLength);
  if (mfilesize != -1 && mfilesize != m_in->fileLength) {
    WHYF("Manifest.filesize (%lld) != actual file size (%lld)", mfilesize, m_in->fileLength);
    return -1;
  }

  /* If payload is empty, ensure manifest has not file hash, otherwis compute the hash of the
     payload and check that it matches manifest. */
  const char *mhexhash = rhizome_manifest_get(m_in, "filehash", NULL, 0);
  if (m_in->fileLength != 0) {
    char hexhashbuf[RHIZOME_FILEHASH_STRLEN + 1];
    if (rhizome_hash_file(m_in,m_in->dataFileName, hexhashbuf))
      return WHY("Could not hash file.");
    memcpy(&m_in->fileHexHash[0], &hexhashbuf[0], sizeof hexhashbuf);
    m_in->fileHashedP = 1;
    if (!mhexhash) return WHY("manifest contains no file hash");
    if (mhexhash && strcmp(m_in->fileHexHash, mhexhash)) {
      WHYF("Manifest.filehash (%s) does not match payload hash (%s)", mhexhash, m_in->fileHexHash);
      return -1;
    }
  } else {
    if (mhexhash != NULL) {
      WHYF("Manifest.filehash (%s) should be absent for empty payload", mhexhash);
      return -1;
    }
  }

  return 0;
}
static int insert_make_manifest(httpd_request *r)
{
  if (!r->u.insert.received_manifest)
    return http_response_form_part(r, "Missing", PART_MANIFEST, NULL, 0);
  if ((r->manifest = rhizome_new_manifest())) {
    if (r->u.insert.manifest.length == 0)
      return 0;
    assert(r->u.insert.manifest.length <= sizeof r->manifest->manifestdata);
    memcpy(r->manifest->manifestdata, r->u.insert.manifest.buffer, r->u.insert.manifest.length);
    r->manifest->manifest_all_bytes = r->u.insert.manifest.length;
    int n = rhizome_manifest_parse(r->manifest);
    switch (n) {
      case -1:
	break;
      case 0:
	if (!r->manifest->malformed)
	  return 0;
	// fall through
      case 1:
	http_request_simple_response(&r->http, 403, "Malformed manifest");
	return 403;
      default:
	WHYF("rhizome_manifest_parse() returned %d", n);
	break;
    }
  }
  return 500;
}
Example #5
0
int form_serval_instance_path(char *buf, size_t bufsiz, const char *path)
{
    if (snprintf(buf, bufsiz, "%s/%s", serval_instancepath(), path) < bufsiz)
        return 1;
    WHYF("Cannot form pathname \"%s/%s\" -- buffer too small (%lu bytes)", serval_instancepath(), path, (unsigned long)bufsiz);
    return 0;
}
Example #6
0
static int rhizome_server_set_response(rhizome_http_request *r, const struct http_response *h)
{
  strbuf b = strbuf_local((char *) r->buffer, r->buffer_size);
  strbuf_build_http_response(b, h);
  if (r->buffer == NULL || strbuf_overrun(b)) {
    // Need a bigger buffer
    if (r->buffer)
      free(r->buffer);
    r->buffer_size = strbuf_count(b) + 1;
    r->buffer = malloc(r->buffer_size);
    if (r->buffer == NULL) {
      WHYF_perror("malloc(%u)", r->buffer_size);
      r->buffer_size = 0;
      return WHY("Cannot send response, out of memory");
    }
    strbuf_init(b, (char *) r->buffer, r->buffer_size);
    strbuf_build_http_response(b, h);
    if (strbuf_overrun(b))
      return WHYF("Bug! Cannot send response, buffer not big enough");
  }
  r->buffer_length = strbuf_len(b);
  r->buffer_offset = 0;
  r->request_type |= RHIZOME_HTTP_REQUEST_FROMBUFFER;
  if (debug & DEBUG_RHIZOME_TX)
    DEBUGF("Sending HTTP response: %s", alloca_toprint(120, (const char *)r->buffer, r->buffer_length));
  return 0;
}
Example #7
0
int cli_arg(int argc, const char *const *argv, struct command_line_option *o, char *argname, const char **dst, int (*validator)(const char *arg), char *defaultvalue)
{
  int arglen = strlen(argname);
  int i;
  const char *word;
  for(i = 0; (word = o->words[i]); ++i) {
    int wordlen = strlen(word);
    /* No need to check that the "<...>" and "[<...>]" are all intact in the command_line_option,
     because that was already checked in parseCommandLine(). */
    if (i < argc
	&&(  (wordlen == arglen + 2 && word[0] == '<' && !strncasecmp(&word[1], argname, arglen))
	   || (wordlen == arglen + 4 && word[0] == '[' && !strncasecmp(&word[2], argname, arglen)))
	) {
      const char *value = argv[i];
      if (validator && !(*validator)(value))
	return WHYF("Invalid argument %d '%s': \"%s\"", i + 1, argname, value);
      *dst = value;
      return 0;
    }
  }
  /* No matching valid argument was found, so return default value.  It might seem that this should
   never happen, but it can because more than one version of a command line option may exist, one
   with a given argument and another without, and allowing a default value means we can have a
   single function handle both in a fairly simple manner. */
  *dst = defaultvalue;
  return 1;
}
Example #8
0
int app_rhizome_direct_sync(const struct cli_parsed *parsed, void *context)
{
  if (config.debug.verbose)
    DEBUG_cli_parsed(parsed);
  /* Attempt to connect with a remote Rhizome Direct instance,
     and negotiate which BARs to synchronise. */
  const char *modeName = (parsed->argc >= 3 ? parsed->args[2] : "sync");
  int mode=3; /* two-way sync */
  if (!strcasecmp(modeName,"push")) mode=1; /* push only */
  if (!strcasecmp(modeName,"pull")) mode=2; /* pull only */
  DEBUGF("sync direction = %d",mode);
  if (parsed->args[3]) {
    struct config_rhizome_peer peer;
    const struct config_rhizome_peer *peers[1] = { &peer };
    int result = cf_opt_rhizome_peer_from_uri(&peer, parsed->args[3]);
    if (result == CFOK)
      return rhizome_sync_with_peers(mode, 1, peers);
    else {
      strbuf b = strbuf_alloca(128);
      strbuf_cf_flag_reason(b, result);
      return WHYF("Invalid peer URI %s -- %s", alloca_str_toprint(parsed->args[3]), strbuf_str(b));
    }
  } else if (config.rhizome.direct.peer.ac == 0) {
    DEBUG("No rhizome direct peers were configured or supplied");
    return -1;
  } else {
    const struct config_rhizome_peer *peers[config.rhizome.direct.peer.ac];
    int i;
    for (i = 0; i < config.rhizome.direct.peer.ac; ++i)
      peers[i] = &config.rhizome.direct.peer.av[i].value;
    return rhizome_sync_with_peers(mode, config.rhizome.direct.peer.ac, peers);
  }
}
static int
dna_helper_harvest(int blocking)
{
  if (dna_helper_pid > 0) {
    if (blocking && (config.debug.dnahelper))
      DEBUGF("DNAHELPER waiting for pid=%d to die", dna_helper_pid);
    int status;
    pid_t pid = waitpid(dna_helper_pid, &status, blocking ? 0 : WNOHANG);
    if (pid == dna_helper_pid) {
      strbuf b = strbuf_alloca(80);
      INFOF("DNAHELPER process pid=%u %s", pid, strbuf_str(strbuf_append_exit_status(b, status)));
      unschedule(&sched_harvester);
      dna_helper_pid = -1;
      if (awaiting_reply) {
	unschedule(&sched_timeout);
	awaiting_reply = 0;
      }
      return 1;
    } else if (pid == -1) {
      return WHYF_perror("waitpid(%d, %s)", dna_helper_pid, blocking ? "0" : "WNOHANG");
    } else if (pid) {
      return WHYF("waitpid(%d, %s) returned %d", dna_helper_pid, blocking ? "0" : "WNOHANG", pid);
    }
  }
  return 0;
}
static int insert_mime_part_header(struct http_request *hr, const struct mime_part_headers *h)
{
  httpd_request *r = (httpd_request *) hr;
  if (strcmp(h->content_disposition.name, PART_AUTHOR) == 0) {
    if (r->u.insert.received_author)
      return http_response_form_part(r, "Duplicate", PART_AUTHOR, NULL, 0);
    r->u.insert.current_part = PART_AUTHOR;
    assert(r->u.insert.author_hex_len == 0);
  }
  else if (strcmp(h->content_disposition.name, PART_SECRET) == 0) {
    if (r->u.insert.received_secret)
      return http_response_form_part(r, "Duplicate", PART_SECRET, NULL, 0);
    r->u.insert.current_part = PART_SECRET;
    assert(r->u.insert.secret_hex_len == 0);
  }
  else if (strcmp(h->content_disposition.name, PART_MANIFEST) == 0) {
    // Reject a request if it has a repeated manifest part.
    if (r->u.insert.received_manifest)
      return http_response_form_part(r, "Duplicate", PART_MANIFEST, NULL, 0);
    form_buf_malloc_init(&r->u.insert.manifest, MAX_MANIFEST_BYTES);
    if (   strcmp(h->content_type.type, "rhizome-manifest") != 0
	|| strcmp(h->content_type.subtype, "text") != 0
    )
      return http_response_form_part(r, "Unsupported Content-Type in", PART_MANIFEST, NULL, 0);
    r->u.insert.current_part = PART_MANIFEST;
  }
  else if (strcmp(h->content_disposition.name, PART_PAYLOAD) == 0) {
    // Reject a request if it has a repeated payload part.
    if (r->u.insert.received_payload)
      return http_response_form_part(r, "Duplicate", PART_PAYLOAD, NULL, 0);
    // Reject a request if it has a missing manifest part preceding the payload part.
    if (!r->u.insert.received_manifest)
      return http_response_form_part(r, "Missing", PART_MANIFEST, NULL, 0);
    assert(r->manifest != NULL);
    r->u.insert.current_part = PART_PAYLOAD;
    // If the manifest does not contain a 'name' field, then assign it from the payload filename.
    if (   strcasecmp(RHIZOME_SERVICE_FILE, r->manifest->service) == 0
	&& r->manifest->name == NULL
	&& *h->content_disposition.filename
    )
      rhizome_manifest_set_name_from_path(r->manifest, h->content_disposition.filename);
    // Start writing the payload content into the Rhizome store.  Note: r->manifest->filesize can be
    // RHIZOME_SIZE_UNSET at this point, if the manifest did not contain a 'filesize' field.
    r->u.insert.payload_status = rhizome_write_open_manifest(&r->u.insert.write, r->manifest);
    r->u.insert.payload_size = 0;
    switch (r->u.insert.payload_status) {
      case RHIZOME_PAYLOAD_STATUS_ERROR:
	WHYF("rhizome_write_open_manifest() returned %d", r->u.insert.payload_status);
	return 500;
      case RHIZOME_PAYLOAD_STATUS_STORED:
	// TODO: initialise payload hash so it can be compared with stored payload
	break;
      default:
	break;
    }
  }
  else
    return http_response_form_part(r, "Unsupported", h->content_disposition.name, NULL, 0);
  return 0;
}
Example #11
0
int overlay_mdp_check_binding(struct subscriber *subscriber, int port, int userGeneratedFrameP,
			      struct sockaddr_un *recvaddr, int recvaddrlen)
{
  /* System generated frames can send anything they want */
  if (!userGeneratedFrameP)
    return 0;

  /* Check if the address is in the list of bound addresses,
     and that the recvaddr matches. */
  
  int i;
  for(i = 0; i < MDP_MAX_BINDINGS; ++i) {
    if (mdp_bindings[i].port != port)
      continue;
    if ((!mdp_bindings[i].subscriber) || mdp_bindings[i].subscriber == subscriber) {
      /* Binding matches, now make sure the sockets match */
      if (  mdp_bindings[i].name_len == recvaddrlen - sizeof(short)
	&&  memcmp(mdp_bindings[i].socket_name, recvaddr->sun_path, recvaddrlen - sizeof(short)) == 0
      ) {
	/* Everything matches, so this unix socket and MDP address combination is valid */
	return 0;
      }
    }
  }

  return WHYF("No such binding: recvaddr=%p %s addr=%s port=%u (0x%x) -- possible spoofing attack",
	recvaddr,
	recvaddr ? alloca_toprint(-1, recvaddr->sun_path, recvaddrlen - sizeof(short)) : "",
	alloca_tohex_sid(subscriber->sid),
	port, port
      );
}
int
dna_helper_enqueue(struct subscriber *source, mdp_port_t source_port, const char *did)
{
  if (config.debug.dnahelper)
    DEBUGF("DNAHELPER request did=%s sid=%s", did, alloca_tohex_sid_t(source->sid));
  if (dna_helper_pid == 0)
    return 0;
  // Only try to restart a DNA helper process if the previous one is well and truly gone.
  if (dna_helper_pid == -1 && dna_helper_stdin == -1 && dna_helper_stdout == -1 && dna_helper_stderr == -1) {
    if (dna_helper_start() == -1) {
      /* Something broke, bail out */
      return WHY("DNAHELPER start failed");
    }
  }
  /* Write request to dna helper.
     Request takes form:  SID-of-Requestor|DID|\n
     By passing the requestor's SID to the helper, we don't need to maintain
     any state, as all we have to do is wait for responses from the helper,
     which will include the requestor's SID.
  */
  if (dna_helper_stdin == -1)
    return 0;
  if (request_bufptr && request_bufptr != request_buffer) {
    WARNF("DNAHELPER currently sending request %s -- dropping new request", request_buffer);
    return 0;
  }
  if (awaiting_reply) {
    WARN("DNAHELPER currently awaiting reply -- dropping new request");
    return 0;
  }
  char buffer[sizeof request_buffer];
  strbuf b = strbuf_local(request_bufptr == request_buffer ? buffer : request_buffer, sizeof buffer);
  strbuf_tohex(b, SID_STRLEN, source->sid.binary);
  strbuf_putc(b, '|');
  strbuf_puts(b, did);
  strbuf_putc(b, '|');
  strbuf_putc(b, '\n');
  if (strbuf_overrun(b)) {
    WHYF("DNAHELPER request buffer overrun: %s -- request not sent", strbuf_str(b));
    request_bufptr = request_bufend = NULL;
  } else {
    if (strbuf_str(b) != request_buffer) {
      if (strcmp(strbuf_str(b), request_buffer) != 0)
	WARNF("DNAHELPER overwriting unsent request %s", request_buffer);
      strcpy(request_buffer, strbuf_str(b));
    }
    request_bufptr = request_buffer;
    request_bufend = request_buffer + strbuf_len(b);
    request_source = source;
    request_port = source_port;
    strncpy(request_did, did, sizeof request_did);
    request_did[sizeof request_did - 1] = '\0';
  }
  if (dna_helper_started) {
    sched_requests.poll.fd = dna_helper_stdin;
    watch(&sched_requests);
  }
  return 1;
}
Example #13
0
// send a request to servald deamon to add a port binding
int overlay_mdp_bind(const sid_t *localaddr, int port) 
{
  overlay_mdp_frame mdp;
  mdp.packetTypeAndFlags=MDP_BIND|MDP_FORCE;
  bcopy(localaddr->binary, mdp.bind.sid, SID_SIZE);
  mdp.bind.port=port;
  int result=overlay_mdp_send(&mdp,MDP_AWAITREPLY,5000);
  if (result) {
    if (mdp.packetTypeAndFlags==MDP_ERROR)
      WHYF("Could not bind to MDP port %d: error=%d, message='%s'",
	   port,mdp.error.error,mdp.error.message);
    else
      WHYF("Could not bind to MDP port %d (no reason given)",port);
    return -1;
  }
  return 0;
}
Example #14
0
int confValueSet(const char *var, const char *value)
{
    if (!config_buffer && read_config() == -1)
        return -1;
    if (!is_configvarname(var))
        return WHYF("Cannot %s %s: invalid variable name", value ? "set" : "delete", var);
    if (value == NULL) {
        unsigned int i;
        for (i = 0; i < confc; ++i) {
            if (strcasecmp(var, confvar[i]) == 0) {
                --confc;
                for (; i < confc; ++i) {
                    confvar[i] = confvar[i + 1];
                    confvalue[i] = confvalue[i + 1];
                }
                return 0;
            }
        }
    } else {
        if (confc >= MAX_CONFIG_VARS)
            return WHYF("Cannot set %s: too many variables", var);
        size_t valuelen = strlen(value);
        unsigned int i;
        for (i = 0; i != confc; ++i) {
            if (strcasecmp(var, confvar[i]) == 0) {
                char *valueptr = confvalue[i];
                if (valuelen > strlen(valueptr)) {
                    if ((valueptr = grow_config_buffer(valuelen + 1)) == NULL)
                        return -1;
                }
                strcpy(confvar[i], var);
                confvalue[i] = strcpy(valueptr, value);
                return 0;
            }
        }
        size_t varlen = strlen(var);
        char *buf = grow_config_buffer(varlen + 1 + valuelen + 1);
        if (buf == NULL)
            return -1;
        confvar[confc] = strcpy(buf, var);
        confvalue[confc] = strcpy(buf + varlen + 1, value);
        ++confc;
    }
    return 0;
}
Example #15
0
static int overlay_frame_build_header(int packet_version, struct decode_context *context, 
			       struct overlay_buffer *buff, 
			       int queue, int type, int modifiers, int ttl, int sequence,
			       struct broadcast *broadcast, struct subscriber *next_hop,
			       struct subscriber *destination, struct subscriber *source)
{
  if (ttl < 0 || ttl > PAYLOAD_TTL_MAX)
    return WHYF("invalid ttl=%d", ttl);

  int flags = modifiers & (PAYLOAD_FLAG_CIPHERED | PAYLOAD_FLAG_SIGNED);
  
  if (ttl==1 && !broadcast)
    flags |= PAYLOAD_FLAG_ONE_HOP;
  if (destination && destination==next_hop)
    flags |= PAYLOAD_FLAG_ONE_HOP;
  
  if (source == context->sender)
    flags |= PAYLOAD_FLAG_SENDER_SAME;
  
  if (!destination)
    flags |= PAYLOAD_FLAG_TO_BROADCAST;
  
  if (type!=OF_TYPE_DATA)
    flags |= PAYLOAD_FLAG_LEGACY_TYPE;
  
  if (ob_append_byte(buff, flags)) return -1;
  
  if (!(flags & PAYLOAD_FLAG_SENDER_SAME)){
    if (overlay_address_append(context, buff, source)) return -1;
  }
  
  if (flags & PAYLOAD_FLAG_TO_BROADCAST){
    if (!(flags & PAYLOAD_FLAG_ONE_HOP)){
      if (overlay_broadcast_append(buff, broadcast)) return -1;
    }
  }else{
    if (overlay_address_append(context, buff, destination)) return -1;
    if (!(flags & PAYLOAD_FLAG_ONE_HOP)){
      if (overlay_address_append(context, buff, next_hop)) return -1;
    }
  }
  
  if (!(flags & PAYLOAD_FLAG_ONE_HOP)){
    if (ob_append_byte(buff, ttl | ((queue&3)<<5))) return -1;
  }
  
  if (flags & PAYLOAD_FLAG_LEGACY_TYPE){
    if (ob_append_byte(buff, type)) return -1;
  }

  if (packet_version >= 1)
    if (ob_append_byte(buff, sequence))
      return -1;
  
  return 0;
}
Example #16
0
const char *confValue(unsigned int index)
{
    if (!config_buffer && read_config() == -1)
        return NULL;
    if (index >= confc) {
        WHYF("Config index=%u too big, confc=%u", index, confc);
        return NULL;
    }
    return confvalue[index];
}
Example #17
0
static int load_directory_config(){
  if (!directory_service){
    const char *sid_hex = confValueGet("directory.service", NULL);
    if (!sid_hex)
      return 0;
    
    unsigned char sid[SID_SIZE];
    if (stowSid(sid, 0, sid_hex)==-1)
      return WHYF("Invalid directory server SID %s", sid_hex);
    
    directory_service = find_subscriber(sid, SID_SIZE, 1);
    if (!directory_service)
      return WHYF("Failed to create subscriber record");
    
    // used by tests
    INFOF("ADD DIRECTORY SERVICE %s", alloca_tohex_sid(directory_service->sid));
  }
  // always attempt to reload the address, may depend on DNS resolution
  return load_subscriber_address(directory_service);
}
static int add_packet(struct msp_window *window, uint16_t seq, uint8_t flags, 
  const uint8_t *payload, size_t len)
{
  
  struct msp_packet **insert_pos=NULL;
  
  if (!window->_head){
    insert_pos = &window->_head;
  }else{
    if (window->_tail->seq == seq){
      // ignore duplicate packets
      return 0;
    }else if (compare_wrapped_uint16(window->_tail->seq, seq)<0){
      if (compare_wrapped_uint16(window->_head->seq, seq)>0){
	// this is ambiguous
	return WHYF("%04x is both < tail (%04x) and > head (%04x)", seq, window->_tail->seq, window->_head->seq);
      }
      insert_pos = &window->_tail->_next;
    }else{
      insert_pos = &window->_head;
      while(compare_wrapped_uint16((*insert_pos)->seq, seq)<0)
	insert_pos = &(*insert_pos)->_next;
      if ((*insert_pos)->seq == seq){
	// ignore duplicate packets
	return 0;
      }
    }
  }
  
  struct msp_packet *packet = emalloc_zero(sizeof(struct msp_packet));
  if (!packet)
    return -1;
    
  packet->_next = (*insert_pos);
  *insert_pos = packet;
  if (!packet->_next)
    window->_tail = packet;
  packet->added = gettime_ms();
  packet->seq = seq;
  packet->flags = flags;
  packet->len = len;
  
  if (payload && len){
    uint8_t *p = emalloc(len);
    if (!p){
      free(packet);
      return -1;
    }
    packet->payload = p;
    bcopy(payload, p, len);
  }
  window->packet_count++;
  return 1;
}
Example #19
0
static int load_directory_config()
{
  if (!directory_service && !is_sid_any(config.directory.service.binary)) {
    directory_service = find_subscriber(config.directory.service.binary, SID_SIZE, 1);
    if (!directory_service)
      return WHYF("Failed to create subscriber record");
    // used by tests
    INFOF("ADD DIRECTORY SERVICE %s", alloca_tohex_sid(directory_service->sid));
  }
  // always attempt to reload the address, may depend on DNS resolution
  return load_subscriber_address(directory_service);
}
Example #20
0
int overlay_mdp_recv(overlay_mdp_frame *mdp, int port, int *ttl) 
{
  char mdp_socket_name[101];
  unsigned char recvaddrbuffer[1024];
  struct sockaddr *recvaddr=(struct sockaddr *)recvaddrbuffer;
  unsigned int recvaddrlen=sizeof(recvaddrbuffer);
  struct sockaddr_un *recvaddr_un;
  
  if (!FORM_SERVAL_INSTANCE_PATH(mdp_socket_name, "mdp.socket"))
    return WHY("Could not find mdp socket");
  mdp->packetTypeAndFlags=0;
  
  /* Check if reply available */
  set_nonblock(mdp_client_socket);
  ssize_t len = recvwithttl(mdp_client_socket,(unsigned char *)mdp, sizeof(overlay_mdp_frame),ttl,recvaddr,&recvaddrlen);
  set_block(mdp_client_socket);
  
  recvaddr_un=(struct sockaddr_un *)recvaddr;
  /* Null terminate received address so that the stat() call below can succeed */
  if (recvaddrlen<1024) recvaddrbuffer[recvaddrlen]=0;
  if (len>0) {
    /* Make sure recvaddr matches who we sent it to */
    if (strncmp(mdp_socket_name, recvaddr_un->sun_path, sizeof(recvaddr_un->sun_path))) {
      /* Okay, reply was PROBABLY not from the server, but on OSX if the path
       has a symlink in it, it is resolved in the reply path, but might not
       be in the request path (mdp_socket_name), thus we need to stat() and
       compare inode numbers etc */
      struct stat sb1,sb2;
      if (stat(mdp_socket_name,&sb1)) return WHY("stat(mdp_socket_name) failed, so could not verify that reply came from MDP server");
      if (stat(recvaddr_un->sun_path,&sb2)) return WHY("stat(ra->sun_path) failed, so could not verify that reply came from MDP server");
      if ((sb1.st_ino!=sb2.st_ino)||(sb1.st_dev!=sb2.st_dev))
	return WHY("Reply did not come from server");
    }
    
    // silently drop incoming packets for the wrong port number
    if (port>0 && port != mdp->in.dst.port){
      WARNF("Ignoring packet for port %d",mdp->in.dst.port);
      return -1;
    }
    
    int expected_len = overlay_mdp_relevant_bytes(mdp);
    
    if (len < expected_len){
      return WHYF("Expected packet length of %d, received only %lld bytes", expected_len, (long long) len);
    }
    
    /* Valid packet received */
    return 0;
  } else 
  /* no packet received */
    return -1;
  
}
static int insert_mime_part_end(struct http_request *hr)
{
  httpd_request *r = (httpd_request *) hr;
  if (r->u.insert.current_part == PART_AUTHOR) {
    if (   r->u.insert.author_hex_len != sizeof r->u.insert.author_hex
	|| strn_to_sid_t(&r->u.insert.author, r->u.insert.author_hex, NULL) == -1
    )
      return http_response_form_part(r, "Invalid", PART_AUTHOR, r->u.insert.author_hex, r->u.insert.author_hex_len);
    r->u.insert.received_author = 1;
    if (config.debug.rhizome)
      DEBUGF("received %s = %s", PART_AUTHOR, alloca_tohex_sid_t(r->u.insert.author));
  }
  else if (r->u.insert.current_part == PART_SECRET) {
    if (   r->u.insert.secret_hex_len != sizeof r->u.insert.secret_hex
	|| strn_to_rhizome_bk_t(&r->u.insert.bundle_secret, r->u.insert.secret_hex, NULL) == -1
    )
      return http_response_form_part(r, "Invalid", PART_SECRET, r->u.insert.secret_hex, r->u.insert.secret_hex_len);
    r->u.insert.received_secret = 1;
    if (config.debug.rhizome)
      DEBUGF("received %s = %s", PART_SECRET, alloca_tohex_rhizome_bk_t(r->u.insert.bundle_secret));
  }
  else if (r->u.insert.current_part == PART_MANIFEST) {
    r->u.insert.received_manifest = 1;
    int result = insert_make_manifest(r);
    if (result)
      return result;
    if (r->manifest->has_id && r->u.insert.received_secret)
      rhizome_apply_bundle_secret(r->manifest, &r->u.insert.bundle_secret);
    if (r->manifest->service == NULL)
      rhizome_manifest_set_service(r->manifest, RHIZOME_SERVICE_FILE);
    if (rhizome_fill_manifest(r->manifest, NULL, r->u.insert.received_author ? &r->u.insert.author: NULL) == -1) {
      WHY("rhizome_fill_manifest() failed");
      return 500;
    }
    if (r->manifest->is_journal) {
      http_request_simple_response(&r->http, 403, "Insert not supported for journals");
      return 403;
    }
    assert(r->manifest != NULL);
  }
  else if (r->u.insert.current_part == PART_PAYLOAD) {
    r->u.insert.received_payload = 1;
    if (r->u.insert.payload_status == RHIZOME_PAYLOAD_STATUS_NEW)
      r->u.insert.payload_status = rhizome_finish_write(&r->u.insert.write);
    if (r->u.insert.payload_status == RHIZOME_PAYLOAD_STATUS_ERROR) {
      WHYF("rhizome_finish_write() returned status = %d", r->u.insert.payload_status);
      return 500;
    }
  } else
    FATALF("current_part = %s", alloca_str_toprint(r->u.insert.current_part));
  r->u.insert.current_part = NULL;
  return 0;
}
Example #22
0
int detectAudioDevice()
{
#ifdef ANDROID
  if (!audev) audev=audio_msm_g1_detect();
#endif
#ifdef HAVE_SYS_ALSA_ASOUNDLIB_H
  if (!audev) audev=audio_alsa_detect();
#endif
  if (audev) {
    WHYF("Detected audio device '%s'",audev->name);
    return 0;
  }
  return -1;
}
Example #23
0
/* Read the symbolic link into the supplied buffer and add a terminating nul.  Return -1 if the
 * buffer is too short to hold the link content and the nul.  If readlink(2) returns an error, then
 * logs it and returns -1.  Otherwise, returns the number of bytes read, including the terminating
 * nul, ie, returns what readlink(2) returns plus one.  If the 'len' argument is given as zero, then
 * returns the number of bytes that would be read, by calling lstat(2) instead of readlink(2), plus
 * one for the terminating nul.  Beware of the following race condition: a symbolic link may be
 * altered between calling the lstat(2) and readlink(2), so the following apparently overflow-proof
 * code may still fail from a buffer overflow in the second call to read_symlink():
 *
 *    char *readlink_malloc(const char *path) {
 *	ssize_t len = read_symlink(path, NULL, 0);
 *	if (len == -1)
 *	  return NULL;
 *	char *buf = malloc(len);
 *	if (buf == NULL)
 *	  return NULL;
 *	if (read_symlink(path, buf, len) == -1) {
 *	  free(buf);
 *	  return NULL;
 *	}
 *	return buf;
 *    }
 *
 * @author Andrew Bettison <*****@*****.**>
 */
ssize_t read_symlink(const char *path, char *buf, size_t len)
{
    if (len == 0) {
        struct stat stat;
        if (lstat(path, &stat) == -1)
            return WHYF_perror("lstat(%s)", path);
        return stat.st_size;
    }
    ssize_t nr = readlink(path, buf, len);
    if (nr == -1)
        return WHYF_perror("readlink(%s)", path);
    if (nr >= len)
        return WHYF("buffer overrun from readlink(%s, len=%lu)", path, (unsigned long) len);
    buf[nr] = '\0';
    return nr;
}
Example #24
0
const char *confValueGet(const char *var, const char *defaultValue)
{
    if (var == NULL) {
        WHYF("NULL var name, returning default value: %s", defaultValue ? defaultValue : "NULL");
        return defaultValue;
    }
    if (!config_buffer && read_config() == -1) {
        if (defaultValue)
            WARNF("Config option %s: using default value: %s", var, defaultValue);
        return defaultValue;
    }
    unsigned int i;
    for (i = 0; i != confc; ++i)
        if (strcasecmp(confvar[i], var) == 0)
            return confvalue[i];
    return defaultValue;
}
Example #25
0
// sign the hash of a message, adding the signature to the end of the message buffer.
int crypto_sign_message(struct keyring_identity *identity, unsigned char *content, size_t buffer_len, size_t *content_len)
{
  if (*content_len + SIGNATURE_BYTES > buffer_len)
    return WHYF("Insufficient space in message buffer to add signature. %zu, need %zu",buffer_len, *content_len + SIGNATURE_BYTES);
  
  struct keypair *key = keyring_find_sas_private(keyring, identity);
  if (!key)
    return WHY("Could not find signing key");
  
  unsigned char hash[crypto_hash_sha512_BYTES];
  crypto_hash_sha512(hash, content, *content_len);
  
  int sig_length = SIGNATURE_BYTES;
  
  int ret=crypto_create_signature(key->private_key, hash, crypto_hash_sha512_BYTES, &content[*content_len], &sig_length);
  *content_len+=sig_length;
  return ret;
}
// a frame destined for one of our local addresses, or broadcast, has arrived. Process it.
int process_incoming_frame(time_ms_t now, struct overlay_interface *interface, struct overlay_frame *f, struct decode_context *context){
  int id = (interface - overlay_interfaces);
  switch(f->type)
  {
      // route control frames
    case OF_TYPE_SELFANNOUNCE:
      if (debug&DEBUG_OVERLAYFRAMES)
	DEBUG("Processing OF_TYPE_SELFANNOUNCE");
      overlay_route_saw_selfannounce(f,now);
      break;
    case OF_TYPE_SELFANNOUNCE_ACK:
      if (debug&DEBUG_OVERLAYFRAMES)
	DEBUG("Processing OF_TYPE_SELFANNOUNCE_ACK");
      overlay_route_saw_selfannounce_ack(f,now);
      break;
    case OF_TYPE_NODEANNOUNCE:
      if (debug&DEBUG_OVERLAYFRAMES)
	DEBUG("Processing OF_TYPE_NODEANNOUNCE");
      overlay_route_saw_advertisements(id,f,context,now);
      break;
      
      // data frames
    case OF_TYPE_RHIZOME_ADVERT:
      if (debug&DEBUG_OVERLAYFRAMES)
	DEBUG("Processing OF_TYPE_RHIZOME_ADVERT");
      overlay_rhizome_saw_advertisements(id,f,now);
      break;
    case OF_TYPE_DATA:
    case OF_TYPE_DATA_VOICE:
      if (debug&DEBUG_OVERLAYFRAMES)
	DEBUG("Processing OF_TYPE_DATA");
      overlay_saw_mdp_containing_frame(f,now);
      break;
    case OF_TYPE_PLEASEEXPLAIN:
      if (debug&DEBUG_OVERLAYFRAMES)
	DEBUG("Processing OF_TYPE_PLEASEEXPLAIN");
      process_explain(f);
      break;
    default:
      return WHYF("Support for f->type=0x%x not yet implemented",f->type);
      break;
  }
  return 0;
}
Example #27
0
int overlay_mdp_reply(int sock,struct sockaddr_un *recvaddr,int recvaddrlen,
			  overlay_mdp_frame *mdpreply)
{
  int replylen;

  if (!recvaddr) return 0;

  replylen=overlay_mdp_relevant_bytes(mdpreply);
  if (replylen<0) return WHY("Invalid MDP frame (could not compute length)");

  errno=0;
  int r=sendto(sock,(char *)mdpreply,replylen,0,
	       (struct sockaddr *)recvaddr,recvaddrlen);
  if (r<replylen) { 
    WHY_perror("sendto(d)"); 
    return WHYF("sendto() failed when sending MDP reply, sock=%d, r=%d", sock, r); 
  } else
    if (0) DEBUGF("reply of %d bytes sent",r);
  return 0;  
}
Example #28
0
int overlay_mdp_reply_error(int sock,
			    struct sockaddr_un *recvaddr,int recvaddrlen,
			    int error_number,char *message)
{
  overlay_mdp_frame mdpreply;

  mdpreply.packetTypeAndFlags=MDP_ERROR;
  mdpreply.error.error=error_number;
  if (error_number)
    WHYF("MDP error, code #%d %s",error_number, message);
  
  if (error_number==0||message)
    snprintf(&mdpreply.error.message[0],128,"%s",message?message:"Success");
  else{
    snprintf(&mdpreply.error.message[0],128,"Error code #%d",error_number);
  }
  mdpreply.error.message[127]=0;

  return overlay_mdp_reply(sock,recvaddr,recvaddrlen,&mdpreply);
}
Example #29
0
int overlay_mdp_check_binding(struct subscriber *subscriber, int port, int userGeneratedFrameP,
			      struct sockaddr_un *recvaddr, int recvaddrlen)
{

  /* Check if the address is in the list of bound addresses,
     and that the recvaddr matches. */
  
  int i;
  for(i = 0; i < MDP_MAX_BINDINGS; ++i) {
    if (mdp_bindings[i].port != port)
      continue;
    if ((!mdp_bindings[i].subscriber) || mdp_bindings[i].subscriber == subscriber) {
      /* Binding matches, now make sure the sockets match */
      if (  mdp_bindings[i].name_len == recvaddrlen - sizeof(short)
	&&  memcmp(mdp_bindings[i].socket_name, recvaddr->sun_path, recvaddrlen - sizeof(short)) == 0
      ) {
	/* Everything matches, so this unix socket and MDP address combination is valid */
	return 0;
      }
    }
  }

  /* Check for build-in port listeners */
  if (!userGeneratedFrameP){
    switch(port) {
    case MDP_PORT_NOREPLY:
    case MDP_PORT_ECHO:
    case MDP_PORT_KEYMAPREQUEST:
    case MDP_PORT_VOMP:
    case MDP_PORT_DNALOOKUP:
      return 0;
    }
  }

  return WHYF("No such binding: recvaddr=%p %s addr=%s port=%u (0x%x) -- possible spoofing attack",
	recvaddr,
	recvaddr ? alloca_toprint(-1, recvaddr->sun_path, recvaddrlen - sizeof(short)) : "",
	alloca_tohex_sid(subscriber->sid),
	port, port
      );
}
Example #30
0
int _cli_arg(struct __sourceloc __whence, const struct cli_parsed *parsed, char *label, const char **dst, int (*validator)(const char *arg), char *defaultvalue)
{
  int labellen = strlen(label);
  if (dst)
    *dst = defaultvalue;
  int i;
  for (i = 0; i < parsed->labelc; ++i) {
    if (parsed->labelv[i].len == labellen && strncasecmp(label, parsed->labelv[i].label, labellen) == 0) {
      const char *value = parsed->labelv[i].text;
      if (validator && !(*validator)(value))
	return WHYF("Invalid '%s' argument \"%s\"", label, value);
      if (dst)
	*dst = value;
      return 0;
    }
  }
  /* No matching valid argument was found, so return default value.  It might seem that this should
   never happen, but it can because more than one version of a command line option may exist, one
   with a given argument and another without, and allowing a default value means we can have a
   single function handle both in a fairly simple manner. */
  return 1;
}