Exemple #1
0
static int rlm_sql_instantiate(CONF_SECTION * conf, void **instance)
{
	SQL_INST *inst;
	const char *xlat_name;

	inst = rad_malloc(sizeof(SQL_INST));
	memset(inst, 0, sizeof(SQL_INST));

	/*
	 *	Export these methods, too.  This avoids RTDL_GLOBAL.
	 */
	inst->sql_set_user		= sql_set_user;
	inst->sql_get_socket		= sql_get_socket;
	inst->sql_release_socket	= sql_release_socket;
	inst->sql_escape_func		= sql_escape_func;
	inst->sql_query			= rlm_sql_query;
	inst->sql_select_query		= rlm_sql_select_query;
	inst->sql_fetch_row		= rlm_sql_fetch_row;
	
	inst->config = rad_malloc(sizeof(SQL_CONFIG));
	memset(inst->config, 0, sizeof(SQL_CONFIG));
	inst->cs = conf;
		
	/*
	 *	If the configuration parameters can't be parsed, then fail.
	 */
	if ((cf_section_parse(conf, inst->config, module_config) < 0) ||
	    (parse_sub_section(conf, inst,
			       &inst->config->accounting,
			       RLM_COMPONENT_ACCT) < 0) ||
	    (parse_sub_section(conf, inst,
			       &inst->config->postauth,
			       RLM_COMPONENT_POST_AUTH) < 0)) {
		radlog(L_ERR, "Failed parsing configuration");
		goto error;
	}

	xlat_name = cf_section_name2(conf);
	if (xlat_name == NULL) {
		xlat_name = cf_section_name1(conf);
	} else {
		char *group_name;
		DICT_ATTR *dattr;
		ATTR_FLAGS flags;

		/*
		 *	Allocate room for <instance>-SQL-Group
		 */
		group_name = rad_malloc((strlen(xlat_name) + 1 + 11) * sizeof(char));
		sprintf(group_name,"%s-SQL-Group", xlat_name);
		DEBUG("rlm_sql Creating new attribute %s",group_name);

		memset(&flags, 0, sizeof(flags));
		dict_addattr(group_name, 0, PW_TYPE_STRING, -1, flags);
		dattr = dict_attrbyname(group_name);
		if (dattr == NULL){
			radlog(L_ERR, "rlm_sql: Failed to create attribute %s",
			       group_name);
			       
			free(group_name);

			goto error;
		}

		if (inst->config->groupmemb_query && 
		    inst->config->groupmemb_query[0]) {
			DEBUG("rlm_sql: Registering sql_groupcmp for %s",
			      group_name);
			paircompare_register(dattr->attr, PW_USER_NAME,
					     sql_groupcmp, inst);
		}

		free(group_name);
	}
	
	rad_assert(xlat_name);

	/*
	 *	Register the SQL xlat function
	 */
	inst->config->xlat_name = strdup(xlat_name);
	xlat_register(xlat_name, sql_xlat, inst);
		
	/*
	 *	Sanity check for crazy people.
	 */
	if (strncmp(inst->config->sql_driver, "rlm_sql_", 8) != 0) {
		radlog(L_ERR, "\"%s\" is NOT an SQL driver!",
		       inst->config->sql_driver);
		goto error;
	}

	/*
	 *	Load the appropriate driver for our database
	 */
	inst->handle = lt_dlopenext(inst->config->sql_driver);
	if (inst->handle == NULL) {
		radlog(L_ERR, "Could not link driver %s: %s",
		       inst->config->sql_driver,
		       lt_dlerror());
		radlog(L_ERR, "Make sure it (and all its dependent libraries!)"
		       "are in the search path of your system's ld.");

		goto error;
	}

	inst->module = (rlm_sql_module_t *) lt_dlsym(inst->handle,
						     inst->config->sql_driver);
	if (!inst->module) {
		radlog(L_ERR, "Could not link symbol %s: %s",
		       inst->config->sql_driver,
		       lt_dlerror());

		goto error;
	}

	radlog(L_INFO, "rlm_sql (%s): Driver %s (module %s) loaded and linked",
	       inst->config->xlat_name, inst->config->sql_driver,
	       inst->module->name);

	/*
	 *	Initialise the connection pool for this instance
	 */
	radlog(L_INFO, "rlm_sql (%s): Attempting to connect to %s@%s:%s/%s",
	       inst->config->xlat_name, inst->config->sql_login,
	       inst->config->sql_server, inst->config->sql_port,
	       inst->config->sql_db);
	       
	if (sql_init_socketpool(inst) < 0)
		goto error;

	if (inst->config->groupmemb_query && 
	    inst->config->groupmemb_query[0]) {
		paircompare_register(PW_SQL_GROUP, PW_USER_NAME, sql_groupcmp, inst);
	}

	if (inst->config->do_clients) {
		if (generate_sql_clients(inst) == -1){
			radlog(L_ERR, "Failed to load clients from SQL.");
			
			goto error;
		}
	}

	*instance = inst;

	return RLM_MODULE_OK;
	
	error:
	rlm_sql_detach(inst);
	
	return -1;
}
/*
 *	Do any per-module initialization that is separate to each
 *	configured instance of the module.  e.g. set up connections
 *	to external databases, read configuration files, set up
 *	dictionary entries, etc.
 *
 *	If configuration information is given in the config section
 *	that must be referenced in later calls, store a handle to it
 *	in *instance otherwise put a null pointer there.
 */
static int checkval_instantiate(CONF_SECTION *conf, void **instance)
{
	rlm_checkval_t *data;
	DICT_ATTR *dattr;
	ATTR_FLAGS flags;

	static const FR_NAME_NUMBER names[] = {
		{ "string", PW_TYPE_STRING },
		{ "integer", PW_TYPE_INTEGER },
		{ "ipaddr", PW_TYPE_IPADDR },
		{ "date", PW_TYPE_DATE },
		{ "abinary", PW_TYPE_OCTETS },
		{ "octets", PW_TYPE_OCTETS },
		{ "binary", PW_TYPE_OCTETS },
		{ NULL, 0 }
	};

	/*
	 *	Set up a storage area for instance data
	 */
	data = rad_malloc(sizeof(*data));
	if (!data) {
		return -1;
	}
	memset(data, 0, sizeof(*data));

	/*
	 *	If the configuration parameters can't be parsed, then
	 *	fail.
	 */
	if (cf_section_parse(conf, data, module_config) < 0) {
		checkval_detach(data);
		return -1;
	}

	/*
	 * Check if data_type exists
	 */
	if (!data->data_type || !*data->data_type){
		radlog(L_ERR, "rlm_checkval: Data type not defined");
		checkval_detach(data);
		return -1;
	}
	if (!data->item_name || !*data->item_name){
		radlog(L_ERR, "rlm_checkval: Item name not defined");
		checkval_detach(data);
		return -1;
	}
	if (!data->check_name || !*data->check_name){
		radlog(L_ERR, "rlm_checkval: Check item name not defined");
		checkval_detach(data);
		return -1;
	}

	/*
	 *	Discover the attribute number of the item name
	 */
	dattr = dict_attrbyname(data->item_name);
	if (!dattr) {
		radlog(L_ERR, "rlm_checkval: No such attribute %s",
		       data->item_name);
		checkval_detach(data);
		return -1;
	}
	data->item_attr = dattr;

	/*
	 *	Add the check attribute name to the dictionary
	 *	if it does not already exists. dict_addattr() handles that
	 */

	memset(&flags, 0, sizeof(flags));
	dict_addattr(data->check_name, -1, 0, PW_TYPE_STRING, flags);
	dattr = dict_attrbyname(data->check_name);
	if (!dattr){
		radlog(L_ERR, "rlm_checkval: No such attribute %s",
		       data->check_name);
		checkval_detach(data);
		return -1;
	}
	data->chk_attr = dattr;
	DEBUG2("rlm_checkval: Registered name %s for attribute %d",
		dattr->name,dattr->attr);

	/*
	 *	Convert the string type to an integer type,
	 *	so we don't have to do string comparisons on each
	 *	packet.
	 */
	data->dat_type = fr_str2int(names, data->data_type, -1);
	if (data->dat_type < 0) {
		radlog(L_ERR, "rlm_checkval: Data type %s in not known",data->data_type);
		checkval_detach(data);
		return -1;
	}

	*instance = data;

	return 0;
}
/*
 *	Main program, either pmwho or fingerd.
 */
