コード例 #1
0
/*
 *	Add hints to the info sent by the terminal server
 *	based on the pattern of the username, and other attributes.
 */
static int hints_setup(PAIR_LIST *hints, REQUEST *request)
{
	char const     	*name;
	VALUE_PAIR	*add;
	VALUE_PAIR	*tmp;
	PAIR_LIST	*i;
	VALUE_PAIR	*request_pairs;
	int		updated = 0, ft;

	request_pairs = request->packet->vps;

	if (!hints || !request_pairs)
		return RLM_MODULE_NOOP;

	/*
	 *	Check for valid input, zero length names not permitted
	 */
	name = (tmp = pairfind(request_pairs, PW_USER_NAME, 0, TAG_ANY)) ?
		tmp->vp_strvalue : NULL;
	if (!name || name[0] == 0) {
		/*
		 *	No name, nothing to do.
		 */
		return RLM_MODULE_NOOP;
	}

	for (i = hints; i; i = i->next) {
		/*
		 *	Use "paircompare", which is a little more general...
		 */
		if (((strcmp(i->name, "DEFAULT") == 0) || (strcmp(i->name, name) == 0)) &&
		    (paircompare(request, request_pairs, i->check, NULL) == 0)) {
			RDEBUG2("  hints: Matched %s at %d", i->name, i->lineno);
			/*
			 *	Now add all attributes to the request list,
			 *	except PW_STRIP_USER_NAME and PW_FALL_THROUGH
			 *	and xlat them.
			 */
			add = paircopy(request->packet, i->reply);
			ft = fallthrough(add);

			pairdelete(&add, PW_STRIP_USER_NAME, 0, TAG_ANY);
			pairdelete(&add, PW_FALL_THROUGH, 0, TAG_ANY);
			radius_xlat_move(request, &request->packet->vps, &add);

			pairfree(&add);
			updated = 1;
			if (!ft) {
				break;
			}
		}
	}

	if (updated == 0) {
		return RLM_MODULE_NOOP;
	}

	return RLM_MODULE_UPDATED;
}
コード例 #2
0
ファイル: rlm_files.c プロジェクト: ehayon/freeradius-server
/*
 *	Common code called by everything below.
 */
