Пример #1
0
/** Add a dynamic client
 *
 */
bool client_add_dynamic(RADCLIENT_LIST *clients, RADCLIENT *master, RADCLIENT *c)
{
    char buffer[128];

    /*
     *	No virtual server defined.  Inherit the parent's
     *	definition.
     */
    if (master->server && !c->server) {
        c->server = talloc_typed_strdup(c, master->server);
    }

    /*
     *	If the client network isn't global (not tied to a
     *	virtual server), then ensure that this clients server
     *	is the same as the enclosing networks virtual server.
     */
    if (master->server && (strcmp(master->server, c->server) != 0)) {
        ERROR("Cannot add client %s/%i: Virtual server %s is not the same as the virtual server for the network",
              fr_inet_ntoh(&c->ipaddr, buffer, sizeof(buffer)), c->ipaddr.prefix, c->server);

        goto error;
    }

    if (!client_add(clients, c)) {
        ERROR("Cannot add client %s/%i: Internal error",
              fr_inet_ntoh(&c->ipaddr, buffer, sizeof(buffer)), c->ipaddr.prefix);

        goto error;
    }

    /*
     *	Initialize the remaining fields.
     */
    c->dynamic = true;
    c->lifetime = master->lifetime;
    c->created = time(NULL);
    c->longname = talloc_typed_strdup(c, c->shortname);

    INFO("Adding client %s/%i with shared secret \"%s\"",
         fr_inet_ntoh(&c->ipaddr, buffer, sizeof(buffer)), c->ipaddr.prefix, c->secret);

    return true;

error:
    client_free(c);
    return false;
}
Пример #2
0
/** Describe the socket we opened to the LDAP server
 *
 * @param[in] listen	abstracting the connection to the server.
 * @param[out] buffer	Where to write text describing the socket.
 * @param[in] bufsize	the length of data written to buffe.r
 * @return 1.
 */
static int proto_ldap_socket_print(rad_listen_t const *listen, char *buffer, size_t bufsize)
{
	size_t			len;
	proto_ldap_inst_t	*inst = listen->data;
	char const		*name = listen->proto->name;

#define FORWARD len = strlen(buffer); if (len >= (bufsize + 1)) return 0;buffer += len;bufsize -= len
#define ADDSTRING(_x) strlcpy(buffer, _x, bufsize);FORWARD

	ADDSTRING(name);

	ADDSTRING(" server ");

	fr_inet_ntoh(&inst->dst_ipaddr, buffer, bufsize);
	FORWARD;

	ADDSTRING(" port ");
	snprintf(buffer, bufsize, "%d", inst->dst_port);
	FORWARD;

	if (listen->server) {
		ADDSTRING(" bound to virtual-server ");
		strlcpy(buffer, listen->server, bufsize);
	}

#undef ADDSTRING
#undef FORWARD

	return 1;
}
Пример #3
0
static int send_with_pcap(RADIUS_PACKET **reply, RADIUS_PACKET *request)
{
	char ip[16];
	char pcap_filter[255];

	pcap = fr_pcap_init(NULL, iface, PCAP_INTERFACE_IN_OUT);
	if (!pcap) {
		ERROR("Failed creating pcap");
		return -1;
	}

	if (fr_pcap_open(pcap) < 0) {
		ERROR("Failed opening interface");
		talloc_free(pcap);
		return -1;
	}

	fr_inet_ntoh(&request->src_ipaddr, ip, sizeof(ip));
	sprintf(pcap_filter, "udp and dst port %d", request->src_port);

	if (fr_pcap_apply_filter(pcap, pcap_filter) < 0) {
		ERROR("Failing setting filter");
		talloc_free(pcap);
		return -1;
	}

	if (fr_dhcpv4_pcap_send(pcap, eth_bcast, request) < 0) {
		ERROR("Failed sending packet");
		talloc_free(pcap);
		return -1;
	}

	if (!reply_expected) return 0;

	*reply = fr_dhcpv4_recv_raw_loop(pcap->fd,
#ifdef HAVE_LINUX_IF_PACKET_H
				      &ll,
#endif
				      request);

	if (!*reply) {
		ERROR("Error receiving reply");
		talloc_free(pcap);
		return -1;
	}

	talloc_free(pcap);
	return 0;
}
Пример #4
0
int proxy_tls_recv(rad_listen_t *listener)
{
	listen_socket_t *sock = listener->data;
	char buffer[256];
	RADIUS_PACKET *packet;
	uint8_t *data;
	ssize_t data_len;

	if (listener->status != RAD_LISTEN_STATUS_KNOWN) return 0;

	DEBUG3("Proxy SSL socket has data to read");
	PTHREAD_MUTEX_LOCK(&sock->mutex);
	data_len = proxy_tls_read(listener);
	PTHREAD_MUTEX_UNLOCK(&sock->mutex);

	if (data_len < 0) {
		DEBUG("Closing TLS socket to home server");
		PTHREAD_MUTEX_LOCK(&sock->mutex);
		tls_socket_close(listener);
		PTHREAD_MUTEX_UNLOCK(&sock->mutex);
		return 0;
	}

	if (data_len == 0) return 0; /* not done yet */

	data = sock->data;

	packet = fr_radius_alloc(sock, false);
	packet->sockfd = listener->fd;
	packet->src_ipaddr = sock->other_ipaddr;
	packet->src_port = sock->other_port;
	packet->dst_ipaddr = sock->my_ipaddr;
	packet->dst_port = sock->my_port;
	packet->code = data[0];
	packet->id = data[1];
	packet->data_len = data_len;
	packet->data = talloc_array(packet, uint8_t, packet->data_len);
	memcpy(packet->data, data, packet->data_len);
	memcpy(packet->vector, packet->data + 4, 16);

	/*
	 *	FIXME: Client MIB updates?
	 */
	switch (packet->code) {
	case PW_CODE_ACCESS_ACCEPT:
	case PW_CODE_ACCESS_CHALLENGE:
	case PW_CODE_ACCESS_REJECT:
		break;

#ifdef WITH_ACCOUNTING
	case PW_CODE_ACCOUNTING_RESPONSE:
		break;
#endif

	default:
		/*
		 *	FIXME: Update MIB for packet types?
		 */
		ERROR("Invalid packet code %d sent to a proxy port "
		       "from home server %s port %d - ID %d : IGNORED",
		       packet->code,
		       fr_inet_ntoh(&packet->src_ipaddr, buffer, sizeof(buffer)),
		       packet->src_port, packet->id);
		fr_radius_free(&packet);
		return 0;
	}

	if (!request_proxy_reply(packet)) {
		fr_radius_free(&packet);
		return 0;
	}

	return 1;
}
Пример #5
0
/** Allocate a new client from a config section
 *
 * @param ctx to allocate new clients in.
 * @param cs to process as a client.
 * @param in_server Whether the client should belong to a specific virtual server.
 * @param with_coa If true and coa_server or coa_pool aren't specified automatically,
 *	create a coa home_server section and add it to the client CONF_SECTION.
 * @return new RADCLIENT struct.
 */