int main(int argc, char **argv)
{
	CONF_SECTION *maincs, *cs;
	FILE *fp;
	struct radutmp rt;
	char inbuf[128];
	char othername[256];
	char nasname[1024];
	char session_id[sizeof(rt.session_id)+1];
	int fingerd = 0;
	int hideshell = 0;
	int showsid = 0;
	int rawoutput = 0;
	int radiusoutput = 0;	/* Radius attributes */
	char *p, *q;
	const char *portind;
	int c;
	unsigned int portno;
	char buffer[2048];
	const char *user = NULL;
	int user_cmp = 0;
	time_t now = 0;
	uint32_t nas_port = ~0;
	uint32_t nas_ip_address = INADDR_NONE;
	int zap = 0;

	radius_dir = RADIUS_DIR;

	while((c = getopt(argc, argv, "d:fF:nN:sSipP:crRu:U:Z")) != EOF) switch(c) {
		case 'd':
			radius_dir = optarg;
			break;
		case 'f':
			fingerd++;
			showname = 0;
			break;
		case 'F':
			radutmp_file = optarg;
			break;
		case 'h':
			usage(0);
			break;
		case 'S':
			hideshell = 1;
			break;
		case 'n':
			showname = 0;
			break;
		case 'N':
			if (inet_pton(AF_INET, optarg, &nas_ip_address) < 0) {
				usage(1);
			}
			break;
		case 's':
			showname = 1;
			break;
		case 'i':
			showsid = 1;
			break;
		case 'p':
			showptype = 1;
			break;
		case 'P':
			nas_port = atoi(optarg);
			break;
		case 'c':
			showcid = 1;
			showname = 1;
			break;
		case 'r':
			rawoutput = 1;
			break;
		case 'R':
			radiusoutput = 1;
			now = time(NULL);
			break;
		case 'u':
			user = optarg;
			user_cmp = 0;
			break;
		case 'U':
			user = optarg;
			user_cmp = 1;
			break;
		case 'Z':
			zap = 1;
			break;
		default:
			usage(1);
			break;
	}

	/*
	 *	Be safe.
	 */
	if (zap && !radiusoutput) zap = 0;

	/*
	 *	zap EVERYONE, but only on this nas
	 */
	if (zap && !user && (~nas_port == 0)) {
		/*
		 *	We need to know which NAS to zap users in.
		 */
		if (nas_ip_address == INADDR_NONE) usage(1);

		printf("Acct-Status-Type = Accounting-Off\n");
		printf("NAS-IP-Address = %s\n",
		       hostname(buffer, sizeof(buffer), nas_ip_address));
		printf("Acct-Delay-Time = 0\n");
		exit(0);	/* don't bother printing anything else */
	}

	if (radutmp_file) goto have_radutmp;

	/*
	 *	Initialize mainconfig
	 */
	memset(&mainconfig, 0, sizeof(mainconfig));
	mainconfig.radlog_dest = RADLOG_STDOUT;

        /* Read radiusd.conf */
	snprintf(buffer, sizeof(buffer), "%.200s/radiusd.conf", radius_dir);
	maincs = cf_file_read(buffer);
	if (!maincs) {
		fprintf(stderr, "%s: Error reading or parsing radiusd.conf.\n", argv[0]);
		exit(1);
	}

        /* Read the radutmp section of radiusd.conf */
        cs = cf_section_find_name2(cf_section_sub_find(maincs, "modules"), "radutmp", NULL);
        if(!cs) {
                fprintf(stderr, "%s: No configuration information in radutmp section of radiusd.conf!\n",
                        argv[0]);
                exit(1);
        }

	cf_section_parse(cs, NULL, module_config);

	/* Assign the correct path for the radutmp file */
	radutmp_file = radutmpconfig.radutmp_fn;

 have_radutmp:
	/*
	 *	See if we are "fingerd".
	 */
	if (strstr(argv[0], "fingerd")) {
		fingerd++;
		eol = "\r\n";
		if (showname < 0) showname = 0;
	}
	if (showname < 0) showname = 1;

	if (fingerd) {
		/*
		 *	Read first line of the input.
		 */
		fgets(inbuf, 128, stdin);
		p = inbuf;
		while(*p == ' ' || *p == '\t') p++;
		if (*p == '/' && *(p + 1)) p += 2;
		while(*p == ' ' || *p == '\t') p++;
		for(q = p; *q && *q != '\r' && *q != '\n'; q++)
			;
		*q = 0;

		/*
		 *	See if we fingered a specific user.
		 */
		ffile("header");
		if (*p) sys_finger(p);
	}

	/*
	 *	Show the users logged in on the terminal server(s).
	 */
	if ((fp = fopen(radutmp_file, "r")) == NULL) {
		fprintf(stderr, "%s: Error reading %s: %s\n",
			progname, radutmp_file, strerror(errno));
		return 0;
	}

	/*
	 *	Don't print the headers if raw or RADIUS
	 */
	if (!rawoutput && !radiusoutput) {
		fputs(showname ? hdr1 : hdr2, stdout);
		fputs(eol, stdout);
	}

	/*
	 *	Read the file, printing out active entries.
	 */
	while (fread(&rt, sizeof(rt), 1, fp) == 1) {
		if (rt.type != P_LOGIN) continue; /* hide logout sessions */

		/*
		 *	We don't show shell users if we are
		 *	fingerd, as we have done that above.
		 */
		if (hideshell && !strchr("PCS", rt.proto))
			continue;

		/*
		 *	Print out sessions only for the given user.
		 */
		if (user) {	/* only for a particular user */
			if (((user_cmp == 0) &&
			     (strncasecmp(rt.login, user, strlen(user)) != 0)) ||
			    ((user_cmp == 1) &&
			     (strncmp(rt.login, user, strlen(user)) != 0))) {
				continue;
			}
		}

		/*
		 *	Print out only for the given NAS port.
		 */
		if (~nas_port != 0) {
			if (rt.nas_port != nas_port) continue;
		}

		/*
		 *	Print out only for the given NAS IP address
		 */
		if (nas_ip_address != INADDR_NONE) {
			if (rt.nas_address != nas_ip_address) continue;
		}

		memcpy(session_id, rt.session_id, sizeof(rt.session_id));
		session_id[sizeof(rt.session_id)] = 0;

		if (!rawoutput && rt.nas_port > (showname ? 999 : 99999)) {
			portind = ">";
			portno = (showname ? 999 : 99999);
		} else {
			portind = "S";
			portno = rt.nas_port;
		}

		/*
		 *	Print output as RADIUS attributes
		 */
		if (radiusoutput) {
			memcpy(nasname, rt.login, sizeof(rt.login));
			nasname[sizeof(rt.login)] = '\0';

			fr_print_string(nasname, 0, buffer,
					 sizeof(buffer));
			printf("User-Name = \"%s\"\n", buffer);

			fr_print_string(session_id, 0, buffer,
					 sizeof(buffer));
			printf("Acct-Session-Id = \"%s\"\n", buffer);

			if (zap) printf("Acct-Status-Type = Stop\n");

			printf("NAS-IP-Address = %s\n",
			       hostname(buffer, sizeof(buffer),
					rt.nas_address));
			printf("NAS-Port = %u\n", rt.nas_port);

			switch (rt.proto) {
				case 'S':
					printf("Service-Type = Framed-User\n");
					printf("Framed-Protocol = SLIP\n");
					break;
				case 'P':
					printf("Service-Type = Framed-User\n");
					printf("Framed-Protocol = PPP\n");
					break;
				default:
					printf("Service-type = Login-User\n");
					break;
			}
			if (rt.framed_address != INADDR_NONE) {
				printf("Framed-IP-Address = %s\n",
				       hostname(buffer, sizeof(buffer),
						rt.framed_address));
			}

			/*
			 *	Some sanity checks on the time
			 */
			if ((rt.time <= now) &&
			    (now - rt.time) <= (86400 * 365)) {
				printf("Acct-Session-Time = %ld\n",
				       now - rt.time);
			}

			if (rt.caller_id[0] != '\0') {
				memcpy(nasname, rt.caller_id,
				       sizeof(rt.caller_id));
				nasname[sizeof(rt.caller_id)] = '\0';

				fr_print_string(nasname, 0, buffer,
						 sizeof(buffer));
				printf("Calling-Station-Id = \"%s\"\n", buffer);
			}

			printf("\n"); /* separate entries with a blank line */
			continue;
		}

		/*
		 *	Show the fill name, or not.
		 */
		if (showname) {
			printf((rawoutput == 0? rfmt1: rfmt1r),
			       rt.login,
			       showcid ? rt.caller_id :
			       (showsid? session_id : fullname(rt.login)),
			       proto(rt.proto, rt.porttype),
			       portind, portno,
			       dotime(rt.time),
			       hostname(nasname, sizeof(nasname), rt.nas_address),
			       hostname(othername, sizeof(othername), rt.framed_address), eol);
		} else {
			printf((rawoutput == 0? rfmt2: rfmt2r),
			       rt.login,
			       portind, portno,
			       proto(rt.proto, rt.porttype),
			       dotime(rt.time),
			       hostname(nasname, sizeof(nasname), rt.nas_address),
			       hostname(othername, sizeof(othername), rt.framed_address),
			       eol);
		}
	}
	fclose(fp);

	return 0;
}
/*
 *  Do chroot, if requested.
 *
 *  Switch UID and GID to what is specified in the config file
 */
static int switch_users(CONF_SECTION *cs)
{
	/*
	 *	Get the current maximum for core files.  Do this
	 *	before anything else so as to ensure it's properly
	 *	initialized.
	 */
	if (fr_set_dumpable_init() < 0) {
		fr_perror("radiusd");
		return 0;
	}

	/*
	 *	Don't do chroot/setuid/setgid if we're in debugging
	 *	as non-root.
	 */
	if (debug_flag && (getuid() != 0)) return 1;

	if (cf_section_parse(cs, NULL, bootstrap_config) < 0) {
		fprintf(stderr, "radiusd: Error: Failed to parse user/group information.\n");
		return 0;
	}


#ifdef HAVE_GRP_H
	/*  Set GID.  */
	if (gid_name) {
		struct group *gr;

		gr = getgrnam(gid_name);
		if (gr == NULL) {
			fprintf(stderr, "%s: Cannot get ID for group %s: %s\n",
				progname, gid_name, fr_syserror(errno));
			return 0;
		}
		server_gid = gr->gr_gid;
	} else {
		server_gid = getgid();
	}
#endif

#ifdef HAVE_PWD_H
	/*  Set UID.  */
	if (uid_name) {
		struct passwd *pw;

		pw = getpwnam(uid_name);
		if (pw == NULL) {
			fprintf(stderr, "%s: Cannot get passwd entry for user %s: %s\n",
				progname, uid_name, fr_syserror(errno));
			return 0;
		}

		if (getuid() == pw->pw_uid) {
			uid_name = NULL;
		} else {

			server_uid = pw->pw_uid;
#ifdef HAVE_INITGROUPS
			if (initgroups(uid_name, server_gid) < 0) {
				fprintf(stderr, "%s: Cannot initialize supplementary group list for user %s: %s\n",
					progname, uid_name, fr_syserror(errno));
				return 0;
			}
#endif
		}
	} else {
		server_uid = getuid();
	}
#endif

	if (chroot_dir) {
		if (chroot(chroot_dir) < 0) {
			fprintf(stderr, "%s: Failed to perform chroot %s: %s",
				progname, chroot_dir, fr_syserror(errno));
			return 0;
		}

		/*
		 *	Note that we leave chdir alone.  It may be
		 *	OUTSIDE of the root.  This allows us to read
		 *	the configuration from "-d ./etc/raddb", with
		 *	the chroot as "./chroot/" for example.  After
		 *	the server has been loaded, it does a "cd
		 *	${logdir}" below, so that core files (if any)
		 *	go to a logging directory.
		 *
		 *	This also allows the configuration of the
		 *	server to be outside of the chroot.  If the
		 *	server is statically linked, then the only
		 *	things needed inside of the chroot are the
		 *	logging directories.
		 */
	}

#ifdef HAVE_GRP_H
	/*  Set GID.  */
	if (gid_name && (setgid(server_gid) < 0)) {
		fprintf(stderr, "%s: Failed setting group to %s: %s",
			progname, gid_name, fr_syserror(errno));
		return 0;
	}
#endif

#ifdef HAVE_SETUID
	/*
	 *	Just before losing root permissions, ensure that the
	 *	log files have the correct owner && group.
	 *
	 *	We have to do this because the log file MAY have been
	 *	specified on the command-line.
	 */
	if (uid_name || gid_name) {
		if ((default_log.dst == L_DST_FILES) &&
		    (default_log.fd < 0)) {
			default_log.fd = open(mainconfig.log_file,
					      O_WRONLY | O_APPEND | O_CREAT, 0640);
			if (default_log.fd < 0) {
				fprintf(stderr, "radiusd: Failed to open log file %s: %s\n", mainconfig.log_file, fr_syserror(errno));
				return 0;
			}

			if (chown(mainconfig.log_file, server_uid, server_gid) < 0) {
				fprintf(stderr, "%s: Cannot change ownership of log file %s: %s\n",
					progname, mainconfig.log_file, fr_syserror(errno));
				return 0;
			}
		}
	}

	if (uid_name) {
		doing_setuid = true;

		fr_suid_down();
	}
#endif

	/*
	 *	This also clears the dumpable flag if core dumps
	 *	aren't allowed.
	 */
	if (fr_set_dumpable(allow_core_dumps) < 0) {
		ERROR("%s", fr_strerror());
	}

	if (allow_core_dumps) {
		INFO("Core dumps are enabled");
	}

	return 1;
}
/*
 *	Read config files.
 *
 *	This function can ONLY be called from the main server process.
 */
