Blame src/parser.y

Packit Service 466431
/* Copyright (C) 2017 mod_auth_gssapi contributors - See COPYING for (C) terms
Packit Service 466431
 *
Packit Service 466431
 * Bison file for the GssapiRequiredNameAttributes option parser.
Packit Service 466431
 *
Packit Service 466431
 * Rule := (RequiredKV | "(" Rule ")"),  { ' ', (AND|OR), ' ', Rule } ;
Packit Service 466431
 * RequiredKV := (Key, "=", Value) | (Key, ":=" BinValue) ;
Packit Service 466431
 * Key := <string> ;
Packit Service 466431
 * Value := <string> | '*' ;
Packit Service 466431
 * BinValue := <base64> ;
Packit Service 466431
 * AND := "and" | "AND" ;
Packit Service 466431
 * OR := "or" | "OR" ;
Packit Service 466431
 *
Packit Service 466431
 */
Packit Service 466431
%{
Packit Service 466431
#include <stdio.h>
Packit Service 466431
#include <stdlib.h>
Packit Service 466431
#include <string.h>
Packit Service 466431
#include <apr_base64.h>
Packit Service 466431
int yylex(void);
Packit Service 466431
typedef struct yy_buffer_state * YY_BUFFER_STATE;
Packit Service 466431
extern void yyerror(const char **keys, const char **vals,
Packit Service 466431
                    int *status, const char *s);
Packit Service 466431
extern int yyparse(const char **keys, const char **vals, int *status);
Packit Service 466431
extern YY_BUFFER_STATE yy_scan_string(char * str);
Packit Service 466431
extern void yy_delete_buffer(YY_BUFFER_STATE buffer);
Packit Service 466431
static size_t b64_len(const char *val);
Packit Service 466431
static char *b64_enc(const char *val, size_t len);
Packit Service 466431
%}
Packit Service 466431
Packit Service 466431
%union {
Packit Service 466431
    char *sval;
Packit Service 466431
    int ival;
Packit Service 466431
}
Packit Service 466431
Packit Service 466431
%token LPAREN
Packit Service 466431
%token RPAREN
Packit Service 466431
%token SPACE
Packit Service 466431
%token OR
Packit Service 466431
%token AND
Packit Service 466431
%token EQUAL
Packit Service 466431
%token EQUALBIN
Packit Service 466431
%token AST
Packit Service 466431
%token STRING
Packit Service 466431
%token INT
Packit Service 466431
Packit Service 466431
%type <sval> STRING
Packit Service 466431
%type <ival> INT rule rule_start requiredkv
Packit Service 466431
Packit Service 466431
%parse-param {const char **keys} {const char **vals} {int *status}
Packit Service 466431
Packit Service 466431
%%
Packit Service 466431
Packit Service 466431
expr: rule {
Packit Service 466431
      if (status != NULL)
Packit Service 466431
          *status = $1;
Packit Service 466431
    }
Packit Service 466431
    ;
Packit Service 466431
Packit Service 466431
rule: rule_start
Packit Service 466431
    | rule_start SPACE AND SPACE rule {
Packit Service 466431
      $$ = $1 && $5;
Packit Service 466431
    }
Packit Service 466431
    | rule_start SPACE OR SPACE rule {
Packit Service 466431
      $$ = $1 || $5;
Packit Service 466431
    }
Packit Service 466431
    ;
Packit Service 466431
Packit Service 466431
rule_start: LPAREN rule RPAREN {
Packit Service 466431
            $$ = $2;
Packit Service 466431
          }
Packit Service 466431
          | requiredkv {
Packit Service 466431
            $$ = $1;
Packit Service 466431
          }
Packit Service 466431
          ;
Packit Service 466431
Packit Service 466431
requiredkv: STRING EQUAL STRING {
Packit Service 466431
            int ret = 0;
Packit Service 466431
            size_t sz;
Packit Service 466431
            if (keys != NULL && vals != NULL) {
Packit Service 466431
                for (int i = 0; keys[i] != NULL && vals[i] != NULL; i++) {
Packit Service 466431
                    if (strcmp($1, keys[i]) != 0) {
Packit Service 466431
                        continue;
Packit Service 466431
                    }
Packit Service 466431
                    sz = 0;
Packit Service 466431
                    memcpy(&sz, vals[i], sizeof(sz));
Packit Service 466431
                    if (sz == 0) {
Packit Service 466431
                        continue;
Packit Service 466431
                    }
Packit Service 466431
                    if (!memcmp($3, vals[i] + sizeof(sz), sz)) {
Packit Service 466431
                        ret = 1;
Packit Service 466431
                        break;
Packit Service 466431
                    }
Packit Service 466431
                }
Packit Service 466431
            }
Packit Service 466431
            $$ = ret;
Packit Service 466431
          }
Packit Service 466431
          | STRING EQUAL AST {
Packit Service 466431
            int ret = 0;
Packit Service 466431
            if (keys != NULL && vals != NULL) {
Packit Service 466431
                for (int i = 0; keys[i] != NULL && vals[i] != NULL; i++) {
Packit Service 466431
                    if (strcmp($1, keys[i]) == 0) {
Packit Service 466431
                       ret = 1;
Packit Service 466431
                       break;
Packit Service 466431
                    }
Packit Service 466431
                }
Packit Service 466431
            }
Packit Service 466431
            $$ = ret;
Packit Service 466431
          }
