Exemplo n.º 1
0
/// Function to enable listening to a particular ethernet multicast address.
/// This is a highly non-portable function.
/// I wonder how you do this on BSD or Slowlaris?
FSTATIC gboolean
_enable_mcast_address(const char * addrstring	///<[in] multicast MAC address string suitable for giving to 'ip'
                      ,		     const char * dev		///<[in] ethernet device
                      ,		     gboolean enable)		///<[in] TRUE to enable, FALSE to disable
{
    GSpawnFlags	flags =  G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL | G_SPAWN_SEARCH_PATH;
    gint		exit_status;
    const gchar*	constargv [] =
    {"ip", "maddress", (enable ? "add" : "delete"), addrstring, "dev", dev, NULL};
    gchar*		argv[DIMOF(constargv)];
    unsigned	j;


    if (NULL == addrstring) {
        return FALSE;
    }

    // This is really stupid and annoying - they have the wrong function prototype for g_spawn_sync...
    for (j=0; j < DIMOF(argv); ++j) {
        argv[j] = g_strdup(constargv[j]);
    }

    DEBUGMSG1("Running IP command %s %s %s %s %s %s", argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
    if (!g_spawn_sync(NULL, argv, NULL, flags, NULL, NULL, NULL, NULL, &exit_status, NULL)) {
        exit_status = 300;
    }
    for (j=0; j < DIMOF(argv); ++j) {
        g_free(argv[j]);
        argv[j] = NULL;
    }
    DEBUGMSG1("Previous IP command returned %d", exit_status);
    return exit_status == 0;
}
Exemplo n.º 2
0
/// Unregister all discovery methods in preparation for shutting down - to make valgrind happy :-D
void
discovery_unregister_all(void)
{
	if (_discovery_timers != NULL) {
		GHashTable*	timers = _discovery_timers;
		_discovery_timers = NULL;
		g_hash_table_remove_all(timers);
		g_hash_table_destroy(timers); timers = NULL;
	}else{
		DEBUGMSG1("Discovery timers were NULL");
	}
}
Exemplo n.º 3
0
/// Create a persistent keypair and write it to disk
/// Returns a MALLOCed string with the key id for the key pair.  Please free!
WINEXPORT char *
cryptcurve25519_gen_persistent_keypair(const char * giveitaname) ///< giveitaname can be NULL
{
    unsigned char*	public_key = g_malloc(crypto_box_PUBLICKEYBYTES);
    unsigned char*	secret_key = g_malloc(crypto_box_SECRETKEYBYTES);
    char*		key_id;
    char*		sysname;

    // This is to try and keep our dummy array from being optimized out
    // so that we get stack protection, and clang doesn't complain...
    crypto_box_keypair(public_key, secret_key);
    if (NULL == giveitaname) {
        char*		checksum_string;
        // Then we'll generate one based on host name and key's checksum
        checksum_string = cryptcurve25519_naming_checksum(public_key, crypto_box_PUBLICKEYBYTES);
        sysname = proj_get_sysname();
        key_id = g_strdup_printf("%s@@%s", sysname, checksum_string);
        g_free(sysname);
        g_free(checksum_string);
    } else {
        key_id = g_strdup(giveitaname);
    }
    DEBUGMSG1("%s.%d: Generating permanent key pair [%s]", __FUNCTION__, __LINE__, key_id);
    // Write out the two generated keys (the key-pair) into the correct names
    if (!_cryptcurve25519_save_a_key(key_id, PUBLICKEY, public_key)
            ||	!_cryptcurve25519_save_a_key(key_id, PRIVATEKEY, secret_key)
            ||	cryptframe_privatekey_new(key_id, secret_key) == NULL
            ||	cryptframe_publickey_new(key_id, public_key) == NULL) {
        // Something didn't work :-(
        cryptcurve25519_purge_keypair(key_id);
        g_free(public_key);
        public_key = NULL;
        g_free(secret_key);
        secret_key = NULL;
        g_free(key_id);
        key_id = NULL;
        return NULL;
    }

    _cache_curve25519_keypair(key_id);
    return key_id;
}
Exemplo n.º 4
0
/// Save a curve25519 key to a file.
FSTATIC gboolean
_cryptcurve25519_save_a_key(const char * key_id,///<[in] key_id to save
			 enum keytype ktype,	///<[in] type of key being saved
			 gconstpointer key)	///<[in] pointer to key
{
	ssize_t		keysize;
	guint32		createmode;
	int		fd;
	int		rc;
	char*		filename;

	if (!_is_legal_curve25519_key_id(key_id)) {
		g_warning("%s.%d: Key id %s is illegal", __FUNCTION__, __LINE__, key_id);
		return FALSE;
	}
	filename = curve25519_key_id_to_filename(key_id, ktype);

	if (PUBLICKEY == ktype) {
		keysize = crypto_box_PUBLICKEYBYTES;
		createmode = 0644;
	}else if (PRIVATEKEY == ktype) {
		keysize = crypto_box_SECRETKEYBYTES;
		createmode = 0600;
	}else{
		g_error("%s.%d: Key type %d is illegal", __FUNCTION__, __LINE__, ktype);
		g_return_val_if_reached(FALSE);
	}
	// If it's a public key, it may exist but not be writable by us...
	if (PUBLICKEY == ktype && g_access(filename, R_OK) == 0) {
		// So, let's check and see if it's what we think it should be...
		if (_cache_curve25519_keypair(key_id)) {
			CryptFramePublicKey*	pub = cryptframe_public_key_by_id(key_id);
			if (pub && memcmp(pub->public_key, key, keysize) == 0) {
				FREE(filename); filename = NULL;
				return TRUE;
			}
		}
	}
	fd = open(filename, O_WRONLY|O_CREAT, createmode);
	if (fd < 0 && (ENOENT == errno)) {
		char*		dirname = _cache_curve25519_key_id_to_dirname(key_id, ktype);
		_cryptcurve25519_make_cryptdir(dirname);
		FREE(dirname);
		fd = open(filename, O_WRONLY|O_CREAT, createmode);
	}
	if (fd < 0) {
		g_warning("%s.%d: cannot create file %s [%s]", __FUNCTION__, __LINE__
		,	filename, g_strerror(errno));
		g_free(filename);
		return FALSE;
	}
	DEBUGMSG4("Saving key to file %s", filename);
	DEBUGCKSUM4("Saved key:", key, keysize);
	rc = write(fd, key, keysize);
	if (rc != keysize) {
		g_warning("%s.%d: cannot write file %s: rc=%d [%s]", __FUNCTION__, __LINE__
		,	filename, rc, g_strerror(errno));
		close(fd);
		g_unlink(filename);
		g_free(filename);
		return FALSE;
	}
	if (close(fd) < 0) {
		g_warning("%s.%d: Close of file %s failed.", __FUNCTION__, __LINE__, filename);
		g_unlink(filename);
		g_free(filename);
		return FALSE;
	}
	chmod(filename, createmode); // Ignore umask...
	DEBUGMSG1("%s.%d: file %s successfully created!", __FUNCTION__, __LINE__, filename);
	g_free(filename);
	return TRUE;
}
Exemplo n.º 5
0
/**
 *  Set up pcap listener for the given interfaces and protocols.
 *  @return a properly configured pcap_t* object for listening for the given protocols - NULL on error
 *  @see pcap_protocols
 */
pcap_t*
create_pcap_listener(const char * dev		///<[in] Device name to listen on
                     ,		     gboolean blocking		///<[in] TRUE if this is a blocking connection
                     ,		     unsigned listenmask	///<[in] Bit mask of protocols to listen for
                     ///< (see @ref pcap_protocols "list of valid bits")
                     ,		     struct bpf_program*prog)	///<[out] Compiled PCAP program
{
    pcap_t*			pcdescr = NULL;
    bpf_u_int32		maskp = 0;
    bpf_u_int32		netp = 0;
    char			errbuf[PCAP_ERRBUF_SIZE];
    char *			expr = NULL;
    int			filterlen = 1;
    unsigned		j;
    int			cnt=0;
    int			rc;
    const char ORWORD [] = " or ";
    gboolean		need_promisc = FALSE;

    BINDDEBUG(pcap_t);
//	setbuf(stdout, NULL);
    setvbuf(stdout, NULL, _IONBF, 0);
    errbuf[0] = '\0';

    // Search the list of valid bits so we can construct the libpcap filter
    // for the given set of protocols on the fly...
    // On this pass we just compute the amount of memory we'll need...
    for (j = 0, cnt = 0; j < DIMOF(filterinfo); ++j) {
        if (listenmask & filterinfo[j].filterbit) {
            ++cnt;
            if (cnt > 1) {
                filterlen += sizeof(ORWORD);
            }
            filterlen += strlen(filterinfo[j].filter);
        }
    }

    if (filterlen < 2) {
        g_warning("Constructed filter is too short - invalid mask argument.");
        return NULL;
    }
    if (NULL == (expr = malloc(filterlen))) {
        g_error("Out of memory!");
        return NULL;
    }
    // Same song, different verse...
    // This time around, we construct the filter
    expr[0] = '\0';
    for (j = 0, cnt = 0; j < DIMOF(filterinfo); ++j) {
        if (listenmask & filterinfo[j].filterbit) {
            ++cnt;
            if (cnt > 1) {
                g_strlcat(expr, ORWORD, filterlen);
            }
            g_strlcat(expr, filterinfo[j].filter, filterlen);
        }
    }
    if (pcap_lookupnet(dev, &netp, &maskp, errbuf) != 0) {
        // This is not a problem for non-IPv4 protocols...
        // It just looks up the ipv4 address - which we mostly don't care about.
        g_info("%s.%d: pcap_lookupnet(\"%s\") failed: [%s]"
               ,	__FUNCTION__, __LINE__, dev, errbuf);
    }

    if (NULL == (pcdescr = pcap_create(dev, errbuf))) {
        g_warning("pcap_create failed: [%s]", errbuf);
        goto oopsie;
    }
    //pcap_set_promisc(pcdescr, FALSE);
    for (j = 0; j < DIMOF(filterinfo); ++j) {
        if (listenmask & filterinfo[j].filterbit) {
            const char * addrstring = filterinfo[j].mcastaddr;
            if (addrstring && !_enable_mcast_address(addrstring, dev, TRUE)) {
                need_promisc = TRUE;
            }
        }
    }
    pcap_set_promisc(pcdescr, need_promisc);
#ifdef HAVE_PCAP_SET_RFMON
    pcap_set_rfmon(pcdescr, FALSE);
#endif
    pcap_setdirection(pcdescr, PCAP_D_IN);
    // Weird bug - returns -3 and doesn't show an error message...
    // And pcap_getnonblock also returns -3... Neither should happen AFAIK...
    errbuf[0] = '\0';
    if ((rc = pcap_setnonblock(pcdescr, !blocking, errbuf)) < 0 && errbuf[0] != '\0') {
        g_warning("pcap_setnonblock(%d) failed: [%s] [rc=%d]", !blocking, errbuf, rc);
        g_warning("Have no idea why this happens - current blocking state is: %d."
                  ,	pcap_getnonblock(pcdescr, errbuf));
    }
    pcap_set_snaplen(pcdescr, 1500);
    /// @todo deal with pcap_set_timeout() call here.
    if (blocking) {
        pcap_set_timeout(pcdescr, 240*1000);
    } else {
        pcap_set_timeout(pcdescr, 1);
    }
    //pcap_set_buffer_size(pcdescr, 1500);

    if (pcap_activate(pcdescr) != 0) {
        g_warning("pcap_activate failed: [%s]", pcap_geterr(pcdescr));
        goto oopsie;
    }
    if (pcap_compile(pcdescr, prog, expr, FALSE, maskp) < 0) {
        g_warning("pcap_compile of [%s] failed: [%s]", expr, pcap_geterr(pcdescr));
        goto oopsie;
    }
    if (pcap_setfilter(pcdescr, prog) < 0) {
        g_warning("pcap_setfilter on [%s] failed: [%s]", expr, pcap_geterr(pcdescr));
        goto oopsie;
    }
    DEBUGMSG1("Compile of [%s] worked!", expr);
    free(expr);
    expr = NULL;
    return(pcdescr);

oopsie:	// Some kind of failure - free things up and return NULL

    g_warning("%s.%d: Could not set up PCAP on %s"
              ,	__FUNCTION__, __LINE__, dev);
    if (expr) {
        free(expr);
        expr = NULL;
    }
    if (pcdescr) {
        close_pcap_listener(pcdescr, dev, listenmask);
        pcdescr = NULL;
    }
    return NULL;
}
Exemplo n.º 6
0
/// Called when an operation completes - it calls requestor's callback if no repeat,
/// and requeues it if it is going to repeat
FSTATIC void
_resource_queue_endnotify
(	ConfigContext*	request
,	gpointer	user_data
,	enum HowDied	exittype
,	int		rc
,	int		signal
,	gboolean	core_dumped
,	const char*	stringresult)
{
	RscQElem*	self = CASTTOCLASS(RscQElem, user_data);
	ResourceQueue*	parent = self->parent;
	ResourceCmd*	cmd = self->cmd;
	gboolean	shouldrepeat = TRUE;


	g_queue_remove(self->ourQ, self);
	parent->activechildcnt -= 1;
	if (parent->shuttingdown && parent->activechildcnt <= 0) {
		_resource_queue_finalize(&parent->baseclass);
		return;
	}
	DEBUGMSG1("%s.%d: EXIT happened exittype:%d repeat:%d, cancelme:%d", __FUNCTION__, __LINE__
	,	exittype,  self->repeatinterval, self->cancelme);

	// Should this request repeat?
	if (self->cancelme || (self->cancelonfail && exittype != EXITED_ZERO)
	||	(0 == self->repeatinterval)) {
		shouldrepeat = FALSE;
	}else{
		shouldrepeat = TRUE;
	}
	// Notify the user that their repeating command flipped status, or has stopped running
	// (i.e., if it was failing but now works, or was working, but now fails)
	if (FALSE == shouldrepeat
	||	(exittype == EXITED_ZERO && !cmd->last_success)
	||	(exittype != EXITED_ZERO && cmd->last_success)) {
		DEBUGMSG1("%s.%d: Calling callback for request id " FMT_64BIT "d."
		,	__FUNCTION__, __LINE__, self->requestid);
		self->callback(request, self->user_data, exittype, rc, signal, core_dumped
		,		stringresult);
		if (shouldrepeat && exittype == EXITED_ZERO && stringresult) {
			g_message("%s: %s", cmd->loggingname, stringresult);
		}
	}
	cmd->last_success = (exittype == EXITED_ZERO);

	if (shouldrepeat) {
		DEBUGMSG1("%s.%d: Repeat request id " FMT_64BIT "d.", __FUNCTION__, __LINE__
		,	self->requestid);
		self->queuetime = g_get_monotonic_time();
		cmd->starttime = self->queuetime + (self->repeatinterval*uSPERSEC);
		g_queue_push_tail(self->ourQ, self);
		_resource_queue_runqueue(self->parent);
	}else{
		DEBUGMSG1("%s.%d: Don't repeat request id " FMT_64BIT "d.", __FUNCTION__, __LINE__
		,	self->requestid);
		if (g_queue_get_length(self->ourQ) == 0) {
			g_hash_table_remove(self->parent->resources, cmd->resourcename);
		}
		_resource_queue_runqueue(self->parent);
		_resource_queue_qelem_finalize(self);
		self = NULL;
	}
	// Undo the ref we did before starting this job
	UNREF(parent);
}