int mainconfig_init(void)
{
	int rcode;
	char const *p = NULL;
	CONF_SECTION *cs;
	struct stat statbuf;
	cached_config_t *cc;
	char buffer[1024];

	if (stat(radius_dir, &statbuf) < 0) {
		ERROR("Errors reading %s: %s",
		       radius_dir, fr_syserror(errno));
		return -1;
	}

#ifdef S_IWOTH
	if ((statbuf.st_mode & S_IWOTH) != 0) {
		ERROR("Configuration directory %s is globally writable.  Refusing to start due to insecure configuration.",
		       radius_dir);
	  return -1;
	}
#endif

#ifdef S_IROTH
	if (0 && (statbuf.st_mode & S_IROTH) != 0) {
		ERROR("Configuration directory %s is globally readable.  Refusing to start due to insecure configuration.",
		       radius_dir);
		return -1;
	}
#endif
	INFO("Starting - reading configuration files ...");

	/*
	 *	We need to load the dictionaries before reading the
	 *	configuration files.  This is because of the
	 *	pre-compilation in conffile.c.  That should probably
	 *	be fixed to be done as a second stage.
	 */
	if (!mainconfig.dictionary_dir) {
		mainconfig.dictionary_dir = talloc_typed_strdup(NULL, DICTDIR);
	}

	/*
	 *	Read the distribution dictionaries first, then
	 *	the ones in raddb.
	 */
	DEBUG2("including dictionary file %s/%s", mainconfig.dictionary_dir, RADIUS_DICTIONARY);
	if (dict_init(mainconfig.dictionary_dir, RADIUS_DICTIONARY) != 0) {
		ERROR("Errors reading dictionary: %s",
		      fr_strerror());
		return -1;
	}

	/*
	 *	Try to load protocol-specific dictionaries.  It's OK
	 *	if they don't exist.
	 */
#ifdef WITH_DHCP
	dict_read(mainconfig.dictionary_dir, "dictionary.dhcp");
#endif

#ifdef WITH_VMPS
	dict_read(mainconfig.dictionary_dir, "dictionary.vqp");
#endif

	/*
	 *	It's OK if this one doesn't exist.
	 */
	rcode = dict_read(radius_dir, RADIUS_DICTIONARY);
	if (rcode == -1) {
		ERROR("Errors reading %s/%s: %s", radius_dir, RADIUS_DICTIONARY,
		      fr_strerror());
		return -1;
	}

	/*
	 *	We print this after reading it.  That way if
	 *	it doesn't exist, it's OK, and we don't print
	 *	anything.
	 */
	if (rcode == 0) {
		DEBUG2("including dictionary file %s/%s", radius_dir, RADIUS_DICTIONARY);
	}

	/* Read the configuration file */
	snprintf(buffer, sizeof(buffer), "%.200s/%.50s.conf",
		 radius_dir, mainconfig.name);
	if ((cs = cf_file_read(buffer)) == NULL) {
		ERROR("Errors reading or parsing %s", buffer);
		return -1;
	}

	/*
	 *	If there was no log destination set on the command line,
	 *	set it now.
	 */
	if (default_log.dst == L_DST_NULL) {
		if (cf_section_parse(cs, NULL, serverdest_config) < 0) {
			fprintf(stderr, "radiusd: Error: Failed to parse log{} section.\n");
			cf_file_free(cs);
			return -1;
		}

		if (!radlog_dest) {
			fprintf(stderr, "radiusd: Error: No log destination specified.\n");
			cf_file_free(cs);
			return -1;
		}

		default_log.dst = fr_str2int(log_str2dst, radlog_dest,
					      L_DST_NUM_DEST);
		if (default_log.dst == L_DST_NUM_DEST) {
			fprintf(stderr, "radiusd: Error: Unknown log_destination %s\n",
				radlog_dest);
			cf_file_free(cs);
			return -1;
		}

		if (default_log.dst == L_DST_SYSLOG) {
			/*
			 *	Make sure syslog_facility isn't NULL
			 *	before using it
			 */
			if (!syslog_facility) {
				fprintf(stderr, "radiusd: Error: Syslog chosen but no facility was specified\n");
				cf_file_free(cs);
				return -1;
			}
			mainconfig.syslog_facility = fr_str2int(syslog_str2fac, syslog_facility, -1);
			if (mainconfig.syslog_facility < 0) {
				fprintf(stderr, "radiusd: Error: Unknown syslog_facility %s\n",
					syslog_facility);
				cf_file_free(cs);
				return -1;
			}

#ifdef HAVE_SYSLOG_H
			/*
			 *	Call openlog only once, when the
			 *	program starts.
			 */
			openlog(progname, LOG_PID, mainconfig.syslog_facility);
#endif

		} else if (default_log.dst == L_DST_FILES) {
			if (!mainconfig.log_file) {
				fprintf(stderr, "radiusd: Error: Specified \"files\" as a log destination, but no log filename was given!\n");
				cf_file_free(cs);
				return -1;
			}
		}
	}

#ifdef HAVE_SETUID
	/*
	 *	Switch users as early as possible.
	 */
	if (!switch_users(cs)) fr_exit(1);
#endif

	/*
	 *	Open the log file AFTER switching uid / gid.  If we
	 *	did switch uid/gid, then the code in switch_users()
	 *	took care of setting the file permissions correctly.
	 */
	if ((default_log.dst == L_DST_FILES) &&
	    (default_log.fd < 0)) {
		default_log.fd = open(mainconfig.log_file,
					    O_WRONLY | O_APPEND | O_CREAT, 0640);
		if (default_log.fd < 0) {
			fprintf(stderr, "radiusd: Failed to open log file %s: %s\n", mainconfig.log_file, fr_syserror(errno));
			cf_file_free(cs);
			return -1;
		}
	}

	/*
	 *	This allows us to figure out where, relative to
	 *	radiusd.conf, the other configuration files exist.
	 */
	if (cf_section_parse(cs, NULL, server_config) < 0) {
		return -1;
	}

	/*
	 *	We ignore colourization of output until after the
	 *	configuration files have been parsed.
	 */
	p = getenv("TERM");
	if (do_colourise && p && isatty(default_log.fd) && strstr(p, "xterm")) {
		default_log.colourise = true;
	} else {
		default_log.colourise = false;
	}

	if (mainconfig.max_request_time == 0) mainconfig.max_request_time = 100;
	if (mainconfig.reject_delay > 5) mainconfig.reject_delay = 5;
	if (mainconfig.cleanup_delay > 5) mainconfig.cleanup_delay =5;

	/*
	 *	Free the old configuration items, and replace them
	 *	with the new ones.
	 *
	 *	Note that where possible, we do atomic switch-overs,
	 *	to ensure that the pointers are always valid.
	 */
	rad_assert(mainconfig.config == NULL);
	root_config = mainconfig.config = cs;

	DEBUG2("%s: #### Loading Realms and Home Servers ####", mainconfig.name);
	if (!realms_init(cs)) {
		return -1;
	}

	DEBUG2("%s: #### Loading Clients ####", mainconfig.name);
	if (!clients_parse_section(cs, false)) {
		return -1;
	}

	/*
	 *  Register the %{config:section.subsection} xlat function.
	 */
	xlat_register("config", xlat_config, NULL, NULL);
	xlat_register("client", xlat_client, NULL, NULL);
	xlat_register("getclient", xlat_getclient, NULL, NULL);

	/*
	 *	Starting the server, WITHOUT "-x" on the
	 *	command-line: use whatever is in the config
	 *	file.
	 */
	if (debug_flag == 0) {
		debug_flag = mainconfig.debug_level;
	}
	fr_debug_flag = debug_flag;

	/*
	 *  Go update our behaviour, based on the configuration
	 *  changes.
	 */

	/*
	 *	Sanity check the configuration for internal
	 *	consistency.
	 */
	if (mainconfig.reject_delay > mainconfig.cleanup_delay) {
		mainconfig.reject_delay = mainconfig.cleanup_delay;
	}
	if (mainconfig.reject_delay < 0) mainconfig.reject_delay = 0;

	if (chroot_dir) {
		if (chdir(radlog_dir) < 0) {
			ERROR("Failed to 'chdir %s' after chroot: %s",
			       radlog_dir, fr_syserror(errno));
			return -1;
		}
	}

	cc = talloc_zero(NULL, cached_config_t);
	if (!cc) return -1;

	cc->cs = talloc_steal(cc ,cs);
	rad_assert(cs_cache == NULL);
	cs_cache = cc;

	/* Clear any unprocessed configuration errors */
	(void) fr_strerror();

	return 0;
}
/*
 *	Allocate the thread pool, and seed it with an initial number
 *	of threads.
 *
 *	FIXME: What to do on a SIGHUP???
 */
