Ejemplo n.º 1
0
/*
 *	Escape unprintable characters.
 */
static size_t linelog_escape_func(UNUSED REQUEST *request,
                                  char *out, size_t outlen, char const *in,
                                  UNUSED void *arg)
{
    if (outlen == 0) return 0;

    if (outlen == 1) {
        *out = '\0';
        return 0;
    }

    return fr_prints(out, outlen, in, -1, 0);
}
Ejemplo n.º 2
0
/** Escape string that may contain binary data, and write it to a new buffer
 *
 * This is useful in situations where we expect printable strings as input,
 * but under some conditions may get binary data. A good example is libldap
 * and the arrays of struct berval ldap_get_values_len returns.
 *
 * @param[in] ctx To allocate new buffer in.
 * @param[in] in String to escape.
 * @param[in] inlen Length of string. Should be >= 0 if the data may contain
 *	embedded \0s. Must be >= 0 if data may not be \0 terminated.
 *	If < 0 inlen will be calculated using strlen.
 * @param[in] quote the quotation character.
 * @return new buffer holding the escaped string.
 */
char *fr_aprints(TALLOC_CTX *ctx, char const *in, ssize_t inlen, char quote)
{
	size_t len, ret;
	char *out;

	len = fr_prints_len(in, inlen, quote);

	out = talloc_array(ctx, char, len);
	ret = fr_prints(out, len, in, inlen, quote);
	/*
	 *	This is a fatal error, but fr_assert is the strongest
	 *	assert we're allowed to use in library functions.
	 */
	if (!fr_assert(ret == (len - 1))) {
		talloc_free(out);
		return NULL;
	}

	return out;
}
Ejemplo n.º 3
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:D:fF:nN:sSipP:crRu:U:Z")) != EOF) switch (c) {
		case 'd':
			raddb_dir = optarg;
			break;
		case 'D':
			dict_dir = optarg;
			break;
		case 'F':
			radutmp_file = optarg;
			break;
		case 'h':
			usage(0);	/* never returns */

		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);	/* never returns */
	}

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

	if (dict_init(dict_dir, RADIUS_DICTIONARY) < 0) {
		fr_perror("radwho");
		return 1;
	}

	if (dict_read(raddb_dir, RADIUS_DICTIONARY) == -1) {
		fr_perror("radwho");
		return 1;
	}
	fr_strerror();	/* Clear the error buffer */

	/*
	 *	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 */
	maincs = cf_section_alloc(NULL, "main", NULL);
	if (!maincs) exit(1);

	snprintf(buffer, sizeof(buffer), "%.200s/radiusd.conf", raddb_dir);
	if (cf_file_read(maincs, buffer) < 0) {
		fprintf(stderr, "%s: Error reading or parsing radiusd.conf\n", argv[0]);
		talloc_free(maincs);
		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_prints(buffer, sizeof(buffer), nasname, -1, '"');
			printf("User-Name = \"%s\"\n", buffer);

			fr_prints(buffer, sizeof(buffer), session_id, -1, '"');
			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_prints(buffer, sizeof(buffer), nasname, -1, '"');
				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;
}
Ejemplo n.º 4
0
/*
 * Make sure user/pass are clean
 * and then log them
 */
