ipa_timerules.c revision b9f94bc83f139df3e143cc020b98e6e652887049
/*
SSSD
IPA Provider Time Rules Parsing
Authors:
Jakub Hrozek <jhrozek@redhat.com>
Copyright (C) Red Hat, Inc 2009
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _XOPEN_SOURCE /* strptime() needs this */
#include <pcre.h>
#include <talloc.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <time.h>
#include <stdbool.h>
#include <limits.h>
#include "providers/ipa/ipa_timerules.h"
} while (0)
} while (0)
return ENOMEM; \
} \
} while (0)
#define CHECK_PTR_JMP(ptr) do { \
goto done; \
} \
} while (0)
return ENOMEM; \
} \
} while (0)
if (bitfield) { \
*resptr = false; \
return EOK; \
} \
} \
} while (0)
if (bitfield) { \
*resptr = false; \
return EOK; \
} \
} \
} while (0)
/* number of match offsets when matching pcre regexes */
#define OVEC_SIZE 30
/* regular expressions describing syntax of our HBAC grammar */
#define RGX_WEEKLY "day (?P<day_of_week>(0|1|2|3|4|5|6|7|Mon|Tue|Wed|Thu|Fri|Sat|Sun|,|-)+)"
#define RGX_MDAY "(?P<mperspec_day>day) (?P<interval_day>[0-9,-]+) "
#define RGX_YDAY "(?P<yperspec_day>day) (?P<day_of_year>[0-9,-]+) "
#define RGX_YMONTH "(?P<yperspec_month>month) (?P<month_number>[0-9,-]+) (?P<m_period>.*?)$"
#define RGX_TIMESPEC "(?P<timeFrom>[0-9]{4}) ~ (?P<timeTo>[0-9]{4})"
#define RGX_GENERALIZED "(?P<year>[0-9]{4})(?P<month>[0-9]{2})(?P<day>[0-9]{2})(?P<hour>[0-9]{2})?(?P<minute>[0-9]{2})?(?P<second>[0-9]{2})?"
#define RGX_PERIODIC "^periodic (?P<perspec>daily|weekly|monthly|yearly) (?P<period>.*?)"RGX_TIMESPEC"$"
#define RGX_ABSOLUTE "^absolute (?P<from>\\S+) ~ (?P<to>\\S+)$"
/* limits on various parameters */
#define DAY_OF_WEEK_MAX 7
#define DAY_OF_MONTH_MAX 31
#define WEEK_OF_MONTH_MAX 5
#define WEEK_OF_YEAR_MAX 54
#define DAY_OF_YEAR_MAX 366
#define MONTH_MAX 12
#define HOUR_MAX 23
#define MINUTE_MAX 59
/* limits on sizes of buffers for bit arrays */
#define DAY_OF_MONTH_BUFSIZE 8
#define DAY_OF_YEAR_BUFSIZE 44
#define WEEK_OF_YEAR_BUFSIZE 13
#define MONTH_BUFSIZE 2
#define HOUR_BUFSIZE 4
#define MINUTE_BUFSIZE 8
/* Lookup tables for translating names of days and months */
static const char *names_day_of_week[] =
static const char *names_months[] =
{ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
/*
* Timelib knows two types of ranges - periodic and absolute
*/
enum rangetypes {
};
struct absolute_range {
};
struct periodic_range {
unsigned char day_of_week;
unsigned char *day_of_month;
unsigned char *day_of_year;
unsigned char week_of_month;
unsigned char *week_of_year;
unsigned char *month;
unsigned char *hour;
unsigned char *minute;
};
/*
* Context of one time rule being analyzed
*/
struct range_ctx {
/* main context with precompiled patterns */
struct time_rules_ctx *trctx;
/* enum rangetypes */
enum rangetypes type;
struct absolute_range *abs;
struct periodic_range *per;
};
/*
* The context of one regular expression
*/
struct parse_ctx {
/* the regular expression used for one parsing */
/* number of matches */
int matches;
/* vector of matches */
int *ovec;
};
/* indexes to the array of precompiled regexes */
enum timelib_rgx {
};
/* matches the indexes */
static const char *lookup_table[] = {
NULL,
};
/*
* Main struct passed outside
* holds precompiled regular expressions
*/
struct time_rules_ctx {
};
/*******************************************************************
* helper function - bit arrays *
*******************************************************************/
/* set a single bit in a bitmap */
{
}
/*
* This function is based on bit_nset macro written originally by Paul Vixie,
* copyrighted by The Regents of the University of California, as found
* in tarball of fcron, file bitstring.h
*/
unsigned int stop)
{
} else {
}
}
}
{
}
/*******************************************************************
* parsing intervals *
*******************************************************************/
/*
* Some ranges allow symbolic names, like Mon..Sun for names of day.
* This routine takes a list of symbolic names as NAME_ARRAY and the
* one we're looking for as KEY and returns its index or -1 when not
* found. The last member of NAME_ARRAY must be NULL.
*/
{
int index = 0;
const char *one;
if (name_array == NULL) {
return -1;
}
}
index++;
}
return -1;
}
/*
* Sets appropriate bits given by an interval in STR (in form of 1,5-7,10) to
* a bitfield given in OUT. Does no boundary checking. STR can also contain
* symbolic names, these would be given in TRANSLATE.
*/
unsigned char *out,
const char *str,
const char **translate)
{
char *copy;
char *end_ptr;
int ret;
char *dash;
while (next) {
if (next) {
*next = '\0';
next++;
}
errno = 0;
continue;
} else {
goto done;
}
*dash = '\0';
++dash;
errno = 0;
if (tokval == -1) {
goto done;
}
}
errno = 0;
if (tokmax == -1) {
goto done;
}
}
} else {
/* Interval wraps around - i.e. from 18.00 to 06.00 */
}
continue;
} else {
/* tokval or tokmax are not between <min, max> */
goto done;
}
/* Try to translate one token by name */
continue;
} else {
goto done;
}
} else {
goto done;
}
}
done:
return ret;
}
/*******************************************************************
* wrappers around regexp handling *
*******************************************************************/
/*
* Copies a named substring SUBSTR_NAME from string STR using the parsing
* information from PCTX. The context PCTX is also used as a talloc context.
*
* The resulting string is stored in OUT.
* Return value is EOK on no error or ENOENT on error capturing the substring
*/
const char *str,
const char *substr_name,
char **out)
{
int ret;
char *o = NULL;
substr_name, str));
return ENOENT;
}
if (o == NULL) {
return ENOMEM;
}
*out = o;
return EOK;
}
/*
* Copies a named substring SUBSTR_NAME from string STR using the parsing
* information from PCTX and converts it to an integer.
* The context PCTX is also used as a talloc context.
*
* The resulting string is stored in OUT.
* Return value is EOK on no error or ENOENT on error capturing the substring
*/
const char *str,
const char *substr_name,
int *out)
{
int ret;
int val;
char *err_ptr;
return ret;
}
errno = 0;
substr));
return EINVAL;
}
return EOK;
}
/*
* Compiles a regular expression REGEXP and tries to match it against the
* string STR. Fills in structure _PCTX with info about matching.
*
* Returns EOK on no error, EFAULT on bad regexp, EINVAL when it cannot
* match the regexp.
*/
struct time_rules_ctx *trctx,
const char *str,
enum timelib_rgx regex,
{
int ret;
if (ret <= 0) {
goto done;
}
return EOK;
done:
return ret;
}
/*******************************************************************
*******************************************************************/
/*
* Returns week number as an integer
* This may seem ugly, but I think it's actually less error prone
* than writing my own routine
*/
{
char buf[3];
return -1;
}
/* %U returns 0-53, we want 1-54 */
}
/*
* Return the week of the month
* Range is 1 to 5
*/
static int get_week_of_month(const struct tm *t)
{
int fs; /* first sunday */
if (fs <= 0) {
fs += 7;
}
}
/*
* Normalize differencies between our HBAC definition and semantics of
* struct tm
*/
{
/* tm defines tm_year as num of yrs since 1900, we have absolute number */
t->tm_year %= 1900;
/* struct tm defines tm_mon as number of month since January */
t->tm_mon--;
}
/*
* Normalize differencies between our HBAC definition and semantics of
* struct tm
*/
{
/* tm defines tm_year as num of yrs since 1900, we have absolute number */
t->tm_year += 1900;
/* struct tm defines tm_mon as number of month since January */
t->tm_mon++;
}
/*******************************************************************
* parsing of HBAC rules themselves *
*******************************************************************/
/*
* Parses generalized time string given in STR and fills the
* information into OUT.
*/
struct time_rules_ctx *trctx,
const char *str,
{
int ret;
/* compulsory */
/* optional */
}
if (*out == -1) {
}
done:
return ret;
}
/*
* Parses absolute timerange string given in STR and fills the
* information into ABS.
*/
struct time_rules_ctx *trctx,
const char *str)
{
int ret;
goto done;
}
goto done;
}
goto done;
}
goto done;
}
}
done:
return ret;
}
{
struct tm t;
char *err;
if (*err != '\0') {
return EINVAL;
}
return EOK;
}
/*
* Parses monthly periodic timerange given in STR.
* Fills the information into PER.
*/
struct time_rules_ctx *trctx,
struct periodic_range *per,
const char *str)
{
int ret;
/* This code would be much less ugly if RHEL5 PCRE knew about PCRE_DUPNAMES */
} else {
}
done:
return ret;
}
/*
* Parses yearly periodic timerange given in STR.
* Fills the information into PER.
*/
struct time_rules_ctx *trctx,
struct periodic_range *per,
const char *str)
{
int ret;
}
}
done:
return ret;
}
/*
* Parses weekly periodic timerange given in STR.
* Fills the information into PER.
*/
struct time_rules_ctx *trctx,
struct periodic_range *per,
const char *str)
{
int ret;
done:
return ret;
}
const char *str)
{
int ret;
int hour_from;
int hour_to;
int min_from;
int min_to;
/* parse out the time */
/* set the interval */
} else {
}
} else {
}
done:
return ret;
}
/*
* Parses periodic timerange given in STR.
* Fills the information into PER.
*/
struct time_rules_ctx *trctx,
const char *str)
{
int ret;
/* These are mandatory */
} else {
goto done;
}
done:
return ret;
}
/*
* Parses time specification given in string RULE into range_ctx
* context CTX.
*/
{
int ret;
} else {
goto done;
}
done:
return ret;
}
/*******************************************************************
* validation of rules against time_t *
*******************************************************************/
bool *result)
{
*result = false;
return EOK;
}
*result = false;
return EOK;
}
*result = true;
return EOK;
}
bool *result)
{
int wnum;
int wom;
DEBUG(0, ("Cannot convert time_t to struct tm\n"));
return EFAULT;
}
if (wnum == -1) {
return EINVAL;
}
if (wnum == -1) {
return EINVAL;
}
/* The validation itself */
*result = true;
return EOK;
}
/*
* Returns EOK if the timerange in range_ctx context is valid compared against a
* given time_t value in NOW, returns ERANGE if the time value is outside the
* specified range.
*/
bool *result)
{
int ret;
case TYPE_ABSOLUTE:
break;
case TYPE_PERIODIC:
break;
default:
break;
}
return ret;
}
/*******************************************************************
* public interface *
*******************************************************************/
/*
* This is actually the meat of the library. The function takes a string
* representation of a time rule in STR and time to check against (usually that
* would be current time) in NOW.
*
* It returns EOK if the rule is valid in the current time, ERANGE if not and
* EINVAL if the rule cannot be parsed
*/
struct time_rules_ctx *trctx,
const char *str,
bool *result)
{
int ret;
goto done;
}
goto done;
}
done:
return EOK;
}
/*
* Frees the resources taken by the precompiled rules
*/
{
int i;
for (i = 0; i< LP_RGX_MAX; ++i) {
}
return 0;
}
/*
* Initializes the parser by precompiling the regular expressions
* for later use
*/
struct time_rules_ctx **_out)
{
const char *errstr;
int errval;
int errpos;
int ret;
int i;
/* Precompile regular expressions */
for (i = LP_RGX_GENERALIZED; i< LP_RGX_MAX; ++i) {
0,
&errval,
&errstr,
&errpos,
NULL);
DEBUG(0, ("Invalid Regular Expression pattern '%s' at position %d"
" (Error: %d [%s])\n", lookup_table[i],
goto done;
}
}
return EOK;
done:
return ret;
}