int thread_pool_init(CONF_SECTION *cs, int *spawn_flag)
{
#ifndef WITH_GCD
	int		i, rcode;
	CONF_SECTION	*pool_cf;
#endif
	time_t		now;

	cs = cs;		/* -Wunused */

	now = time(NULL);

	rad_assert(spawn_flag != NULL);
	rad_assert(*spawn_flag == TRUE);
	rad_assert(pool_initialized == FALSE); /* not called on HUP */

#ifndef WITH_GCD
	pool_cf = cf_subsection_find_next(cs, NULL, "thread");
	if (!pool_cf) *spawn_flag = FALSE;
#endif

	/*
	 *	Initialize the thread pool to some reasonable values.
	 */
	memset(&thread_pool, 0, sizeof(THREAD_POOL));
#ifndef WITH_GCD
	thread_pool.head = NULL;
	thread_pool.tail = NULL;
	thread_pool.total_threads = 0;
	thread_pool.max_thread_num = 1;
	thread_pool.cleanup_delay = 5;
#endif
	thread_pool.spawn_flag = *spawn_flag;
	
	/*
	 *	Don't bother initializing the mutexes or
	 *	creating the hash tables.  They won't be used.
	 */
	if (!*spawn_flag) return 0;
	
#ifdef WNOHANG
	if ((pthread_mutex_init(&thread_pool.wait_mutex,NULL) != 0)) {
		radlog(L_ERR, "FATAL: Failed to initialize wait mutex: %s",
		       strerror(errno));
		return -1;
	}
	
	/*
	 *	Create the hash table of child PID's
	 */
	thread_pool.waiters = fr_hash_table_create(pid_hash,
						   pid_cmp,
						   free);
	if (!thread_pool.waiters) {
		radlog(L_ERR, "FATAL: Failed to set up wait hash");
		return -1;
	}
#endif

#ifndef WITH_GCD
	if (cf_section_parse(pool_cf, NULL, thread_config) < 0) {
		return -1;
	}

	/*
	 *	Catch corner cases.
	 */
	if (thread_pool.min_spare_threads < 1)
		thread_pool.min_spare_threads = 1;
	if (thread_pool.max_spare_threads < 1)
		thread_pool.max_spare_threads = 1;
	if (thread_pool.max_spare_threads < thread_pool.min_spare_threads)
		thread_pool.max_spare_threads = thread_pool.min_spare_threads;
	if (thread_pool.max_threads == 0)
		thread_pool.max_threads = 256;
#endif	/* WITH_GCD */

	/*
	 *	The pool has already been initialized.  Don't spawn
	 *	new threads, and don't forget about forked children,
	 */
	if (pool_initialized) {
		return 0;
	}

#ifndef WITH_GCD
	/*
	 *	Initialize the queue of requests.
	 */
	memset(&thread_pool.semaphore, 0, sizeof(thread_pool.semaphore));
	rcode = sem_init(&thread_pool.semaphore, 0, SEMAPHORE_LOCKED);
	if (rcode != 0) {
		radlog(L_ERR, "FATAL: Failed to initialize semaphore: %s",
		       strerror(errno));
		return -1;
	}

	rcode = pthread_mutex_init(&thread_pool.queue_mutex,NULL);
	if (rcode != 0) {
		radlog(L_ERR, "FATAL: Failed to initialize queue mutex: %s",
		       strerror(errno));
		return -1;
	}

	/*
	 *	Allocate multiple fifos.
	 */
	for (i = 0; i < RAD_LISTEN_MAX; i++) {
		thread_pool.fifo[i] = fr_fifo_create(65536, NULL);
		if (!thread_pool.fifo[i]) {
			radlog(L_ERR, "FATAL: Failed to set up request fifo");
			return -1;
		}
	}
#endif

#ifdef HAVE_OPENSSL_CRYPTO_H
	/*
	 *	If we're linking with OpenSSL too, then we need
	 *	to set up the mutexes and enable the thread callbacks.
	 */
	if (!setup_ssl_mutexes()) {
		radlog(L_ERR, "FATAL: Failed to set up SSL mutexes");
		return -1;
	}
#endif


#ifndef WITH_GCD
	/*
	 *	Create a number of waiting threads.
	 *
	 *	If we fail while creating them, do something intelligent.
	 */
	for (i = 0; i < thread_pool.start_threads; i++) {
		if (spawn_thread(now, 0) == NULL) {
			return -1;
		}
	}
#else
	thread_pool.queue = dispatch_queue_create("org.freeradius.threads", NULL);
	if (!thread_pool.queue) {
		radlog(L_ERR, "Failed creating dispatch queue: %s\n",
		       strerror(errno));
		exit(1);
	}
#endif

	DEBUG2("Thread pool initialized");
	pool_initialized = TRUE;
	return 0;
}
Exemple #7
0
/*
 *	Do any per-module initialization that is separate to each
 *	configured instance of the module.  e.g. set up connections
 *	to external databases, read configuration files, set up
 *	dictionary entries, etc.
 *
 *	If configuration information is given in the config section
 *	that must be referenced in later calls, store a handle to it
 *	in *instance otherwise put a null pointer there.
 *
 *	Boyan:
 *	Setup a hashes wich we will use later
 *	parse a module and give him a chance to live
 *
 */
static int perl_instantiate(CONF_SECTION *conf, void **instance)
{
	PERL_INST       *inst = (PERL_INST *) instance;
	HV		*rad_reply_hv;
	HV		*rad_check_hv;
	HV		*rad_config_hv;
	HV		*rad_request_hv;
#ifdef WITH_PROXY
	HV		*rad_request_proxy_hv;
	HV		*rad_request_proxy_reply_hv;
#endif
	AV		*end_AV;

	char **embed;
        char **envp = NULL;
	const char *xlat_name;
	int exitstatus = 0, argc=0;

        embed = rad_malloc(4*(sizeof(char *)));
        memset(embed, 0, sizeof(4*(sizeof(char *))));
	/*
	 *	Set up a storage area for instance data
	 */
	inst = rad_malloc(sizeof(PERL_INST));
	memset(inst, 0, sizeof(PERL_INST));

	/*
	 *	If the configuration parameters can't be parsed, then
	 *	fail.
	 */
	if (cf_section_parse(conf, inst, module_config) < 0) {
		free(inst);
		return -1;
	}
	
	/*
	 *	Create pthread key. This key will be stored in instance
	 */

#ifdef USE_ITHREADS
	inst->thread_key = rad_malloc(sizeof(*inst->thread_key));
	memset(inst->thread_key,0,sizeof(*inst->thread_key));
	
	rlm_perl_make_key(inst->thread_key);
#endif
	embed[0] = NULL;
	if (inst->perl_flags) {
		embed[1] = inst->perl_flags;
		embed[2] = inst->module;
		embed[3] = "0";
		argc = 4;
	} else {
		embed[1] = inst->module;
		embed[2] = "0";
		argc = 3;
	}

        PERL_SYS_INIT3(&argc, &embed, &envp);
#ifdef USE_ITHREADS
	if ((inst->perl = perl_alloc()) == NULL) {
		radlog(L_DBG, "rlm_perl: No memory for allocating new perl !");
		return (-1);
	}

	perl_construct(inst->perl);
	PL_perl_destruct_level = 2;

	{
	dTHXa(inst->perl);
	}
	PERL_SET_CONTEXT(inst->perl);
#else
	if ((inst->perl = perl_alloc()) == NULL) {
		radlog(L_ERR, "rlm_perl: No memory for allocating new perl !");
		return -1;
	}

	perl_construct(inst->perl);
#endif

#if PERL_REVISION >= 5 && PERL_VERSION >=8
	PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
#endif

	exitstatus = perl_parse(inst->perl, xs_init, argc, embed, NULL);

	end_AV = PL_endav;
	PL_endav = Nullav;

	if(!exitstatus) {
		exitstatus = perl_run(inst->perl);
	} else {
		radlog(L_ERR,"rlm_perl: perl_parse failed: %s not found or has syntax errors. \n", inst->module);
		return (-1);
	}

	PL_endav = end_AV;

        newXS("radiusd::radlog",XS_radiusd_radlog, "rlm_perl.c");

	rad_reply_hv = newHV();
	rad_check_hv = newHV();
	rad_config_hv = newHV();
	rad_request_hv = newHV();
#ifdef WITH_PROXY
	rad_request_proxy_hv = newHV();
	rad_request_proxy_reply_hv = newHV();
#endif

	rad_reply_hv = get_hv("RAD_REPLY",1);
        rad_check_hv = get_hv("RAD_CHECK",1);
	rad_config_hv = get_hv("RAD_CONFIG",1);
        rad_request_hv = get_hv("RAD_REQUEST",1);
#ifdef WITH_PROXY
	rad_request_proxy_hv = get_hv("RAD_REQUEST_PROXY",1);
	rad_request_proxy_reply_hv = get_hv("RAD_REQUEST_PROXY_REPLY",1);
#endif

	xlat_name = cf_section_name2(conf);
	if (xlat_name == NULL)
		xlat_name = cf_section_name1(conf);
	if (xlat_name){
		inst->xlat_name = strdup(xlat_name);
		xlat_register(xlat_name, perl_xlat, inst);
	}

	*instance = inst;

	return 0;
}
Exemple #8
0
/*
 * read the config section and load all the eap authentication types present.
 */