static rlm_rcode_t file_common(rlm_files_t *inst, REQUEST *request,
		       char const *filename, fr_hash_table_t *ht,
		       VALUE_PAIR *request_pairs, VALUE_PAIR **reply_pairs)
{
	char const	*name, *match;
	VALUE_PAIR	*check_tmp;
	VALUE_PAIR	*reply_tmp;
	const PAIR_LIST	*user_pl, *default_pl;
	int		found = 0;
	PAIR_LIST	my_pl;
	char		buffer[256];

	if (!inst->key) {
		VALUE_PAIR	*namepair;

		namepair = request->username;
		name = namepair ? namepair->vp_strvalue : "NONE";
	} else {
		int len;

		len = radius_xlat(buffer, sizeof(buffer), request, inst->key, NULL, NULL);
		if (len < 0) {
			return RLM_MODULE_FAIL;
		}
		
		name = len ? buffer : "NONE";
	}

	if (!ht) return RLM_MODULE_NOOP;

	my_pl.name = name;
	user_pl = fr_hash_table_finddata(ht, &my_pl);
	my_pl.name = "DEFAULT";
	default_pl = fr_hash_table_finddata(ht, &my_pl);

	/*
	 *	Find the entry for the user.
	 */
	while (user_pl || default_pl) {
		const PAIR_LIST *pl;

		if (!default_pl && user_pl) {
			pl = user_pl;
			match = name;
			user_pl = user_pl->next;

		} else if (!user_pl && default_pl) {
			pl = default_pl;
			match = "DEFAULT";
			default_pl = default_pl->next;

		} else if (user_pl->order < default_pl->order) {
			pl = user_pl;
			match = name;
			user_pl = user_pl->next;

		} else {
			pl = default_pl;
			match = "DEFAULT";
			default_pl = default_pl->next;
		}

		if (paircompare(request, request_pairs, pl->check, reply_pairs) == 0) {
			RDEBUG2("%s: Matched entry %s at line %d",
			       filename, match, pl->lineno);
			found = 1;
			check_tmp = paircopy(request, pl->check);

			/* ctx may be reply or proxy */
			reply_tmp = paircopy(request, pl->reply);
			radius_xlat_move(request, reply_pairs, &reply_tmp);
			pairmove(request, &request->config_items, &check_tmp);
			pairfree(&reply_tmp);
			pairfree(&check_tmp);

			/*
			 *	Fallthrough?
			 */
			if (!fallthrough(pl->reply))
				break;
		}
	}

	/*
	 *	Remove server internal parameters.
	 */
	pairdelete(reply_pairs, PW_FALL_THROUGH, 0, TAG_ANY);

	/*
	 *	See if we succeeded.
	 */
	if (!found)
		return RLM_MODULE_NOOP; /* on to the next module */

	return RLM_MODULE_OK;

}
コード例 #3
0
ファイル: rlm_sql.c プロジェクト: Gejove/freeradius-server
static rlm_rcode_t rlm_sql_authorize(void *instance, REQUEST * request)
{
	int ret = RLM_MODULE_NOTFOUND;
	
	rlm_sql_t *inst = instance;
	rlm_sql_handle_t  *handle;
	
	VALUE_PAIR *check_tmp = NULL;
	VALUE_PAIR *reply_tmp = NULL;
	VALUE_PAIR *user_profile = NULL;

	int	dofallthrough = 1;
	int	rows;

	char	querystr[MAX_QUERY_LEN];

	/*
	 *  Set, escape, and check the user attr here
	 */
	if (sql_set_user(inst, request, NULL) < 0)
		return RLM_MODULE_FAIL;

	/*
	 *  Reserve a socket 
	 *
	 *  After this point use goto error or goto release to cleanup sockets
	 *  temporary pairlists and temporary attributes.
	 */
	handle = sql_get_socket(inst);
	if (handle == NULL)
		goto error;

	/*
	 *  Query the check table to find any conditions associated with 
	 *  this user/realm/whatever...
	 */
	if (inst->config->authorize_check_query &&
	    *inst->config->authorize_check_query) {
		if (!radius_xlat(querystr, sizeof(querystr), inst->config->authorize_check_query, request, sql_escape_func, inst)) {
			radlog_request(L_ERR, 0, request, "Error generating query; rejecting user");
	
			goto error;
		}
		
		rows = sql_getvpdata(inst, &handle, &check_tmp, querystr);
		if (rows < 0) {
			radlog_request(L_ERR, 0, request, "SQL query error; rejecting user");
	
			goto error;
		}
		
		/*
		 *  Only do this if *some* check pairs were returned
		 */
		if ((rows > 0) && 
		    (paircompare(request, request->packet->vps, check_tmp, &request->reply->vps) == 0)) {	
			RDEBUG2("User found in radcheck table");
			
			radius_xlat_move(request, &request->config_items, &check_tmp);
			
			ret = RLM_MODULE_OK;
		}
		
		/*
		 *  We only process reply table items if check conditions
		 *  were verified
		 */
		else
			goto skipreply;
	}
	
	if (inst->config->authorize_reply_query &&
	    *inst->config->authorize_reply_query) {
		/*
		 *  Now get the reply pairs since the paircompare matched
		 */
		if (!radius_xlat(querystr, sizeof(querystr), inst->config->authorize_reply_query, request, sql_escape_func, inst)) {
			radlog_request(L_ERR, 0, request, "Error generating query; rejecting user");
			
			goto error;
		}
		
		rows = sql_getvpdata(inst, &handle, &reply_tmp, querystr);
		if (rows < 0) {
			radlog_request(L_ERR, 0, request, "SQL query error; rejecting user");

			goto error;
		}
		
		if (rows > 0) {
			if (!inst->config->read_groups) {
				dofallthrough = fallthrough(reply_tmp);
			}
			
			RDEBUG2("User found in radreply table");
			
			radius_xlat_move(request, &request->reply->vps, &reply_tmp);
			
			ret = RLM_MODULE_OK;
		}
	}
	
	skipreply:

	/*
	 *  Clear out the pairlists
	 */
	pairfree(&check_tmp);
	pairfree(&reply_tmp);

	/*
	 *  dofallthrough is set to 1 by default so that if the user information
	 *  is not found, we will still process groups.  If the user information,
	 *  however, *is* found, Fall-Through must be set in order to process
	 *  the groups as well.
	 */
	if (dofallthrough) {
		rows = rlm_sql_process_groups(inst, request, handle, &dofallthrough);
		if (rows < 0) {
			radlog_request(L_ERR, 0, request, "Error processing groups; rejecting user");

			goto error;
		}
		
		if (rows > 0)
			ret = RLM_MODULE_OK;
	}

	/*
	 *  Repeat the above process with the default profile or User-Profile
	 */
	if (dofallthrough) {
		/*
	 	 *  Check for a default_profile or for a User-Profile.
		 */
		user_profile = pairfind(request->config_items, PW_USER_PROFILE, 0, TAG_ANY);
		
		const char *profile = user_profile ?
				      user_profile->vp_strvalue :
				      inst->config->default_profile;
			
		if (!profile || !*profile)
			goto release;
			
		RDEBUG("Checking profile %s", profile);
		
		if (sql_set_user(inst, request, profile) < 0) {
			radlog_request(L_ERR, 0, request, "Error setting profile; rejecting user");

			goto error;
		}
		
		rows = rlm_sql_process_groups(inst, request, handle, &dofallthrough);
		if (rows < 0) {
			radlog_request(L_ERR, 0, request, "Error processing profile groups; rejecting user");

			goto error;
		}
		
		if (rows > 0)
			ret = RLM_MODULE_OK;
	}
	
	goto release;
	
	error:
	ret = RLM_MODULE_FAIL;
	
	release:
	sql_release_socket(inst, handle);
		
	pairfree(&check_tmp);
	pairfree(&reply_tmp);
	
	return ret;
}
コード例 #4
0
ファイル: rlm_sql.c プロジェクト: Gejove/freeradius-server
static int rlm_sql_process_groups(rlm_sql_t *inst, REQUEST *request, rlm_sql_handle_t *handle, int *dofallthrough)
{
	VALUE_PAIR *check_tmp = NULL;
	VALUE_PAIR *reply_tmp = NULL;
	rlm_sql_grouplist_t *group_list, *group_list_tmp;
	VALUE_PAIR *sql_group = NULL;
	char    querystr[MAX_QUERY_LEN];
	int found = 0;
	int rows;

	/*
	 *	Get the list of groups this user is a member of
	 */
	if (sql_get_grouplist(inst, handle, request, &group_list) < 0) {
		radlog_request(L_ERR, 0, request, "Error retrieving group list");
		return -1;
	}

	for (group_list_tmp = group_list; group_list_tmp != NULL && *dofallthrough != 0; group_list_tmp = group_list_tmp->next) {
		/*
		 *	Add the Sql-Group attribute to the request list so we know
		 *	which group we're retrieving attributes for
		 */
		sql_group = pairmake("Sql-Group", group_list_tmp->groupname, T_OP_EQ);
		if (!sql_group) {
			radlog_request(L_ERR, 0, request,
				       "Error creating Sql-Group attribute");
			sql_grouplist_free(&group_list);
			return -1;
		}
		pairadd(&request->packet->vps, sql_group);
		if (!radius_xlat(querystr, sizeof(querystr), inst->config->authorize_group_check_query, request, sql_escape_func, inst)) {
			radlog_request(L_ERR, 0, request,
				       "Error generating query; rejecting user");
			/* Remove the grouup we added above */
			pairdelete(&request->packet->vps, PW_SQL_GROUP, 0, TAG_ANY);
			sql_grouplist_free(&group_list);
			return -1;
		}
		rows = sql_getvpdata(inst, &handle, &check_tmp, querystr);
		if (rows < 0) {
			radlog_request(L_ERR, 0, request, "Error retrieving check pairs for group %s",
			       group_list_tmp->groupname);
			/* Remove the grouup we added above */
			pairdelete(&request->packet->vps, PW_SQL_GROUP, 0, TAG_ANY);
			pairfree(&check_tmp);
			sql_grouplist_free(&group_list);
			return -1;
		} else if (rows > 0) {
			/*
			 *	Only do this if *some* check pairs were returned
			 */
			if (paircompare(request, request->packet->vps, check_tmp, &request->reply->vps) == 0) {
				found = 1;
				RDEBUG2("User found in group %s",
					group_list_tmp->groupname);
				/*
				 *	Now get the reply pairs since the paircompare matched
				 */
				if (!radius_xlat(querystr, sizeof(querystr), inst->config->authorize_group_reply_query, request, sql_escape_func, inst)) {
					radlog_request(L_ERR, 0, request, "Error generating query; rejecting user");
					/* Remove the grouup we added above */
					pairdelete(&request->packet->vps, PW_SQL_GROUP, 0, TAG_ANY);
					pairfree(&check_tmp);
					sql_grouplist_free(&group_list);
					return -1;
				}
				if (sql_getvpdata(inst, &handle, &reply_tmp, querystr) < 0) {
					radlog_request(L_ERR, 0, request, "Error retrieving reply pairs for group %s",
					       group_list_tmp->groupname);
					/* Remove the grouup we added above */
					pairdelete(&request->packet->vps, PW_SQL_GROUP, 0, TAG_ANY);
					pairfree(&check_tmp);
					pairfree(&reply_tmp);
					sql_grouplist_free(&group_list);
					return -1;
				}
				*dofallthrough = fallthrough(reply_tmp);
				radius_xlat_move(request, &request->reply->vps, &reply_tmp);
				radius_xlat_move(request, &request->config_items, &check_tmp);
			}
		} else {
			/*
			 *	rows == 0.  This is like having the username on a line
			 * 	in the user's file with no check vp's.  As such, we treat
			 *	it as found and add the reply attributes, so that we
			 *	match expected behavior
			 */
			found = 1;
			RDEBUG2("User found in group %s",
				group_list_tmp->groupname);
			/*
			 *	Now get the reply pairs since the paircompare matched
			 */
			if (!radius_xlat(querystr, sizeof(querystr), inst->config->authorize_group_reply_query, request, sql_escape_func, inst)) {
				radlog_request(L_ERR, 0, request, "Error generating query; rejecting user");
				/* Remove the grouup we added above */
				pairdelete(&request->packet->vps, PW_SQL_GROUP, 0, TAG_ANY);
				pairfree(&check_tmp);
				sql_grouplist_free(&group_list);
				return -1;
			}
			if (sql_getvpdata(inst, &handle, &reply_tmp, querystr) < 0) {
				radlog_request(L_ERR, 0, request, "Error retrieving reply pairs for group %s",
				       group_list_tmp->groupname);
				/* Remove the grouup we added above */
				pairdelete(&request->packet->vps, PW_SQL_GROUP, 0, TAG_ANY);
				pairfree(&check_tmp);
				pairfree(&reply_tmp);
				sql_grouplist_free(&group_list);
				return -1;
			}
			*dofallthrough = fallthrough(reply_tmp);
			radius_xlat_move(request, &request->reply->vps, &reply_tmp);
			radius_xlat_move(request, &request->config_items, &check_tmp);
		}

		/*
		 * Delete the Sql-Group we added above
		 * And clear out the pairlists
		 */
		pairdelete(&request->packet->vps, PW_SQL_GROUP, 0, TAG_ANY);
		pairfree(&check_tmp);
		pairfree(&reply_tmp);
	}

	sql_grouplist_free(&group_list);
	return found;
}
コード例 #5
0
/*
 *	Common attr_filter checks
 */
