Example #1
0
static int parse_config_file(const char *uname, int ctrl,
			     struct pam_limit_s *pl)
{
    FILE *fil;
    char buf[LINE_LENGTH];
    
#define CONF_FILE (pl->conf_file[0])?pl->conf_file:LIMITS_FILE
    /* check for the LIMITS_FILE */
    if (ctrl & PAM_DEBUG_ARG)
        _pam_log(LOG_DEBUG,"reading settings from '%s'", CONF_FILE);
    fil = fopen(CONF_FILE, "r");
    if (fil == NULL) {
        _pam_log (LOG_WARNING, "can not read settings from %s", CONF_FILE);
        return PAM_SERVICE_ERR;
    }
#undef CONF_FILE
    
    /* init things */
    memset(buf, 0, sizeof(buf));
    /* start the show */
    while (fgets(buf, LINE_LENGTH, fil) != NULL) {
        char domain[LINE_LENGTH];
        char ltype[LINE_LENGTH];
        char item[LINE_LENGTH];
        char value[LINE_LENGTH];
        int i,j;
        char *tptr;
        
        tptr = buf;
        /* skip the leading white space */
        while (*tptr && isspace(*tptr))
            tptr++;
        strcpy(buf, (const char *)tptr);
                                
        /* Rip off the comments */
        tptr = strchr(buf,'#');
        if (tptr)
            *tptr = '\0';
        /* Rip off the newline char */
        tptr = strchr(buf,'\n');
        if (tptr)
            *tptr = '\0';
        /* Anything left ? */
        if (!strlen(buf)) {
            memset(buf, 0, sizeof(buf));
            continue;
        }

        memset(domain, 0, sizeof(domain));
        memset(ltype, 0, sizeof(ltype));
        memset(item, 0, sizeof(item));
        memset(value, 0, sizeof(value));
        
        i = sscanf(buf,"%s%s%s%s", domain, ltype, item, value);
	D(("scanned line[%d]: domain[%s], ltype[%s], item[%s], value[%s]",
	   i, domain, ltype, item, value));

        for(j=0; j < strlen(domain); j++)
            domain[j]=tolower(domain[j]);
        for(j=0; j < strlen(ltype); j++)
            ltype[j]=tolower(ltype[j]);
        for(j=0; j < strlen(item); j++)
            item[j]=tolower(item[j]);
        for(j=0; j < strlen(value); j++)
            value[j]=tolower(value[j]);

        if (i == 4) { /* a complete line */
            if (strcmp(uname, domain) == 0) /* this user have a limit */
                process_limit(LIMITS_DEF_USER, ltype, item, value, ctrl, pl);
            else if (domain[0]=='@') {
                if (is_on_group(uname, domain+1))
                    process_limit(LIMITS_DEF_GROUP, ltype, item, value, ctrl,
				  pl);
            } else if (strcmp(domain, "*") == 0)
                process_limit(LIMITS_DEF_DEFAULT, ltype, item, value, ctrl,
			      pl);
	} else if (i == 2 && ltype[0] == '-') { /* Probably a no-limit line */
	    if (strcmp(uname, domain) == 0) {
		_pam_log(LOG_DEBUG, "no limits for '%s'", uname);
		fclose(fil);
		return PAM_IGNORE;
	    } else if (domain[0] == '@' && is_on_group(uname, domain+1)) {
		_pam_log(LOG_DEBUG, "no limits for '%s' in group '%s'",
			 uname, domain+1);
		fclose(fil);
		return PAM_IGNORE;
	    }
        } else {
            _pam_log(LOG_DEBUG,"invalid line '%s' - skipped", buf);
	}
    }
    fclose(fil);
    return PAM_SUCCESS;    
}
Example #2
0
static int
parse_config_file(pam_handle_t *pamh, const char *uname, uid_t uid, gid_t gid,
			     int ctrl, struct pam_limit_s *pl)
{
    FILE *fil;
    char buf[LINE_LENGTH];

    /* check for the LIMITS_FILE */
    if (ctrl & PAM_DEBUG_ARG)
        pam_syslog(pamh, LOG_DEBUG, "reading settings from '%s'", CONF_FILE);
    fil = fopen(CONF_FILE, "r");
    if (fil == NULL) {
        pam_syslog (pamh, LOG_WARNING,
		    "cannot read settings from %s: %m", CONF_FILE);
        return PAM_SERVICE_ERR;
    }

    /* start the show */
    while (fgets(buf, LINE_LENGTH, fil) != NULL) {
        char domain[LINE_LENGTH];
        char ltype[LINE_LENGTH];
        char item[LINE_LENGTH];
        char value[LINE_LENGTH];
        int i;
        int rngtype;
        size_t j;
        char *tptr,*line;
        uid_t min_uid = (uid_t)-1, max_uid = (uid_t)-1;

        line = buf;
        /* skip the leading white space */
        while (*line && isspace(*line))
            line++;

        /* Rip off the comments */
        tptr = strchr(line,'#');
        if (tptr)
            *tptr = '\0';
        /* Rip off the newline char */
        tptr = strchr(line,'\n');
        if (tptr)
            *tptr = '\0';
        /* Anything left ? */
        if (!strlen(line))
            continue;

	domain[0] = ltype[0] = item[0] = value[0] = '\0';

	i = sscanf(line,"%s%s%s%s", domain, ltype, item, value);
	D(("scanned line[%d]: domain[%s], ltype[%s], item[%s], value[%s]",
	   i, domain, ltype, item, value));

        for(j=0; j < strlen(ltype); j++)
            ltype[j]=tolower(ltype[j]);

	if ((rngtype=parse_uid_range(pamh, domain, &min_uid, &max_uid)) < 0) {
	    pam_syslog(pamh, LOG_WARNING, "invalid uid range '%s' - skipped", domain);
	    continue;
	}

        if (i == 4) { /* a complete line */
	    for(j=0; j < strlen(item); j++)
		item[j]=tolower(item[j]);
	    for(j=0; j < strlen(value); j++)
		value[j]=tolower(value[j]);

            if (strcmp(uname, domain) == 0) /* this user have a limit */
                process_limit(pamh, LIMITS_DEF_USER, ltype, item, value, ctrl, pl);
            else if (domain[0]=='@') {
		if (ctrl & PAM_DEBUG_ARG) {
			pam_syslog(pamh, LOG_DEBUG,
				   "checking if %s is in group %s",
				   uname, domain + 1);
		}
		switch(rngtype) {
		    case LIMIT_RANGE_NONE:
			if (pam_modutil_user_in_group_nam_nam(pamh, uname, domain+1))
			    process_limit(pamh, LIMITS_DEF_GROUP, ltype, item, value, ctrl,
					  pl);
			break;
		    case LIMIT_RANGE_ONE:
			if (pam_modutil_user_in_group_nam_gid(pamh, uname, (gid_t)max_uid))
			    process_limit(pamh, LIMITS_DEF_GROUP, ltype, item, value, ctrl,
				  pl);
			break;
		    case LIMIT_RANGE_MM:
			if (gid > (gid_t)max_uid)
			    break;
			/* fallthrough */
		    case LIMIT_RANGE_MIN:
			if (gid >= (gid_t)min_uid)
			    process_limit(pamh, LIMITS_DEF_GROUP, ltype, item, value, ctrl,
					  pl);
		}
            } else if (domain[0]=='%') {
		if (ctrl & PAM_DEBUG_ARG) {
			pam_syslog(pamh, LOG_DEBUG,
				   "checking if %s is in group %s",
				   uname, domain + 1);
		}
		switch(rngtype) {
		    case LIMIT_RANGE_NONE:
			if (strcmp(domain,"%") == 0)
			    process_limit(pamh, LIMITS_DEF_ALL, ltype, item, value, ctrl,
					  pl);
			else if (pam_modutil_user_in_group_nam_nam(pamh, uname, domain+1)) {
			    strcpy(pl->login_group, domain+1);
			    process_limit(pamh, LIMITS_DEF_ALLGROUP, ltype, item, value, ctrl,
					  pl);
			}
			break;
		    case LIMIT_RANGE_ONE:
			if (pam_modutil_user_in_group_nam_gid(pamh, uname, (gid_t)max_uid)) {
			    struct group *grp;
			    grp = pam_modutil_getgrgid(pamh, (gid_t)max_uid);
			    strncpy(pl->login_group, grp->gr_name, sizeof(pl->login_group));
			    pl->login_group[sizeof(pl->login_group)-1] = '\0';
			    process_limit(pamh, LIMITS_DEF_ALLGROUP, ltype, item, value, ctrl,
					  pl);
			}
			break;
		    case LIMIT_RANGE_MIN:
		    case LIMIT_RANGE_MM:
			pam_syslog(pamh, LOG_WARNING, "range unsupported for %%group matching - ignored");
		}
            } else {
		switch(rngtype) {
		    case LIMIT_RANGE_NONE:
			if (strcmp(domain, "*") == 0)
			    process_limit(pamh, LIMITS_DEF_DEFAULT, ltype, item, value, ctrl,
					  pl);
			break;
		    case LIMIT_RANGE_ONE:
			if (uid != max_uid)
			    break;
			/* fallthrough */
		    case LIMIT_RANGE_MM:
			if (uid > max_uid)
			    break;
			/* fallthrough */
		    case LIMIT_RANGE_MIN:
			if (uid >= min_uid)
			    process_limit(pamh, LIMITS_DEF_USER, ltype, item, value, ctrl, pl);
		}
	    }
	} else if (i == 2 && ltype[0] == '-') { /* Probably a no-limit line */
	    if (strcmp(uname, domain) == 0) {
		if (ctrl & PAM_DEBUG_ARG) {
		    pam_syslog(pamh, LOG_DEBUG, "no limits for '%s'", uname);
		}
	    } else if (domain[0] == '@') {
		switch(rngtype) {
		    case LIMIT_RANGE_NONE:
			if (!pam_modutil_user_in_group_nam_nam(pamh, uname, domain+1))
			    continue; /* next line */
			break;
		    case LIMIT_RANGE_ONE:
			if (!pam_modutil_user_in_group_nam_gid(pamh, uname, (gid_t)max_uid))
			    continue; /* next line */
			break;
		    case LIMIT_RANGE_MM:
			if (gid > (gid_t)max_uid)
			    continue;  /* next line */
			/* fallthrough */
		    case LIMIT_RANGE_MIN:
			if (gid < (gid_t)min_uid)
			    continue;  /* next line */
		}
		if (ctrl & PAM_DEBUG_ARG) {
		    pam_syslog(pamh, LOG_DEBUG,
			       "no limits for '%s' in group '%s'",
			       uname, domain+1);
		}
	    } else {
		switch(rngtype) {
		    case LIMIT_RANGE_NONE:
			continue;  /* next line */
		    case LIMIT_RANGE_ONE:
			if (uid != max_uid)
			    continue;  /* next line */
			break;
		    case LIMIT_RANGE_MM:
			if (uid > max_uid)
			    continue;  /* next line */
			/* fallthrough */
		    case LIMIT_RANGE_MIN:
			if (uid >= min_uid)
			    break;
			continue;  /* next line */
		}
		if (ctrl & PAM_DEBUG_ARG) {
		    pam_syslog(pamh, LOG_DEBUG, "no limits for '%s'", uname);
		}
	    }
	    fclose(fil);
	    return PAM_IGNORE;
        } else {
            pam_syslog(pamh, LOG_WARNING, "invalid line '%s' - skipped", line);
	}
    }
    fclose(fil);
    return PAM_SUCCESS;
}