static int eap_instantiate(CONF_SECTION *cs, void **instance)
{
	int i, num_types;
	int		has_tls, do_tls;
	rlm_eap_t	*inst;
	CONF_SECTION	*scs;

	inst = (rlm_eap_t *) malloc(sizeof(*inst));
	if (!inst) {
		return -1;
	}
	memset(inst, 0, sizeof(*inst));
	if (cf_section_parse(cs, inst, module_config) < 0) {
		eap_detach(inst);
		return -1;
	}

	/*
	 *	Create our own random pool.
	 */
	for (i = 0; i < 256; i++) {
		inst->rand_pool.randrsl[i] = fr_rand();
	}
	fr_randinit(&inst->rand_pool, 1);

	/*
	 *	List of sessions are set to NULL by the memset
	 *	of 'inst', above.
	 */

	/*
	 *	Lookup sessions in the tree.  We don't free them in
	 *	the tree, as that's taken care of elsewhere...
	 */
	inst->session_tree = rbtree_create(eap_handler_cmp, NULL, 0);
	if (!inst->session_tree) {
		radlog(L_ERR|L_CONS, "rlm_eap2: Cannot initialize tree");
		eap_detach(inst);
		return -1;
	}

	/*
	 *	This registers ALL available methods.
	 *
	 *	FIXME: we probably want to selectively register
	 *	some methods.
	 */
	if (eap_server_register_methods() < 0) {
		eap_detach(inst);
		return -1;
	}

	/* Load all the configured EAP-Types */
	num_types = 0;
	has_tls = do_tls = 0;
	for (scs=cf_subsection_find_next(cs, NULL, NULL);
		scs != NULL;
		scs=cf_subsection_find_next(cs, scs, NULL)) {
		const char	*auth_type;
		char		buffer[64], *p;

		auth_type = cf_section_name1(scs);

		if (!auth_type)  continue;

		if (num_types >= EAP_MAX_METHODS) {
			radlog(L_INFO, "WARNING: Ignoring EAP type %s: too many types defined", auth_type);
			continue;
		}

		/*
		 *	Hostapd doesn't do case-insensitive comparisons.
		 *	So we mash everything to uppercase for it.
		 */
		strlcpy(buffer, auth_type, sizeof(buffer));

		for (p = buffer; *p; p++) {
			if (!islower((int)*p)) continue;
			*p = toupper((int)*p);
		}

		inst->methods[num_types] = eap_server_get_type(buffer,
							       &inst->vendors[num_types]);
		if (inst->methods[num_types] == EAP_TYPE_NONE) {
			radlog(L_ERR|L_CONS, "rlm_eap2: Unknown EAP type %s",
			       auth_type);
			eap_detach(inst);
			return -1;
		}

		switch (inst->methods[num_types]) {
		case EAP_TYPE_TLS:
			has_tls = TRUE;
			/* FALL-THROUGH */

		case EAP_TYPE_TTLS:
		case EAP_TYPE_PEAP:
		case EAP_TYPE_FAST:
			do_tls = TRUE;
			break;

		default:
			break;
		}

		num_types++;	/* successfully loaded one more types */
	}
	inst->num_types = num_types;

	if (do_tls && !has_tls) {
		radlog(L_ERR|L_CONS, "rlm_eap2: TLS has not been configured.  Cannot do methods that need TLS.");
		eap_detach(inst);
		return -1;
	}

	if (do_tls) {
		/*
		 *	Initialize TLS.
		 */
		if (eap_example_server_init_tls(inst) < 0) {
			radlog(L_ERR|L_CONS, "rlm_eap2: Cannot initialize TLS");
			eap_detach(inst);
			return -1;
		}
	}

	pthread_mutex_init(&(inst->session_mutex), NULL);

	*instance = inst;
	return 0;
}
Exemple #9
0
/*
 * read the config section and load all the eap authentication types present.
 */
static int eap_instantiate(CONF_SECTION *cs, void **instance)
{
	int		i, eap_type;
	int		num_types;
	CONF_SECTION 	*scs;
	rlm_eap_t	*inst;

	inst = (rlm_eap_t *) malloc(sizeof(*inst));
	if (!inst) {
		return -1;
	}
	memset(inst, 0, sizeof(*inst));
	if (cf_section_parse(cs, inst, module_config) < 0) {
		eap_detach(inst);
		return -1;
	}

	/*
	 *	Create our own random pool.
	 */
	for (i = 0; i < 256; i++) {
		inst->rand_pool.randrsl[i] = fr_rand();
	}
	fr_randinit(&inst->rand_pool, 1);
	inst->rand_pool.randcnt = 0;

	inst->xlat_name = cf_section_name2(cs);
	if (!inst->xlat_name) inst->xlat_name = "EAP";

	/* Load all the configured EAP-Types */
	num_types = 0;
	for(scs=cf_subsection_find_next(cs, NULL, NULL);
		scs != NULL;
		scs=cf_subsection_find_next(cs, scs, NULL)) {

		const char	*auth_type;

		auth_type = cf_section_name1(scs);

		if (!auth_type)  continue;

		eap_type = eaptype_name2type(auth_type);
		if (eap_type < 0) {
			radlog(L_ERR, "rlm_eap: Unknown EAP type %s",
			       auth_type);
			eap_detach(inst);
			return -1;
		}

#ifndef HAVE_OPENSSL_SSL_H
		/*
		 *	This allows the default configuration to be
		 *	shipped with EAP-TLS, etc. enabled.  If the
		 *	system doesn't have OpenSSL, they will be
		 *	ignored.
		 *
		 *	If the system does have OpenSSL, then this
		 *	code will not be used.  The administrator will
		 *	then have to delete the tls,
		 *	etc. configurations from eap.conf in order to
		 *	have EAP without the TLS types.
		 */
		if ((eap_type == PW_EAP_TLS) ||
		    (eap_type == PW_EAP_TTLS) ||
		    (eap_type == PW_EAP_PEAP)) {
			DEBUG2("Ignoring EAP-Type/%s because we do not have OpenSSL support.", auth_type);
			continue;
		}
#endif

		/*
		 *	If we're asked to load TTLS or PEAP, ensure
		 *	that we've first loaded TLS.
		 */
		if (((eap_type == PW_EAP_TTLS) ||
		     (eap_type == PW_EAP_PEAP)) &&
		    (inst->types[PW_EAP_TLS] == NULL)) {
			radlog(L_ERR, "rlm_eap: Unable to load EAP-Type/%s, as EAP-Type/TLS is required first.",
			       auth_type);
			return -1;
		}

		/*
		 *	Load the type.
		 */
		if (eaptype_load(&inst->types[eap_type], eap_type, scs) < 0) {
			eap_detach(inst);
			return -1;
		}

		num_types++;	/* successfully loaded one more types */
	}

	if (num_types == 0) {
		radlog(L_ERR|L_CONS, "rlm_eap: No EAP type configured, module cannot do anything.");
		eap_detach(inst);
		return -1;
	}

	/*
	 *	Ensure that the default EAP type is loaded.
	 */
	eap_type = eaptype_name2type(inst->default_eap_type_name);
	if (eap_type < 0) {
		radlog(L_ERR|L_CONS, "rlm_eap: Unknown default EAP type %s",
		       inst->default_eap_type_name);
		eap_detach(inst);
		return -1;
	}

	if (inst->types[eap_type] == NULL) {
		radlog(L_ERR|L_CONS, "rlm_eap: No such sub-type for default EAP type %s",
		       inst->default_eap_type_name);
		eap_detach(inst);
		return -1;
	}
	inst->default_eap_type = eap_type; /* save the numerical type */

	/*
	 *	List of sessions are set to NULL by the memset
	 *	of 'inst', above.
	 */

	/*
	 *	Lookup sessions in the tree.  We don't free them in
	 *	the tree, as that's taken care of elsewhere...
	 */
	inst->session_tree = rbtree_create(eap_handler_cmp, NULL, 0);
	if (!inst->session_tree) {
		radlog(L_ERR|L_CONS, "rlm_eap: Cannot initialize tree");
		eap_detach(inst);
		return -1;
	}

	if (fr_debug_flag) {
		inst->handler_tree = rbtree_create(eap_handler_ptr_cmp, NULL, 0);
		if (!inst->handler_tree) {
			radlog(L_ERR|L_CONS, "rlm_eap: Cannot initialize tree");
			eap_detach(inst);
			return -1;
		}

#ifdef HAVE_PTHREAD_H
		if (pthread_mutex_init(&(inst->handler_mutex), NULL) < 0) {
			radlog(L_ERR|L_CONS, "rlm_eap: Failed initializing mutex: %s", strerror(errno));
			eap_detach(inst);
			return -1;
		}
#endif
	}

#ifdef HAVE_PTHREAD_H
	if (pthread_mutex_init(&(inst->session_mutex), NULL) < 0) {
		radlog(L_ERR|L_CONS, "rlm_eap: Failed initializing mutex: %s", strerror(errno));
		eap_detach(inst);
		return -1;
	}
#endif

	*instance = inst;
	return 0;
}
static int attr_rewrite_instantiate(CONF_SECTION *conf, void **instance)
{
	rlm_attr_rewrite_t *data;
	DICT_ATTR *dattr;

	/*
	 *	Set up a storage area for instance data
	 */
	data = rad_malloc(sizeof(*data));
	if (!data) {
		return -1;
	}
	memset(data, 0, sizeof(*data));

	/*
	 *	If the configuration parameters can't be parsed, then
	 *	fail.
	 */
	if (cf_section_parse(conf, data, module_config) < 0) {
		free(data);
		return -1;
	}

	/*
	 *	Discover the attribute number of the key.
	 */
	if (data->attribute == NULL) {
		radlog(L_ERR, "rlm_attr_rewrite: 'attribute' must be set.");
		return -1;
	}
	if (data->search == NULL || data->replace == NULL) {
		radlog(L_ERR, "rlm_attr_rewrite: search/replace strings must be set.");
		return -1;
	}
	data->search_len = strlen(data->search);
	data->replace_len = strlen(data->replace);

	if (data->replace_len == 0 && data->new_attr){
		radlog(L_ERR, "rlm_attr_rewrite: replace string must not be zero length in order to create new attribute.");
		return -1;
	}

	if (data->num_matches < 1 || data->num_matches > MAX_STRING_LEN) {
		radlog(L_ERR, "rlm_attr_rewrite: Illegal range for match number.");
		return -1;
	}
	if (data->searchin_str == NULL) {
		radlog(L_ERR, "rlm_attr_rewrite: Illegal searchin directive given. Assuming packet.");
		data->searchin = RLM_REGEX_INPACKET;
	}
	else{
		if (strcmp(data->searchin_str, "packet") == 0)
			data->searchin = RLM_REGEX_INPACKET;
		else if (strcmp(data->searchin_str, "config") == 0)
			data->searchin = RLM_REGEX_INCONFIG;
		else if (strcmp(data->searchin_str, "control") == 0)
			data->searchin = RLM_REGEX_INCONFIG;
		else if (strcmp(data->searchin_str, "reply") == 0)
			data->searchin = RLM_REGEX_INREPLY;
#ifdef WITH_PROXY
		else if (strcmp(data->searchin_str, "proxy") == 0)
			data->searchin = RLM_REGEX_INPROXY;
		else if (strcmp(data->searchin_str, "proxy_reply") == 0)
			data->searchin = RLM_REGEX_INPROXYREPLY;
#endif
		else {
			radlog(L_ERR, "rlm_attr_rewrite: Illegal searchin directive given. Assuming packet.");
			data->searchin = RLM_REGEX_INPACKET;
		}
	}
	dattr = dict_attrbyname(data->attribute);
	if (dattr == NULL) {
		radlog(L_ERR, "rlm_attr_rewrite: No such attribute %s",
				data->attribute);
		return -1;
	}
	data->da = dattr;
	/* Add the module instance name */
	data->name = cf_section_name2(conf); /* may be NULL */

	*instance = data;

	return 0;
}
/*
 *	Main program
 */