static rlm_rcode_t attr_filter_common(void *instance, REQUEST *request,
                                      RADIUS_PACKET *packet)
{
    rlm_attr_filter_t *inst = instance;
    VALUE_PAIR	*vp;
    VALUE_PAIR	*output;
    VALUE_PAIR	**output_tail;
    VALUE_PAIR	*check_item;
    PAIR_LIST	*pl;
    int		found = 0;
    int		pass, fail = 0;
    char		*keyname = NULL;
    VALUE_PAIR	**input;
    char		buffer[256];

    if (!packet) return RLM_MODULE_NOOP;

    input = &(packet->vps);

    if (!inst->key) {
        VALUE_PAIR	*namepair;

        namepair = pairfind(request->packet->vps, PW_REALM, 0, TAG_ANY);
        if (!namepair) {
            return (RLM_MODULE_NOOP);
        }
        keyname = namepair->vp_strvalue;
    } else {
        int len;

        len = radius_xlat(buffer, sizeof(buffer), inst->key,
                          request, NULL, NULL);
        if (!len) {
            return RLM_MODULE_NOOP;
        }
        keyname = buffer;
    }

    output = NULL;
    output_tail = &output;

    /*
     *      Find the attr_filter profile entry for the entry.
     */
    for (pl = inst->attrs; pl; pl = pl->next) {
        int fall_through = 0;
        int relax_filter = inst->relaxed;

        /*
         *  If the current entry is NOT a default,
         *  AND the realm does NOT match the current entry,
         *  then skip to the next entry.
         */
        if ((strcmp(pl->name, "DEFAULT") != 0) &&
                (strcmp(keyname, pl->name) != 0))  {
            continue;
        }

        RDEBUG2("Matched entry %s at line %d", pl->name,
                pl->lineno);
        found = 1;

        for (check_item = pl->check;
                check_item != NULL;
                check_item = check_item->next) {
            if (!check_item->da->vendor &&
                    (check_item->da->attr == PW_FALL_THROUGH) &&
                    (check_item->vp_integer == 1)) {
                fall_through = 1;
                continue;
            }
            else if (!check_item->da->vendor &&
                     check_item->da->attr == PW_RELAX_FILTER) {
                relax_filter = check_item->vp_integer;
                continue;
            }

            /*
             *    If it is a SET operator, add the attribute to
             *    the output list without checking it.
             */
            if (check_item->op == T_OP_SET ) {
                vp = paircopyvp(packet, check_item);
                if (!vp) {
                    pairfree(&output);
                    return RLM_MODULE_FAIL;
                }
                radius_xlat_move(request, output_tail, &vp);
                output_tail = &((*output_tail)->next);
            }
        }

        /*
         *	Iterate through the input items, comparing
         *	each item to every rule, then moving it to the
         *	output list only if it matches all rules
         *	for that attribute.  IE, Idle-Timeout is moved
         *	only if it matches all rules that describe an
         *	Idle-Timeout.
         */
        for (vp = *input; vp != NULL; vp = vp->next ) {
            /* reset the pass,fail vars for each reply item */
            pass = fail = 0;

            /*
             *	reset the check_item pointer to
             *	beginning of the list
             */
            for (check_item = pl->check;
                    check_item != NULL;
                    check_item = check_item->next) {
                /*
                 *	Vendor-Specific is special, and
                 *	matches any VSA if the comparison
                 *	is always true.
                 */
                if ((check_item->da->attr == PW_VENDOR_SPECIFIC) &&
                        (vp->da->vendor != 0) &&
                        (check_item->op == T_OP_CMP_TRUE)) {
                    pass++;
                    continue;
                }

                if (vp->da->attr == check_item->da->attr) {
                    check_pair(check_item, vp,
                               &pass, &fail);
                }
            }

            /*
             *  Only move attribute if it passed all rules,
             *  or if the config says we should copy unmatched
             *  attributes ('relaxed' mode).
             */
            if (fail == 0 && (pass > 0 || relax_filter)) {
                if (!pass) {
                    RDEBUG3("Attribute (%s) allowed by relaxed mode", vp->da->name);
                }
                *output_tail = paircopyvp(packet, vp);
                if (!*output_tail) {
                    pairfree(&output);
                    return RLM_MODULE_FAIL;
                }
                output_tail = &((*output_tail)->next);
            }
        }

        /* If we shouldn't fall through, break */
        if (!fall_through)
            break;
    }

    /*
     *	No entry matched.  We didn't do anything.
     */
    if (!found) {
        rad_assert(!output);
        return RLM_MODULE_NOOP;
    }

    pairfree(input);
    *input = output;

    if (request->packet->code == PW_AUTHENTICATION_REQUEST) {
        request->username = pairfind(request->packet->vps, PW_STRIPPED_USER_NAME, 0, TAG_ANY);
        if (!request->username)
            request->username = pairfind(request->packet->vps, PW_USER_NAME, 0, TAG_ANY);
        request->password = pairfind(request->packet->vps, PW_USER_PASSWORD, 0, TAG_ANY);
    }

    return RLM_MODULE_UPDATED;
}
コード例 #6
0
static rlm_rcode_t rlm_sql_process_groups(rlm_sql_t *inst, REQUEST *request, rlm_sql_handle_t *handle,
					  int *dofallthrough)
{
	rlm_rcode_t		rcode = RLM_MODULE_NOOP;
	VALUE_PAIR		*check_tmp = NULL, *reply_tmp = NULL, *sql_group = NULL;
	rlm_sql_grouplist_t	*head = NULL, *entry = NULL;

	char			*expanded = NULL;
	int			rows;

	/*
	 *	Get the list of groups this user is a member of
	 */
	if (sql_get_grouplist(inst, handle, request, &head) < 0) {
		REDEBUG("Error retrieving group list");

		return RLM_MODULE_FAIL;
	}

	for (entry = head; entry != NULL && *dofallthrough != 0; entry = entry->next) {
		/*
		 *	Add the Sql-Group attribute to the request list so we know
		 *	which group we're retrieving attributes for
		 */
		sql_group = pairmake_packet("Sql-Group", entry->name, T_OP_EQ);
		if (!sql_group) {
			REDEBUG("Error creating Sql-Group attribute");
			rcode = RLM_MODULE_FAIL;

			goto finish;
		}

		/*
		 *	Expand the group query
		 */
		if (radius_axlat(&expanded, request, inst->config->authorize_group_check_query, sql_escape_func,
				inst) < 0) {
			REDEBUG("Error generating query");
			rcode = RLM_MODULE_FAIL;

			goto finish;
		}

		rows = sql_getvpdata(inst, &handle, request, &check_tmp, expanded);
		TALLOC_FREE(expanded);
		if (rows < 0) {
			REDEBUG("Error retrieving check pairs for group %s", entry->name);
			rcode = RLM_MODULE_FAIL;

			goto finish;
		}

		/*
		 *	If we got check rows we need to process them before we decide to process the reply rows
		 */
		if ((rows > 0) && (paircompare(request, request->packet->vps, check_tmp, &request->reply->vps) != 0)) {
			pairfree(&check_tmp);
			pairdelete(&request->packet->vps, PW_SQL_GROUP, 0, TAG_ANY);

			continue;
		}

		RDEBUG2("User found in= RLM_MODULE_OK; group %s", entry->name);

		/*
		 *	Now get the reply pairs since the paircompare matched
		 */
		if (radius_axlat(&expanded, request, inst->config->authorize_group_reply_query, sql_escape_func,
				inst) < 0) {
			REDEBUG("Error generating query");
			rcode = RLM_MODULE_FAIL;

			goto finish;
		}

		if (sql_getvpdata(inst, &handle, request->reply, &reply_tmp, expanded) < 0) {
			REDEBUG("Error retrieving reply pairs for group %s", entry->name);
			rcode = RLM_MODULE_FAIL;

			goto finish;
		}

		*dofallthrough = fallthrough(reply_tmp);

		pairdelete(&request->packet->vps, PW_SQL_GROUP, 0, TAG_ANY);

		radius_xlat_move(request, &request->reply->vps, &reply_tmp);
		reply_tmp = NULL;

		radius_xlat_move(request, &request->config_items, &check_tmp);
		check_tmp = NULL;
	}

	finish:

	talloc_free(expanded);
	talloc_free(head);

	pairdelete(&request->packet->vps, PW_SQL_GROUP, 0, TAG_ANY);
	pairfree(&check_tmp);

	return rcode;
}