diff options
Diffstat (limited to 'xpa/acl.c')
-rw-r--r-- | xpa/acl.c | 568 |
1 files changed, 568 insertions, 0 deletions
diff --git a/xpa/acl.c b/xpa/acl.c new file mode 100644 index 0000000..24b4489 --- /dev/null +++ b/xpa/acl.c @@ -0,0 +1,568 @@ +/* + * Copyright (c) 1999-2003 Smithsonian Astrophysical Observatory + */ + +/* + * + * acl.c -- xpa access control list management + * + */ + +#include <xpap.h> + +/* + *---------------------------------------------------------------------------- + * + * + * Private Routines + * + * + *---------------------------------------------------------------------------- + */ + +/* this is the head of the global list -- too lazy to do anything more */ +static XACL aclhead=NULL; + +#ifdef ANSI_FUNC +static XACL +XPAAclLookup (char *xclass, char *name, unsigned int ip, int exact) +#else +static XACL XPAAclLookup(xclass, name, ip, exact) + char *xclass; + char *name; + unsigned int ip; + int exact; +#endif +{ + XACL cur; + /* look for exact match */ + for(cur=aclhead; cur!=NULL; cur=cur->next){ + if( !strcmp(xclass, cur->xclass) && + !strcmp(name, cur->name) && + ((cur->ip == 0) || (cur->ip == ip)) ){ + return(cur); + } + } + /* otherwise look for a template match (unless exact was specified) */ + if( !exact ){ + for(cur=aclhead; cur!=NULL; cur=cur->next){ + if( tmatch(xclass, cur->xclass) && + tmatch(name, cur->name) && + ((cur->ip == 0) || (cur->ip == ip)) ){ + return(cur); + } + } + } + return(NULL); +} + +/* + *---------------------------------------------------------------------------- + * + * Routine: XPAAclParse + * + * Purpose: parse acl list into components + * + * Returns: 0 on success, -1 on failure + * + *---------------------------------------------------------------------------- + */ +#ifdef ANSI_FUNC +static int +XPAAclParse (char *lbuf, char *xclass, char *name, unsigned int *ip, + char *acl, int len) +#else +static int XPAAclParse(lbuf, xclass, name, ip, acl, len) + char *lbuf; + char *xclass; + char *name; + unsigned int *ip; + char *acl; + int len; +#endif +{ + char tbuf[SZ_LINE]; + int lp=0; + + /* class:name is required */ + if( word(lbuf, tbuf, &lp) ){ + XPAParseName(tbuf, xclass, name, len); + } + else + return(-1); + + /* host is required but can be "*" for "all hosts" */ + if( word(lbuf, tbuf, &lp) ){ + if( !strcmp(tbuf, "*") ) + *ip = 0; + else + *ip = gethostip(tbuf); + } + else + return(-1); + + /* acl is required */ + if( word(lbuf, tbuf, &lp) ){ + if( !strcmp(tbuf, "+") ) + strcpy(acl, XPA_ACLS); + else if( !strcmp(tbuf, "-") ) + *acl = '\0'; + else + strcpy(acl, tbuf); + return(0); + } + else + return(-1); +} + +/* + *---------------------------------------------------------------------------- + * + * + * Semi-Public Routines (used by command.c) + * + * + *---------------------------------------------------------------------------- + */ + +/* + *---------------------------------------------------------------------------- + * + * Routine: XPAReceiveAcl + * + * Purpose: add or modify the acl for this access point + * + * Returns: 0 for success, -1 for failure + * + *---------------------------------------------------------------------------- + */ +#ifdef ANSI_FUNC +int +XPAReceiveAcl (void *client_data, void *call_data, char *paramlist, + char *buf, size_t len) +#else +int XPAReceiveAcl(client_data, call_data, paramlist, buf, len) + void *client_data; + void *call_data; + char *paramlist; + char *buf; + size_t len; +#endif +{ + XPA xpa = (XPA)call_data; + XPAComm comm; + int i; + int got; + char *s=NULL; + char lbuf[SZ_LINE]; + char tbuf[SZ_LINE]; + + if( paramlist && *paramlist ){ + s = paramlist; + while( isspace((int)*s) ) + s++; + snprintf(tbuf, SZ_LINE, "%s:%s %s\n", xpa->xclass, xpa->name, s); + if( XPAAclEdit(tbuf) < 0 ){ + snprintf(lbuf, SZ_LINE, "invalid acl: %s\n", tbuf); + XPAError(xpa, lbuf); + return(-1); + } + } + else{ + while((XPAGets(xpa, xpa_datafd(xpa), lbuf, SZ_LINE, XPAShortTimeout())>0)&& + *lbuf ){ + snprintf(tbuf, SZ_LINE, "%s:%s %s\n", xpa->xclass, xpa->name, lbuf); + got = XPAAclEdit(tbuf); + if( got < 0 ){ + snprintf(lbuf, SZ_LINE, "invalid acl: %s\n", tbuf); + XPAError(xpa, lbuf); + return(-1); + } + } + } + + /* reset all acl flags for this xpa so acl is recalculated */ + for(comm=xpa->commhead; comm!=NULL; comm=comm->next){ + for(i=0; i<4; i++){ + comm->acl[i] = -1; + } + } + + return(0); +} + +/* + *---------------------------------------------------------------------------- + * + * Routine: XPASendAcl + * + * Purpose: return the acl for this access point + * + * Returns: 0 for success, -1 for failure + * + *---------------------------------------------------------------------------- + */ +#ifdef ANSI_FUNC +int +XPASendAcl (void *client_data, void *call_data, char *paramlist, + char **buf, size_t *len) +#else +int XPASendAcl(client_data, call_data, paramlist, buf, len) + void *client_data; + void *call_data; + char *paramlist; + char **buf; + size_t *len; +#endif +{ + XPA xpa = (XPA)call_data; + XACL cur; + int got = 0; + char tbuf[SZ_LINE]; + + /* zero all flags */ + for(cur=aclhead; cur!=NULL; cur=cur->next){ + cur->flag = 0; + } + /* look for exact matches */ + for(cur=aclhead; cur!=NULL; cur=cur->next){ + if(!strcmp(xpa->xclass, cur->xclass) && !strcmp(xpa->name, cur->name)){ + snprintf(tbuf, SZ_LINE, "%s:%s %s %s\n", + cur->xclass, cur->name, getiphost(cur->ip), cur->acl); + send(xpa_datafd(xpa), tbuf, strlen(tbuf), 0); + cur->flag = 1; + got++; + } + } + /* look for template matches that we have not printed yet */ + for(cur=aclhead; cur!=NULL; cur=cur->next){ + if( cur->flag == 0 ){ + if(tmatch(xpa->xclass, cur->xclass) && tmatch(xpa->name, cur->name)){ + snprintf(tbuf, SZ_LINE, "%s:%s %s %s\n", + cur->xclass, cur->name, getiphost(cur->ip), cur->acl); + send(xpa_datafd(xpa), tbuf, strlen(tbuf), 0); + got++; + } + } + } + /* zero all flags */ + for(cur=aclhead; cur!=NULL; cur=cur->next){ + cur->flag = 0; + } + if( got == 0 ){ + send(xpa_datafd(xpa), "\n", 1, 0); + } + return(0); +} + +/* + *---------------------------------------------------------------------------- + * + * + * Public Routines + * + * + *---------------------------------------------------------------------------- + */ + +/* + *---------------------------------------------------------------------------- + * + * Routine: XPAAclEdit + * + * Purpose: add or modify acl entry in the xpa acl list + * + * Returns: 0 on success, -1 on failure + * + *---------------------------------------------------------------------------- + */ +#ifdef ANSI_FUNC +int +XPAAclEdit (char *lbuf) +#else +int XPAAclEdit(lbuf) + char *lbuf; +#endif +{ + XACL cur; + char xclass[SZ_LINE]; + char name[SZ_LINE]; + char acl[SZ_LINE]; + unsigned int ip; + + if( XPAAclParse(lbuf, xclass, name, &ip, acl, SZ_LINE) < 0 ) + return(-1); + if( ip == 0 ) + return(-1); + cur = XPAAclLookup(xclass, name, ip, 1); + if( cur == NULL ) + return(XPAAclAdd(lbuf)); + else{ + if( *acl == '\0' ){ + XPAAclDel(cur); + } + else{ + if( cur->acl ) + xfree(cur->acl); + cur->acl = xstrdup(acl); + } + return(0); + } +} + + +/* + *---------------------------------------------------------------------------- + * + * Routine: XPAAclAdd + * + * Purpose: add one acl entry to the xpa acl list + * + * Returns: 0 on success, -1 on failure + * + *---------------------------------------------------------------------------- + */ +#ifdef ANSI_FUNC +int +XPAAclAdd (char *lbuf) +#else +int XPAAclAdd(lbuf) + char *lbuf; +#endif +{ + XACL xnew; + XACL cur; + char xclass[SZ_LINE]; + char name[SZ_LINE]; + char acl[SZ_LINE]; + unsigned int ip; + + /* allocate acl struct */ + if( (xnew = (XACL)xcalloc(1, sizeof(XACLRec))) == NULL ) + goto error; + + /* parse info from line buffer */ + if( XPAAclParse(lbuf, xclass, name, &ip, acl, SZ_LINE) < 0 ) + goto error; + + /* fill in the blanks */ + xnew->xclass = xstrdup(xclass); + xnew->name = xstrdup(name); + xnew->ip = ip; + xnew->acl = xstrdup(acl); + + /* add this acl to end of list of acl's */ + if( aclhead == NULL ){ + aclhead = xnew; + } + else{ + for(cur=aclhead; cur->next!=NULL; cur=cur->next) + ; + cur->next = xnew; + } + return(0); + +error: + if( xnew ) + xfree(xnew); + return(-1); +} + +/* + *--------------------------------------------------------------------------- + * + * Routine: XPAAclDel + * + * Purpose: free up memory in the acl record structure + * + * Results: 0 on success, -1 for failure + * + *--------------------------------------------------------------------------- + */ +#ifdef ANSI_FUNC +int +XPAAclDel (XACL acl) +#else +int XPAAclDel(acl) + XACL acl; +#endif +{ + XACL cur; + + if( acl == NULL ) + return(-1); + + /* remove from list of acl's */ + if( aclhead ){ + if( aclhead == acl ){ + aclhead = aclhead->next; + } + else{ + for(cur=aclhead; cur!=NULL; cur=cur->next){ + if( cur->next == acl ){ + cur->next = (cur->next)->next; + break; + } + } + } + } + + /* free up string space */ + if( acl->xclass ) xfree(acl->xclass); + if( acl->name ) xfree(acl->name); + if( acl->acl ) xfree(acl->acl); + + /* free up record struct */ + xfree((char *)acl); + return(0); +} + +/* + *---------------------------------------------------------------------------- + * + * Routine: XPAAclFree + * + * Purpose: + * + * Results: 1 on success, 0 for failure + * + *---------------------------------------------------------------------------- + */ +#ifdef ANSI_FUNC +void +XPAAclFree (void) +#else +void XPAAclFree() +#endif +{ + XACL cur, tacl; + + for(cur=aclhead; cur!=NULL; ){ + tacl = cur->next; + XPAAclDel(cur); + cur = tacl; + } +} + +/* + *---------------------------------------------------------------------------- + * + * Routine: XPAAclNew + * + * Purpose: read or re-read the acl list + * + * Results: number of lines in list (including default) + * + *---------------------------------------------------------------------------- + */ +#ifdef ANSI_FUNC +int +XPAAclNew (char *aname, int flag) +#else +int XPAAclNew(aname, flag) + char *aname; + int flag; +#endif +{ + int got=0; + char lbuf[SZ_LINE]; + char hostname[SZ_LINE]; + char *s; + char *obuf; + char *aclname=NULL; + char *aclpath=NULL; + char *defacl=NULL; + char *defcopy=NULL; + char *keywords[10]; + char *values[10]; + int nkeys; + FILE *fp=NULL; + + /* if there is an old list, free it */ + if( flag == 0 ) + XPAAclFree(); + + /* get acl file name */ + if( aname && *aname ) + aclname = aname; + else if( (aclname=(char *)getenv("XPA_ACLFILE")) == NULL ) + aclname = XPA_ACLFILE; + + /* get the default acl */ + if( (defacl=(char *)getenv("XPA_DEFACL")) == NULL ) + defacl = XPA_DEFACL; + + /* macro-expand it to deal with the host name */ + gethost(hostname, SZ_LINE); + nkeys = 0; + keywords[0] = "host"; values[0] = hostname; nkeys++; + + /* open the acl file */ + if( (aclpath=(char *)Access(aclname, "r")) != NULL ){ + if( (fp=fopen(aclpath, "r")) != NULL ){ + while( fgets(lbuf, SZ_LINE, fp) ){ + if( *lbuf == '#' ){ + continue; + } + if( (obuf=macro(lbuf, keywords, values, nkeys, NULL, NULL)) != NULL ){ + if( XPAAclAdd(obuf) == 0 ) + got++; + xfree(obuf); + } + } + fclose(fp); + } + xfree(aclpath); + } + + /* add default acl (it very likely was overridden in the file) */ + defcopy=(char *)xstrdup(defacl); + for(s=(char *)strtok(defcopy,";"); s!=NULL; s=(char *)strtok(NULL,";")){ + if( (obuf = macro(s, keywords, values, nkeys, NULL, NULL)) != NULL ){ + if( XPAAclAdd(obuf) == 0 ) + got++; + xfree(obuf); + } + } + if( defcopy) xfree(defcopy); + + /* return the news */ + return(got); +} + +/* + *---------------------------------------------------------------------------- + * + * Routine: XPAAclCheck + * + * Purpose: validate an acl for a given class, name, and host + * + * Results: 1 on success, 0 on failure + * + *---------------------------------------------------------------------------- + */ +#ifdef ANSI_FUNC +int +XPAAclCheck (XPA xpa, unsigned int ip, char *acl) +#else +int XPAAclCheck(xpa, ip, acl) + XPA xpa; + unsigned int ip; + char *acl; +#endif +{ + char *s; + XACL cur; + + if( !(cur = XPAAclLookup(xpa->xclass, xpa->name, ip, 0)) ) + return(0); + else if( cur->acl == NULL ) + return(0); + else{ + for(s=acl; *s; s++){ + if( !strchr(cur->acl, *s) ) + return(0); + } + return(1); + } +} |