int main(int argc, char **argv)
{
	CONF_SECTION *maincs, *cs;
	FILE *fp;
	struct radutmp rt;
	char othername[256];
	char nasname[1024];
	char session_id[sizeof(rt.session_id)+1];
	int hideshell = 0;
	int showsid = 0;
	int rawoutput = 0;
	int radiusoutput = 0;	/* Radius attributes */
	char const *portind;
	int c;
	unsigned int portno;
	char buffer[2048];
	char const *user = NULL;
	int user_cmp = 0;
	time_t now = 0;
	uint32_t nas_port = ~0;
	uint32_t nas_ip_address = INADDR_NONE;
	int zap = 0;

	raddb_dir = RADIUS_DIR;

#ifndef NDEBUG
	if (fr_fault_setup(getenv("PANIC_ACTION"), argv[0]) < 0) {
		fr_perror("radwho");
		exit(EXIT_FAILURE);
	}
#endif

	talloc_set_log_stderr();

	while((c = getopt(argc, argv, "d:fF:nN:sSipP:crRu:U:Z")) != EOF) switch(c) {
		case 'd':
			raddb_dir = optarg;
			break;
		case 'F':
			radutmp_file = optarg;
			break;
		case 'h':
			usage(0);
			break;
		case 'S':
			hideshell = 1;
			break;
		case 'n':
			showname = 0;
			break;
		case 'N':
			if (inet_pton(AF_INET, optarg, &nas_ip_address) < 0) {
				usage(1);
			}
			break;
		case 's':
			showname = 1;
			break;
		case 'i':
			showsid = 1;
			break;
		case 'p':
			showptype = 1;
			break;
		case 'P':
			nas_port = atoi(optarg);
			break;
		case 'c':
			showcid = 1;
			showname = 1;
			break;
		case 'r':
			rawoutput = 1;
			break;
		case 'R':
			radiusoutput = 1;
			now = time(NULL);
			break;
		case 'u':
			user = optarg;
			user_cmp = 0;
			break;
		case 'U':
			user = optarg;
			user_cmp = 1;
			break;
		case 'Z':
			zap = 1;
			break;
		default:
			usage(1);
			break;
	}

	/*
	 *	Mismatch between the binary and the libraries it depends on
	 */
	if (fr_check_lib_magic(RADIUSD_MAGIC_NUMBER) < 0) {
		fr_perror("radwho");
		return 1;
	}

	/*
	 *	Be safe.
	 */
	if (zap && !radiusoutput) zap = 0;

	/*
	 *	zap EVERYONE, but only on this nas
	 */
	if (zap && !user && (~nas_port == 0)) {
		/*
		 *	We need to know which NAS to zap users in.
		 */
		if (nas_ip_address == INADDR_NONE) usage(1);

		printf("Acct-Status-Type = Accounting-Off\n");
		printf("NAS-IP-Address = %s\n",
		       hostname(buffer, sizeof(buffer), nas_ip_address));
		printf("Acct-Delay-Time = 0\n");
		exit(0);	/* don't bother printing anything else */
	}

	if (radutmp_file) goto have_radutmp;

	/*
	 *	Initialize main_config
	 */
	memset(&main_config, 0, sizeof(main_config));

	/* Read radiusd.conf */
	snprintf(buffer, sizeof(buffer), "%.200s/radiusd.conf", raddb_dir);
	maincs = cf_file_read(buffer);
	if (!maincs) {
		fprintf(stderr, "%s: Error reading or parsing radiusd.conf\n", argv[0]);
		exit(1);
	}

	cs = cf_section_sub_find(maincs, "modules");
	if (!cs) {
		fprintf(stderr, "%s: No modules section found in radiusd.conf\n", argv[0]);
		exit(1);
	}
	/* Read the radutmp section of radiusd.conf */
	cs = cf_section_sub_find_name2(cs, "radutmp", NULL);
	if (!cs) {
		fprintf(stderr, "%s: No configuration information in radutmp section of radiusd.conf\n", argv[0]);
		exit(1);
	}

	cf_section_parse(cs, NULL, module_config);

	/* Assign the correct path for the radutmp file */
	radutmp_file = radutmpconfig.radutmp_fn;

 have_radutmp:
	if (showname < 0) showname = 1;

	/*
	 *	Show the users logged in on the terminal server(s).
	 */
	if ((fp = fopen(radutmp_file, "r")) == NULL) {
		fprintf(stderr, "%s: Error reading %s: %s\n",
			progname, radutmp_file, fr_syserror(errno));
		return 0;
	}

	/*
	 *	Don't print the headers if raw or RADIUS
	 */
	if (!rawoutput && !radiusoutput) {
		fputs(showname ? hdr1 : hdr2, stdout);
		fputs(eol, stdout);
	}

	/*
	 *	Read the file, printing out active entries.
	 */
	while (fread(&rt, sizeof(rt), 1, fp) == 1) {
		char name[sizeof(rt.login) + 1];

		if (rt.type != P_LOGIN) continue; /* hide logout sessions */

		/*
		 *	We don't show shell users if we are
		 *	fingerd, as we have done that above.
		 */
		if (hideshell && !strchr("PCS", rt.proto))
			continue;

		/*
		 *	Print out sessions only for the given user.
		 */
		if (user) {	/* only for a particular user */
			if (((user_cmp == 0) &&
			     (strncasecmp(rt.login, user, strlen(user)) != 0)) ||
			    ((user_cmp == 1) &&
			     (strncmp(rt.login, user, strlen(user)) != 0))) {
				continue;
			}
		}

		/*
		 *	Print out only for the given NAS port.
		 */
		if (~nas_port != 0) {
			if (rt.nas_port != nas_port) continue;
		}

		/*
		 *	Print out only for the given NAS IP address
		 */
		if (nas_ip_address != INADDR_NONE) {
			if (rt.nas_address != nas_ip_address) continue;
		}

		memcpy(session_id, rt.session_id, sizeof(rt.session_id));
		session_id[sizeof(rt.session_id)] = 0;

		if (!rawoutput && rt.nas_port > (showname ? 999 : 99999)) {
			portind = ">";
			portno = (showname ? 999 : 99999);
		} else {
			portind = "S";
			portno = rt.nas_port;
		}

		/*
		 *	Print output as RADIUS attributes
		 */
		if (radiusoutput) {
			memcpy(nasname, rt.login, sizeof(rt.login));
			nasname[sizeof(rt.login)] = '\0';

			fr_print_string(nasname, 0, buffer,
					 sizeof(buffer), '"');
			printf("User-Name = \"%s\"\n", buffer);

			fr_print_string(session_id, 0, buffer,
					sizeof(buffer), '"');
			printf("Acct-Session-Id = \"%s\"\n", buffer);

			if (zap) printf("Acct-Status-Type = Stop\n");

			printf("NAS-IP-Address = %s\n",
			       hostname(buffer, sizeof(buffer),
					rt.nas_address));
			printf("NAS-Port = %u\n", rt.nas_port);

			switch (rt.proto) {
			case 'S':
				printf("Service-Type = Framed-User\n");
				printf("Framed-Protocol = SLIP\n");
				break;

			case 'P':
				printf("Service-Type = Framed-User\n");
				printf("Framed-Protocol = PPP\n");
				break;

			default:
				printf("Service-type = Login-User\n");
				break;
			}
			if (rt.framed_address != INADDR_NONE) {
				printf("Framed-IP-Address = %s\n",
				       hostname(buffer, sizeof(buffer),
						rt.framed_address));
			}

			/*
			 *	Some sanity checks on the time
			 */
			if ((rt.time <= now) &&
			    (now - rt.time) <= (86400 * 365)) {
				printf("Acct-Session-Time = %" PRId64 "\n", (int64_t) (now - rt.time));
			}

			if (rt.caller_id[0] != '\0') {
				memcpy(nasname, rt.caller_id,
				       sizeof(rt.caller_id));
				nasname[sizeof(rt.caller_id)] = '\0';

				fr_print_string(nasname, 0, buffer,
						 sizeof(buffer), '"');
				printf("Calling-Station-Id = \"%s\"\n", buffer);
			}

			printf("\n"); /* separate entries with a blank line */
			continue;
		}

		/*
		 *	Show the fill name, or not.
		 */
		memcpy(name, rt.login, sizeof(rt.login));
		name[sizeof(rt.login)] = '\0';

		if (showname) {
			if (rawoutput == 0) {
				printf("%-10.10s %-17.17s %-5.5s %s%-3u %-9.9s %-15.15s %-.19s%s",
				       name,
				       showcid ? rt.caller_id :
				       (showsid? session_id : fullname(rt.login)),
				       proto(rt.proto, rt.porttype),
				       portind, portno,
				       dotime(rt.time),
				       hostname(nasname, sizeof(nasname), rt.nas_address),
				       hostname(othername, sizeof(othername), rt.framed_address), eol);
			} else {
				printf("%s,%s,%s,%s%u,%s,%s,%s%s",
				       name,
				       showcid ? rt.caller_id :
				       (showsid? session_id : fullname(rt.login)),
				       proto(rt.proto, rt.porttype),
				       portind, portno,
				       dotime(rt.time),
				       hostname(nasname, sizeof(nasname), rt.nas_address),
				       hostname(othername, sizeof(othername), rt.framed_address), eol);
			}
		} else {
			if (rawoutput == 0) {
				printf("%-10.10s %s%-5u  %-6.6s %-13.13s %-15.15s %-.28s%s",
				       name,
				       portind, portno,
				       proto(rt.proto, rt.porttype),
				       dotime(rt.time),
				       hostname(nasname, sizeof(nasname), rt.nas_address),
				       hostname(othername, sizeof(othername), rt.framed_address),
				       eol);
			} else {
				printf("%s,%s%u,%s,%s,%s,%s%s",
				       name,
				       portind, portno,
				       proto(rt.proto, rt.porttype),
				       dotime(rt.time),
				       hostname(nasname, sizeof(nasname), rt.nas_address),
				       hostname(othername, sizeof(othername), rt.framed_address),
				       eol);
			}
		}
	}
	fclose(fp);

	return 0;
}
Exemple #12
0
/*
 *	Do any per-module initialization that is separate to each
 *	configured instance of the module.  e.g. set up connections
 *	to external databases, read configuration files, set up
 *	dictionary entries, etc.
 *
 *	If configuration information is given in the config section
 *	that must be referenced in later calls, store a handle to it
 *	in *instance otherwise put a null pointer there.
 */
