bool client_validate(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)) { DEBUG("- Cannot add client %s: Virtual server %s is not the same as the virtual server for the network", ip_ntoh(&c->ipaddr, buffer, sizeof(buffer)), c->server); goto error; } if (!client_add(clients, c)) { DEBUG("- Cannot add client %s: Internal error", ip_ntoh(&c->ipaddr, buffer, sizeof(buffer))); 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); DEBUG("- Added client %s with shared secret %s", ip_ntoh(&c->ipaddr, buffer, sizeof(buffer)), c->secret); return true; error: client_free(c); return false; }
/* * Find the client definition. */ static rlm_rcode_t mod_authorize(UNUSED void *instance, REQUEST *request) { size_t length; const char *value; CONF_PAIR *cp; RADCLIENT *c; 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)) { RDEBUG("Improper configuration"); return RLM_MODULE_NOOP; } if (!request->client || !request->client->cs) { RDEBUG("Unknown client definition"); return RLM_MODULE_NOOP; } cp = cf_pair_find(request->client->cs, "directory"); if (!cp) { RDEBUG("No directory configuration in the client"); return RLM_MODULE_NOOP; } value = cf_pair_value(cp); if (!value) { RDEBUG("No value given for the directory entry in the client."); return RLM_MODULE_NOOP; } length = strlen(value); if (length > (sizeof(buffer) - 256)) { RDEBUG("Directory name too long"); return RLM_MODULE_NOOP; } memcpy(buffer, value, length + 1); ip_ntoh(&request->packet->src_ipaddr, buffer + length, sizeof(buffer) - length - 1); /* * Read the buffer and generate the client. */ c = client_read(buffer, (request->client->server != NULL), 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; }
/** Add a client from a result set (LDAP, SQL, et al) * * @param ctx Talloc context. * @param identifier Client IP Address / IPv4 subnet / IPv6 subnet / FQDN. * @param secret Client secret. * @param shortname Client friendly name. * @param type NAS-Type. * @param server Virtual-Server to associate clients with. * @param require_ma If true all packets from client must include a message-authenticator. * @return The new client, or NULL on error. */ RADCLIENT *client_from_query(TALLOC_CTX *ctx, char const *identifier, char const *secret, char const *shortname, char const *type, char const *server, bool require_ma) { RADCLIENT *c; char buffer[128]; rad_assert(identifier); rad_assert(secret); c = talloc_zero(ctx, RADCLIENT); if (fr_pton(&c->ipaddr, identifier, 0, true) < 0) { ERROR("%s", fr_strerror()); talloc_free(c); return NULL; } #ifdef WITH_DYNAMIC_CLIENTS c->dynamic = true; #endif ip_ntoh(&c->ipaddr, buffer, sizeof(buffer)); c->longname = talloc_typed_strdup(c, buffer); /* * Other values (secret, shortname, nas_type, virtual_server) */ c->secret = talloc_typed_strdup(c, secret); if (shortname) c->shortname = talloc_typed_strdup(c, shortname); if (type) c->nas_type = talloc_typed_strdup(c, type); if (server) c->server = talloc_typed_strdup(c, server); c->message_authenticator = require_ma; return c; }
/* * Recieve packets from a proxy socket. */ static int proxy_socket_tcp_recv(rad_listen_t *listener, RAD_REQUEST_FUNP *pfun, REQUEST **prequest) { REQUEST *request; RADIUS_PACKET *packet; RAD_REQUEST_FUNP fun = NULL; char buffer[128]; packet = fr_tcp_recv(listener->fd, 0); if (!packet) { proxy_close_tcp_listener(listener); return 0; } /* * FIXME: Client MIB updates? */ switch(packet->code) { case PW_AUTHENTICATION_ACK: case PW_ACCESS_CHALLENGE: case PW_AUTHENTICATION_REJECT: fun = rad_authenticate; break; #ifdef WITH_ACCOUNTING case PW_ACCOUNTING_RESPONSE: fun = rad_accounting; break; #endif default: /* * FIXME: Update MIB for packet types? */ radlog(L_ERR, "Invalid packet code %d sent to a proxy port " "from home server %s port %d - ID %d : IGNORED", packet->code, ip_ntoh(&packet->src_ipaddr, buffer, sizeof(buffer)), packet->src_port, packet->id); rad_free(&packet); return 0; } request = received_proxy_tcp_response(packet, fr_listen2tcp(listener)); if (!request) { return 0; } rad_assert(fun != NULL); *pfun = fun; *prequest = request; return 1; }
static void send_with_pcap(void) { pcap = fr_pcap_init(NULL, iface, PCAP_INTERFACE_IN_OUT); if (!pcap) { fprintf(stderr, "Failed creating pcap \n"); fr_exit_now(1); } if (fr_pcap_open(pcap) < 0) { fprintf(stderr, "Failed opening interface: %s", fr_strerror()); fr_exit_now(1); } char ip[16]; ip_ntoh(&request->src_ipaddr, ip, sizeof(ip)); char pcap_filter[255]; sprintf(pcap_filter, "udp and dst port %d", client_port); if (fr_pcap_apply_filter(pcap, pcap_filter) < 0) { fprintf(stderr, "Failed setting filter for interface: %s \n", fr_strerror()); fr_exit_now(1); } if (fr_dhcp_send_pcap(pcap, eth_bcast, request) < 0) { fprintf(stderr, "dhcpclient: failed sending: %s\n", pcap_geterr(pcap->handle)); fr_exit_now(1); } if (!reply_expected) return; reply = fr_dhcp_recv_raw_loop(pcap->fd, #ifdef HAVE_LINUX_IF_PACKET_H &ll, #endif request); if (!reply) { fprintf(stderr, "dhcpclient: Error receiving reply\n"); fr_exit_now(1); } }
/* * Read a client definition from the given filename. */ RADCLIENT *client_read(char const *filename, int in_server, int flag) { char const *p; RADCLIENT *c; CONF_SECTION *cs; char buffer[256]; if (!filename) return NULL; cs = cf_file_read(filename); if (!cs) return NULL; cs = cf_section_sub_find(cs, "client"); if (!cs) { ERROR("No \"client\" section found in client file"); return NULL; } c = client_parse(cs, in_server); if (!c) return NULL; p = strrchr(filename, FR_DIR_SEP); if (p) { p++; } else { p = filename; } if (!flag) return c; /* * Additional validations */ ip_ntoh(&c->ipaddr, buffer, sizeof(buffer)); if (strcmp(p, buffer) != 0) { DEBUG("Invalid client definition in %s: IP address %s does not match name %s", filename, buffer, p); client_free(c); return NULL; } return c; }
static int send_packet(RADIUS_PACKET *req, RADIUS_PACKET **rep) { int i; struct timeval tv; if (!req || !rep || !*rep) return -1; for (i = 0; i < retries; i++) { fd_set rdfdesc; debug_packet(req, R_SENT); if (rad_send(req, NULL, secret) < 0) { fr_perror("radeapclient"); exit(1); } /* And wait for reply, timing out as necessary */ FD_ZERO(&rdfdesc); FD_SET(req->sockfd, &rdfdesc); tv.tv_sec = (int)timeout; tv.tv_usec = 1000000 * (timeout - (int) timeout); /* Something's wrong if we don't get exactly one fd. */ if (select(req->sockfd + 1, &rdfdesc, NULL, NULL, &tv) != 1) { continue; } *rep = rad_recv(req->sockfd, 0); if (*rep != NULL) { /* * If we get a response from a machine * which we did NOT send a request to, * then complain. */ if (((*rep)->src_ipaddr.af != req->dst_ipaddr.af) || (memcmp(&(*rep)->src_ipaddr.ipaddr, &req->dst_ipaddr.ipaddr, ((req->dst_ipaddr.af == AF_INET ? /* AF_INET6? */ sizeof(req->dst_ipaddr.ipaddr.ip4addr) : /* FIXME: AF_INET6 */ sizeof(req->dst_ipaddr.ipaddr.ip6addr)))) != 0) || ((*rep)->src_port != req->dst_port)) { char src[128], dst[128]; ip_ntoh(&(*rep)->src_ipaddr, src, sizeof(src)); ip_ntoh(&req->dst_ipaddr, dst, sizeof(dst)); fprintf(stderr, "radclient: ERROR: Sent request to host %s port %d, got response from host %s port %d\n!", dst, req->dst_port, src, (*rep)->src_port); exit(1); } break; } else { /* NULL: couldn't receive the packet */ fr_perror("radclient"); exit(1); } } /* No response or no data read (?) */ if (i == retries) { fprintf(stderr, "radclient: no response from server\n"); exit(1); } /* * FIXME: Discard the packet & listen for another. * * Hmm... we should really be using eapol_test, which does * a lot more than radeapclient. */ if (rad_verify(*rep, req, secret) != 0) { fr_perror("rad_verify"); exit(1); } if (rad_decode(*rep, req, secret) != 0) { fr_perror("rad_decode"); exit(1); } /* libradius debug already prints out the value pairs for us */ if (!fr_debug_flag && do_output) { debug_packet(*rep, R_RECV); } if((*rep)->code == PW_CODE_AUTHENTICATION_ACK) { totalapp++; } else if ((*rep)->code == PW_CODE_AUTHENTICATION_REJECT) { totaldeny++; } return 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. */ ip_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_pton4(&c->src_ipaddr, cl_srcipaddr, -1, true, false) < 0) { cf_log_err_cs(cs, "Failed parsing src_ipaddr: %s", fr_strerror()); goto error; } break; case AF_INET6: if (fr_pton6(&c->src_ipaddr, cl_srcipaddr, -1, true, false) < 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); }
static int generate_sql_clients(rlm_sql_t *inst) { rlm_sql_handle_t *handle; rlm_sql_row_t row; char querystr[MAX_QUERY_LEN]; RADCLIENT *c; char *prefix_ptr = NULL; unsigned int i = 0; int numf = 0; DEBUG("rlm_sql (%s): Processing generate_sql_clients", inst->config->xlat_name); /* NAS query isn't xlat'ed */ strlcpy(querystr, inst->config->nas_query, sizeof(querystr)); DEBUG("rlm_sql (%s) in generate_sql_clients: query is %s", inst->config->xlat_name, querystr); handle = sql_get_socket(inst); if (handle == NULL) return -1; if (rlm_sql_select_query(&handle,inst,querystr)){ return -1; } while(rlm_sql_fetch_row(&handle, inst) == 0) { i++; row = handle->row; if (row == NULL) break; /* * The return data for each row MUST be in the following order: * * 0. Row ID (currently unused) * 1. Name (or IP address) * 2. Shortname * 3. Type * 4. Secret * 5. Virtual Server (optional) */ if (!row[0]){ radlog(L_ERR, "rlm_sql (%s): No row id found on pass %d",inst->config->xlat_name,i); continue; } if (!row[1]){ radlog(L_ERR, "rlm_sql (%s): No nasname found for row %s",inst->config->xlat_name,row[0]); continue; } if (!row[2]){ radlog(L_ERR, "rlm_sql (%s): No short name found for row %s",inst->config->xlat_name,row[0]); continue; } if (!row[4]){ radlog(L_ERR, "rlm_sql (%s): No secret found for row %s",inst->config->xlat_name,row[0]); continue; } DEBUG("rlm_sql (%s): Read entry nasname=%s,shortname=%s,secret=%s",inst->config->xlat_name, row[1],row[2],row[4]); c = talloc_zero(inst, RADCLIENT); #ifdef WITH_DYNAMIC_CLIENTS c->dynamic = 1; #endif /* * Look for prefixes */ c->prefix = -1; prefix_ptr = strchr(row[1], '/'); if (prefix_ptr) { c->prefix = atoi(prefix_ptr + 1); if ((c->prefix < 0) || (c->prefix > 128)) { radlog(L_ERR, "rlm_sql (%s): Invalid Prefix value '%s' for IP.", inst->config->xlat_name, prefix_ptr + 1); talloc_free(c); continue; } /* Replace '/' with '\0' */ *prefix_ptr = '\0'; } /* * Always get the numeric representation of IP */ if (ip_hton(row[1], AF_UNSPEC, &c->ipaddr) < 0) { radlog(L_ERR, "rlm_sql (%s): Failed to look up hostname %s: %s", inst->config->xlat_name, row[1], fr_strerror()); talloc_free(c); continue; } else { char buffer[256]; ip_ntoh(&c->ipaddr, buffer, sizeof(buffer)); c->longname = talloc_strdup(c, buffer); } if (c->prefix < 0) switch (c->ipaddr.af) { case AF_INET: c->prefix = 32; break; case AF_INET6: c->prefix = 128; break; default: break; } /* * Other values (secret, shortname, nastype, virtual_server) */ c->secret = talloc_strdup(c, row[4]); c->shortname = talloc_strdup(c, row[2]); if(row[3] != NULL) c->nastype = strdup(row[3]); numf = (inst->module->sql_num_fields)(handle, inst->config); if ((numf > 5) && (row[5] != NULL) && *row[5]) c->server = strdup(row[5]); DEBUG("rlm_sql (%s): Adding client %s (%s, server=%s) to clients list", inst->config->xlat_name, c->longname,c->shortname, c->server ? c->server : "<none>"); if (!client_add(NULL, c)) { sql_release_socket(inst, handle); DEBUG("rlm_sql (%s): Failed to add client %s (%s) to clients list. Maybe there's a duplicate?", inst->config->xlat_name, c->longname,c->shortname); client_free(c); return -1; } } (inst->module->sql_finish_select_query)(handle, inst->config); sql_release_socket(inst, handle); return 0; }
/* * member of the radius group? */ static rlm_rcode_t mod_authorize(UNUSED void *instance, REQUEST *request) { struct passwd *userdata = NULL; struct group *groupdata = NULL; int ismember = 0; RADCLIENT *rad_client = NULL; uuid_t uuid; uuid_t guid_sacl; uuid_t guid_nasgroup; int err; char host_ipaddr[128] = {0}; if (!request || !request->username) { RDEBUG("OpenDirectory requires a User-Name attribute."); return RLM_MODULE_NOOP; } /* resolve SACL */ uuid_clear(guid_sacl); groupdata = getgrnam(kRadiusSACLName); if (groupdata != NULL) { err = mbr_gid_to_uuid(groupdata->gr_gid, guid_sacl); if (err != 0) { ERROR("rlm_opendirectory: The group \"%s\" does not have a GUID.", kRadiusSACLName); return RLM_MODULE_FAIL; } } else { RDEBUG("The SACL group \"%s\" does not exist on this system.", kRadiusSACLName); } /* resolve client access list */ uuid_clear(guid_nasgroup); rad_client = request->client; #if 0 if (rad_client->community[0] != '\0' ) { /* * The "community" can be a GUID (Globally Unique ID) or * a group name */ if (uuid_parse(rad_client->community, guid_nasgroup) != 0) { /* attempt to resolve the name */ groupdata = getgrnam(rad_client->community); if (!groupdata) { AUTH("rlm_opendirectory: The group \"%s\" does not exist on this system.", rad_client->community); return RLM_MODULE_FAIL; } err = mbr_gid_to_uuid(groupdata->gr_gid, guid_nasgroup); if (err != 0) { AUTH("rlm_opendirectory: The group \"%s\" does not have a GUID.", rad_client->community); return RLM_MODULE_FAIL; } } } else #endif { if (!rad_client) { RDEBUG("The client record could not be found for host %s.", ip_ntoh(&request->packet->src_ipaddr, host_ipaddr, sizeof(host_ipaddr))); } else { RDEBUG("The host %s does not have an access group.", ip_ntoh(&request->packet->src_ipaddr, host_ipaddr, sizeof(host_ipaddr))); } } if (uuid_is_null(guid_sacl) && uuid_is_null(guid_nasgroup)) { RDEBUG("no access control groups, all users allowed."); if (pairfind(request->config_items, PW_AUTH_TYPE, 0, TAG_ANY) == NULL) { pairmake_config("Auth-Type", kAuthType, T_OP_EQ); RDEBUG("Setting Auth-Type = %s", kAuthType); } return RLM_MODULE_OK; } /* resolve user */ uuid_clear(uuid); userdata = getpwnam(request->username->vp_strvalue); if (userdata != NULL) { err = mbr_uid_to_uuid(userdata->pw_uid, uuid); if (err != 0) uuid_clear(uuid); } if (uuid_is_null(uuid)) { REDEBUG("Could not get the user's uuid", T_OP_EQ); return RLM_MODULE_NOTFOUND; } if (!uuid_is_null(guid_sacl)) { err = mbr_check_service_membership(uuid, kRadiusServiceName, &ismember); if (err != 0) { REDEBUG("Failed to check group membership", T_OP_EQ); return RLM_MODULE_FAIL; } if (ismember == 0) { REDEBUG("User is not authorized", T_OP_EQ); return RLM_MODULE_USERLOCK; } } if (!uuid_is_null(guid_nasgroup)) { err = mbr_check_membership_refresh(uuid, guid_nasgroup, &ismember); if (err != 0) { REDEBUG("Failed to check group membership", T_OP_EQ); return RLM_MODULE_FAIL; } if (ismember == 0) { REDEBUG("User is not authorized", T_OP_EQ); return RLM_MODULE_USERLOCK; } } if (pairfind(request->config_items, PW_AUTH_TYPE, 0, TAG_ANY) == NULL) { pairmake_config("Auth-Type", kAuthType, T_OP_EQ); RDEBUG("Setting Auth-Type = %s", kAuthType); } return RLM_MODULE_OK; }
/* * Recieve packets from a proxy socket. */ static int proxy_socket_recv(rad_listen_t *listener, RAD_REQUEST_FUNP *pfun, REQUEST **prequest) { REQUEST *request; RADIUS_PACKET *packet; char buffer[128]; RAD_REQUEST_FUNP fun = NULL; packet = rad_recv(listener->fd, 0); if (!packet) { radlog(L_ERR, "%s", fr_strerror()); return 0; } /* * FIXME: Client MIB updates? */ switch(packet->code) { case PW_AUTHENTICATION_ACK: case PW_ACCESS_CHALLENGE: case PW_AUTHENTICATION_REJECT: #ifdef WITH_ACCOUNTING case PW_ACCOUNTING_RESPONSE: #endif break; #ifdef WITH_COA case PW_DISCONNECT_ACK: case PW_DISCONNECT_NAK: case PW_COA_ACK: case PW_COA_NAK: break; #endif default: /* * FIXME: Update MIB for packet types? */ radlog(L_ERR, "Invalid packet code %d sent to a proxy port " "from home server %s port %d - ID %d : IGNORED", packet->code, ip_ntoh(&packet->src_ipaddr, buffer, sizeof(buffer)), packet->src_port, packet->id); rad_free(&packet); return 0; } request = received_proxy_response(packet); if (!request) { return 0; } rad_assert(request->process != NULL); #ifdef WITH_COA /* * Distinguish proxied CoA requests from ones we * originate. If we've proxied a DIFFERENT packet type * than the original, then it MUST be a CoA packet. In * that case, we process it as a CoA reply packet, rather * than re-running the original method. */ if (request->packet->code != request->proxy->code) { rad_assert((request->proxy->code == PW_COA_REQUEST) || (request->proxy->code == PW_DISCONNECT_REQUEST)); fun = rad_coa_reply; /* run NEW function */ } else #endif *pfun = request->process; /* re-run original function */ *prequest = request; return 1; }
/* * Recieve packets from a proxy socket. */ static int proxy_socket_recv(rad_listen_t *listener, RAD_REQUEST_FUNP *pfun, REQUEST **prequest) { REQUEST *request; RADIUS_PACKET *packet; char buffer[128]; RAD_REQUEST_FUNP fun = NULL; packet = rad_recv(listener->fd, 0); if (!packet) { radlog(L_ERR, "%s", fr_strerror()); return 0; } /* * FIXME: Client MIB updates? */ switch(packet->code) { case PW_AUTHENTICATION_ACK: case PW_ACCESS_CHALLENGE: case PW_AUTHENTICATION_REJECT: #ifdef WITH_ACCOUNTING case PW_ACCOUNTING_RESPONSE: #endif break; #ifdef WITH_COA case PW_DISCONNECT_ACK: case PW_DISCONNECT_NAK: case PW_COA_ACK: case PW_COA_NAK: fun = rad_coa_reply; /* run NEW function */ break; #endif default: /* * FIXME: Update MIB for packet types? */ radlog(L_ERR, "Invalid packet code %d sent to a proxy port " "from home server %s port %d - ID %d : IGNORED", packet->code, ip_ntoh(&packet->src_ipaddr, buffer, sizeof(buffer)), packet->src_port, packet->id); rad_free(&packet); return 0; } request = received_proxy_response(packet); if (!request) { return 0; } rad_assert(request->process != NULL); #ifdef WITH_COA if (!fun) #endif fun = request->process; /* re-run original function */ *pfun = fun; *prequest = request; return 1; }
process netin(void) { status retval; /* return value from function */ recv_packets = 0; /* initialize */ netbufpool = mkbufpool(PACKLEN, UDP_SLOTS * UDP_QSIZ + ICMP_SLOTS * ICMP_QSIZ + ICMP_OQSIZ + 1); if (netbufpool == SYSERR) { kprintf("Cannot allocate network buffer pool"); kill(getpid()); } /* Copy Ethernet address to global variable */ control(ETHER0, ETH_CTRL_GET_MAC, (int32)NetData.ethaddr, 0); /* Indicate that IP address, mask, and router are not yet valid */ NetData.ipvalid = FALSE; NetData.ipaddr = 0; NetData.addrmask = 0; NetData.routeraddr = 0; /* Initialize ARP cache */ arp_init(); /* Initialize UDP table */ udp_init(); currpkt = (struct netpacket *)getbuf(netbufpool); /* Do forever: read packets from the network and process */ //kprintf("[netin]: start to read packets\r\n"); while(1) { retval = read(ETHER0, (char *)currpkt, PACKLEN); if (retval == SYSERR) { panic("Ethernet read error"); } /* Convert Ethernet Type to host order */ eth_ntoh(currpkt); /* Demultiplex on Ethernet type */ switch (currpkt->net_ethtype) { case ETH_ARP: arp_in(); /* Handle an ARP packet */ continue; case ETH_IP: /* Convert IP packet to host order */ if (ipcksum(currpkt) != 0) { kprintf("checksum failed\n\r"); continue; } if (currpkt->net_ipvh != 0x45) { kprintf("version failed\n\r"); continue; } /* Convert IP packet to host byte order */ ip_ntoh(currpkt); if ( (currpkt->net_ipdst != IP_BCAST) && (NetData.ipvalid) && (currpkt->net_ipdst != NetData.ipaddr) ) { continue; } /* Demultiplex UDP and ignore others */ if (currpkt->net_ipproto == IP_UDP) { //kprintf("[netin]: UDP# %d\r\n", ++recv_packets); udp_in();/* Handle a UDP packet */ } continue; default: /* Ignore all other Ethernet types */ kprintf("\n"); continue; } } }
RADCLIENT *client_from_request(RADCLIENT_LIST *clients, REQUEST *request) { int i, *pi; char **p; RADCLIENT *c; char buffer[128]; if (!clients || !request) return NULL; c = talloc_zero(clients, RADCLIENT); c->cs = request->client->cs; c->ipaddr.af = AF_UNSPEC; c->src_ipaddr.af = AF_UNSPEC; for (i = 0; dynamic_config[i].name != NULL; i++) { DICT_ATTR const *da; VALUE_PAIR *vp; da = dict_attrbyname(dynamic_config[i].name); if (!da) { DEBUG("- Cannot add client %s: attribute \"%s\"is not in the dictionary", ip_ntoh(&request->packet->src_ipaddr, buffer, sizeof(buffer)), dynamic_config[i].name); error: client_free(c); return NULL; } vp = pairfind(request->config_items, da->attr, da->vendor, TAG_ANY); if (!vp) { /* * Not required. Skip it. */ if (!dynamic_config[i].dflt) continue; DEBUG("- Cannot add client %s: Required attribute \"%s\" is missing.", ip_ntoh(&request->packet->src_ipaddr, buffer, sizeof(buffer)), dynamic_config[i].name); goto error; } switch (dynamic_config[i].type) { case PW_TYPE_IPV4_ADDR: if (da->attr == PW_FREERADIUS_CLIENT_IP_ADDRESS) { c->ipaddr.af = AF_INET; c->ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr; c->ipaddr.prefix = 32; } else if (da->attr == PW_FREERADIUS_CLIENT_SRC_IP_ADDRESS) { #ifdef WITH_UDPFROMTO c->src_ipaddr.af = AF_INET; c->src_ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr; #else WARN("Server not built with udpfromto, ignoring FreeRADIUS-Client-Src-IP-Address"); #endif } break; case PW_TYPE_IPV6_ADDR: if (da->attr == PW_FREERADIUS_CLIENT_IPV6_ADDRESS) { c->ipaddr.af = AF_INET6; c->ipaddr.ipaddr.ip6addr = vp->vp_ipv6addr; c->ipaddr.prefix = 128; } else if (da->attr == PW_FREERADIUS_CLIENT_SRC_IPV6_ADDRESS) { #ifdef WITH_UDPFROMTO c->src_ipaddr.af = AF_INET6; c->src_ipaddr.ipaddr.ip6addr = vp->vp_ipv6addr; #else WARN("Server not built with udpfromto, ignoring FreeRADIUS-Client-Src-IPv6-Address"); #endif } break; case PW_TYPE_IPV4_PREFIX: if (da->attr == PW_FREERADIUS_CLIENT_IP_PREFIX) { c->ipaddr.af = AF_INET; memcpy(&c->ipaddr.ipaddr.ip4addr.s_addr, &(vp->vp_ipv4prefix[2]), sizeof(c->ipaddr.ipaddr.ip4addr.s_addr)); fr_ipaddr_mask(&c->ipaddr, (vp->vp_ipv4prefix[1] & 0x3f)); } break; case PW_TYPE_IPV6_PREFIX: if (da->attr == PW_FREERADIUS_CLIENT_IPV6_PREFIX) { c->ipaddr.af = AF_INET6; memcpy(&c->ipaddr.ipaddr.ip6addr, &(vp->vp_ipv6prefix[2]), sizeof(c->ipaddr.ipaddr.ip6addr)); fr_ipaddr_mask(&c->ipaddr, vp->vp_ipv6prefix[1]); } break; case PW_TYPE_STRING: p = (char **) ((char *) c + dynamic_config[i].offset); if (*p) talloc_free(*p); if (vp->vp_strvalue[0]) { *p = talloc_typed_strdup(c->cs, vp->vp_strvalue); } else { *p = NULL; } break; case PW_TYPE_BOOLEAN: pi = (int *) ((bool *) ((char *) c + dynamic_config[i].offset)); *pi = vp->vp_integer; break; default: goto error; } } if (c->ipaddr.af == AF_UNSPEC) { DEBUG("- Cannot add client %s: No IP address was specified.", ip_ntoh(&request->packet->src_ipaddr, buffer, sizeof(buffer))); goto error; } { fr_ipaddr_t addr; /* * Need to apply the same mask as we set for the client * else clients created with FreeRADIUS-Client-IPv6-Prefix * or FreeRADIUS-Client-IPv4-Prefix will fail this check. */ addr = request->packet->src_ipaddr; fr_ipaddr_mask(&addr, c->ipaddr.prefix); if (fr_ipaddr_cmp(&addr, &c->ipaddr) != 0) { char buf2[128]; DEBUG("- Cannot add client %s: IP address %s do not match", ip_ntoh(&request->packet->src_ipaddr, buffer, sizeof(buffer)), ip_ntoh(&c->ipaddr, buf2, sizeof(buf2))); goto error; } } if (!c->secret || !*c->secret) { DEBUG("- Cannot add client %s: No secret was specified.", ip_ntoh(&request->packet->src_ipaddr, buffer, sizeof(buffer))); goto error; } if (!client_validate(clients, request->client, c)) { return NULL; } if ((c->src_ipaddr.af != AF_UNSPEC) && (c->src_ipaddr.af != c->ipaddr.af)) { DEBUG("- Cannot add client %s: Client IP and src address are different IP version.", ip_ntoh(&request->packet->src_ipaddr, buffer, sizeof(buffer))); goto error; } return c; }
static RADCLIENT *client_parse(CONF_SECTION *cs, int in_server) { 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(cs, 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. */ ip_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 { ERROR("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_pton4(&c->src_ipaddr, cl_srcipaddr, 0, true, false) < 0) { cf_log_err_cs(cs, "Failed parsing src_ipaddr: %s", fr_strerror()); goto error; } break; case AF_INET6: if (fr_pton6(&c->src_ipaddr, cl_srcipaddr, 0, true, false) < 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; } 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); #ifdef WITH_DYNAMIC_CLIENTS if (c->client_server) { c->secret = talloc_typed_strdup(c, "testing123"); if (((c->ipaddr.af == AF_INET) && (c->ipaddr.prefix == 32)) || ((c->ipaddr.af == AF_INET6) && (c->ipaddr.prefix == 128))) { cf_log_err_cs(cs, "Dynamic clients MUST be a network, not a single IP address"); goto error; } return c; } #endif if (!c->secret || (c->secret[0] == '\0')) { #ifdef WITH_DHCP char const *value = NULL; CONF_PAIR *cp = cf_pair_find(cs, "dhcp"); if (cp) value = cf_pair_value(cp); /* * Secrets aren't needed for DHCP. */ if (value && (strcmp(value, "yes") == 0)) return c; #endif #ifdef WITH_TLS /* * If the client is TLS only, the secret can be * omitted. When omitted, it's hard-coded to * "radsec". See RFC 6614. */ if (c->tls_required) { c->secret = talloc_typed_strdup(cs, "radsec"); } else #endif { cf_log_err_cs(cs, "secret must be at least 1 character long"); goto error; } } #ifdef WITH_COA /* * Point the client to the home server pool, OR to the * home server. This gets around the problem of figuring * out which port to use. */ if (c->coa_name) { c->coa_pool = home_pool_byname(c->coa_name, HOME_TYPE_COA); if (!c->coa_pool) { c->coa_server = home_server_byname(c->coa_name, HOME_TYPE_COA); } if (!c->coa_pool && !c->coa_server) { cf_log_err_cs(cs, "No such home_server or home_server_pool \"%s\"", c->coa_name); goto error; } } #endif #ifdef WITH_TCP if ((c->proto == IPPROTO_TCP) || (c->proto == IPPROTO_IP)) { if ((c->limit.idle_timeout > 0) && (c->limit.idle_timeout < 5)) c->limit.idle_timeout = 5; if ((c->limit.lifetime > 0) && (c->limit.lifetime < 5)) c->limit.lifetime = 5; if ((c->limit.lifetime > 0) && (c->limit.idle_timeout > c->limit.lifetime)) c->limit.idle_timeout = 0; } #endif return c; }
int proxy_tls_recv(rad_listen_t *listener) { int rcode; size_t length; listen_socket_t *sock = listener->data; char buffer[256]; RADIUS_PACKET *packet; RAD_REQUEST_FUNP fun = NULL; uint8_t *data; if (!sock->data) sock->data = rad_malloc(sock->ssn->offset); data = sock->data; DEBUG3("Proxy SSL socket has data to read"); PTHREAD_MUTEX_LOCK(&sock->mutex); redo: rcode = SSL_read(sock->ssn->ssl, data, 4); if (rcode <= 0) { int err = SSL_get_error(sock->ssn->ssl, rcode); switch (err) { case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: rcode = 0; goto redo; case SSL_ERROR_ZERO_RETURN: /* remote end sent close_notify, send one back */ SSL_shutdown(sock->ssn->ssl); case SSL_ERROR_SYSCALL: do_close: PTHREAD_MUTEX_UNLOCK(&sock->mutex); tls_socket_close(listener); return 0; default: while ((err = ERR_get_error())) { DEBUG("proxy recv says %s", ERR_error_string(err, NULL)); } goto do_close; } } length = (data[2] << 8) | data[3]; DEBUG3("Proxy received header saying we have a packet of %u bytes", (unsigned int) length); if (length > sock->ssn->offset) { radlog(L_INFO, "Received packet will be too large! Set \"fragment_size=%u\"", (data[2] << 8) | data[3]); goto do_close; } rcode = SSL_read(sock->ssn->ssl, data + 4, length); if (rcode <= 0) { switch (SSL_get_error(sock->ssn->ssl, rcode)) { case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: rcode = 0; break; case SSL_ERROR_ZERO_RETURN: /* remote end sent close_notify, send one back */ SSL_shutdown(sock->ssn->ssl); goto do_close; default: goto do_close; } } PTHREAD_MUTEX_UNLOCK(&sock->mutex); packet = rad_alloc(0); 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 = length; packet->data = rad_malloc(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_AUTHENTICATION_ACK: case PW_ACCESS_CHALLENGE: case PW_AUTHENTICATION_REJECT: fun = rad_authenticate; break; #ifdef WITH_ACCOUNTING case PW_ACCOUNTING_RESPONSE: fun = rad_accounting; break; #endif default: /* * FIXME: Update MIB for packet types? */ radlog(L_ERR, "Invalid packet code %d sent to a proxy port " "from home server %s port %d - ID %d : IGNORED", packet->code, ip_ntoh(&packet->src_ipaddr, buffer, sizeof(buffer)), packet->src_port, packet->id); rad_free(&packet); return 0; } if (!request_proxy_reply(packet)) { rad_free(&packet); return 0; } return 1; }
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 = rad_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, ip_ntoh(&packet->src_ipaddr, buffer, sizeof(buffer)), packet->src_port, packet->id); rad_free(&packet); return 0; } if (!request_proxy_reply(packet)) { rad_free(&packet); return 0; } return 1; }
process netin(void) { status retval; /* return value from function */ int i=0; struct ipv4_packet* ippkt = NULL; /* * FIXME : This might now work */ netbufpool = mkbufpool(PACKLEN, UDP_SLOTS * UDP_QSIZ + ICMP_SLOTS * ICMP_QSIZ + ICMP_OQSIZ + 1); if (netbufpool == SYSERR) { kprintf("Cannot allocate network buffer pool"); kill(getpid()); } /* Copy Ethernet address to global variable */ control(ETHER0, ETH_CTRL_GET_MAC, (int32)NetData.ethaddr, 0); /* Indicate that IP address, mask, and router are not yet valid */ NetData.ipvalid = FALSE; NetData.ipaddr = 0; NetData.addrmask = 0; NetData.routeraddr = 0; kprintf("My Mac is : %06x\r\n", *(NetData.ethaddr+4)); /* Initialize ARP cache */ arp_init(); /* Initialize UDP table */ udp_init(); currpkt = (struct eth_packet *)getbuf(netbufpool); /* Do forever: read packets from the network and process */ while(1) { retval = read(ETHER0, (char *)currpkt, PACKLEN); if (retval == SYSERR) { panic("Ethernet read error"); } /* Convert Ethernet Type to host order */ eth_ntoh(currpkt); /* Demultiplex on Ethernet type */ switch (currpkt->net_ethtype) { case ETH_ARP: arp_in(); /* Handle an ARP packet */ continue; case ETH_IP: //kprintf("Ip packet received \r\n"); ippkt = (struct ipv4_packet *)(currpkt->net_ethdata); if (ipcksum(ippkt) != 0) { kprintf("checksum failed\n\r"); continue; } if (ippkt->net_ipvh != 0x45) { kprintf("version failed\n\r"); continue; } /* Convert IP packet to host order */ ip_ntoh(ippkt); if ( (ippkt->net_ipdst != IP_BCAST) && (NetData.ipvalid) && (ippkt->net_ipdst != NetData.ipaddr) ) { continue; } /* Demultiplex UDP and ignore others */ if (ippkt->net_ipproto == IP_UDP) { udp_in();/* Handle a UDP packet */ }else if (ippkt->net_ipproto == IP_ICMP){ kprintf("ICMP Packet \r\n"); icmp_in();/* Handle ICMP packet */ } continue; case 0x1000: #ifdef DEBUG kprintf("Received a simulator packet\r\n"); #endif wait(rpl_sim_write_sem); memcpy((char *)&sim_queue[i], currpkt->net_ethdata, sizeof(struct rpl_sim_packet)); #ifdef DEBUG kprintf("Netin working with iter [%d] message type : %d dest : %04x source : %04x\r\n",i, sim_queue[i].msg_type, *((uint32 *)(sim_queue[i].dest_node)), *((uint32 *)(sim_queue[i].src_node))); #endif signal(rpl_sim_read_sem); i = (i+1)%RPL_SIM_RECV_QUEUE_LEN; continue; default: /* Ignore all other Ethernet types */ continue; } } }