Packit Service 466431
          | STRING EQUALBIN STRING {
Packit Service 466431
            int ret = 0;
Packit Service 466431
            if (keys != NULL && vals != NULL) {
Packit Service 466431
                for (int i = 0; keys[i] != NULL && vals[i] != NULL; i++) {
Packit Service 466431
                    if (strcmp($1, keys[i]) != 0) {
Packit Service 466431
                        continue;
Packit Service 466431
                    }
Packit Service 466431
                    size_t b64len = b64_len(vals[i]);
Packit Service 466431
                    /* b64len includes the NULL terminator. */
Packit Service 466431
                    if (strlen($3) + 1 != b64len) {
Packit Service 466431
                        continue;
Packit Service 466431
                    }
Packit Service 466431
                    char *b64val = b64_enc(vals[i], b64len);
Packit Service 466431
                    if (!b64val) {
Packit Service 466431
                        continue;
Packit Service 466431
                    }
Packit Service 466431
                    if (strcmp($3, b64val) == 0) {
Packit Service 466431
                        ret = 1;
Packit Service 466431
                    }
Packit Service 466431
                    free(b64val);
Packit Service 466431
                    if (ret) {
Packit Service 466431
                        break;
Packit Service 466431
                    }
Packit Service 466431
                }
Packit Service 466431
            }
Packit Service 466431
            $$ = ret;
Packit Service 466431
          }
Packit Service 466431
          ;
Packit Service 466431
Packit Service 466431
%%
Packit Service 466431
Packit Service 466431
static size_t b64_len(const char *val)
Packit Service 466431
{
Packit Service 466431
    size_t sz = 0;
Packit Service 466431
Packit Service 466431
    memcpy(&sz, val, sizeof(sz));
Packit Service 466431
    if (sz == 0)
Packit Service 466431
        return sz;
Packit Service 466431
Packit Service 466431
    return apr_base64_encode_len(sz);
Packit Service 466431
}
Packit Service 466431
Packit Service 466431
static char *b64_enc(const char *val, size_t len)
Packit Service 466431
{
Packit Service 466431
    size_t sz = 0;
Packit Service 466431
    char *b64val;
Packit Service 466431
Packit Service 466431
    memcpy(&sz, val, sizeof(sz));
Packit Service 466431
    if (sz == 0)
Packit Service 466431
        return NULL;
Packit Service 466431
Packit Service 466431
    b64val = calloc(1, len + 1);
Packit Service 466431
    if (!b64val)
Packit Service 466431
        return NULL;
Packit Service 466431
Packit Service 466431
    apr_base64_encode(b64val, val + sizeof(sz), sz);
Packit Service 466431
    return b64val;
Packit Service 466431
}
Packit Service 466431
Packit Service 466431
/* Return 1 if the given name attributes and values (NULL terminated arrays)
Packit Service 466431
 * satisfy the expression.  This does not handle parsing errors from yyparse,
Packit Service 466431
 * so expr should be checked by required_name_attr_expr_check() first. */
Packit Service 466431
int mag_verify_name_attributes(const char *expr, const char **attrs,
Packit Service 466431
                               const char **vals)
Packit Service 466431
{
Packit Service 466431
    int ret = 0, status = 0;
Packit Service 466431
    YY_BUFFER_STATE buffer;
Packit Service 466431
Packit Service 466431
    /* No name attribute requirements. Pass. */
Packit Service 466431
    if (expr == NULL) {
Packit Service 466431
        return 1;
Packit Service 466431
    }
Packit Service 466431
Packit Service 466431
    /* No name attributes but required attributes are specified. Fail. */
Packit Service 466431
    if (attrs == NULL || vals == NULL ||
Packit Service 466431
        attrs[0] == NULL || vals[0] == NULL) {
Packit Service 466431
        return 0;
Packit Service 466431
    }
Packit Service 466431
Packit Service 466431
    buffer = yy_scan_string((char *)expr);
Packit Service 466431
    ret = yyparse(attrs, vals, &status);
Packit Service 466431
    yy_delete_buffer(buffer);
Packit Service 466431
Packit Service 466431
    return ret == 0 && status;
Packit Service 466431
}
Packit Service 466431
Packit Service 466431
/* Return 1 if the expression is provided and valid, else return 0. */
Packit Service 466431
int mag_check_name_attr_expr(const char *expr)
Packit Service 466431
{
Packit Service 466431
    int ret;
Packit Service 466431
    YY_BUFFER_STATE buffer = yy_scan_string((char *)expr);
Packit Service 466431
Packit Service 466431
    /* Just verify the syntax. */
Packit Service 466431
    ret = yyparse(NULL, NULL, NULL);
Packit Service 466431
    yy_delete_buffer(buffer);
Packit Service 466431
Packit Service 466431
    return ret == 0;
Packit Service 466431
}
Packit Service 466431
Packit Service 466431
/* Define a no-op yyerror().  Syntax errors are logged outside of calling
Packit Service 466431
 * required_name_attr_expr_check(). */
Packit Service 466431
void yyerror(const char **keys, const char **vals, int *status, const char *s)
Packit Service 466431
{
Packit Service 466431
    return;
Packit Service 466431
}