static int rad_authlog(char const *msg, REQUEST *request, int goodpass)
{
	int logit;
	char const *extra_msg = NULL;
	char clean_password[1024];
	char clean_username[1024];
	char buf[1024];
	char extra[1024];
	char *p;
	VALUE_PAIR *username = NULL;

	if (!request->root->log_auth) {
		return 0;
	}

	/*
	 * Get the correct username based on the configured value
	 */
	if (!log_stripped_names) {
		username = pairfind(request->packet->vps, PW_USER_NAME, 0, TAG_ANY);
	} else {
		username = request->username;
	}

	/*
	 *	Clean up the username
	 */
	if (username == NULL) {
		strcpy(clean_username, "<no User-Name attribute>");
	} else {
		fr_prints(clean_username, sizeof(clean_username), username->vp_strvalue, username->vp_length, '\0');
	}

	/*
	 *	Clean up the password
	 */
	if (request->root->log_auth_badpass || request->root->log_auth_goodpass) {
		if (!request->password) {
			VALUE_PAIR *auth_type;

			auth_type = pairfind(request->config, PW_AUTH_TYPE, 0, TAG_ANY);
			if (auth_type) {
				snprintf(clean_password, sizeof(clean_password),
					 "<via Auth-Type = %s>",
					 dict_valnamebyattr(PW_AUTH_TYPE, 0,
							    auth_type->vp_integer));
			} else {
				strcpy(clean_password, "<no User-Password attribute>");
			}
		} else if (pairfind(request->packet->vps, PW_CHAP_PASSWORD, 0, TAG_ANY)) {
			strcpy(clean_password, "<CHAP-Password>");
		} else {
			fr_prints(clean_password, sizeof(clean_password),
				  request->password->vp_strvalue, request->password->vp_length, '\0');
		}
	}

	if (goodpass) {
		logit = request->root->log_auth_goodpass;
		extra_msg = request->root->auth_goodpass_msg;
	} else {
		logit = request->root->log_auth_badpass;
		extra_msg = request->root->auth_badpass_msg;
	}

	if (extra_msg) {
		extra[0] = ' ';
		p = extra + 1;
		if (radius_xlat(p, sizeof(extra) - 1, request, extra_msg, NULL, NULL) < 0) {
			return -1;
		}
	} else {
		*extra = '\0';
	}

	RAUTH("%s: [%s%s%s] (%s)%s",
		       msg,
		       clean_username,
		       logit ? "/" : "",
		       logit ? clean_password : "",
		       auth_name(buf, sizeof(buf), request, 1),
		       extra);

	return 0;
}
Ejemplo n.º 5
0
/** Find the length of the buffer required to fully escape a string with fr_prints
 *
 * Were assuming here that's it's cheaper to figure out the length and do one
 * alloc than repeatedly expand the buffer when we find extra chars which need
 * to be added.
 *
 * @param in string to calculate the escaped length for.
 * @param inlen length of the input string, if < 0 strlen will be used to check the length.
 * @param[in] quote the quotation character.
 * @return the size of buffer required to hold the escaped string including the NUL byte.
 */
size_t fr_prints_len(char const *in, ssize_t inlen, char quote)
{
	return fr_prints(NULL, 0, in, inlen, quote) + 1;
}
Ejemplo n.º 6
0
/** Allocates a stats template which describes a single guage/counter
 *
 * This is just intended to simplify allocating a fairly complex memory structure
 * src and dst pointers must be set
 *
 * @param ctx Context to allocate collectd struct in.
 * @param conf Radsniff configuration.
 * @param plugin_instance usually the type of packet (in our case).
 * @param type string, the name of a collection of stats e.g. exchange
 * @param type_instance the name of the counter/guage within the collection e.g. latency.
 * @param stats structure to derive statistics from.
 * @param values Value templates used to populate lcc_value_list.
 * @return a new rs_stats_tmpl_t on success or NULL on failure.
 */
