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; }
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; }