コード例 #1
0
/** Convert module specific attribute id to value_pair_tmpl_t.
 *
 * @param[in] name string to convert.
 * @param[in] type Type of quoting around value.
 * @return pointer to new VPT.
 */
value_pair_tmpl_t *radius_str2tmpl(const char *name, FR_TOKEN type)
{
	value_pair_tmpl_t *vpt;
	
	vpt = rad_calloc(sizeof(value_pair_tmpl_t));
	vpt->name = strdup(name);
	
	switch (type)
	{
		case T_BARE_WORD:
		case T_SINGLE_QUOTED_STRING:
			vpt->type = VPT_TYPE_LITERAL;
			break;
		case T_DOUBLE_QUOTED_STRING:
			vpt->type = VPT_TYPE_XLAT;	
			break;
		case T_BACK_QUOTED_STRING:
			vpt->type = VPT_TYPE_EXEC;
			break;
		default:
			rad_assert(0);
			return NULL;
	}
	
	return vpt;
}
コード例 #2
0
/** Parse qualifiers to convert attrname into a value_pair_tmpl_t.
 *
 * VPTs are used in various places where we need to pre-parse configuration 
 * sections into attribute mappings.
 *
 * @param[in] name attribute name including qualifiers.
 * @param[in] request_def The default request to insert unqualified 
 *	attributes into.
 * @param[in] list_def The default list to insert unqualified attributes into.
 * @return pointer to a value_pair_tmpl_t struct (must be freed with 
 *	radius_tmplfree) or NULL on error.
 */
value_pair_tmpl_t *radius_attr2tmpl(const char *name,
				    request_refs_t request_def,
				    pair_lists_t list_def)
{
	value_pair_tmpl_t *vpt;
	const char *copy = strdup(name);
	
	vpt = rad_calloc(sizeof(value_pair_tmpl_t));
	
	if (radius_parse_attr(copy, vpt, request_def, list_def) < 0) {
		radius_tmplfree(&vpt);
		return NULL;
	}
	
	return vpt;
}
コード例 #3
0
/** Convert CONFIG_PAIR (which may contain refs) to value_pair_map_t.
 *
 * Treats the left operand as an attribute reference
 * @verbatim<request>.<list>.<attribute>@endverbatim 
 *
 * Treatment of left operand depends on quotation, barewords are treated as
 * attribute references, double quoted values are treated as expandable strings,
 * single quoted values are treated as literal strings.
 *
 * Return must be freed with radius_mapfree.
 *
 * @param[in] cp to convert to map.
 * @param[in] dst_request_def The default request to insert unqualified
 *	attributes into.
 * @param[in] dst_list_def The default list to insert unqualified attributes
 *	into.
 * @param[in] src_request_def The default request to resolve attribute
 *	references in.
 * @param[in] src_list_def The default list to resolve unqualified attributes
 *	in.
 * @return value_pair_map_t if successful or NULL on error.
 */