static rs_stats_tmpl_t *rs_stats_collectd_init(TALLOC_CTX *ctx, rs_t *conf,
					       char const *plugin_instance,
					       char const *type, char const *type_instance,
					       void *stats,
					       rs_stats_value_tmpl_t const *values)
{
	static char hostname[255];
	static char fqdn[LCC_NAME_LEN];

	size_t len;
	int i;
	char *p;

	rs_stats_tmpl_t *tmpl;
	lcc_value_list_t *value;

	assert(conf);
	assert(type);
	assert(type_instance);

	for (len = 0; values[len].src; len++) {} ;
	assert(len > 0);

	/*
	 *	Initialise hostname once so we don't call gethostname every time
	 */
	if (*fqdn == '\0') {
		int ret;
		struct addrinfo hints, *info = NULL;

		if (gethostname(hostname, sizeof(hostname)) < 0) {
			ERROR("Error getting hostname: %s", fr_syserror(errno));

			return NULL;
		}

		memset(&hints, 0, sizeof hints);
		hints.ai_family = AF_UNSPEC; /*either IPV4 or IPV6*/
		hints.ai_socktype = SOCK_STREAM;
		hints.ai_flags = AI_CANONNAME;

		if ((ret = getaddrinfo(hostname, "radius", &hints, &info)) != 0) {
			ERROR("Error getting hostname: %s", gai_strerror(ret));
			return NULL;
		}

		strlcpy(fqdn, info->ai_canonname, sizeof(fqdn));

		freeaddrinfo(info);
	}

	tmpl = talloc_zero(ctx, rs_stats_tmpl_t);
	if (!tmpl) {
		return NULL;
	}

	tmpl->value_tmpl = talloc_zero_array(tmpl, rs_stats_value_tmpl_t, len);
	if (!tmpl->value_tmpl) {
		goto error;
	}

	tmpl->stats = stats;

	value = talloc_zero(tmpl, lcc_value_list_t);
	if (!value) {
		goto error;
	}
	tmpl->value = value;

	value->interval = conf->stats.interval;
	value->values_len = len;

	value->values_types = talloc_zero_array(value, int, len);
	if (!value->values_types) {
		goto error;
	}

	value->values = talloc_zero_array(value, value_t, len);
	if (!value->values) {
		goto error;
	}

	for (i = 0; i < (int) len; i++) {
		assert(values[i].src);
		assert(values[i].cb);

		tmpl->value_tmpl[i] = values[i];
		switch (tmpl->value_tmpl[i].type) {
		case LCC_TYPE_COUNTER:
			tmpl->value_tmpl[i].dst = &value->values[i].counter;
			break;

		case LCC_TYPE_GAUGE:
			tmpl->value_tmpl[i].dst = &value->values[i].gauge;
			break;

		case LCC_TYPE_DERIVE:
			tmpl->value_tmpl[i].dst = &value->values[i].derive;
			break;

		case LCC_TYPE_ABSOLUTE:
			tmpl->value_tmpl[i].dst = &value->values[i].absolute;
			break;

		default:
			assert(0);
		}
		value->values_types[i] = tmpl->value_tmpl[i].type;
	}

	/*
	 *	These should be OK as is
	 */
	strlcpy(value->identifier.host, fqdn, sizeof(value->identifier.host));

	/*
	 *	Plugin is ASCII only and no '/'
	 */
	fr_prints(value->identifier.plugin, sizeof(value->identifier.plugin),
		  conf->stats.prefix, strlen(conf->stats.prefix), '\0');
	for (p = value->identifier.plugin; *p; ++p) {
		if ((*p == '-') || (*p == '/'))*p = '_';
	}

	/*
	 *	Plugin instance is ASCII only (assuming printable only) and no '/'
	 */
	fr_prints(value->identifier.plugin_instance, sizeof(value->identifier.plugin_instance),
		  plugin_instance, strlen(plugin_instance), '\0');
	for (p = value->identifier.plugin_instance; *p; ++p) {
		if ((*p == '-') || (*p == '/')) *p = '_';
	}

	/*
	 *	Type is ASCII only (assuming printable only) and no '/' or '-'
	 */
	fr_prints(value->identifier.type, sizeof(value->identifier.type),
		  type, strlen(type), '\0');
	for (p = value->identifier.type; *p; ++p) {
		if ((*p == '-') || (*p == '/')) *p = '_';
	}

	fr_prints(value->identifier.type_instance, sizeof(value->identifier.type_instance),
		  type_instance, strlen(type_instance), '\0');
	for (p = value->identifier.type_instance; *p; ++p) {
		if ((*p == '-') || (*p == '/')) *p = '_';
	}


	return tmpl;

error:
	talloc_free(tmpl);
	return NULL;
}