30 RCSID(
"$Id: 329ed2916ae82a2a17f60377f26d5a21d7777f3d $")
33 #include <freeradius-devel/radiusd.h>
46 # include <sys/security.h>
55 #include <freeradius-devel/modules.h>
56 #include <freeradius-devel/sysutmp.h>
58 static char trans[64] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
59 #define ENC(c) trans[c]
93 if (
rad_getgrnam(request, &grp, check->vp_strvalue) < 0) {
103 if (pwd->pw_gid == grp->gr_gid) {
107 for (member = grp->gr_mem; *member && retval; member++) {
108 if (strcmp(*member, pwd->pw_name) == 0) {
139 ERROR(
"rlm_unix (%s): 'Group' attribute not found in dictionary", inst->
name);
145 ERROR(
"rlm_unix (%s): 'User-Name' attribute not found in dictionary", inst->
name);
158 if (!group_name_da) {
159 ERROR(
"rlm_unix (%s): 'Group-Name' attribute not found in dictionary", inst->
name);
167 ERROR(
"rlm_unix (%s): Failed registering Unix-Group: %s", inst->
name,
183 char const *encrypted_pass;
185 struct spwd *spwd = NULL;
188 struct pr_passwd *pr_pw;
192 #ifdef HAVE_GETUSERSHELL
201 if (!request->username) {
205 name = request->username->vp_strvalue;
206 encrypted_pass = NULL;
209 if ((pr_pw = getprpwnam(name)) == NULL)
211 encrypted_pass = pr_pw->ufld.fd_encrypt;
216 if (pr_pw->uflg.fg_lock!=1) {
217 AUTH(
"rlm_unix: [%s]: account locked", name);
221 if ((pwd = getpwnam(name)) == NULL) {
224 encrypted_pass = pwd->pw_passwd;
237 if ((!encrypted_pass) || (strlen(encrypted_pass) < 10)) {
238 if ((spwd = getspnam(name)) == NULL) {
241 encrypted_pass = spwd->sp_pwdp;
253 if (strcmp(pwd->pw_shell, DENY_SHELL) == 0) {
254 RAUTH(
"rlm_unix: [%s]: invalid shell", name);
259 #ifdef HAVE_GETUSERSHELL
264 while ((shell = getusershell()) != NULL) {
265 if (strcmp(shell, pwd->pw_shell) == 0 ||
266 strcmp(shell,
"/RADIUSD/ANY/SHELL") == 0) {
272 RAUTH(
"[%s]: invalid shell [%s]",
273 name, pwd->pw_shell);
279 #if defined(HAVE_GETSPNAM) && !defined(M_UNIX)
283 if (spwd && spwd->sp_lstchg > 0 && spwd->sp_max >= 0 &&
284 (request->timestamp.tv_sec / 86400) > (spwd->sp_lstchg + spwd->sp_max)) {
285 RAUTH(
"[%s]: password has expired", name);
291 if (spwd && spwd->sp_expire > 0 &&
292 (request->timestamp.tv_sec / 86400) > spwd->sp_expire) {
293 RAUTH(
"[%s]: account has expired", name);
298 #if defined(__FreeBSD__) || defined(bsdi) || defined(_PWF_EXPIRE)
302 if ((pwd->pw_expire > 0) &&
303 (request->timestamp.tv_sec > pwd->pw_expire)) {
304 RAUTH(
"[%s]: password has expired", name);
314 if (encrypted_pass[0] == 0)
329 static char *
uue(
void *in)
332 static unsigned char res[7];
333 unsigned char *
data = (
unsigned char *)in;
335 res[0] =
ENC( data[0] >> 2 );
336 res[1] =
ENC( ((data[0] << 4) & 060) + ((data[1] >> 4) & 017) );
337 res[2] =
ENC( ((data[1] << 2) & 074) + ((data[2] >> 6) & 03) );
338 res[3] =
ENC( data[2] & 077 );
340 res[4] =
ENC( data[3] >> 2 );
341 res[5] =
ENC( (data[3] << 4) & 060 );
344 for(i = 0; i < 6; i++) {
345 if (res[i] ==
' ') res[i] =
'`';
346 if (res[i] < 32 || res[i] > 127)
347 printf(
"uue: protocol error ?!\n");
368 int framed_address = 0;
373 bool port_seen =
true;
380 RDEBUG2(
"No radwtmp file configured. Ignoring accounting request");
384 if (request->packet->src_ipaddr.af != AF_INET) {
385 RDEBUG2(
"IPv6 is not supported!");
393 RDEBUG(
"no Accounting-Status-Type attribute in request");
396 status = vp->vp_integer;
412 t = request->timestamp.tv_sec;
413 memset(&ut, 0,
sizeof(ut));
423 if (vp->vp_length >=
sizeof(ut.ut_name)) {
424 memcpy(ut.ut_name, vp->vp_strvalue,
sizeof(ut.ut_name));
426 strlcpy(ut.ut_name, vp->vp_strvalue,
sizeof(ut.ut_name));
430 case PW_LOGIN_IP_HOST:
431 case PW_FRAMED_IP_ADDRESS:
432 framed_address = vp->vp_ipaddr;
435 case PW_FRAMED_PROTOCOL:
436 protocol = vp->vp_integer;
439 case PW_NAS_IP_ADDRESS:
440 nas_address = vp->vp_ipaddr;
444 nas_port = vp->vp_integer;
448 case PW_ACCT_DELAY_TIME:
449 delay = vp->vp_ipaddr;
458 if (strncmp(ut.ut_name,
"!root",
sizeof(ut.ut_name)) == 0 || !port_seen)
465 if (nas_address == 0) {
466 nas_address = request->packet->src_ipaddr.ipaddr.ip4addr.s_addr;
468 s = request->client->shortname;
469 if (!s || s[0] == 0) s =
uue(&(nas_address));
475 ut.ut_addr = framed_address;
481 snprintf(buf,
sizeof(buf),
"%03d:%s", nas_port, s);
482 strlcpy(ut.ut_line, buf,
sizeof(ut.ut_line));
488 if (framed_address) {
489 inet_ntop(AF_INET, &framed_address, buf,
sizeof(buf));
490 strlcpy(ut.ut_host, buf,
sizeof(ut.ut_host));
494 ut.ut_xtime = t- delay;
496 ut.ut_time = t - delay;
504 strcpy(ut.ut_id,
"P");
506 strcpy(ut.ut_id,
"S");
508 strcpy(ut.ut_id,
"T");
521 if ((fp = fopen(inst->
radwtmp,
"a")) != NULL) {
522 if ((fwrite(&ut,
sizeof(ut), 1, fp)) != 1) {
540 .config = module_config,
int paircompare_register(fr_dict_attr_t const *attribute, fr_dict_attr_t const *from, bool first_only, RAD_COMPARE_FUNC func, void *instance)
Register a function as compare function.
static rlm_rcode_t CC_HINT(nonnull)
static rlm_rcode_t mod_accounting(void *instance, REQUEST *request)
Write accounting data to Couchbase documents.
static char * uue(void *in)
The module is OK, continue.
Metadata exported by the module.
#define RLM_TYPE_THREAD_UNSAFE
Module is not threadsafe.
struct rlm_unix rlm_unix_t
static rlm_rcode_t mod_authorize(void *instance, REQUEST *request)
Handle authorization requests using Couchbase document data.
VALUE_PAIR * username
Cached username VALUE_PAIR from request RADIUS_PACKET.
#define CONF_PARSER_TERMINATOR
char const * inet_ntop(int af, void const *src, char *dst, size_t cnt)
VALUE_PAIR * fr_cursor_init(vp_cursor_t *cursor, VALUE_PAIR *const *node)
Setup a cursor to iterate over attribute pairs.
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
Defines a CONF_PAIR to C data type mapping.
Abstraction to allow iterating over different configurations of VALUE_PAIRs.
Reject the request (user is locked out).
#define pair_make_config(_a, _b, _c)
unsigned int attr
Attribute number.
Immediately reject the request.
3 methods index for accounting section.
unsigned int vendor
Vendor that defines this attribute.
Stores an attribute, a value and various bits of other data.
int rad_getpwnam(TALLOC_CTX *ctx, struct passwd **out, char const *name)
Resolve a username to a passwd entry.
static int groupcmp(UNUSED void *instance, REQUEST *request, UNUSED VALUE_PAIR *req_vp, VALUE_PAIR *check, UNUSED VALUE_PAIR *check_pairs, UNUSED VALUE_PAIR **reply_pairs)
static const CONF_PARSER module_config[]
enum rlm_rcodes rlm_rcode_t
Return codes indicating the result of the module call.
char const * name
Instance name.
char const * fr_strerror(void)
Get the last library error.
char const * cf_section_name1(CONF_SECTION const *cs)
Module succeeded without doing anything.
uint64_t magic
Used to validate module struct.
Module failed, don't reply.
#define PW_TYPE_FILE_OUTPUT
File matching value must exist, and must be writeable.
int rad_getgrnam(TALLOC_CTX *ctx, struct group **out, char const *name)
Resolve a group name to a group database entry.
#define FR_CONF_OFFSET(_n, _t, _s, _f)
VALUE_PAIR * fr_cursor_next(vp_cursor_t *cursor)
Advanced the cursor to the next VALUE_PAIR.
int paircompare_register_byname(char const *name, fr_dict_attr_t const *from, bool first_only, RAD_COMPARE_FUNC func, void *instance)
Register a function as compare function.
static int mod_bootstrap(CONF_SECTION *conf, void *instance)
#define PW_TYPE_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
VALUE_PAIR * fr_pair_find_by_num(VALUE_PAIR *head, unsigned int vendor, unsigned int attr, int8_t tag)
Find the pair with the matching attribute.
size_t strlcpy(char *dst, char const *src, size_t siz)
fr_dict_attr_t const * da
Dictionary attribute defines the attribute.
fr_dict_attr_t const * fr_dict_attr_by_num(fr_dict_t *dict, unsigned int vendor, unsigned int attr)
Lookup a fr_dict_attr_t by its vendor and attribute numbers.
1 methods index for authorize section.
char const * cf_section_name2(CONF_SECTION const *cs)
#define USES_APPLE_DEPRECATED_API
static USES_APPLE_DEPRECATED_API char trans[64]