|
|
@@ -1,2241 +0,0 @@
|
|
|
-/** BEGIN COPYRIGHT BLOCK
|
|
|
- * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
|
|
|
- * Copyright (C) 2005 Red Hat, Inc.
|
|
|
- * All rights reserved.
|
|
|
- * END COPYRIGHT BLOCK **/
|
|
|
-
|
|
|
-/*
|
|
|
- * Description (aclparse.c)
|
|
|
- *
|
|
|
- * This module provides functions for parsing a file containing
|
|
|
- * Access Control List (ACL) definitions. It builds a representation
|
|
|
- * of the ACLs in memory, using the services of the aclbuild module.
|
|
|
- */
|
|
|
-
|
|
|
-#include <base/systems.h>
|
|
|
-#include <base/file.h>
|
|
|
-#include <base/util.h>
|
|
|
-#include <netsite.h>
|
|
|
-#include <libaccess/nsadb.h>
|
|
|
-#include <libaccess/aclerror.h>
|
|
|
-#include <libaccess/aclparse.h>
|
|
|
-#include <libaccess/symbols.h>
|
|
|
-
|
|
|
-#ifdef XP_UNIX
|
|
|
-#include <sys/types.h>
|
|
|
-#include <netinet/in.h> /* ntohl */
|
|
|
-#include <arpa/inet.h>
|
|
|
-#endif
|
|
|
-
|
|
|
-void * aclChTab = 0; /* character class table handle */
|
|
|
-
|
|
|
-static char * classv[] = {
|
|
|
- " \t\r\f\013", /* class 0 - whitespace */
|
|
|
- "\n", /* class 1 - newline */
|
|
|
- ",.;@*()+{}\"\'", /* class 2 - special characters */
|
|
|
- "0123456789", /* class 3 - digits */
|
|
|
- /* class 4 - letters */
|
|
|
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
|
|
|
- "-", /* class 5 - hyphen */
|
|
|
- "_", /* class 6 - underscore */
|
|
|
- "/-_.:" /* class 7 - filename special characters */
|
|
|
-};
|
|
|
-
|
|
|
-static int classc = sizeof(classv)/sizeof(char *);
|
|
|
-
|
|
|
-/*
|
|
|
- * Description (aclAuthListParse)
|
|
|
- *
|
|
|
- * This function parses an auth-list. An auth-list specifies
|
|
|
- * combinations of user/group names and host addresses/names.
|
|
|
- * An auth-list entry can identify a collection of users and/or
|
|
|
- * groups, a collection of hosts by IP addresses or DNS names,
|
|
|
- * or a combination of the two. Each auth-spec adds another
|
|
|
- * ACClients_t structure to the specified list.
|
|
|
- *
|
|
|
- * The syntax for an auth-list is:
|
|
|
- *
|
|
|
- * auth-list ::= auth-spec | auth-list "," auth-spec
|
|
|
- * auth-spec ::= auth-users [at-token auth-hosts]
|
|
|
- * auth-users - see aclAuthUsersParse()
|
|
|
- * auth-hosts - see aclAuthHostsParse()
|
|
|
- * at-token ::= "at" | "@"
|
|
|
- *
|
|
|
- * The caller provides a pointer to a ClientSpec_t structure,
|
|
|
- * which is built up with new information as auth-specs are parsed.
|
|
|
- *
|
|
|
- * Arguments:
|
|
|
- *
|
|
|
- * errp - error frame list pointer (may be null)
|
|
|
- * acf - pointer to ACLFile_t for ACL file
|
|
|
- * acc - pointer to ACL context object
|
|
|
- * rlm - pointer to authentication realm object
|
|
|
- * clsp - pointer to returned ACClients_t list head
|
|
|
- *
|
|
|
- * Returns:
|
|
|
- *
|
|
|
- * If successful, the return value is the token type of the token
|
|
|
- * following the auth-list, i.e. the first token which is not
|
|
|
- * recognized as the start of an auth-spec. It is the caller's
|
|
|
- * responsibility to validate this token as a legitimate terminator
|
|
|
- * of an auth-list. If a parsing error occurs in the middle of
|
|
|
- * an auth-spec, the return value is ACLERRPARSE, and an error frame
|
|
|
- * is generated if an error list is provided. For other kinds of
|
|
|
- * errors a negative error code (from aclerror.h) is returned.
|
|
|
- */
|
|
|
-
|
|
|
-int aclAuthListParse(NSErr_t * errp, ACLFile_t * acf,
|
|
|
- ACContext_t * acc, Realm_t * rlm, ACClients_t **clsp)
|
|
|
-{
|
|
|
- void * token = acf->acf_token; /* token handle */
|
|
|
- ACClients_t * csp; /* client spec pointer */
|
|
|
- UserSpec_t * usp; /* user spec pointer */
|
|
|
- HostSpec_t * hsp; /* host spec pointer */
|
|
|
- int rv; /* result value */
|
|
|
- int eid; /* error id */
|
|
|
-
|
|
|
- /* Loop once for each auth-spec */
|
|
|
- for (rv = acf->acf_ttype; ; rv = aclGetToken(errp, acf, 0)) {
|
|
|
-
|
|
|
- usp = 0;
|
|
|
- hsp = 0;
|
|
|
-
|
|
|
- /* Parse auth-users into user and group lists in the ACClients_t */
|
|
|
- rv = aclAuthUsersParse(errp, acf, rlm, &usp, 0);
|
|
|
- if (rv < 0) break;
|
|
|
-
|
|
|
- /* Is the at-token there? */
|
|
|
- if ((rv == TOKEN_AT) || !strcasecmp(lex_token(token), KEYWORD_AT)) {
|
|
|
-
|
|
|
- /* Step to the next token after the at-token */
|
|
|
- rv = aclGetToken(errp, acf, 0);
|
|
|
- if (rv < 0) break;
|
|
|
-
|
|
|
- /* Parse auth-hosts part, adding information to the HostSpec_t */
|
|
|
- rv = aclAuthHostsParse(errp, acf, acc, &hsp);
|
|
|
- if (rv < 0) break;
|
|
|
- }
|
|
|
-
|
|
|
- /* Create a new ACClients_t structure for the parsed information */
|
|
|
- csp = (ACClients_t *)MALLOC(sizeof(ACClients_t));
|
|
|
- if (csp == 0) goto err_nomem;
|
|
|
-
|
|
|
- csp->cl_next = 0;
|
|
|
- csp->cl_user = usp;
|
|
|
- csp->cl_host = hsp;
|
|
|
-
|
|
|
- /* Add it to the end of the list referenced by clsp */
|
|
|
- while (*clsp != 0) clsp = &(*clsp)->cl_next;
|
|
|
- *clsp = csp;
|
|
|
-
|
|
|
- /* Need a "," to keep going */
|
|
|
- if (rv != TOKEN_COMMA) break;
|
|
|
- }
|
|
|
-
|
|
|
- return rv;
|
|
|
-
|
|
|
- err_nomem:
|
|
|
- eid = ACLERR1000;
|
|
|
- nserrGenerate(errp, ACLERRNOMEM, eid, ACL_Program, 0);
|
|
|
- return ACLERRNOMEM;
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * Description (aclAuthHostsParse)
|
|
|
- *
|
|
|
- * This function parses a list of IP address and/or DNS name
|
|
|
- * specifications, adding information to the IP and DNS filters
|
|
|
- * associated with a specified HostSpec_t. The syntax of the
|
|
|
- * auth-hosts construct is:
|
|
|
- *
|
|
|
- * auth-hosts ::= auth-host-elem | "(" auth-host-list ")"
|
|
|
- * | "hosts" host-list-name
|
|
|
- * auth-host-elem ::= auth-ip-spec | auth-dns-spec
|
|
|
- * auth-ip-spec ::= ipaddr | ipaddr netmask
|
|
|
- * auth-dns-spec ::= fqdn | dns-suffix
|
|
|
- * auth-host-list ::= auth-host-elem | auth-host-list "," auth-host-elem
|
|
|
- *
|
|
|
- * Arguments:
|
|
|
- *
|
|
|
- * errp - error frame list pointer (may be null)
|
|
|
- * acf - pointer to ACLFile_t for ACL file
|
|
|
- * acc - pointer to ACL context object
|
|
|
- * hspp - pointer to HostSpec_t pointer
|
|
|
- *
|
|
|
- * Returns:
|
|
|
- *
|
|
|
- * If successful, the return value is the token type of the token
|
|
|
- * following the auth-hosts, i.e. either the first token after a
|
|
|
- * single auth-host-elem or the first token after the closing ")"
|
|
|
- * of a list of auth-host-elems. It is the caller's responsibility
|
|
|
- * to validate this token as a legitimate successor of auth-hosts.
|
|
|
- * If a parsing error occurs in the middle of auth-hosts, the return
|
|
|
- * value is ACLERRPARSE, and an error frame is generated if an error
|
|
|
- * list is provided. For other kinds of errors a negative error
|
|
|
- * code (from aclerror.h) is returned.
|
|
|
- */
|
|
|
-
|
|
|
-int aclAuthHostsParse(NSErr_t * errp,
|
|
|
- ACLFile_t * acf, ACContext_t * acc, HostSpec_t **hspp)
|
|
|
-{
|
|
|
- void * token = acf->acf_token; /* token handle */
|
|
|
- char * tokenstr; /* token string pointer */
|
|
|
- int islist = 0; /* true if auth-host-list */
|
|
|
- int fqdn; /* fully qualified domain name */
|
|
|
- IPAddr_t ipaddr; /* IP address value */
|
|
|
- IPAddr_t netmask; /* IP netmask value */
|
|
|
- int arv; /* alternate result value */
|
|
|
- int rv; /* result value */
|
|
|
- int eid; /* error id */
|
|
|
- char linestr[16]; /* line number string buffer */
|
|
|
-
|
|
|
- rv = acf->acf_ttype;
|
|
|
-
|
|
|
- /* Are we starting an auth-host-list? */
|
|
|
- if (rv == TOKEN_LPAREN) {
|
|
|
-
|
|
|
- /* Yes, it appears so */
|
|
|
- islist = 1;
|
|
|
-
|
|
|
- /* Step token to first auth-host-elem */
|
|
|
- rv = aclGetToken(errp, acf, 0);
|
|
|
- if (rv < 0) goto punt;
|
|
|
- }
|
|
|
- else if (rv == TOKEN_IDENT) {
|
|
|
-
|
|
|
- /* Could this be "hosts host-list-name"? */
|
|
|
- tokenstr = lex_token(token);
|
|
|
-
|
|
|
- if (!strcasecmp(tokenstr, KEYWORD_HOSTS)) {
|
|
|
-
|
|
|
- /* We don't support lists of host lists yet */
|
|
|
- if (*hspp != 0) goto err_unshl;
|
|
|
-
|
|
|
- /* Get host-list-name */
|
|
|
- rv = aclGetToken(errp, acf, 0);
|
|
|
- if (rv < 0) goto punt;
|
|
|
-
|
|
|
- if (rv != TOKEN_IDENT) goto err_hlname;
|
|
|
-
|
|
|
- tokenstr = lex_token(token);
|
|
|
-
|
|
|
- /* Look up the host-list-name in the ACL symbol table */
|
|
|
- rv = symTableFindSym(acc->acc_stp,
|
|
|
- tokenstr, ACLSYMHOST, (void **)hspp);
|
|
|
- if (rv < 0) goto err_undefhl;
|
|
|
-
|
|
|
- /* Step to token after the host-list-name */
|
|
|
- rv = aclGetToken(errp, acf, 0);
|
|
|
-
|
|
|
- return rv;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /* Loop for each auth-host-elem */
|
|
|
- for (rv = acf->acf_ttype; ; rv = aclGetToken(errp, acf, 0)) {
|
|
|
-
|
|
|
- /* Does this look like an auth-ip-spec? */
|
|
|
- if (rv == TOKEN_NUMBER) {
|
|
|
-
|
|
|
- /* Yes, go parse it */
|
|
|
- rv = aclGetIPAddr(errp, acf, &ipaddr, &netmask);
|
|
|
- if (rv < 0) goto punt;
|
|
|
-
|
|
|
- arv = aclAuthIPAdd(hspp, ipaddr, netmask);
|
|
|
- if (arv < 0) goto err_ipadd;
|
|
|
- }
|
|
|
- else if ((rv == TOKEN_STAR) || (rv == TOKEN_IDENT)) {
|
|
|
-
|
|
|
- /* Get fully qualified DNS name indicator value */
|
|
|
- fqdn = (rv == TOKEN_IDENT) ? 1 : 0;
|
|
|
-
|
|
|
- /* This looks like the start of an auth-dns-spec */
|
|
|
- rv = aclGetDNSString(errp, acf);
|
|
|
- if (rv < 0) goto punt;
|
|
|
-
|
|
|
- tokenstr = lex_token(token);
|
|
|
-
|
|
|
- /* If the DNS spec begins with "*.", strip the "*" */
|
|
|
- if (tokenstr && (tokenstr[0] == '*') && (tokenstr[1] == '.')) {
|
|
|
- tokenstr += 1;
|
|
|
- }
|
|
|
-
|
|
|
- arv = aclAuthDNSAdd(hspp, tokenstr, fqdn);
|
|
|
- if (arv < 0) goto err_dnsadd;
|
|
|
-
|
|
|
- /* Pick up the next token */
|
|
|
- rv = aclGetToken(errp, acf, 0);
|
|
|
- }
|
|
|
- else break;
|
|
|
-
|
|
|
- /* If this is a list, we need a "," to keep going */
|
|
|
- if (!islist || (rv != TOKEN_COMMA)) break;
|
|
|
- }
|
|
|
-
|
|
|
- /* Were we parsing an auth-host-list? */
|
|
|
- if (islist) {
|
|
|
-
|
|
|
- /* Yes, check for closing ")" */
|
|
|
- if (acf->acf_ttype != TOKEN_RPAREN) goto err_norp;
|
|
|
-
|
|
|
- /* Got it. Step to next token for caller. */
|
|
|
- rv = aclGetToken(errp, acf, 0);
|
|
|
- }
|
|
|
-
|
|
|
- punt:
|
|
|
- return rv;
|
|
|
-
|
|
|
- err_unshl:
|
|
|
- eid = ACLERR1100;
|
|
|
- goto err_parse;
|
|
|
-
|
|
|
- err_hlname:
|
|
|
- eid = ACLERR1120;
|
|
|
- goto err_parse;
|
|
|
-
|
|
|
- err_undefhl:
|
|
|
- eid = ACLERR1140;
|
|
|
- rv = ACLERRUNDEF;
|
|
|
- sprintf(linestr, "%d", acf->acf_lineno);
|
|
|
- nserrGenerate(errp, rv, eid, ACL_Program,
|
|
|
- 3, acf->acf_filename, linestr, tokenstr);
|
|
|
- goto punt;
|
|
|
-
|
|
|
- err_ipadd:
|
|
|
- eid = ACLERR1180;
|
|
|
- rv = arv;
|
|
|
- goto err_ret;
|
|
|
-
|
|
|
- err_dnsadd:
|
|
|
- eid = ACLERR1200;
|
|
|
- rv = arv;
|
|
|
- goto err_ret;
|
|
|
-
|
|
|
- err_ret:
|
|
|
- nserrGenerate(errp, rv, eid, ACL_Program, 0);
|
|
|
- goto punt;
|
|
|
-
|
|
|
- err_norp:
|
|
|
- eid = ACLERR1220;
|
|
|
- err_parse:
|
|
|
- rv = ACLERRPARSE;
|
|
|
- sprintf(linestr, "%d", acf->acf_lineno);
|
|
|
- nserrGenerate(errp, rv, eid, ACL_Program, 2, acf->acf_filename, linestr);
|
|
|
- goto punt;
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * Description (aclAuthUsersParse)
|
|
|
- *
|
|
|
- * This function parses a list of users and groups subject to
|
|
|
- * authorization, adding the information to a specified UserSpec_t.
|
|
|
- * The syntax it parses is:
|
|
|
- *
|
|
|
- * auth-users ::= auth-user-elem | "(" auth-user-list ")"
|
|
|
- * auth-user-elem ::= username | groupname
|
|
|
- * | "all" | "anyone"
|
|
|
- * auth-user-list ::= auth-user-elem | auth-user-list "," auth-user-elem
|
|
|
- *
|
|
|
- * If the 'elist' argument is non-null, an auth-user-list will be
|
|
|
- * accepted without the enclosing parentheses. Any invalid user
|
|
|
- * or group names will not cause a fatal error, but will be returned
|
|
|
- * in an array of strings via 'elist'.
|
|
|
- *
|
|
|
- * Arguments:
|
|
|
- *
|
|
|
- * errp - error frame list pointer (may be null)
|
|
|
- * acf - pointer to ACLFile_t for ACL file
|
|
|
- * rlm - pointer to authentication realm object
|
|
|
- * uspp - pointer to UserSpec_t pointer
|
|
|
- * elist - pointer to returned pointer to array
|
|
|
- * of strings containing invalid user or
|
|
|
- * group names (may be null)
|
|
|
- *
|
|
|
- * Returns:
|
|
|
- *
|
|
|
- * If successful, the return value is the token type of the token
|
|
|
- * following the auth-users, i.e. either the first token after a
|
|
|
- * single auth-user-elem or the first token after the closing ")"
|
|
|
- * of a list of auth-user-elems. It is the caller's responsibility
|
|
|
- * to validate this token as a legitimate successor of auth-users.
|
|
|
- * If a parsing error occurs in the middle of auth-users, the return
|
|
|
- * value is ACLERRPARSE, and an error frame is generated if an error
|
|
|
- * list is provided. For other kinds of errors a negative error
|
|
|
- * code (from aclerror.h) is returned.
|
|
|
- */
|
|
|
-
|
|
|
-int aclAuthUsersParse(NSErr_t * errp, ACLFile_t * acf,
|
|
|
- Realm_t * rlm, UserSpec_t **uspp, char ***elist)
|
|
|
-{
|
|
|
- void * token = acf->acf_token; /* token handle */
|
|
|
- char * tokenstr; /* token string pointer */
|
|
|
- UserSpec_t * usp; /* user list head structure */
|
|
|
- int islist = 0; /* true if auth-user-list */
|
|
|
- int inlist = 0; /* true if UserSpec_t was supplied */
|
|
|
- int any = 0; /* true if KEYWORD_ANY seen */
|
|
|
- int all = 0; /* true if KEYWORD_ALL seen */
|
|
|
- int elemcnt = 0; /* count of auth-user-elem seen */
|
|
|
- int elen = 0; /* length of evec in (char *) */
|
|
|
- int ecnt = 0; /* entries used in evec */
|
|
|
- char **evec = 0; /* list of bad user/group names */
|
|
|
- int rv; /* result value */
|
|
|
- int eid; /* error id */
|
|
|
- char linestr[16]; /* line number string buffer */
|
|
|
- int errc = 2;
|
|
|
-
|
|
|
- usp = *uspp;
|
|
|
- if ((usp != 0) && (usp->us_flags & ACL_USALL)) all = 1;
|
|
|
-
|
|
|
- if (elist != 0) inlist = 1;
|
|
|
- else {
|
|
|
-
|
|
|
- /* Check for opening "(" */
|
|
|
- if (acf->acf_ttype == TOKEN_LPAREN) {
|
|
|
-
|
|
|
- /* Looks like an auth-user-list */
|
|
|
- islist = 1;
|
|
|
-
|
|
|
- /* Step token to first auth-user-elem */
|
|
|
- rv = aclGetToken(errp, acf, 0);
|
|
|
- if (rv < 0) goto punt;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /* Loop for each auth-user-elem */
|
|
|
- for (rv = acf->acf_ttype; ; rv = aclGetToken(errp, acf, 0)) {
|
|
|
-
|
|
|
- /* Looking for a user or group identifier */
|
|
|
- if ((rv == TOKEN_IDENT) || (rv == TOKEN_STRING)) {
|
|
|
-
|
|
|
- /*
|
|
|
- * If KEYWORD_ALL or KEYWORD_ANY has already appeared
|
|
|
- * in this auth-spec, then return an error.
|
|
|
- */
|
|
|
- if (all | any) goto err_allany;
|
|
|
-
|
|
|
- /* Check for reserved words */
|
|
|
- tokenstr = lex_token(token);
|
|
|
-
|
|
|
- /* KEYWORD_AT begins auth-hosts, but is invalid here */
|
|
|
- if (!strcasecmp(tokenstr, KEYWORD_AT)) break;
|
|
|
-
|
|
|
- /* Check for special group names */
|
|
|
- if (!strcasecmp(tokenstr, KEYWORD_ANY)) {
|
|
|
-
|
|
|
- /*
|
|
|
- * Any user, with no authentication needed. This can
|
|
|
- * only appear once in an auth-spec, and cannot be used
|
|
|
- * in combination with KEYWORD_ALL (or any other user or
|
|
|
- * group identifiers, but that will get checked before
|
|
|
- * we return).
|
|
|
- */
|
|
|
-
|
|
|
- if ((elemcnt > 0) || (usp != 0)) goto err_any;
|
|
|
- any = 1;
|
|
|
- }
|
|
|
- else if (!strcasecmp(tokenstr, KEYWORD_ALL)) {
|
|
|
-
|
|
|
- /*
|
|
|
- * Any authenticated user. This can only appear once in
|
|
|
- * an auth-spec, and cannot be used in combination with
|
|
|
- * KEYWORD_ANY (or any other user or group identifiers,
|
|
|
- * but that will get checked before we return).
|
|
|
- */
|
|
|
-
|
|
|
- if (elemcnt > 0) goto err_all;
|
|
|
-
|
|
|
- /* Create a UserSpec_t structure if we haven't got one yet */
|
|
|
- if (usp == 0) {
|
|
|
- usp = aclUserSpecCreate();
|
|
|
- if (usp == 0) goto err_nomem1;
|
|
|
- *uspp = usp;
|
|
|
- }
|
|
|
-
|
|
|
- usp->us_flags |= ACL_USALL;
|
|
|
- all = 1;
|
|
|
- }
|
|
|
- else {
|
|
|
-
|
|
|
- /* Create a UserSpec_t structure if we haven't got one yet */
|
|
|
- if (usp == 0) {
|
|
|
- usp = aclUserSpecCreate();
|
|
|
- if (usp == 0) goto err_nomem2;
|
|
|
- *uspp = usp;
|
|
|
- }
|
|
|
-
|
|
|
- /* This should be a user or group name */
|
|
|
- rv = aclAuthNameAdd(errp, usp, rlm, tokenstr);
|
|
|
- if (rv <= 0) {
|
|
|
-
|
|
|
- /* The name was not found in the authentication DB */
|
|
|
- if (elist != 0) {
|
|
|
- if (evec == 0) {
|
|
|
- evec = (char **)MALLOC(4*sizeof(char *));
|
|
|
- evec[0] = 0;
|
|
|
- ecnt = 1;
|
|
|
- elen = 4;
|
|
|
- }
|
|
|
- else if (ecnt >= elen) {
|
|
|
- elen += 4;
|
|
|
- evec = (char **)REALLOC(evec, elen*sizeof(char *));
|
|
|
- }
|
|
|
- evec[ecnt-1] = STRDUP(tokenstr);
|
|
|
- evec[ecnt] = 0;
|
|
|
- ++ecnt;
|
|
|
-
|
|
|
- }
|
|
|
- else if (rv < 0) goto err_badgun;
|
|
|
- }
|
|
|
-
|
|
|
- /* Don't allow duplicate names */
|
|
|
- if (rv & ANA_DUP) {
|
|
|
- if (elist == 0) goto err_dupgun;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /* Count number of auth-user-elems seen */
|
|
|
- elemcnt += 1;
|
|
|
-
|
|
|
- /* Get the token after the auth-user-elem */
|
|
|
- rv = aclGetToken(errp, acf, 0);
|
|
|
- if (rv < 0) goto punt;
|
|
|
- }
|
|
|
-
|
|
|
- /* If this is a list, we need a "," to keep going */
|
|
|
- if (!(islist | inlist) || (rv != TOKEN_COMMA)) break;
|
|
|
- }
|
|
|
-
|
|
|
- /* Were we parsing an auth-user-list? */
|
|
|
- if (islist) {
|
|
|
-
|
|
|
- /* Yes, check for closing ")" */
|
|
|
- if (acf->acf_ttype != TOKEN_RPAREN) goto err_norp;
|
|
|
-
|
|
|
- /* Got it. Step to next token for caller. */
|
|
|
- rv = aclGetToken(errp, acf, 0);
|
|
|
- if (rv < 0) goto punt;
|
|
|
- }
|
|
|
-
|
|
|
- /*
|
|
|
- * If we didn't see any auth-user-elems, then the auth-user we were
|
|
|
- * called to parse is missing. We will forgive and forget if the
|
|
|
- * current token is a comma, however, so as to allow empty auth-specs.
|
|
|
- */
|
|
|
- if ((elemcnt <= 0) && (rv != TOKEN_COMMA)) {
|
|
|
- goto err_noelem;
|
|
|
- }
|
|
|
-
|
|
|
- punt:
|
|
|
- /* Return list of bad names if indicated */
|
|
|
- if (elist != 0) *elist = evec;
|
|
|
-
|
|
|
- return rv;
|
|
|
-
|
|
|
- err_badgun:
|
|
|
- /* Encountered an unknown user or group name */
|
|
|
- eid = ACLERR1360;
|
|
|
- rv = ACLERRUNDEF;
|
|
|
- goto err_retgun;
|
|
|
-
|
|
|
- err_dupgun:
|
|
|
- /* A user or group name was specified multiple times */
|
|
|
- eid = ACLERR1380;
|
|
|
- rv = ACLERRDUPSYM;
|
|
|
- goto err_retgun;
|
|
|
-
|
|
|
- err_retgun:
|
|
|
- sprintf(linestr, "%d", acf->acf_lineno);
|
|
|
- nserrGenerate(errp, rv, eid, ACL_Program,
|
|
|
- 3, acf->acf_filename, linestr, tokenstr);
|
|
|
- goto punt;
|
|
|
-
|
|
|
- err_norp:
|
|
|
- /* Missing ")" */
|
|
|
- eid = ACLERR1400;
|
|
|
- goto err_parse;
|
|
|
-
|
|
|
- err_noelem:
|
|
|
- eid = ACLERR1420;
|
|
|
- goto err_parse;
|
|
|
-
|
|
|
- err_all:
|
|
|
- eid = ACLERR1440;
|
|
|
- goto err_parse;
|
|
|
-
|
|
|
- err_any:
|
|
|
- eid = ACLERR1460;
|
|
|
- goto err_parse;
|
|
|
-
|
|
|
- err_allany:
|
|
|
- eid = ACLERR1480;
|
|
|
- goto err_parse;
|
|
|
-
|
|
|
- err_nomem1:
|
|
|
- eid = ACLERR1500;
|
|
|
- rv = ACLERRNOMEM;
|
|
|
- errc = 0;
|
|
|
- goto err_ret;
|
|
|
-
|
|
|
- err_nomem2:
|
|
|
- eid = ACLERR1520;
|
|
|
- rv = ACLERRNOMEM;
|
|
|
- errc = 0;
|
|
|
- goto err_ret;
|
|
|
-
|
|
|
- err_parse:
|
|
|
- rv = ACLERRPARSE;
|
|
|
- err_ret:
|
|
|
- sprintf(linestr, "%d", acf->acf_lineno);
|
|
|
- nserrGenerate(errp, rv, eid, ACL_Program, errc, acf->acf_filename, linestr);
|
|
|
- goto punt;
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * Description (aclDirectivesParse)
|
|
|
- *
|
|
|
- * This function parses the directives inside an ACL definition.
|
|
|
- * The syntax for a directive list is:
|
|
|
- *
|
|
|
- * dir-list ::= directive | dir-list ";" directive
|
|
|
- * directive ::= auth-directive | access-directive | exec-directive
|
|
|
- * auth-directive ::= dir-force "authenticate" ["in" realm-spec]
|
|
|
- * access-directive ::= dir-force dir-access auth-list
|
|
|
- * exec-directive ::= dir-force "execute" ["if" exec-optlist]
|
|
|
- * exec-optlist ::= exec-condition | exec-optlist "," exec-condition
|
|
|
- * exec-condition ::= dir-access | "authenticate"
|
|
|
- * dir-force ::= "Always" | "Default"
|
|
|
- * dir-access ::= "allow" | "deny"
|
|
|
- *
|
|
|
- * See aclAuthListParse() for auth-list syntax.
|
|
|
- * See aclRealmSpecParse() for realm-spec syntax.
|
|
|
- *
|
|
|
- * The caller provides a pointer to an ACL structure, which is
|
|
|
- * built up with new information as directives are parsed.
|
|
|
- *
|
|
|
- * Arguments:
|
|
|
- *
|
|
|
- * errp - error frame list pointer (may be null)
|
|
|
- * acf - pointer to ACLFile_t for ACL file
|
|
|
- * acl - pointer to ACL structure
|
|
|
- *
|
|
|
- * Returns:
|
|
|
- *
|
|
|
- * If successful, the return value is the token type of the token
|
|
|
- * following the directive list, i.e. the first token which is not
|
|
|
- * recognized as the start of a directive. It is the caller's
|
|
|
- * responsibility to validate this token as a legitimate terminator
|
|
|
- * of a directive list. If a parsing error occurs in the middle of
|
|
|
- * a directive, the return value is ACLERRPARSE, and an error frame
|
|
|
- * is generated if an error list is provided. For other kinds of
|
|
|
- * errors a negative error code (from aclerror.h) is returned.
|
|
|
- */
|
|
|
-
|
|
|
-int aclDirectivesParse(NSErr_t * errp, ACLFile_t * acf, ACL_t * acl)
|
|
|
-{
|
|
|
- void * token = acf->acf_token; /* token handle */
|
|
|
- char * tokenstr; /* token string */
|
|
|
- Realm_t * rlm = 0; /* current realm pointer */
|
|
|
- ACDirective_t * acd; /* directive pointer */
|
|
|
- int action; /* directive action code */
|
|
|
- int flags; /* directive action flags */
|
|
|
- int arv; /* alternate return value */
|
|
|
- int rv; /* result value */
|
|
|
- int eid; /* error id */
|
|
|
- char linestr[16]; /* line number string buffer */
|
|
|
-
|
|
|
- /* Look for top-level directives */
|
|
|
- for (rv = acf->acf_ttype; ; rv = aclGetToken(errp, acf, 0)) {
|
|
|
-
|
|
|
- action = 0;
|
|
|
- flags = 0;
|
|
|
-
|
|
|
- /* Check for beginning of directive */
|
|
|
- if (rv == TOKEN_IDENT) {
|
|
|
-
|
|
|
- /* Check identifier for directive dir-force keywords */
|
|
|
- tokenstr = lex_token(token);
|
|
|
-
|
|
|
- if (!strcasecmp(tokenstr, KEYWORD_DEFAULT)) {
|
|
|
- flags = ACD_DEFAULT;
|
|
|
- }
|
|
|
- else if (!strcasecmp(tokenstr, "always")) {
|
|
|
- flags = ACD_ALWAYS;
|
|
|
- }
|
|
|
- else break;
|
|
|
-
|
|
|
- /*
|
|
|
- * Now we're looking for dir-access, "authenticate",
|
|
|
- * or "execute".
|
|
|
- */
|
|
|
- rv = aclGetToken(errp, acf, 0);
|
|
|
-
|
|
|
- /* An identifier would be nice ... */
|
|
|
- if (rv != TOKEN_IDENT) goto err_access;
|
|
|
-
|
|
|
- tokenstr = lex_token(token);
|
|
|
-
|
|
|
- if (!strcasecmp(tokenstr, KEYWORD_AUTH)) {
|
|
|
-
|
|
|
- /* process auth-directive */
|
|
|
- action = ACD_AUTH;
|
|
|
-
|
|
|
- /* Create a new directive object */
|
|
|
- acd = aclDirectiveCreate();
|
|
|
- if (acd == 0) goto err_nomem1;
|
|
|
-
|
|
|
- /* Get the next token after KEYWORD_AUTH */
|
|
|
- rv = aclGetToken(errp, acf, 0);
|
|
|
- if (rv < 0) break;
|
|
|
-
|
|
|
- /* Could we have "in" realm-spec here? */
|
|
|
- if (rv == TOKEN_IDENT) {
|
|
|
-
|
|
|
- tokenstr = lex_token(token);
|
|
|
-
|
|
|
- if (!strcasecmp(tokenstr, KEYWORD_IN)) {
|
|
|
-
|
|
|
- /* Get the next token after KEYWORD_IN */
|
|
|
- rv = aclGetToken(errp, acf, 0);
|
|
|
- if (rv < 0) break;
|
|
|
-
|
|
|
- /* Parse the realm-spec */
|
|
|
- rv = aclRealmSpecParse(errp, acf, acl->acl_acc,
|
|
|
- &acd->acd_auth.au_realm);
|
|
|
- if (rv < 0) break;
|
|
|
-
|
|
|
- /* Set current realm */
|
|
|
- if (acd->acd_auth.au_realm != 0) {
|
|
|
-
|
|
|
- /* Close database in current realm if any */
|
|
|
- if (rlm && rlm->rlm_authdb) {
|
|
|
- (*rlm->rlm_aif->aif_close)(rlm->rlm_authdb, 0);
|
|
|
- rlm->rlm_authdb = 0;
|
|
|
- }
|
|
|
-
|
|
|
- rlm = &acd->acd_auth.au_realm->rs_realm;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /* Add this directive to the ACL */
|
|
|
- acd->acd_action = action;
|
|
|
- acd->acd_flags = flags;
|
|
|
-
|
|
|
- arv = aclDirectiveAdd(acl, acd);
|
|
|
- if (arv < 0) goto err_diradd1;
|
|
|
- }
|
|
|
- else if (!strcasecmp(tokenstr, KEYWORD_EXECUTE)) {
|
|
|
-
|
|
|
- /* process exec-directive */
|
|
|
- action = ACD_EXEC;
|
|
|
-
|
|
|
- /* Create a new directive object */
|
|
|
- acd = aclDirectiveCreate();
|
|
|
- if (acd == 0) goto err_nomem3;
|
|
|
-
|
|
|
- /* Get the next token after KEYWORD_EXECUTE */
|
|
|
- rv = aclGetToken(errp, acf, 0);
|
|
|
- if (rv < 0) break;
|
|
|
-
|
|
|
- /* Could we have "if" exec-optlist here? */
|
|
|
- if (rv == TOKEN_IDENT) {
|
|
|
-
|
|
|
- tokenstr = lex_token(token);
|
|
|
-
|
|
|
- if (!strcasecmp(tokenstr, KEYWORD_IF)) {
|
|
|
-
|
|
|
- for (;;) {
|
|
|
-
|
|
|
- /* Get the next token after KEYWORD_IF or "," */
|
|
|
- rv = aclGetToken(errp, acf, 0);
|
|
|
- if (rv < 0) break;
|
|
|
-
|
|
|
- /*
|
|
|
- * Looking for "allow", "deny", or "authenticate"
|
|
|
- */
|
|
|
- if (rv == TOKEN_IDENT) {
|
|
|
-
|
|
|
- tokenstr = lex_token(token);
|
|
|
-
|
|
|
- if (!strcasecmp(tokenstr, KEYWORD_ALLOW)) {
|
|
|
- flags |= ACD_EXALLOW;
|
|
|
- }
|
|
|
- else if (!strcasecmp(tokenstr, KEYWORD_DENY)) {
|
|
|
- flags |= ACD_EXDENY;
|
|
|
- }
|
|
|
- else if (!strcasecmp(tokenstr, KEYWORD_AUTH)) {
|
|
|
- flags |= ACD_EXAUTH;
|
|
|
- }
|
|
|
- else goto err_exarg;
|
|
|
- }
|
|
|
-
|
|
|
- /* End of directive if no comma */
|
|
|
- rv = aclGetToken(errp, acf, 0);
|
|
|
- if (rv < 0) break;
|
|
|
-
|
|
|
- if (rv != TOKEN_COMMA) break;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- else flags = (ACD_EXALLOW|ACD_EXDENY|ACD_EXAUTH);
|
|
|
-
|
|
|
- if (rv < 0) break;
|
|
|
-
|
|
|
- /* Add this directive to the ACL */
|
|
|
- acd->acd_action = action;
|
|
|
- acd->acd_flags = flags;
|
|
|
-
|
|
|
- arv = aclDirectiveAdd(acl, acd);
|
|
|
- if (arv < 0) goto err_diradd3;
|
|
|
- }
|
|
|
- else {
|
|
|
-
|
|
|
- /* process access-directive */
|
|
|
-
|
|
|
- if (!strcasecmp(tokenstr, KEYWORD_ALLOW)) {
|
|
|
- action = ACD_ALLOW;
|
|
|
- }
|
|
|
- else if (!strcasecmp(tokenstr, KEYWORD_DENY)) {
|
|
|
- action = ACD_DENY;
|
|
|
- }
|
|
|
- else goto err_acctype;
|
|
|
-
|
|
|
- /* Get the next token after dir-access */
|
|
|
- rv = aclGetToken(errp, acf, 0);
|
|
|
-
|
|
|
- /* Create a new directive object */
|
|
|
- acd = aclDirectiveCreate();
|
|
|
- if (acd == 0) goto err_nomem2;
|
|
|
-
|
|
|
- /* Parse a list of auth-specs */
|
|
|
- rv = aclAuthListParse(errp, acf, acl->acl_acc, rlm,
|
|
|
- &acd->acd_cl);
|
|
|
- if (rv < 0) break;
|
|
|
-
|
|
|
- /* Add this directive to the ACL */
|
|
|
- acd->acd_action = action;
|
|
|
- acd->acd_flags = flags;
|
|
|
-
|
|
|
- arv = aclDirectiveAdd(acl, acd);
|
|
|
- if (arv < 0) goto err_diradd2;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /* Need a ";" to keep going */
|
|
|
- if (rv != TOKEN_EOS) break;
|
|
|
- }
|
|
|
-
|
|
|
- punt:
|
|
|
- /* Close database in current realm if any */
|
|
|
- if (rlm && rlm->rlm_authdb) {
|
|
|
- (*rlm->rlm_aif->aif_close)(rlm->rlm_authdb, 0);
|
|
|
- rlm->rlm_authdb = 0;
|
|
|
- }
|
|
|
-
|
|
|
- return rv;
|
|
|
-
|
|
|
- err_access:
|
|
|
- /* dir-access not present */
|
|
|
- eid = ACLERR1600;
|
|
|
- rv = ACLERRPARSE;
|
|
|
- goto err_ret;
|
|
|
-
|
|
|
- err_acctype:
|
|
|
- /* dir-access identifier is invalid */
|
|
|
- eid = ACLERR1620;
|
|
|
- rv = ACLERRPARSE;
|
|
|
- goto err_ret;
|
|
|
-
|
|
|
- err_diradd1:
|
|
|
- eid = ACLERR1640;
|
|
|
- rv = arv;
|
|
|
- tokenstr = 0;
|
|
|
- goto err_ret;
|
|
|
-
|
|
|
- err_diradd2:
|
|
|
- eid = ACLERR1650;
|
|
|
- rv = arv;
|
|
|
- tokenstr = 0;
|
|
|
- goto err_ret;
|
|
|
-
|
|
|
- err_nomem1:
|
|
|
- eid = ACLERR1660;
|
|
|
- rv = ACLERRNOMEM;
|
|
|
- tokenstr = 0;
|
|
|
- goto err_ret;
|
|
|
-
|
|
|
- err_nomem2:
|
|
|
- eid = ACLERR1680;
|
|
|
- rv = ACLERRNOMEM;
|
|
|
- tokenstr = 0;
|
|
|
- goto err_ret;
|
|
|
-
|
|
|
- err_nomem3:
|
|
|
- eid = ACLERR1685;
|
|
|
- rv = ACLERRNOMEM;
|
|
|
- tokenstr = 0;
|
|
|
- goto err_ret;
|
|
|
-
|
|
|
- err_diradd3:
|
|
|
- eid = ACLERR1690;
|
|
|
- rv = arv;
|
|
|
- tokenstr = 0;
|
|
|
- goto err_ret;
|
|
|
-
|
|
|
- err_exarg:
|
|
|
- eid = ACLERR1695;
|
|
|
- rv = ACLERRSYNTAX;
|
|
|
- goto err_ret;
|
|
|
-
|
|
|
- err_ret:
|
|
|
- sprintf(linestr, "%d", acf->acf_lineno);
|
|
|
- if (tokenstr) {
|
|
|
- nserrGenerate(errp, rv, eid, ACL_Program,
|
|
|
- 3, acf->acf_filename, linestr, tokenstr);
|
|
|
- }
|
|
|
- else {
|
|
|
- nserrGenerate(errp, rv, eid, ACL_Program,
|
|
|
- 2, acf->acf_filename, linestr);
|
|
|
- }
|
|
|
- goto punt;
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * Description (aclACLParse)
|
|
|
- *
|
|
|
- * This function parses a data stream containing ACL definitions,
|
|
|
- * and builds a representation of the ACLs in memory. Each ACL
|
|
|
- * has a user-specified name, and a pointer to the ACL structure
|
|
|
- * is stored under the name in a symbol table provided by the caller.
|
|
|
- *
|
|
|
- * Arguments:
|
|
|
- *
|
|
|
- * errp - error frame list pointer (may be null)
|
|
|
- * acf - pointer to ACLFile_t for ACL file
|
|
|
- * acc - pointer to ACContext_t structure
|
|
|
- * flags - bit flags (unused - must be zero)
|
|
|
- *
|
|
|
- * Returns:
|
|
|
- *
|
|
|
- * The return value is zero if the stream is parsed successfully.
|
|
|
- * Otherwise it is a negative error code (ACLERRxxxx - see aclerror.h),
|
|
|
- * and an error frame will be generated if an error list is provided.
|
|
|
- */
|
|
|
-
|
|
|
-int aclACLParse(NSErr_t * errp, ACLFile_t * acf, ACContext_t * acc, int flags)
|
|
|
-{
|
|
|
- void * token = acf->acf_token; /* handle for current token */
|
|
|
- char * tokenstr; /* current token string */
|
|
|
- char * aclname; /* ACL name string */
|
|
|
- ACL_t * aclp; /* pointer to ACL structure */
|
|
|
- int rv; /* result value */
|
|
|
- int eid; /* error id value */
|
|
|
- char linestr[16]; /* line number string buffer */
|
|
|
-
|
|
|
- /* Look for top-level statements */
|
|
|
- for (;;) {
|
|
|
-
|
|
|
- /* Get a token to begin a statement */
|
|
|
- rv = aclGetToken(errp, acf, 0);
|
|
|
-
|
|
|
- /* An identifier would be nice ... */
|
|
|
- if (rv != TOKEN_IDENT) {
|
|
|
-
|
|
|
- /* Empty statements are ok, if pointless */
|
|
|
- if (rv == TOKEN_EOS) continue;
|
|
|
-
|
|
|
- /* EOF is valid here */
|
|
|
- if (rv == TOKEN_EOF) break;
|
|
|
-
|
|
|
- /* Anything else is unacceptable */
|
|
|
- goto err_nostmt;
|
|
|
- }
|
|
|
-
|
|
|
- /* Check identifier for statement keywords */
|
|
|
- tokenstr = lex_token(token);
|
|
|
-
|
|
|
- if (!strcasecmp(tokenstr, KEYWORD_ACL)) {
|
|
|
-
|
|
|
- /* ACL name rights-list { acl-def-list }; */
|
|
|
-
|
|
|
- /* Get the name of the ACL */
|
|
|
- rv = aclGetToken(errp, acf, 0);
|
|
|
- if (rv != TOKEN_IDENT) goto err_aclname;
|
|
|
- aclname = lex_token(token);
|
|
|
-
|
|
|
- /* Create the ACL structure */
|
|
|
- rv = aclCreate(errp, acc, aclname, &aclp);
|
|
|
- if (rv < 0) goto punt;
|
|
|
-
|
|
|
- /* Get the next token after the ACL name */
|
|
|
- rv = aclGetToken(errp, acf, 0);
|
|
|
-
|
|
|
- /* Parse the rights specification */
|
|
|
- rv = aclRightsParse(errp, acf, acc, &aclp->acl_rights);
|
|
|
-
|
|
|
- /* Want a "{" to open the ACL directive list */
|
|
|
- if (rv != TOKEN_LBRACE) {
|
|
|
- if (rv < 0) goto punt;
|
|
|
- goto err_aclopen;
|
|
|
- }
|
|
|
-
|
|
|
- /* Get the first token in the ACL directive list */
|
|
|
- rv = aclGetToken(errp, acf, 0);
|
|
|
- if (rv < 0) goto punt;
|
|
|
-
|
|
|
- /* Parse the ACL directive list */
|
|
|
- rv = aclDirectivesParse(errp, acf, aclp);
|
|
|
-
|
|
|
- /* Want a "}" to close the ACL directive list */
|
|
|
- if (rv != TOKEN_RBRACE) {
|
|
|
- if (rv < 0) goto punt;
|
|
|
- goto err_aclclose;
|
|
|
- }
|
|
|
- }
|
|
|
- else if (!strcasecmp(tokenstr, KEYWORD_INCLUDE)) {
|
|
|
- /* Include "filename"; */
|
|
|
- }
|
|
|
- else if (!strcasecmp(tokenstr, KEYWORD_REALM)) {
|
|
|
- /* Realm name realm-spec */
|
|
|
- }
|
|
|
- else if (!strcasecmp(tokenstr, KEYWORD_RIGHTS)) {
|
|
|
- /* Rights name rights-def; */
|
|
|
- }
|
|
|
- else if (!strcasecmp(tokenstr, KEYWORD_HOSTS)) {
|
|
|
- /* Hosts name auth-hosts; */
|
|
|
- }
|
|
|
- else goto err_syntax;
|
|
|
- }
|
|
|
-
|
|
|
- return 0;
|
|
|
-
|
|
|
- err_nostmt:
|
|
|
- eid = ACLERR1700;
|
|
|
- rv = ACLERRPARSE;
|
|
|
- goto err_ret;
|
|
|
-
|
|
|
- err_aclname:
|
|
|
- eid = ACLERR1720;
|
|
|
- rv = ACLERRPARSE;
|
|
|
- goto err_ret;
|
|
|
-
|
|
|
- err_aclopen:
|
|
|
- eid = ACLERR1740;
|
|
|
- rv = ACLERRPARSE;
|
|
|
- goto err_ret;
|
|
|
-
|
|
|
- err_aclclose:
|
|
|
- eid = ACLERR1760;
|
|
|
- rv = ACLERRPARSE;
|
|
|
- goto err_ret;
|
|
|
-
|
|
|
- err_ret:
|
|
|
- sprintf(linestr, "%d", acf->acf_lineno);
|
|
|
- nserrGenerate(errp, rv, eid, ACL_Program, 2, acf->acf_filename, linestr);
|
|
|
- goto punt;
|
|
|
-
|
|
|
- err_syntax:
|
|
|
- eid = ACLERR1780;
|
|
|
- rv = ACLERRPARSE;
|
|
|
- sprintf(linestr, "%d", acf->acf_lineno);
|
|
|
- nserrGenerate(errp, rv, eid, ACL_Program,
|
|
|
- 3, acf->acf_filename, linestr, tokenstr);
|
|
|
-
|
|
|
- punt:
|
|
|
- return rv;
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * Description (aclFileClose)
|
|
|
- *
|
|
|
- * This function closes an ACL file previously opened by aclFileOpen(),
|
|
|
- * and frees any associated data structures.
|
|
|
- *
|
|
|
- * Arguments:
|
|
|
- *
|
|
|
- * acf - pointer to ACL file information
|
|
|
- * flags - bit flags (unused - must be zero)
|
|
|
- */
|
|
|
-
|
|
|
-void aclFileClose(ACLFile_t * acf, int flags)
|
|
|
-{
|
|
|
- if (acf != 0) {
|
|
|
-
|
|
|
- /* Destroy the associated lexer stream if any */
|
|
|
- if (acf->acf_lst != 0) {
|
|
|
- lex_stream_destroy(acf->acf_lst);
|
|
|
- }
|
|
|
-
|
|
|
- /* Close the file if it's open */
|
|
|
- if (acf->acf_fd != SYS_ERROR_FD) {
|
|
|
- system_fclose(acf->acf_fd);
|
|
|
- }
|
|
|
-
|
|
|
- /* Destroy any associated token */
|
|
|
- if (acf->acf_token != 0) {
|
|
|
- lex_token_destroy(acf->acf_token);
|
|
|
- }
|
|
|
-
|
|
|
- /* Free the filename string if any */
|
|
|
- if (acf->acf_filename != 0) {
|
|
|
- FREE(acf->acf_filename);
|
|
|
- }
|
|
|
-
|
|
|
- /* Free the ACLFile_t structure */
|
|
|
- FREE(acf);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * Description (aclFileOpen)
|
|
|
- *
|
|
|
- * This function opens a specified filename and creates a structure
|
|
|
- * to contain information about the file during parsing. This
|
|
|
- * includes a handle for a LEX data stream for the file.
|
|
|
- *
|
|
|
- * Arguments:
|
|
|
- *
|
|
|
- * errp - error frame list pointer (may be null)
|
|
|
- * filename - name of file to be opened
|
|
|
- * flags - bit flags (unused - must be zero)
|
|
|
- * pacf - pointer to returned ACLFile_t pointer
|
|
|
- *
|
|
|
- * Returns:
|
|
|
- *
|
|
|
- * The return value is zero if the file is opened successfully, and
|
|
|
- * a pointer to the ACLFile_t is returned in the location specified
|
|
|
- * by 'pacf'. Otherwise a negative error code (ACLERRxxxx - see
|
|
|
- * aclerror.h) is returned, and an error frame will be generated if
|
|
|
- * an error list is provided.
|
|
|
- */
|
|
|
-
|
|
|
-int aclFileOpen(NSErr_t * errp,
|
|
|
- char * filename, int flags, ACLFile_t **pacf)
|
|
|
-{
|
|
|
- ACLFile_t * acf; /* pointer to ACL file structure */
|
|
|
- int rv; /* return value */
|
|
|
- int eid; /* error identifier */
|
|
|
- char * errmsg; /* system error message string */
|
|
|
-
|
|
|
- *pacf = 0;
|
|
|
-
|
|
|
- /* Allocate the ACLFile_t structure */
|
|
|
- acf = (ACLFile_t *)MALLOC(sizeof(ACLFile_t));
|
|
|
- if (acf == 0) goto err_nomem1;
|
|
|
-
|
|
|
- memset((void *)acf, 0, sizeof(ACLFile_t));
|
|
|
- acf->acf_filename = STRDUP(filename);
|
|
|
- acf->acf_lineno = 1;
|
|
|
- acf->acf_flags = flags;
|
|
|
-
|
|
|
- /* Create a LEX token object */
|
|
|
- rv = lex_token_new((pool_handle_t *)0, 32, 8, &acf->acf_token);
|
|
|
- if (rv < 0) goto err_nomem2;
|
|
|
-
|
|
|
- /* Open the file */
|
|
|
- acf->acf_fd = system_fopenRO(acf->acf_filename);
|
|
|
- if (acf->acf_fd == SYS_ERROR_FD) goto err_open;
|
|
|
-
|
|
|
- /* Create a LEX stream for the file */
|
|
|
- acf->acf_lst = lex_stream_create(aclStreamGet,
|
|
|
- (void *)acf->acf_fd, 0, 8192);
|
|
|
- if (acf->acf_lst == 0) goto err_nomem3;
|
|
|
-
|
|
|
- *pacf = acf;
|
|
|
- return 0;
|
|
|
-
|
|
|
- err_open: /* file open error */
|
|
|
- rv = ACLERROPEN;
|
|
|
- eid = ACLERR1900;
|
|
|
- errmsg = system_errmsg();
|
|
|
- nserrGenerate(errp, rv, eid, ACL_Program, 2, filename, errmsg);
|
|
|
- goto punt;
|
|
|
-
|
|
|
- err_nomem1: /* MALLOC of ACLFile_t failed */
|
|
|
- rv = ACLERRNOMEM;
|
|
|
- eid = ACLERR1920;
|
|
|
- goto err_mem;
|
|
|
-
|
|
|
- err_nomem2: /* lex_token_new() failed */
|
|
|
- rv = ACLERRNOMEM;
|
|
|
- eid = ACLERR1940;
|
|
|
- goto err_mem;
|
|
|
-
|
|
|
- err_nomem3: /* lex_stream_create() failed */
|
|
|
- system_fclose(acf->acf_fd);
|
|
|
- rv = ACLERRNOMEM;
|
|
|
- eid = ACLERR1960;
|
|
|
-
|
|
|
- err_mem:
|
|
|
- nserrGenerate(errp, rv, eid, ACL_Program, 0);
|
|
|
- goto punt;
|
|
|
-
|
|
|
- punt:
|
|
|
- return rv;
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * Description (aclGetDNSString)
|
|
|
- *
|
|
|
- * This function parses a DNS name specification, which consists
|
|
|
- * of a sequence of DNS name components separated by ".". Each
|
|
|
- * name component must start with a letter, and contains only
|
|
|
- * letters, digits, and hyphens. An exception is that the first
|
|
|
- * component may be the wildcard indicator, "*". This function
|
|
|
- * assumes that the current token already contains a TOKEN_STAR
|
|
|
- * or TOKEN_IDENT. The complete DNS name specification is
|
|
|
- * returned as the current token string.
|
|
|
- *
|
|
|
- * Arguments:
|
|
|
- *
|
|
|
- * errp - error frame list pointer (may be null)
|
|
|
- * acf - pointer to ACLFile_t for ACL file
|
|
|
- *
|
|
|
- * Returns:
|
|
|
- *
|
|
|
- * The character terminating the DNS name specification is returned
|
|
|
- * as the function value. The current token type is unchanged, but
|
|
|
- * the string associated with the current token contains the
|
|
|
- * complete DNS name specification. An error is indicated by a
|
|
|
- * negative return value, and an error frame is generated if an
|
|
|
- * error list is provided.
|
|
|
- */
|
|
|
-
|
|
|
-int aclGetDNSString(NSErr_t * errp, ACLFile_t * acf)
|
|
|
-{
|
|
|
- LEXStream_t * lst = acf->acf_lst; /* LEX stream handle */
|
|
|
- void * token = acf->acf_token; /* LEX token handle */
|
|
|
- int rv; /* result value */
|
|
|
- int eid; /* error id value */
|
|
|
- char linestr[16]; /* line number string buffer */
|
|
|
-
|
|
|
- /* The current token should be TOKEN_STAR or TOKEN_IDENT */
|
|
|
- rv = acf->acf_ttype;
|
|
|
-
|
|
|
- if ((rv != TOKEN_STAR) && (rv != TOKEN_IDENT)) goto err_dns1;
|
|
|
-
|
|
|
- /* Loop to parse [ "." dns-component ]+ */
|
|
|
- for (;;) {
|
|
|
-
|
|
|
- /* Try to step over a "." */
|
|
|
- rv = lex_next_char(lst, aclChTab, 0);
|
|
|
-
|
|
|
- /* End of DNS string if there's not one there */
|
|
|
- if (rv != '.') break;
|
|
|
-
|
|
|
- /* Append the "." to the token string */
|
|
|
- (void)lex_token_append(token, 1, ".");
|
|
|
-
|
|
|
- /* Advance the input stream past the "." */
|
|
|
- rv = lex_next_char(lst, aclChTab, CCM_SPECIAL);
|
|
|
-
|
|
|
- /* Next we want to see a letter */
|
|
|
- rv = lex_next_char(lst, aclChTab, 0);
|
|
|
-
|
|
|
- /* Error if it's not there */
|
|
|
- if (!lex_class_check(aclChTab, rv, CCM_LETTER)) goto err_dns2;
|
|
|
-
|
|
|
- /* Append a string of letters, digits, hyphens to token */
|
|
|
- rv = lex_scan_over(lst, aclChTab, (CCM_LETTER|CCM_DIGIT|CCM_HYPHEN),
|
|
|
- token);
|
|
|
- if (rv < 0) goto err_dns3;
|
|
|
- }
|
|
|
-
|
|
|
- punt:
|
|
|
- return rv;
|
|
|
-
|
|
|
- err_dns1:
|
|
|
- eid = ACLERR2100;
|
|
|
- rv = ACLERRPARSE;
|
|
|
- goto err_ret;
|
|
|
-
|
|
|
- err_dns2:
|
|
|
- eid = ACLERR2120;
|
|
|
- rv = ACLERRPARSE;
|
|
|
- goto err_ret;
|
|
|
-
|
|
|
- err_dns3:
|
|
|
- eid = ACLERR2140;
|
|
|
- rv = ACLERRPARSE;
|
|
|
- goto err_ret;
|
|
|
-
|
|
|
- err_ret:
|
|
|
- sprintf(linestr, "%d", acf->acf_lineno);
|
|
|
- nserrGenerate(errp, rv, eid, ACL_Program, 2, acf->acf_filename, linestr);
|
|
|
- goto punt;
|
|
|
-}
|
|
|
-
|
|
|
-int aclGetFileSpec(NSErr_t * errp, ACLFile_t * acf, int flags)
|
|
|
-{
|
|
|
- LEXStream_t * lst = acf->acf_lst; /* LEX stream handle */
|
|
|
- void * token = acf->acf_token; /* LEX token handle */
|
|
|
- char * tokenstr; /* token string pointer */
|
|
|
- int rv; /* result value */
|
|
|
- int eid; /* error id value */
|
|
|
- char linestr[16]; /* line number string buffer */
|
|
|
-
|
|
|
- /* Skip whitespace */
|
|
|
- rv = lex_skip_over(lst, aclChTab, CCM_WS);
|
|
|
- if (rv < 0) goto err_lex1;
|
|
|
-
|
|
|
- /* Begin a new token string */
|
|
|
- rv = lex_token_start(token);
|
|
|
-
|
|
|
- rv = lex_scan_over(lst, aclChTab, CCM_FILENAME, token);
|
|
|
- if (rv < 0) goto err_lex2;
|
|
|
-
|
|
|
- tokenstr = lex_token(token);
|
|
|
-
|
|
|
- if (!tokenstr || !*tokenstr) goto err_nofn;
|
|
|
-
|
|
|
- punt:
|
|
|
- return rv;
|
|
|
-
|
|
|
- err_lex1:
|
|
|
- eid = ACLERR2900;
|
|
|
- goto err_parse;
|
|
|
-
|
|
|
- err_lex2:
|
|
|
- eid = ACLERR2920;
|
|
|
- goto err_parse;
|
|
|
-
|
|
|
- err_nofn:
|
|
|
- eid = ACLERR2940;
|
|
|
-
|
|
|
- err_parse:
|
|
|
- rv = ACLERRPARSE;
|
|
|
- sprintf(linestr, "%d", acf->acf_lineno);
|
|
|
- nserrGenerate(errp, rv, eid, ACL_Program, 2, acf->acf_filename, linestr);
|
|
|
- goto punt;
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * Description (aclGetIPAddr)
|
|
|
- *
|
|
|
- * This function retrieves an IP address specification from a given
|
|
|
- * input stream. The specification consists of an IP address expressed
|
|
|
- * in the standard "." notation, possibly followed by whitespace and a
|
|
|
- * netmask, also in "." form. The IP address and netmask values are
|
|
|
- * returned. If no netmask is specified, a default value of 0xffffffff
|
|
|
- * is returned.
|
|
|
- *
|
|
|
- * Arguments:
|
|
|
- *
|
|
|
- * errp - error frame list pointer (may be null)
|
|
|
- * acf - pointer to ACLFile_t for ACL file
|
|
|
- * pip - pointer to returned IP address value
|
|
|
- * pmask - pointer to returned IP netmask value
|
|
|
- *
|
|
|
- * Returns:
|
|
|
- *
|
|
|
- * If successful, the return value identifies the type of the token
|
|
|
- * following the IP address specification. This token type value is
|
|
|
- * also returned in acf_ttype. An error is indicated by a negative
|
|
|
- * error code (ACLERRxxxx - see aclerror.h), and an error frame will
|
|
|
- * be generated if an error list is provided. The token type code in
|
|
|
- * acf_ttype is TOKEN_ERROR when an error code is returned.
|
|
|
- */
|
|
|
-
|
|
|
-int aclGetIPAddr(NSErr_t * errp,
|
|
|
- ACLFile_t * acf, IPAddr_t * pip, IPAddr_t * pmask)
|
|
|
-{
|
|
|
- LEXStream_t * lst = acf->acf_lst; /* LEX stream handle */
|
|
|
- void * token = acf->acf_token; /* LEX token handle */
|
|
|
- char * tokenstr; /* token string pointer */
|
|
|
- IPAddr_t ipaddr; /* IP address */
|
|
|
- IPAddr_t netmask; /* IP netmask */
|
|
|
- int dotcnt; /* count of '.' seen in address */
|
|
|
- int rv; /* result value */
|
|
|
- int eid; /* error id value */
|
|
|
- char linestr[16]; /* line number string buffer */
|
|
|
-
|
|
|
- /* Set default return values */
|
|
|
- *pip = 0;
|
|
|
- *pmask = 0xffffffff;
|
|
|
-
|
|
|
- rv = acf->acf_ttype;
|
|
|
-
|
|
|
- /* The current token must be a number */
|
|
|
- if (rv != TOKEN_NUMBER) {
|
|
|
-
|
|
|
- /* No IP address present */
|
|
|
- return rv;
|
|
|
- }
|
|
|
-
|
|
|
- /* Assume no netmask */
|
|
|
- netmask = 0xffffffff;
|
|
|
-
|
|
|
- for (dotcnt = 0;;) {
|
|
|
-
|
|
|
- /* Append digits and letters to the current token */
|
|
|
- rv = lex_scan_over(lst, aclChTab, (CCM_DIGIT|CCM_LETTER), token);
|
|
|
- if (rv < 0) goto err_lex1;
|
|
|
-
|
|
|
- /* Stop when no "." follows the digits and letters */
|
|
|
- if (rv != '.') break;
|
|
|
-
|
|
|
- /* Stop if we've already seen three "." */
|
|
|
- if (++dotcnt > 3) break;
|
|
|
-
|
|
|
- /* Advance past the "." */
|
|
|
- (void)lex_next_char(lst, aclChTab, CCM_SPECIAL);
|
|
|
-
|
|
|
- /* Check the next character for a "*" */
|
|
|
- rv = lex_next_char(lst, aclChTab, 0);
|
|
|
- if (rv == '*') {
|
|
|
-
|
|
|
- /* Advance past the "*" */
|
|
|
- (void)lex_next_char(lst, aclChTab, CCM_SPECIAL);
|
|
|
-
|
|
|
- netmask <<= ((4-dotcnt)*8);
|
|
|
- netmask = htonl(netmask);
|
|
|
-
|
|
|
- while (dotcnt < 4) {
|
|
|
- (void)lex_token_append(token, 2, ".0");
|
|
|
- ++dotcnt;
|
|
|
- }
|
|
|
- break;
|
|
|
- }
|
|
|
- else {
|
|
|
- /* Append the "." to the token string */
|
|
|
- (void)lex_token_append(token, 1, ".");
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /* Get a pointer to the token string */
|
|
|
- tokenstr = lex_token(token);
|
|
|
-
|
|
|
- /* A NULL pointer or an empty string is an error */
|
|
|
- if (!tokenstr || !*tokenstr) goto err_noip;
|
|
|
-
|
|
|
- /* Convert IP address to binary */
|
|
|
- ipaddr = inet_addr(tokenstr);
|
|
|
- if (ipaddr == (unsigned long)-1) goto err_badip;
|
|
|
-
|
|
|
- /* Skip whitespace */
|
|
|
- rv = lex_skip_over(lst, aclChTab, CCM_WS);
|
|
|
- if (rv < 0) goto err_lex2;
|
|
|
-
|
|
|
- /* A digit is the start of a netmask */
|
|
|
- if ((netmask == 0xffffffff) && lex_class_check(aclChTab, rv, CCM_DIGIT)) {
|
|
|
-
|
|
|
- /* Initialize token for network mask */
|
|
|
- rv = lex_token_start(token);
|
|
|
-
|
|
|
- for (dotcnt = 0;;) {
|
|
|
-
|
|
|
- /* Collect token including digits, letters, and periods */
|
|
|
- rv = lex_scan_over(lst, aclChTab, (CCM_DIGIT|CCM_LETTER), token);
|
|
|
- if (rv < 0) goto err_lex3;
|
|
|
-
|
|
|
- /* Stop when no "." follows the digits and letters */
|
|
|
- if (rv != '.') break;
|
|
|
-
|
|
|
- /* Stop if we've already seen three "." */
|
|
|
- if (++dotcnt > 3) break;
|
|
|
-
|
|
|
- /* Append the "." to the token string */
|
|
|
- (void)lex_token_append(token, 1, ".");
|
|
|
-
|
|
|
- /* Advance past the "." */
|
|
|
- (void)lex_next_char(lst, aclChTab, CCM_SPECIAL);
|
|
|
- }
|
|
|
-
|
|
|
- /* Get a pointer to the token string */
|
|
|
- tokenstr = lex_token(token);
|
|
|
-
|
|
|
- /* A NULL pointer or an empty string is an error */
|
|
|
- if (!tokenstr || !*tokenstr) goto err_nonm;
|
|
|
-
|
|
|
- /* Convert netmask to binary. */
|
|
|
- netmask = inet_addr(tokenstr);
|
|
|
- if (netmask == (unsigned long)-1) {
|
|
|
-
|
|
|
- /*
|
|
|
- * Unfortunately inet_addr() doesn't distinguish between an
|
|
|
- * error and a valid conversion of "255.255.255.255". So
|
|
|
- * we check for it explicitly. Too bad if "0xff.0xff.0xff.0xff"
|
|
|
- * is specified. Don't do that!
|
|
|
- */
|
|
|
- if (strcmp(tokenstr, "255.255.255.255")) goto err_badnm;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /* Return the IP address and netmask in host byte order */
|
|
|
- *pip = ntohl(ipaddr);
|
|
|
- *pmask = ntohl(netmask);
|
|
|
-
|
|
|
- /* Get the token following the IP address (and netmask) */
|
|
|
- rv = aclGetToken(errp, acf, 0);
|
|
|
-
|
|
|
- punt:
|
|
|
- acf->acf_ttype = (rv < 0) ? TOKEN_ERROR : rv;
|
|
|
- return rv;
|
|
|
-
|
|
|
- err_lex1:
|
|
|
- eid = ACLERR2200;
|
|
|
- rv = ACLERRPARSE;
|
|
|
- goto err_ret;
|
|
|
-
|
|
|
- err_lex2:
|
|
|
- eid = ACLERR2220;
|
|
|
- rv = ACLERRPARSE;
|
|
|
- goto err_ret;
|
|
|
-
|
|
|
- err_lex3:
|
|
|
- eid = ACLERR2240;
|
|
|
- rv = ACLERRPARSE;
|
|
|
- goto err_ret;
|
|
|
-
|
|
|
- err_noip:
|
|
|
- eid = ACLERR2260;
|
|
|
- rv = ACLERRPARSE;
|
|
|
- goto err_ret;
|
|
|
-
|
|
|
- err_badip:
|
|
|
- eid = ACLERR2280;
|
|
|
- rv = ACLERRPARSE;
|
|
|
- goto err_ret;
|
|
|
-
|
|
|
- err_nonm:
|
|
|
- eid = ACLERR2300;
|
|
|
- rv = ACLERRPARSE;
|
|
|
- goto err_ret;
|
|
|
-
|
|
|
- err_badnm:
|
|
|
- eid = ACLERR2320;
|
|
|
- rv = ACLERRPARSE;
|
|
|
- goto err_ret;
|
|
|
-
|
|
|
- err_ret:
|
|
|
- sprintf(linestr, "%d", acf->acf_lineno);
|
|
|
- nserrGenerate(errp, rv, eid, ACL_Program, 2, acf->acf_filename, linestr);
|
|
|
- goto punt;
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * Description (aclGetToken)
|
|
|
- *
|
|
|
- * This function retrieves the next token in an ACL definition file.
|
|
|
- * It skips blank lines, comments, and white space. It updates
|
|
|
- * the current line number as newlines are encountered.
|
|
|
- *
|
|
|
- * Arguments:
|
|
|
- *
|
|
|
- * errp - error frame list pointer (may be null)
|
|
|
- * acf - pointer to ACLFile_t for ACL file
|
|
|
- * flags - bit flags:
|
|
|
- * AGT_NOSKIP - don't skip leading whitespace
|
|
|
- * AGT_APPEND - append to token buffer
|
|
|
- * (else start new token)
|
|
|
- *
|
|
|
- * Returns:
|
|
|
- *
|
|
|
- * The return value is a code identifying the next token if successful.
|
|
|
- * This token type value is also returned in acf_ttype. An error
|
|
|
- * is indicated by a negative error code (ACLERRxxxx - see aclerror.h),
|
|
|
- * and an error frame will be generated if an error list is provided.
|
|
|
- * The token type code in acf_ttype is TOKEN_ERROR when an error code
|
|
|
- * is returned.
|
|
|
- */
|
|
|
-
|
|
|
-int aclGetToken(NSErr_t * errp, ACLFile_t * acf, int flags)
|
|
|
-{
|
|
|
- LEXStream_t * lst = acf->acf_lst; /* LEX stream handle */
|
|
|
- void * token = acf->acf_token; /* LEX token handle */
|
|
|
- int dospecial = 0; /* handle CCM_SPECIAL character */
|
|
|
- int tv; /* token value */
|
|
|
- int rv; /* result value */
|
|
|
- int eid; /* error id */
|
|
|
- char spech;
|
|
|
- char linestr[16]; /* line number string buffer */
|
|
|
-
|
|
|
- /* Begin a new token, unless AGT_APPEND is set */
|
|
|
- if (!(flags & AGT_APPEND)) {
|
|
|
- rv = lex_token_start(token);
|
|
|
- }
|
|
|
-
|
|
|
- /* Loop to read file */
|
|
|
- tv = 0;
|
|
|
- do {
|
|
|
-
|
|
|
- /*
|
|
|
- * If the AGT_NOSKIP flag is not set, skip whitespace (but not
|
|
|
- * newline). If the flag is set, just get the next character.
|
|
|
- */
|
|
|
- rv = lex_skip_over(lst, aclChTab, (flags & AGT_NOSKIP) ? 0 : CCM_WS);
|
|
|
- if (rv <= 0) {
|
|
|
- if (rv < 0) goto err_lex1;
|
|
|
-
|
|
|
- /* Exit loop if EOF */
|
|
|
- if (rv == 0) {
|
|
|
- tv = TOKEN_EOF;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /* Analyze character after whitespace */
|
|
|
- switch (rv) {
|
|
|
-
|
|
|
- case '\n': /* newline */
|
|
|
-
|
|
|
- /* Keep count of lines as we're skipping whitespace */
|
|
|
- acf->acf_lineno += 1;
|
|
|
- (void)lex_next_char(lst, aclChTab, CCM_NL);
|
|
|
- break;
|
|
|
-
|
|
|
- case '#': /* Beginning of comment */
|
|
|
-
|
|
|
- /* Skip to a newline if so */
|
|
|
- rv = lex_skip_to(lst, aclChTab, CCM_NL);
|
|
|
- break;
|
|
|
-
|
|
|
- case ';': /* End of statement */
|
|
|
- tv = TOKEN_EOS;
|
|
|
- dospecial = 1;
|
|
|
- break;
|
|
|
-
|
|
|
- case '@': /* at sign */
|
|
|
- tv = TOKEN_AT;
|
|
|
- dospecial = 1;
|
|
|
- break;
|
|
|
-
|
|
|
- case '+': /* plus sign */
|
|
|
- tv = TOKEN_PLUS;
|
|
|
- dospecial = 1;
|
|
|
- break;
|
|
|
-
|
|
|
- case '*': /* asterisk */
|
|
|
- tv = TOKEN_STAR;
|
|
|
- dospecial = 1;
|
|
|
- break;
|
|
|
-
|
|
|
- case '.': /* period */
|
|
|
- tv = TOKEN_PERIOD;
|
|
|
- dospecial = 1;
|
|
|
- break;
|
|
|
-
|
|
|
- case ',': /* comma */
|
|
|
- tv = TOKEN_COMMA;
|
|
|
- dospecial = 1;
|
|
|
- break;
|
|
|
-
|
|
|
- case '(': /* left parenthesis */
|
|
|
- tv = TOKEN_LPAREN;
|
|
|
- dospecial = 1;
|
|
|
- break;
|
|
|
-
|
|
|
- case ')': /* right parenthesis */
|
|
|
- tv = TOKEN_RPAREN;
|
|
|
- dospecial = 1;
|
|
|
- break;
|
|
|
-
|
|
|
- case '{': /* left brace */
|
|
|
- tv = TOKEN_LBRACE;
|
|
|
- dospecial = 1;
|
|
|
- break;
|
|
|
-
|
|
|
- case '}': /* right brace */
|
|
|
- tv = TOKEN_RBRACE;
|
|
|
- dospecial = 1;
|
|
|
- break;
|
|
|
-
|
|
|
- case '\"': /* double quote */
|
|
|
- case '\'': /* single quote */
|
|
|
-
|
|
|
- /* Append string contents to token buffer */
|
|
|
- rv = lex_scan_string(lst, token, 0);
|
|
|
- tv = TOKEN_STRING;
|
|
|
- break;
|
|
|
-
|
|
|
- default:
|
|
|
-
|
|
|
- /* Check for identifier, beginning with a letter */
|
|
|
- if (lex_class_check(aclChTab, rv, CCM_LETTER)) {
|
|
|
-
|
|
|
- /* Append valid identifier characters to token buffer */
|
|
|
- rv = lex_scan_over(lst, aclChTab, CCM_IDENT, token);
|
|
|
- tv = TOKEN_IDENT;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- /* Check for a number, beginning with a digit */
|
|
|
- if (lex_class_check(aclChTab, rv, CCM_DIGIT)) {
|
|
|
- char digit;
|
|
|
-
|
|
|
- /* Save the first digit */
|
|
|
- digit = (char)rv;
|
|
|
-
|
|
|
- /* Append the first digit to the token */
|
|
|
- rv = lex_token_append(token, 1, &digit);
|
|
|
-
|
|
|
- /* Skip over the first digit */
|
|
|
- rv = lex_next_char(lst, aclChTab, CCM_DIGIT);
|
|
|
-
|
|
|
- /* If it's '0', we might have "0x.." */
|
|
|
- if (rv == '0') {
|
|
|
-
|
|
|
- /* Pick up the next character */
|
|
|
- rv = lex_next_char(lst, aclChTab, 0);
|
|
|
-
|
|
|
- /* Is it 'x'? */
|
|
|
- if (rv == 'x') {
|
|
|
-
|
|
|
- /* Yes, append it to the token */
|
|
|
- digit = (char)rv;
|
|
|
- rv = lex_token_append(token, 1, &digit);
|
|
|
-
|
|
|
- /* Step over it */
|
|
|
- rv = lex_next_char(lst, aclChTab, CCM_LETTER);
|
|
|
- }
|
|
|
- }
|
|
|
- /* Get more digits, if any */
|
|
|
- rv = lex_scan_over(lst, aclChTab, CCM_DIGIT, token);
|
|
|
- tv = TOKEN_NUMBER;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- /* Unrecognized character */
|
|
|
-
|
|
|
- spech = *lst->lst_cp;
|
|
|
- lex_token_append(token, 1, &spech);
|
|
|
- lst->lst_cp += 1;
|
|
|
- lst->lst_len -= 1;
|
|
|
- tv = TOKEN_HUH;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- /* Handle CCM_SPECIAL character? */
|
|
|
- if (dospecial) {
|
|
|
-
|
|
|
- /* Yes, clear the flag for next time */
|
|
|
- dospecial = 0;
|
|
|
-
|
|
|
- /* Get the character and advance past it */
|
|
|
- rv = lex_next_char(lst, aclChTab, CCM_SPECIAL);
|
|
|
-
|
|
|
- /* Append the character to the token buffer */
|
|
|
- spech = (char)rv;
|
|
|
- (void)lex_token_append(token, 1, &spech);
|
|
|
- }
|
|
|
- }
|
|
|
- while ((tv == 0) && (rv > 0));
|
|
|
-
|
|
|
- if (rv < 0) {
|
|
|
- tv = TOKEN_ERROR;
|
|
|
- }
|
|
|
- else rv = tv;
|
|
|
-
|
|
|
- acf->acf_ttype = tv;
|
|
|
- return rv;
|
|
|
-
|
|
|
- err_lex1:
|
|
|
- rv = ACLERRPARSE;
|
|
|
- eid = ACLERR2400;
|
|
|
-
|
|
|
- sprintf(linestr, "%d", acf->acf_lineno);
|
|
|
- nserrGenerate(errp, rv, eid, ACL_Program, 2, acf->acf_filename, linestr);
|
|
|
-
|
|
|
- acf->acf_ttype = TOKEN_ERROR;
|
|
|
- return rv;
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * Description (aclParseInit)
|
|
|
- *
|
|
|
- * This function is called to initialize the ACL parser. It
|
|
|
- * creates a LEX character class table to assist in parsing.
|
|
|
- *
|
|
|
- * Arguments:
|
|
|
- *
|
|
|
- * None.
|
|
|
- *
|
|
|
- * Returns:
|
|
|
- *
|
|
|
- * If successful, the return value is zero. An error is indicated
|
|
|
- * by a negative return value.
|
|
|
- */
|
|
|
-
|
|
|
-int aclParseInit()
|
|
|
-{
|
|
|
- int rv; /* result value */
|
|
|
-
|
|
|
- /* Have we created the character class table yet? */
|
|
|
- if (aclChTab == 0) {
|
|
|
-
|
|
|
- /* No, initialize character classes for lexer processing */
|
|
|
- rv = lex_class_create(classc, classv, &aclChTab);
|
|
|
- if (rv < 0) goto err_nomem;
|
|
|
- }
|
|
|
-
|
|
|
- return 0;
|
|
|
-
|
|
|
- err_nomem:
|
|
|
- return ACLERRNOMEM;
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * Description (aclRealmSpecParse)
|
|
|
- *
|
|
|
- * This function parses an authentication realm specification. An
|
|
|
- * authentication realm includes an authentication database and
|
|
|
- * an authentication method. The syntax of a realm-spec is:
|
|
|
- *
|
|
|
- * realm-spec ::= "{" realm-directive-list "}" | "realm" realm-name
|
|
|
- * realm-directive-list ::= realm-directive |
|
|
|
- * realm-directive-list ";" realm-directive
|
|
|
- * realm-directive ::= realm-db-directive | realm-meth-directive
|
|
|
- * | realm-prompt-directive
|
|
|
- * realm-db-directive ::= "database" db-file-path
|
|
|
- * realm-meth-directive ::= "method" auth-method-name
|
|
|
- * auth-method-name ::= "basic" | "SSL"
|
|
|
- * realm-prompt-directive ::= "prompt" quote-char string quote-char
|
|
|
- *
|
|
|
- * Arguments:
|
|
|
- *
|
|
|
- * errp - error frame list pointer (may be null)
|
|
|
- * acf - pointer to ACLFile_t for ACL file
|
|
|
- * acc - pointer to ACContext_t structure
|
|
|
- * rspp - pointer to RealmSpec_t pointer
|
|
|
- *
|
|
|
- * Returns:
|
|
|
- *
|
|
|
- * If successful, the return value is the token type of the token
|
|
|
- * following the realm-spec, i.e. either the first token after a
|
|
|
- * realm-name or the first token after the closing "}". It is the
|
|
|
- * caller's responsibility to validate this token as a legitimate
|
|
|
- * successor of a realm-spec. If a parsing error occurs in the
|
|
|
- * middle of a realm-spec, the return value is ACLERRPARSE, and an
|
|
|
- * error frame is generated if an error list is provided. For
|
|
|
- * other kinds of errors a negative error code (from aclerror.h)
|
|
|
- * is returned.
|
|
|
- */
|
|
|
-
|
|
|
-int aclRealmSpecParse(NSErr_t * errp,
|
|
|
- ACLFile_t * acf, ACContext_t * acc, RealmSpec_t **rspp)
|
|
|
-{
|
|
|
- void * token = acf->acf_token; /* handle for current token */
|
|
|
- char * tokenstr; /* current token string */
|
|
|
- RealmSpec_t * rsp; /* realm spec pointer */
|
|
|
- RealmSpec_t * nrsp; /* named realm spec pointer */
|
|
|
- int rv; /* result value */
|
|
|
- int eid; /* error id value */
|
|
|
- char linestr[16]; /* line number string buffer */
|
|
|
-
|
|
|
- rv = acf->acf_ttype;
|
|
|
-
|
|
|
- /* Is the current token a "{" ? */
|
|
|
- if (rv != TOKEN_LBRACE) {
|
|
|
-
|
|
|
- /* No, could it be KEYWORD_REALM? */
|
|
|
- if (rv == TOKEN_IDENT) {
|
|
|
-
|
|
|
- tokenstr = lex_token(token);
|
|
|
-
|
|
|
- if (!strcasecmp(tokenstr, KEYWORD_REALM)) {
|
|
|
-
|
|
|
- /* Yes, step to the realm name */
|
|
|
- rv = aclGetToken(errp, acf, 0);
|
|
|
- if (rv != TOKEN_IDENT) {
|
|
|
- if (rv < 0) goto punt;
|
|
|
- goto err_rlmname;
|
|
|
- }
|
|
|
-
|
|
|
- tokenstr = lex_token(token);
|
|
|
-
|
|
|
- /* Look up the named realm specification */
|
|
|
- rv = symTableFindSym(acc->acc_stp, tokenstr, ACLSYMREALM,
|
|
|
- (void **)&nrsp);
|
|
|
- if (rv < 0) goto err_undrlm;
|
|
|
-
|
|
|
- /* Return the named realm specification */
|
|
|
- *rspp = nrsp;
|
|
|
-
|
|
|
- /* Step to the token after the realm name */
|
|
|
- rv = aclGetToken(errp, acf, 0);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return rv;
|
|
|
- }
|
|
|
-
|
|
|
- /* Step to the token after the "{" */
|
|
|
- rv = aclGetToken(errp, acf, 0);
|
|
|
- if (rv < 0) goto punt;
|
|
|
-
|
|
|
- rsp = *rspp;
|
|
|
- if (rsp == 0) {
|
|
|
- rsp = (RealmSpec_t *)MALLOC(sizeof(RealmSpec_t));
|
|
|
- if (rsp == 0) goto err_nomem;
|
|
|
- memset((void *)rsp, 0, sizeof(RealmSpec_t));
|
|
|
- rsp->rs_sym.sym_type = ACLSYMREALM;
|
|
|
- *rspp = rsp;
|
|
|
- }
|
|
|
-
|
|
|
- /* Loop for each realm-directive */
|
|
|
- for (;; rv = aclGetToken(errp, acf, 0)) {
|
|
|
-
|
|
|
- if (rv != TOKEN_IDENT) {
|
|
|
-
|
|
|
- /* Exit loop on "}" */
|
|
|
- if (rv == TOKEN_RBRACE) break;
|
|
|
-
|
|
|
- /* Ignore null directives */
|
|
|
- if (rv == TOKEN_EOS) continue;
|
|
|
-
|
|
|
- /* Otherwise need an identifier to start a directive */
|
|
|
- goto err_nodir;
|
|
|
- }
|
|
|
-
|
|
|
- tokenstr = lex_token(token);
|
|
|
-
|
|
|
- /* Figure out which realm-directive this is */
|
|
|
- if (!strcasecmp(tokenstr, KEYWORD_DATABASE)) {
|
|
|
-
|
|
|
- /* Get a file specification for the database */
|
|
|
- rv = aclGetToken(errp, acf, 0);
|
|
|
- if (rv != TOKEN_STRING) {
|
|
|
- if (rv < 0) goto punt;
|
|
|
- goto err_nodb;
|
|
|
- }
|
|
|
-
|
|
|
- rsp->rs_realm.rlm_dbname = lex_token_take(token);
|
|
|
- rsp->rs_realm.rlm_aif = &NSADB_AuthIF;
|
|
|
- }
|
|
|
- else if (!strcasecmp(tokenstr, KEYWORD_METHOD)) {
|
|
|
-
|
|
|
- /* Step to the method identifier */
|
|
|
- rv = aclGetToken(errp, acf, 0);
|
|
|
- if (rv != TOKEN_IDENT) {
|
|
|
- if (rv < 0) goto punt;
|
|
|
- goto err_nometh;
|
|
|
- }
|
|
|
-
|
|
|
- tokenstr = lex_token(token);
|
|
|
-
|
|
|
- /* Interpret method name and set method in realm structure */
|
|
|
- if (!strcasecmp(tokenstr, KEYWORD_BASIC)) {
|
|
|
- rsp->rs_realm.rlm_ameth = AUTH_METHOD_BASIC;
|
|
|
- }
|
|
|
- else if (!strcasecmp(tokenstr, KEYWORD_SSL) && server_enterprise) {
|
|
|
- rsp->rs_realm.rlm_ameth = AUTH_METHOD_SSL;
|
|
|
- }
|
|
|
- else goto err_badmeth;
|
|
|
- }
|
|
|
- else if (!strcasecmp(tokenstr, KEYWORD_PROMPT)) {
|
|
|
-
|
|
|
- /* Step to the realm prompt string */
|
|
|
- rv = aclGetToken(errp, acf, 0);
|
|
|
- if ((rv != TOKEN_STRING) && (rv != TOKEN_IDENT)) {
|
|
|
- if (rv < 0) goto punt;
|
|
|
- goto err_noprompt;
|
|
|
- }
|
|
|
-
|
|
|
- /* Reference a copy of the prompt string from the realm */
|
|
|
- rsp->rs_realm.rlm_prompt = lex_token_take(token);
|
|
|
- }
|
|
|
- else goto err_baddir;
|
|
|
-
|
|
|
- /* Get the token after the realm-directive */
|
|
|
- rv = aclGetToken(errp, acf, 0);
|
|
|
-
|
|
|
- /* Need a ";" to keep going */
|
|
|
- if (rv != TOKEN_EOS) break;
|
|
|
- }
|
|
|
-
|
|
|
- if (rv != TOKEN_RBRACE) goto err_rbrace;
|
|
|
-
|
|
|
- /* Get the token after the realm-spec */
|
|
|
- rv = aclGetToken(errp, acf, 0);
|
|
|
-
|
|
|
- punt:
|
|
|
- return rv;
|
|
|
-
|
|
|
- err_rlmname:
|
|
|
- eid = ACLERR2500;
|
|
|
- goto err_parse;
|
|
|
-
|
|
|
- err_undrlm:
|
|
|
- eid = ACLERR2520;
|
|
|
- rv = ACLERRUNDEF;
|
|
|
- goto err_sym;
|
|
|
-
|
|
|
- err_nomem:
|
|
|
- eid = ACLERR2540;
|
|
|
- rv = ACLERRNOMEM;
|
|
|
- goto ret_err;
|
|
|
-
|
|
|
- err_nodir:
|
|
|
- eid = ACLERR2560;
|
|
|
- goto err_parse;
|
|
|
-
|
|
|
- err_nodb:
|
|
|
- eid = ACLERR2570;
|
|
|
- goto err_parse;
|
|
|
-
|
|
|
- err_nometh:
|
|
|
- eid = ACLERR2580;
|
|
|
- goto err_parse;
|
|
|
-
|
|
|
- err_badmeth:
|
|
|
- eid = ACLERR2600;
|
|
|
- goto err_sym;
|
|
|
-
|
|
|
- err_noprompt:
|
|
|
- eid = ACLERR2605;
|
|
|
- goto err_parse;
|
|
|
-
|
|
|
- err_baddir:
|
|
|
- eid = ACLERR2610;
|
|
|
- goto err_sym;
|
|
|
-
|
|
|
- err_rbrace:
|
|
|
- eid = ACLERR2620;
|
|
|
- goto err_parse;
|
|
|
-
|
|
|
- err_sym:
|
|
|
- sprintf(linestr, "%d", acf->acf_lineno);
|
|
|
- nserrGenerate(errp, rv, eid, ACL_Program,
|
|
|
- 3, acf->acf_filename, linestr, tokenstr);
|
|
|
- goto punt;
|
|
|
-
|
|
|
- err_parse:
|
|
|
- rv = ACLERRPARSE;
|
|
|
- ret_err:
|
|
|
- sprintf(linestr, "%d", acf->acf_lineno);
|
|
|
- nserrGenerate(errp, rv, eid, ACL_Program, 2, acf->acf_filename, linestr);
|
|
|
- goto punt;
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * Description (aclRightsParse)
|
|
|
- *
|
|
|
- * This function parse an access rights list. The syntax for an
|
|
|
- * access rights list is:
|
|
|
- *
|
|
|
- * rights-list ::= "(" list-of-rights ")"
|
|
|
- * list-of-rights ::= rights-elem | list-of-rights "," rights-elem
|
|
|
- * rights-elem ::= right-name | "+" rights-def-name
|
|
|
- * right-name ::= identifier
|
|
|
- * rights-def-name ::= identifier
|
|
|
- *
|
|
|
- * An element of a rights list is either the name of a particular
|
|
|
- * access right (e.g. Read), or the name associated with an
|
|
|
- * external definition of an access rights list, preceded by "+"
|
|
|
- * (e.g. +editor-rights). The list is enclosed in parentheses,
|
|
|
- * and the elements are separated by commas.
|
|
|
- *
|
|
|
- * This function adds to a list of rights provided by the caller.
|
|
|
- * Access rights are internally assigned unique integer identifiers,
|
|
|
- * and a symbol table is maintained to map an access right name to
|
|
|
- * its identifier.
|
|
|
- *
|
|
|
- * Arguments:
|
|
|
- *
|
|
|
- * errp - error frame list pointer (may be null)
|
|
|
- * acf - pointer to ACLFile_t for ACL file
|
|
|
- * acc - pointer to ACContext_t structure
|
|
|
- * rights - pointer to rights list head
|
|
|
- *
|
|
|
- * Returns:
|
|
|
- *
|
|
|
- * The return value is a code identifying the next token if successful.
|
|
|
- * End-of-stream is indicated by a return value of TOKEN_EOF. An error
|
|
|
- * is indicated by a negative error code (ACLERRxxxx - see aclerror.h),
|
|
|
- * and an error frame will be generated if an error list is provided.
|
|
|
- */
|
|
|
-
|
|
|
-int aclRightsParse(NSErr_t * errp, ACLFile_t * acf, ACContext_t * acc,
|
|
|
- RightSpec_t **rights)
|
|
|
-{
|
|
|
- void * token = acf->acf_token; /* LEX token handle */
|
|
|
- char * ename; /* element name string pointer */
|
|
|
- RightSpec_t * rsp; /* rights specification pointer */
|
|
|
- RightSpec_t * nrsp; /* named rights spec pointer */
|
|
|
- RightDef_t * rdp; /* right definition pointer */
|
|
|
- int rv; /* result value */
|
|
|
- int eid; /* error id */
|
|
|
- char linestr[16]; /* line number string buffer */
|
|
|
-
|
|
|
- /* Look for a left parenthesis */
|
|
|
- if (acf->acf_ttype != TOKEN_LPAREN) {
|
|
|
-
|
|
|
- /* No rights list present */
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
- rsp = *rights;
|
|
|
-
|
|
|
- /* Create a RightSpec_t if we don't have one */
|
|
|
- if (rsp == 0) {
|
|
|
- rsp = (RightSpec_t *)MALLOC(sizeof(RightSpec_t));
|
|
|
- if (rsp == 0) goto err_nomem1;
|
|
|
- memset((void *)rsp, 0, sizeof(RightSpec_t));
|
|
|
- rsp->rs_sym.sym_type = ACLSYMRDEF;
|
|
|
- *rights = rsp;
|
|
|
- }
|
|
|
-
|
|
|
- /* Parse list elements */
|
|
|
- for (;;) {
|
|
|
-
|
|
|
- /* Look for an identifier */
|
|
|
- rv = aclGetToken(errp, acf, 0);
|
|
|
- if (rv != TOKEN_IDENT) {
|
|
|
-
|
|
|
- /* No, maybe a "+" preceding a rights definition name? */
|
|
|
- if (rv != TOKEN_PLUS) {
|
|
|
-
|
|
|
- /* One more chance, we'll allow the closing ")" after "," */
|
|
|
- if (rv != TOKEN_RPAREN) {
|
|
|
- /* No, bad news */
|
|
|
- if (rv < 0) goto punt;
|
|
|
- goto err_elem;
|
|
|
- }
|
|
|
-
|
|
|
- /* Got right paren after comma */
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- /* Got a "+", try for the rights definition name */
|
|
|
- rv = aclGetToken(errp, acf, 0);
|
|
|
- if (rv != TOKEN_IDENT) {
|
|
|
- if (rv < 0) goto punt;
|
|
|
- goto err_rdef;
|
|
|
- }
|
|
|
-
|
|
|
- /* Get a pointer to the token string */
|
|
|
- ename = lex_token(token);
|
|
|
-
|
|
|
- /* See if it matches a rights definition in the symbol table */
|
|
|
- rv = symTableFindSym(acc->acc_stp, ename, ACLSYMRDEF,
|
|
|
- (void **)&nrsp);
|
|
|
- if (rv) goto err_undef;
|
|
|
-
|
|
|
- /*
|
|
|
- * Merge the rights from the named rights list into the
|
|
|
- * current rights list.
|
|
|
- */
|
|
|
- rv = uilMerge(&rsp->rs_list, &nrsp->rs_list);
|
|
|
- if (rv < 0) goto err_nomem2;
|
|
|
- }
|
|
|
- else {
|
|
|
-
|
|
|
- /* The current token is an access right name */
|
|
|
-
|
|
|
- /* Get a pointer to the token string */
|
|
|
- ename = lex_token(token);
|
|
|
-
|
|
|
-
|
|
|
- /* Find or create an access right definition */
|
|
|
- rv = aclRightDef(errp, acc, ename, &rdp);
|
|
|
- if (rv < 0) goto err_radd;
|
|
|
-
|
|
|
- /* Add the id for this right to the current rights list */
|
|
|
- rv = usiInsert(&rsp->rs_list, rdp->rd_id);
|
|
|
- if (rv < 0) goto err_nomem3;
|
|
|
- }
|
|
|
-
|
|
|
- rv = aclGetToken(errp, acf, 0);
|
|
|
-
|
|
|
- /* Want a comma to continue the list */
|
|
|
- if (rv != TOKEN_COMMA) {
|
|
|
-
|
|
|
- /* A right parenthesis will end the list nicely */
|
|
|
- if (rv == TOKEN_RPAREN) {
|
|
|
-
|
|
|
- /* Get the first token after the rights list */
|
|
|
- rv = aclGetToken(errp, acf, 0);
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- /* Anything else is an error */
|
|
|
- if (rv < 0) goto punt;
|
|
|
- goto err_list;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return rv;
|
|
|
-
|
|
|
- err_elem:
|
|
|
- eid = ACLERR2700;
|
|
|
- rv = ACLERRSYNTAX;
|
|
|
- goto err_ret;
|
|
|
-
|
|
|
- err_rdef:
|
|
|
- eid = ACLERR2720;
|
|
|
- rv = ACLERRSYNTAX;
|
|
|
- goto err_ret;
|
|
|
-
|
|
|
- err_undef:
|
|
|
- eid = ACLERR2740;
|
|
|
- rv = ACLERRUNDEF;
|
|
|
- sprintf(linestr, "%d", acf->acf_lineno);
|
|
|
- nserrGenerate(errp, rv, eid, ACL_Program,
|
|
|
- 3, acf->acf_filename, linestr, ename);
|
|
|
- return rv;
|
|
|
-
|
|
|
- err_nomem1:
|
|
|
- eid = ACLERR2760;
|
|
|
- goto err_nomem;
|
|
|
-
|
|
|
- err_nomem2:
|
|
|
- eid = ACLERR2780;
|
|
|
- goto err_nomem;
|
|
|
-
|
|
|
- err_radd:
|
|
|
- eid = ACLERR2800;
|
|
|
- goto err_ret;
|
|
|
-
|
|
|
- err_nomem3:
|
|
|
- eid = ACLERR2820;
|
|
|
- goto err_nomem;
|
|
|
-
|
|
|
- err_nomem:
|
|
|
- rv = ACLERRNOMEM;
|
|
|
- goto err_ret;
|
|
|
-
|
|
|
- err_list:
|
|
|
-
|
|
|
- eid = ACLERR2840;
|
|
|
- rv = ACLERRSYNTAX;
|
|
|
-
|
|
|
- err_ret:
|
|
|
- sprintf(linestr, "%d", acf->acf_lineno);
|
|
|
- nserrGenerate(errp, rv, eid, ACL_Program, 2, acf->acf_filename, linestr);
|
|
|
-
|
|
|
- punt:
|
|
|
- return rv;
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * Description (aclStreamGet)
|
|
|
- *
|
|
|
- * This function is the stream read function designated by
|
|
|
- * aclFileOpen() to read the file associated with the LEX stream
|
|
|
- * it creates. It reads the next chunk of the file into the
|
|
|
- * stream buffer.
|
|
|
- *
|
|
|
- * Arguments:
|
|
|
- *
|
|
|
- * lst - pointer to LEX stream structure
|
|
|
- *
|
|
|
- * Returns:
|
|
|
- *
|
|
|
- * The return value is the number of bytes read if successful.
|
|
|
- * A return value of zero indicates end-of-file. An error is
|
|
|
- * indicated by a negative return value.
|
|
|
- */
|
|
|
-
|
|
|
-int aclStreamGet(LEXStream_t * lst)
|
|
|
-{
|
|
|
- SYS_FILE fd = (SYS_FILE)(lst->lst_strmid);
|
|
|
- int len;
|
|
|
-
|
|
|
- len = system_fread(fd, lst->lst_buf, lst->lst_buflen);
|
|
|
- if (len >= 0) {
|
|
|
- lst->lst_len = len;
|
|
|
- lst->lst_cp = lst->lst_buf;
|
|
|
- }
|
|
|
-
|
|
|
- return len;
|
|
|
-}
|