value_pair_map_t *radius_cp2map(CONF_PAIR *cp,
				request_refs_t dst_request_def,
				pair_lists_t dst_list_def,
				request_refs_t src_request_def,
				pair_lists_t src_list_def)
{
	value_pair_map_t *map;
	const char *attr;
	const char *value;
	FR_TOKEN type;
	CONF_ITEM *ci = cf_pairtoitem(cp); 
	
	if (!cp) return NULL;
	
	map = rad_calloc(sizeof(value_pair_map_t));

	attr = cf_pair_attr(cp);
	value = cf_pair_value(cp);
	if (!value) {
		cf_log_err(ci, "Missing attribute value");
		
		goto error;
	}
	
	map->dst = radius_attr2tmpl(attr, dst_request_def, dst_list_def);
	if (!map->dst){
		goto error;
	}

	/*
	 *	Bare words always mean attribute references.
	 */
	type = cf_pair_value_type(cp);
	map->src = type == T_BARE_WORD ?
		   radius_attr2tmpl(value, src_request_def, src_list_def) :
		   radius_str2tmpl(value, type);

	if (!map->src) {
		goto error;
	}

	map->op = cf_pair_operator(cp);
	map->ci = ci;
	
	/*
	 *	Lots of sanity checks for insane people...
	 */
	 
	/*
	 *	We don't support implicit type conversion
	 */
	if (map->dst->da && map->src->da &&
	    (map->src->da->type != map->dst->da->type)) {
		cf_log_err(ci, "Attribute type mismatch");
		
		goto error;
	}
	
	/*
	 *	What exactly where you expecting to happen here?
	 */
	if ((map->dst->type == VPT_TYPE_ATTR) &&
	    (map->src->type == VPT_TYPE_LIST)) {
		cf_log_err(ci, "Can't copy list into an attribute");
		
		goto error;
	}

	switch (map->src->type) 
	{
	
		/*
		 *	Only += and -= operators are supported for list copy.
		 */
		case VPT_TYPE_LIST:
			switch (map->op) {
			case T_OP_SUB:
			case T_OP_ADD:
				break;
			
			default:
				cf_log_err(ci, "Operator \"%s\" not allowed "
					   "for list copy",
					   fr_int2str(fr_tokens, map->op,
						      "¿unknown?"));
				goto error;
			}
		break;
		/*
		 *	@todo add support for exec expansion.
		 */
		case VPT_TYPE_EXEC:
			cf_log_err(ci, "Exec values are not allowed");
			break;
		default:
			break;
	}
	
	return map;
	
	error:
		radius_mapfree(&map);
		return NULL;
}
コード例 #4
0
static int krb5_instantiate(CONF_SECTION *conf, void **instance)
{
	rlm_krb5_t *inst;
	krb5_error_code ret;
	
	krb5_context *context;
	char *princ_name;
	
#ifndef HEIMDAL_KRB5
	radlog(L_ERR, "rlm_krb5 (*): Using MIT Kerberos library");
#else
	radlog(L_ERR, "rlm_krb5 (*): Using Heimdal Kerberos library");
#endif
	/*
 	 *	@todo Update configure script to call krb5_is_thread_safe,
 	 *	this should really be a warning.
 	 */
	if (!krb5_is_thread_safe()) {
		radlog(L_ERR, "rlm_krb5 (*): krb5 library is not threadsafe, "
		       "please recompile it with thread support enabled");
		       
		return -1;
	}

	inst = rad_calloc(sizeof(*inst));
	if (cf_section_parse(conf, inst, module_config) < 0) {
		free(inst);
		return -1;
	}
	
	inst->xlat_name = cf_section_name2(conf);
	if (!inst->xlat_name) {
		inst->xlat_name = cf_section_name1(conf);
	}

	rad_assert(inst->xlat_name);
	
	context = inst->context = rad_calloc(sizeof(*context));
	ret = krb5_init_context(context);
	if (ret) {
		radlog(L_ERR, "rlm_krb5 (%s): Context initialisation "
		       "failed: %s", inst->xlat_name, error_message(ret));
  
		goto error;
	} else {
		radlog(L_DBG, "rlm_krb5 (%s): Context initialised "
		       "successfully", inst->xlat_name);
	}
	
	/*
	 *	Split service principal into service and host components
	 *	they're needed to build the server principal in MIT,
	 *	and to set the validation service in Heimdal.
	 */
	if (inst->service_princ) {
		size_t len;
		/* Service principal appears to contain a host component */
		inst->hostname = strchr(inst->service_princ, '/');
		if (inst->hostname) {	
			len = (inst->hostname - inst->service_princ);			
			inst->hostname++;
		} else {
			len = SERVICE_NAME_LEN;
		}
		
		if (len) {
			inst->service = rad_malloc(len + 1);
			strlcpy(inst->service, inst->service_princ, len);
		}
	}
	
#ifndef HEIMDAL_KRB5
	/*
	 *	Convert the service principal string to a krb5 principal.
	 */
	ret = krb5_sname_to_principal(*context, inst->hostname,
				      inst->service, KRB5_NT_SRV_HST,
				      &(inst->server));
	if (ret) {
		radlog(L_ERR, "rlm_krb5 (%s): Failed parsing service "
		       "principal: %s", inst->xlat_name, error_message(ret));

		goto error;
	}
	
	ret = krb5_unparse_name(*context, inst->server, &princ_name);
	if (ret) {
		/* Uh? */
		radlog(L_ERR, "rlm_krb5 (%s): Failed constructing service "
		       "principal string: %s", inst->xlat_name,
		       error_message(ret));

		goto error;
	}
	
	/*
	 *	Not necessarily the same as the config item
	 */
	radlog(L_DBG, "rlm_krb5 (%s): Using service principal \"%s\"",
	       inst->xlat_name, princ_name);
	       
	krb5_free_unparsed_name(*context, princ_name);
	
	/*
	 *	Setup options for getting credentials and verifying them
	 */
	 
	/* For some reason the 'init' version of this function is deprecated */
	ret = krb5_get_init_creds_opt_alloc(*context, &(inst->gic_options));
	if (ret) {
		radlog(L_ERR, "rlm_krb5 (%s): Couldn't allocated inital "
		       "credential options: %s", inst->xlat_name,
		       error_message(ret));
		
		goto error;
	}
	
	inst->vic_options = rad_calloc(sizeof(*(inst->vic_options)));
	if (!inst->vic_options) goto error;
	
	krb5_verify_init_creds_opt_init(inst->vic_options);
	krb5_verify_init_creds_opt_set_ap_req_nofail(inst->vic_options,
						     TRUE);
	
#else
	if (inst->hostname) {
		radlog(L_DBG, "rlm_krb5 (%s): Ignoring hostname component of "
		       "service principal \"%s\", not needed/supported by "
		       "Heimdal", inst->xlat_name, hostname);
	}
#endif
	 
	*instance = inst;
	return 0;
	
	error:
	krb5_detach(inst);
	return -1;
}