static int sqlippool_instantiate(CONF_SECTION * conf, void ** instance)
{
	module_instance_t *modinst;
	rlm_sqlippool_t * data;
	const char * pool_name = NULL;

	/*
	 *	Set up a storage area for instance data
	 */
	data = rad_malloc(sizeof(*data));
	memset(data, 0, sizeof(*data));

	/*
	 *	If the configuration parameters can't be parsed, then
	 *	fail.
	 */
	if (cf_section_parse(conf, data, module_config) < 0) {
		free(data);
		return -1;
	}

	if ((data->sql_instance_name == NULL) ||
	    (strlen(data->sql_instance_name) == 0)) {
		radlog(L_ERR, "rlm_sqlippool: the 'sql-instance-name' variable must be set.");
		sqlippool_detach(data);
		return -1;
	}

	/*
	 *	Check that all the queries are in place
	 */

	if ((data->allocate_clear == NULL) ||
	    (strlen(data->allocate_clear) == 0)) {
		radlog(L_ERR, "rlm_sqlippool: the 'allocate-clear' statement must be set.");
		sqlippool_detach(data);
		return -1;
	}

	if ((data->allocate_find == NULL) || 
	    (strlen(data->allocate_find) == 0)) {
		radlog(L_ERR, "rlm_sqlippool: the 'allocate_find' statement must be set.");
		sqlippool_detach(data);
		return -1;
	}

	if ((data->allocate_update == NULL) ||
	    (strlen(data->allocate_update) == 0)) {
		radlog(L_ERR, "rlm_sqlippool: the 'allocate_update' statement must be set.");
		sqlippool_detach(data);
		return -1;
	}

	if ((data->start_update == NULL) ||
	    (strlen(data->start_update) == 0)) {
		radlog(L_ERR, "rlm_sqlippool: the 'start-update' statement must be set.");
		sqlippool_detach(data);
		return -1;
	}

	if ((data->alive_update == NULL) ||
	     (strlen(data->alive_update) == 0)) {
		radlog(L_ERR, "rlm_sqlippool: the 'alive-update' statement must be set.");
		sqlippool_detach(data);
		return -1;
	}

	if ((data->stop_clear == NULL) ||
	     (strlen(data->stop_clear) == 0)) {
		radlog(L_ERR, "rlm_sqlippool: the 'stop-clear' statement must be set.");
		sqlippool_detach(data);
		return -1;
	}

	if ((data->on_clear == NULL) ||
	     (strlen(data->on_clear) == 0)) {
		radlog(L_ERR, "rlm_sqlippool: the 'on-clear' statement must be set.");
		sqlippool_detach(data);
		return -1;
	}

	if ((data->off_clear == NULL) ||
	    (strlen(data->off_clear) == 0)) {
		radlog(L_ERR, "rlm_sqlippool: the 'off-clear' statement must be set.");
		sqlippool_detach(data);
		return -1;
	}

	pool_name = cf_section_name2(conf);
	if (pool_name != NULL)
		data->pool_name = strdup(pool_name);
	else
		data->pool_name = strdup("ippool");

	modinst = find_module_instance(cf_section_find("modules"),
				       data->sql_instance_name, 1);
	if (!modinst) {
		radlog(L_ERR, "sqlippool_instantiate: failed to find sql instance named %s", data->sql_instance_name);
		sqlippool_detach(data);
		return -1;
	}

	if (strcmp(modinst->entry->name, "rlm_sql") != 0) {
		radlog(L_ERR, "sqlippool_instantiate: Module \"%s\""
		       " is not an instance of the rlm_sql module",
		       data->sql_instance_name);
		sqlippool_detach(data);
		return -1;
	}

	data->sql_inst = (SQL_INST *) modinst->insthandle;

	*instance = data;
	return 0;
}
Exemple #13
0
/*
 *	Allocate the thread pool, and seed it with an initial number
 *	of threads.
 *
 *	FIXME: What to do on a SIGHUP???
 */
int thread_pool_init(CONF_SECTION *cs, int spawn_flag)
{
	int		i, rcode;
	CONF_SECTION	*pool_cf;
	time_t		now;

	now = time(NULL);

	/*
	 *	We're not spawning new threads, don't do
	 *	anything.
	 */
	if (!spawn_flag) return 0;

	/*
	 *	After a SIGHUP, we don't over-write the previous values.
	 */
	if (!pool_initialized) {
		/*
		 *	Initialize the thread pool to some reasonable values.
		 */
		memset(&thread_pool, 0, sizeof(THREAD_POOL));
		thread_pool.head = NULL;
		thread_pool.tail = NULL;
		thread_pool.total_threads = 0;
		thread_pool.max_thread_num = 1;
		thread_pool.cleanup_delay = 5;
		thread_pool.spawn_flag = spawn_flag;

#ifdef WNOHANG
		if ((pthread_mutex_init(&thread_pool.wait_mutex,NULL) != 0)) {
			radlog(L_ERR, "FATAL: Failed to initialize wait mutex: %s",
			       strerror(errno));
			return -1;
		}

		/*
		 *	Create the hash table of child PID's
		 */
		thread_pool.waiters = fr_hash_table_create(pid_hash,
							     pid_cmp,
							     free);
		if (!thread_pool.waiters) {
			radlog(L_ERR, "FATAL: Failed to set up wait hash");
			return -1;
		}
#endif
	}

	pool_cf = cf_subsection_find_next(cs, NULL, "thread");
	if (!pool_cf) {
		radlog(L_ERR, "FATAL: Attempting to start in multi-threaded mode with no thread configuration in radiusd.conf");
		return -1;
	}

	if (cf_section_parse(pool_cf, NULL, thread_config) < 0) {
		return -1;
	}

	/*
	 *	Catch corner cases.
	 */
	if (thread_pool.min_spare_threads < 1)
		thread_pool.min_spare_threads = 1;
	if (thread_pool.max_spare_threads < 1)
		thread_pool.max_spare_threads = 1;
	if (thread_pool.max_spare_threads < thread_pool.min_spare_threads)
		thread_pool.max_spare_threads = thread_pool.min_spare_threads;

	/*
	 *	The pool has already been initialized.  Don't spawn
	 *	new threads, and don't forget about forked children,
	 */
	if (pool_initialized) {
		return 0;
	}

	/*
	 *	Initialize the queue of requests.
	 */
	memset(&thread_pool.semaphore, 0, sizeof(thread_pool.semaphore));
	rcode = sem_init(&thread_pool.semaphore, 0, SEMAPHORE_LOCKED);
	if (rcode != 0) {
		radlog(L_ERR, "FATAL: Failed to initialize semaphore: %s",
		       strerror(errno));
		return -1;
	}

	rcode = pthread_mutex_init(&thread_pool.queue_mutex,NULL);
	if (rcode != 0) {
		radlog(L_ERR, "FATAL: Failed to initialize queue mutex: %s",
		       strerror(errno));
		return -1;
	}

	/*
	 *	Allocate multiple fifos.
	 */
	for (i = 0; i < RAD_LISTEN_MAX; i++) {
		thread_pool.fifo[i] = fr_fifo_create(65536, NULL);
		if (!thread_pool.fifo[i]) {
			radlog(L_ERR, "FATAL: Failed to set up request fifo");
			return -1;
		}
	}

#ifdef HAVE_OPENSSL_CRYPTO_H
	/*
	 *	If we're linking with OpenSSL too, then we need
	 *	to set up the mutexes and enable the thread callbacks.
	 */
	if (!setup_ssl_mutexes()) {
		radlog(L_ERR, "FATAL: Failed to set up SSL mutexes");
		return -1;
	}
#endif


	/*
	 *	Create a number of waiting threads.
	 *
	 *	If we fail while creating them, do something intelligent.
	 */
	for (i = 0; i < thread_pool.start_threads; i++) {
		if (spawn_thread(now) == NULL) {
			return -1;
		}
	}

	DEBUG2("Thread pool initialized");
	pool_initialized = TRUE;
	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);
	}
Exemple #15
0
/** Configure EAP-ikev2 handler
 *
 */
static int mod_instantiate(CONF_SECTION *conf, void **instance)
{
	int ret;

	struct ikev2_ctx *i2;
	rlm_eap_ikev2_t *inst;

	char *server_auth_type, *default_auth_type, *users_file_name;

	ikev2_set_log_callback(vxlogf);

	inst = talloc_zero(conf, rlm_eap_ikev2_t);
	if (cf_section_parse(conf, &inst, module_config) < 0) return -1;

	i2 = Create_ikev2_ctx();
	if (!i2) return -1;
	*instance = i2;

	/*
	 *	Map our config structure onto the IKEv2 context
	 */
	memcpy(&i2->trusted, &inst->tls_ca_file, sizeof(i2->trusted));
	memcpy(&i2->pkfile, &inst->tls_private_key_file, sizeof(i2->pkfile));
	memcpy(&i2->pkfile_pwd, &inst->tls_private_key_password, sizeof(i2->pkfile_pwd));
	memcpy(&i2->certfile, &inst->tls_certificate_file, sizeof(i2->certfile));
	memcpy(&i2->id, &inst->id, sizeof(i2->id));
	i2->max_fragment_size = inst->max_fragment_size;
	i2->DHCounterMax = inst->dh_counter_max;
	i2->sendCertReq = (uint8_t) inst->send_cert_request;
	i2->fastExpire = inst->fast_expire;
	i2->enableFastDHEx = inst->enable_fast_dhex;
	i2->enableFastReconnect = inst->enable_fast_reconnect;

	memcpy(&server_auth_type, &inst->server_auth_type, sizeof(server_auth_type));
	memcpy(&default_auth_type, &inst->default_auth_type, sizeof(default_auth_type));
	memcpy(&users_file_name, &inst->users_file_name, sizeof(users_file_name));
	hexalize(&i2->id, &i2->idlen);

	i2->authtype = rad_get_authtype(server_auth_type);
	if (!i2->id) {
		ERROR(IKEv2_LOG_PREFIX "'id' configuration option is required!!!");
		return -1;
	}

	switch (i2->authtype) {
	default:
	case IKEv2_AUTH_SK:
		break;

	case IKEv2_AUTH_CERT:
		if (!i2->certfile || !i2->pkfile) {
			ERROR(IKEv2_LOG_PREFIX "'certificate_file' and 'private_key_file' items are required "
			      "for 'cert' auth type");
			return -1;
		}

		if (!file_exists(i2->certfile)) {
			ERROR(IKEv2_LOG_PREFIX "Can not open 'certificate_file' %s", i2->certfile);
			return -1;
		}

		if (!file_exists(i2->pkfile)) {
			ERROR(IKEv2_LOG_PREFIX "Can not open 'private_key_file' %s",i2->pkfile);
			return -1;
		}
		break;
	}

	if (!i2->trusted) {
		AUTH(IKEv2_LOG_PREFIX "'ca_file' item not set, client cert based authentication will fail");
	} else {
		if (!file_exists(i2->trusted)) {
			ERROR(IKEv2_LOG_PREFIX "Can not open 'ca_file' %s", i2->trusted);
			return -1;
		}
	}

	if (i2->crl_file) {
		if (!file_exists(i2->crl_file)) {
			ERROR(IKEv2_LOG_PREFIX "Can not open 'crl_file' %s", i2->crl_file);
			return -1;
		}
	}

	i2->idtype = IdTypeFromName(inst->server_id_type);
	if (i2->idtype <= 0) {
		ERROR(IKEv2_LOG_PREFIX "Unsupported 'idtype': %s", inst->server_id_type);
		return -1;
	}

	if (rad_load_proposals(i2, conf)) {
		ERROR(IKEv2_LOG_PREFIX "Failed to load proposals");
		return -1;
	}

	ret = rad_load_credentials(instance, i2, users_file_name, default_auth_type);
	if (ret == -1) {
		ERROR(IKEv2_LOG_PREFIX "Error while loading users credentials");
		return -1;
	}

	i2->x509_store = NULL;
	if(CertInit(i2)){
		ERROR(IKEv2_LOG_PREFIX "Error while loading certs/crl");
		return -1;
	}

	return 0;
}
Exemple #16
0
/*
 *	Do any per-module initialization that is separate to each
 *	configured instance of the module.  e.g. set up connections
 *	to external databases, read configuration files, set up
 *	dictionary entries, etc.
 *
 *	If configuration information is given in the config section
 *	that must be referenced in later calls, store a handle to it
 *	in *instance otherwise put a null pointer there.
 */