RADCLIENT *client_afrom_cs(TALLOC_CTX *ctx, CONF_SECTION *cs, bool in_server, bool with_coa)
{
    RADCLIENT	*c;
    char const	*name2;

    name2 = cf_section_name2(cs);
    if (!name2) {
        cf_log_err_cs(cs, "Missing client name");
        return NULL;
    }

    /*
     *	The size is fine.. Let's create the buffer
     */
    c = talloc_zero(ctx, RADCLIENT);
    c->cs = cs;

    memset(&cl_ipaddr, 0, sizeof(cl_ipaddr));
    if (cf_section_parse(cs, c, client_config) < 0) {
        cf_log_err_cs(cs, "Error parsing client section");
error:
        client_free(c);
#ifdef WITH_TCP
        hs_proto = NULL;
        cl_srcipaddr = NULL;
#endif

        return NULL;
    }

    /*
     *	Global clients can set servers to use, per-server clients cannot.
     */
    if (in_server && c->server) {
        cf_log_err_cs(cs, "Clients inside of an server section cannot point to a server");
        goto error;
    }

    /*
     *	Newer style client definitions with either ipaddr or ipaddr6
     *	config items.
     */
    if (cf_pair_find(cs, "ipaddr") || cf_pair_find(cs, "ipv4addr") || cf_pair_find(cs, "ipv6addr")) {
        char buffer[128];

        /*
         *	Sets ipv4/ipv6 address and prefix.
         */
        c->ipaddr = cl_ipaddr;

        /*
         *	Set the long name to be the result of a reverse lookup on the IP address.
         */
        fr_inet_ntoh(&c->ipaddr, buffer, sizeof(buffer));
        c->longname = talloc_typed_strdup(c, buffer);

        /*
         *	Set the short name to the name2.
         */
        if (!c->shortname) c->shortname = talloc_typed_strdup(c, name2);
        /*
         *	No "ipaddr" or "ipv6addr", use old-style "client <ipaddr> {" syntax.
         */
    } else {
        cf_log_err_cs(cs, "No 'ipaddr' or 'ipv4addr' or 'ipv6addr' configuration "
                      "directive found in client %s", name2);
        goto error;
    }

    c->proto = IPPROTO_UDP;
    if (hs_proto) {
        if (strcmp(hs_proto, "udp") == 0) {
            hs_proto = NULL;

#ifdef WITH_TCP
        } else if (strcmp(hs_proto, "tcp") == 0) {
            hs_proto = NULL;
            c->proto = IPPROTO_TCP;
#  ifdef WITH_TLS
        } else if (strcmp(hs_proto, "tls") == 0) {
            hs_proto = NULL;
            c->proto = IPPROTO_TCP;
            c->tls_required = true;

        } else if (strcmp(hs_proto, "radsec") == 0) {
            hs_proto = NULL;
            c->proto = IPPROTO_TCP;
            c->tls_required = true;
#  endif
        } else if (strcmp(hs_proto, "*") == 0) {
            hs_proto = NULL;
            c->proto = IPPROTO_IP; /* fake for dual */
#endif
        } else {
            cf_log_err_cs(cs, "Unknown proto \"%s\".", hs_proto);
            goto error;
        }
    }

    /*
     *	If a src_ipaddr is specified, when we send the return packet
     *	we will use this address instead of the src from the
     *	request.
     */
    if (cl_srcipaddr) {
#ifdef WITH_UDPFROMTO
        switch (c->ipaddr.af) {
        case AF_INET:
            if (fr_inet_pton4(&c->src_ipaddr, cl_srcipaddr, -1, true, false, true) < 0) {
                cf_log_err_cs(cs, "Failed parsing src_ipaddr: %s", fr_strerror());
                goto error;
            }
            break;

        case AF_INET6:
            if (fr_inet_pton6(&c->src_ipaddr, cl_srcipaddr, -1, true, false, true) < 0) {
                cf_log_err_cs(cs, "Failed parsing src_ipaddr: %s", fr_strerror());
                goto error;
            }
            break;
        default:
            rad_assert(0);
        }
#else
        WARN("Server not built with udpfromto, ignoring client src_ipaddr");
#endif
        cl_srcipaddr = NULL;
    }

    /*
     *	A response_window of zero is OK, and means that it's
     *	ignored by the rest of the server timers.
     */
    if (timerisset(&c->response_window)) {
        FR_TIMEVAL_BOUND_CHECK("response_window", &c->response_window, >=, 0, 1000);
        FR_TIMEVAL_BOUND_CHECK("response_window", &c->response_window, <=, 60, 0);
        FR_TIMEVAL_BOUND_CHECK("response_window", &c->response_window, <=, main_config.max_request_time, 0);
    }
Пример #6
0
/*
 *	Find the client definition.
 */
static rlm_rcode_t CC_HINT(nonnull) mod_authorize(UNUSED void *instance, UNUSED void *thread, REQUEST *request)
{
	size_t length;
	char const *value;
	CONF_PAIR *cp;
	RADCLIENT *c;
	CONF_SECTION *server_cs;
	char buffer[2048];

	/*
	 *	Ensure we're only being called from the main thread,
	 *	with fake packets.
	 */
	if ((request->packet->src_port != 0) || (request->packet->vps != NULL) ||
	    (request->parent != NULL)) {
		REDEBUG("Improper configuration");
		return RLM_MODULE_NOOP;
	}

	if (!request->client || !request->client->cs) {
		REDEBUG("Unknown client definition");
		return RLM_MODULE_NOOP;
	}

	cp = cf_pair_find(request->client->cs, "directory");
	if (!cp) {
		REDEBUG("No directory configuration in the client");
		return RLM_MODULE_NOOP;
	}

	value = cf_pair_value(cp);
	if (!value) {
		REDEBUG("No value given for the directory entry in the client");
		return RLM_MODULE_NOOP;
	}

	length = strlen(value);
	if (length > (sizeof(buffer) - 256)) {
		REDEBUG("Directory name too long");
		return RLM_MODULE_NOOP;
	}

	memcpy(buffer, value, length + 1);
	fr_inet_ntoh(&request->packet->src_ipaddr, buffer + length, sizeof(buffer) - length - 1);

	/*
	 *	Read the buffer and generate the client.
	 */
	if (request->client->server) {
		server_cs = request->client->server_cs;

	} else if (request->listener) {
		server_cs = request->listener->server_cs;
	} else {
		return RLM_MODULE_FAIL;
	}

	c = client_read(buffer, server_cs, true);
	if (!c) return RLM_MODULE_FAIL;

	/*
	 *	Replace the client.  This is more than a bit of a
	 *	hack.
	 */
	request->client = c;

	return RLM_MODULE_OK;
}