static int mod_instantiate(CONF_SECTION *conf, void **instance)
{
	rlm_exec_t	*inst;
	const char	*xlat_name;

	/*
	 *	Set up a storage area for instance data
	 */
	*instance = inst = talloc_zero(conf, rlm_exec_t);
	if (!inst) return -1;
	
	xlat_name = cf_section_name2(conf);
	if (!xlat_name) {
		xlat_name = cf_section_name1(conf);
		inst->bare = 1;
	}
	if (xlat_name) {
		inst->xlat_name = xlat_name;
		xlat_register(xlat_name, exec_xlat, inst);
	}

	/*
	 *	If the configuration parameters can't be parsed, then
	 *	fail.
	 */
	if (cf_section_parse(conf, inst, module_config) < 0) {
		radlog(L_ERR, "rlm_exec (%s): Failed parsing the "
		       "configuration", xlat_name);
		mod_detach(inst);
		return -1;
	}

	/*
	 *	No input pairs defined.  Why are we executing a program?
	 */
	if (!inst->input) {
		radlog(L_ERR, "rlm_exec (%s): Must define input pairs for "
		       "external program", xlat_name);
		mod_detach(inst);
		return -1;
	}

	/*
	 *	Sanity check the config.  If we're told to NOT wait,
	 *	then the output pairs must not be defined.
	 */
	if (!inst->wait &&
	    (inst->output != NULL)) {
		radlog(L_ERR, "rlm_exec (%s): Cannot read output pairs if "
			      "wait=no", xlat_name);
		mod_detach(inst);
		return -1;
	}

	/*
	 *	Get the packet type on which to execute
	 */
	if (!inst->packet_type) {
		inst->packet_code = 0;
	} else {
		DICT_VALUE	*dval;

		dval = dict_valbyname(PW_PACKET_TYPE, 0, inst->packet_type);
		if (!dval) {
			radlog(L_ERR, "rlm_exec (%s): Unknown packet type %s: "
			       "See list of VALUEs for Packet-Type in "
			       "share/dictionary", xlat_name,
			       inst->packet_type);
			mod_detach(inst);
			return -1;
		}
		inst->packet_code = dval->value;
	}

	return 0;
}
/** Parse socket configuration
 *
 * @param[in] cs	specifying the listener configuration.
 * @param[in] listen	structure encapsulating the libldap socket.
 * @return
 *	- 0 on success.
 *	- -1 on error.
 */
static int proto_ldap_socket_parse(CONF_SECTION *cs, rad_listen_t *listen)
{
	proto_ldap_inst_t 	*inst = listen->data;
	CONF_SECTION		*sync_cs;
	size_t		 	i;
	int			ret;

	/*
	 *	Always cache the CONF_SECTION of the server.
	 */
	listen->server_cs = virtual_server_find(listen->server);
	if (!listen->server_cs) {
		cf_log_err(cs, "Failed to find virtual server '%s'", listen->server);
		return -1;
	}

	if (cf_section_rules_push(cs, module_config) < 0) return -1;
	ret = cf_section_parse(inst, inst, cs);
	if (ret < 0) return ret;

	talloc_set_type(inst, proto_ldap_inst_t);

	rad_assert(inst->handle_config.server_str[0]);
	inst->handle_config.name = talloc_typed_asprintf(inst, "proto_ldap_conn (%s)", listen->server);

	memcpy(&inst->handle_config.server, &inst->handle_config.server_str[0], sizeof(inst->handle_config.server));

	/*
	 *	Convert scope strings to enumerated constants
	 */
	for (sync_cs = cf_section_find(cs, "sync", NULL), i = 0;
	     sync_cs;
	     sync_cs = cf_section_find_next(cs, sync_cs, "sync", NULL), i++) {
		int		scope;
		void		**tmp;
		CONF_SECTION	*map_cs;

		talloc_set_type(inst->sync_config[i], sync_config_t);

		scope = fr_str2int(fr_ldap_scope, inst->sync_config[i]->scope_str, -1);
		if (scope < 0) {
#ifdef LDAP_SCOPE_CHILDREN
			cf_log_err(cs, "Invalid 'user.scope' value \"%s\", expected 'sub', 'one'"
				   ", 'base' or 'children'", inst->sync_config[i]->scope_str);
#else
			cf_log_err(cs, "Invalid 'user.scope' value \"%s\", expected 'sub', 'one'"
				   " or 'base'", inst->sync_config[i]->scope_str)
#endif
			return -1;
		}
		inst->sync_config[i]->scope = scope;

		/*
		 *	Needs to be NULL terminated as that's what libldap needs
		 */
		if (inst->sync_config[i]->attrs) {
			memcpy(&tmp, &inst->sync_config[i]->attrs, sizeof(tmp));
			tmp = talloc_array_null_terminate(tmp);
			memcpy(&inst->sync_config[i]->attrs, tmp, sizeof(inst->sync_config[i]->attrs));
		}

		inst->sync_config[i]->persist = true;
		inst->sync_config[i]->user_ctx = listen;
		inst->sync_config[i]->cookie = _proto_ldap_cookie_store;
		inst->sync_config[i]->entry = _proto_ldap_entry;
		inst->sync_config[i]->refresh_required = _proto_ldap_refresh_required;
		inst->sync_config[i]->present = _proto_ldap_present;

		/*
		 *	Parse and validate any maps
		 */
		map_cs = cf_section_find(sync_cs, "update", NULL);
		if (map_cs && map_afrom_cs(inst, &inst->sync_config[i]->entry_map, map_cs,
					   NULL, NULL, fr_ldap_map_verify, NULL,
					   LDAP_MAX_ATTRMAP) < 0) {
			return -1;
		}
	}
/*
 *	Do any per-module initialization that is separate to each
 *	configured instance of the module.  e.g. set up connections
 *	to external databases, read configuration files, set up
 *	dictionary entries, etc.
 *
 *	If configuration information is given in the config section
 *	that must be referenced in later calls, store a handle to it
 *	in *instance otherwise put a null pointer there.
 */
static int sqlippool_instantiate(CONF_SECTION *conf, void **instance)
{
	module_instance_t *sqlinst;
	rlm_sqlippool_t *inst;
	const char * pool_name = NULL;

	/*
	 *	Set up a storage area for instance data
	 */
	*instance = inst = talloc_zero(conf, rlm_sqlippool_t);

	/*
	 *	If the configuration parameters can't be parsed, then
	 *	fail.
	 */
	if (cf_section_parse(conf, inst, module_config) < 0) {
		return -1;
	}

	if (IS_EMPTY(inst->sql_instance_name)) {
		radlog(L_ERR, "rlm_sqlippool: the 'sql-instance-name' variable must be set.");
		return -1;
	}

	/*
	 *	Check that all the queries are in place
	 */

	if (IS_EMPTY(inst->allocate_clear)) {
		radlog(L_ERR, "rlm_sqlippool: the 'allocate-clear' statement must be set.");
		return -1;
	}

	if (IS_EMPTY(inst->allocate_find)) {
		radlog(L_ERR, "rlm_sqlippool: the 'allocate-find' statement must be set.");
		return -1;
	}

	if (IS_EMPTY(inst->allocate_update)) {
		radlog(L_ERR, "rlm_sqlippool: the 'allocate-update' statement must be set.");
		return -1;
	}

	if (IS_EMPTY(inst->start_update)) {
		radlog(L_ERR, "rlm_sqlippool: the 'start-update' statement must be set.");
		return -1;
	}

	if (IS_EMPTY(inst->alive_update)) {
		radlog(L_ERR, "rlm_sqlippool: the 'alive-update' statement must be set.");
		return -1;
	}

	if (IS_EMPTY(inst->stop_clear)) {
		radlog(L_ERR, "rlm_sqlippool: the 'stop-clear' statement must be set.");
		return -1;
	}

	if (IS_EMPTY(inst->on_clear)) {
		radlog(L_ERR, "rlm_sqlippool: the 'on-clear' statement must be set.");
		return -1;
	}

	if (IS_EMPTY(inst->off_clear)) {
		radlog(L_ERR, "rlm_sqlippool: the 'off-clear' statement must be set.");
		return -1;
	}

	pool_name = cf_section_name2(conf);
	if (pool_name != NULL)
		inst->pool_name = talloc_strdup(inst, pool_name);
	else
		inst->pool_name = talloc_strdup(inst, "ippool");

	sqlinst = find_module_instance(cf_section_find("modules"),
				       inst->sql_instance_name, 1);
	if (!sqlinst) {
		radlog(L_ERR, "sqlippool_instantiate: failed to find sql instance named %s", inst->sql_instance_name);
		return -1;
	}

	if (strcmp(sqlinst->entry->name, "rlm_sql") != 0) {
		radlog(L_ERR, "sqlippool_instantiate: Module \"%s\""
		       " is not an instance of the rlm_sql module",
		       inst->sql_instance_name);
		return -1;
	}

	inst->sql_inst = (SQL_INST *) sqlinst->insthandle;
	return 0;
}