This is akcs.c in view mode; [Download] [Up]
/* @(#)contrib/akcs/akcs.c 1.2 24 Oct 1990 05:17:09 */ /* * Copyright (C) 1987, 1988 Ronald S. Karr and Landon Curt Noll * * Changed, modified, mangled and hacked by Karl Denninger * (karl@ddsw1.MCS.COM); changes copyright 1989 Karl Denninger. * * See the file COPYING, distributed with smail, for restriction * and warranty information. */ /* * akcs.c: * direct mail to a transport which will deliver to local AKCS(tm) * mailboxes. Match only local addresses which are login names * for AKCS on the local host. * * Specifications for the akcs directing driver: * * private attribute data: * transport (name): the name of the transport to use in delivering * mail to local users. */ #include <stdio.h> #include <pwd.h> #include "defs.h" #include "../smail.h" #include "../smailconf.h" #include "../parse.h" #include "../addr.h" #include "../log.h" #include "../direct.h" #include "../transport.h" #include "../exitcodes.h" #include "../dys.h" #include "akcs.h" #ifndef DEPEND # include "../extern.h" # include "../debug.h" # include "../error.h" #endif /* * akcs_user_info - fill an addr structure with user information * * if the remainder field if the addr structure matches a username, * fill in fields which pertain to the user's password file entry. * Note that this only checks the AKCS information files. * */ void akcs_user_info(addr) struct addr *addr; /* addr structure to check */ { char tmp[512]; /* Temporary space */ char usr[32]; /* User space */ char basedir[132]; FILE *fid, *fid2; if (addr->flags & (ADDR_NOTUSER|ADDR_ISUSER)) { /* a previous call to akcs_user_info() already took care of this */ return; } /* get the AKCS password entry if one exists */ if ((fid = fopen("/etc/akcsparams", "r")) == NULL) { addr->flags |= ADDR_NOTUSER; /* No parameter file, no AKCS! */ return; /* Pass on this one... */ } while (fgets(tmp, 132, fid) != NULL) { if (sscanf(tmp, "Base: %[!-z]", basedir)) { sprintf(tmp, "%s/AKCS.p.users", basedir); if ((fid2 = fopen(tmp, "r")) == NULL) { /* Open user file */ fclose(fid); /* Close parameter file */ addr->flags |= ADDR_NOTUSER; /* Not there */ return; } while (fgets(tmp, 512, fid2) != NULL) { if (sscanf(tmp, "%[!-z]", usr) <= 0) continue; /* There's a problem */ if (!strcmp(usr, addr->remainder)) { /* This user? */ addr->flags |= ADDR_ISUSER; /* Save it if so */ sprintf(tmp, "%s/.users/%s", basedir, addr->remainder); addr->home = COPY_STRING(tmp); fclose(fid); /* Close parameter file */ fclose(fid2); return; /* Exit with success */ } } fclose(fid2); } } fclose(fid); addr->flags |= ADDR_NOTUSER; return; } /* * dtd_akcs - direct to local akcs mailboxes */ /*ARGSUSED*/ struct addr * dtd_akcs(dp, in, out, new, defer, fail) struct director *dp; /* director entry */ struct addr *in; /* input local-form addrs */ struct addr **out; /* output resolved addrs */ struct addr **new; /* output new addrs to resolve */ struct addr **defer; /* addrs to defer to a later time */ struct addr **fail; /* unresolvable addrs */ { register struct addr *cur; /* temp for processing input */ struct addr *pass = NULL; /* addrs to pass to next director */ struct addr *next; /* next value for cur */ struct akcs_private *priv = (struct akcs_private *)dp->private; DEBUG(DBG_DRIVER_HI, "dtd_akcs called\n"); for (cur = in; cur; cur = next) { next = cur->succ; if (priv->prefix) { struct addr *new; int len = strlen(priv->prefix); /* * if we are testing against a prefix, strip the prefix and * lookup the name in the passwd file. If found, return a * new fully resolved addr. */ if (strncmpic(priv->prefix, cur->remainder, len) != 0) { cur->succ = pass; pass = cur; continue; /* did not start with prefix */ } new = alloc_addr(); new->remainder = COPY_STRING(cur->remainder + len); akcs_user_info(new); if (new->flags&ADDR_NOTUSER) { /* we did not match a user on the local host */ xfree(new->remainder); xfree((char *)new); cur->succ = pass; pass = cur; continue; } new->in_addr = COPY_STRING(new->remainder); new->director = dp; new->parent = cur; cur = new; } else { /* The prefix didn't match, ignore it */ cur->succ = pass; pass = cur; continue; } DEBUG2(DBG_DRIVER_LO, "director %s matched user %s\n", dp->name, cur->remainder); cur->director = dp; /* matched address */ /* attach the transport */ cur->transport = find_transport(priv->transport); if (cur->transport == NULL) { /* * ERR_122 - user transport not specified * * DESCRIPTION * No transport attribute was specified for a user * director. The attribute is required. * * ACTIONS * Defer the message with a configuration error. * * RESOLUTION * The director file should be edited to specify the * correct transport for local delivery. */ cur->error = note_error(ERR_CONFERR|ERR_122, xprintf("director %s: transport not defined", dp->name)); cur->succ = *defer; *defer = cur; continue; } cur->next_addr = COPY_STRING(cur->remainder); cur->succ = *out; *out = cur; } return pass; /* return addrs for next director */ } /* * dtv_akcs - verify a AKCS user on the local host */ /*ARGSUSED*/ void dtv_akcs(dp, in, retry, okay, defer, fail) struct director *dp; /* director entry */ struct addr *in; /* input local-form addrs */ struct addr **retry; /* output list of unmatched addrs */ struct addr **okay; /* output list of verified addrs */ struct addr **defer; /* temporariliy unverifiable addrs */ struct addr **fail; /* unverified addrs */ { register struct addr *cur; /* temp for processing input */ struct addr *next; /* next value for cur */ struct akcs_private *priv = (struct akcs_private *)dp->private; DEBUG(DBG_DRIVER_HI, "dtv_akcs called\n"); /* loop over all of the input addrs */ for (cur = in; cur; cur = next) { next = cur->succ; if (priv->prefix) { int len = strlen(priv->prefix); /* * if we are testing against a prefix, strip the prefix and * see if the remaining string matches a local user */ if (strncmpic(priv->prefix, cur->remainder, len) == 0 && akcs_user_valid(cur->remainder + len)) { /* matched */ cur->succ = *okay; *okay = cur; continue; } } else { /* fill in any user information */ akcs_user_info(cur); /* match only if this is a user */ if (cur->flags&ADDR_ISUSER) { cur->succ = *okay; *okay = cur; continue; } } /* didn't match */ cur->succ = *retry; *retry = cur; } } /* * dtb_user - read the configuration file attributes */ char * dtb_akcs(dp, attrs) struct director *dp; /* director entry being defined */ struct attribute *attrs; /* list of per-driver attributes */ { char *error; static struct attr_table akcs_attributes[] = { { "transport", t_string, NULL, NULL, OFFSET(akcs_private, transport) }, { "prefix", t_string, NULL, NULL, OFFSET(akcs_private, prefix) }, }; static struct attr_table *end_akcs_attributes = ENDTABLE(akcs_attributes); static struct akcs_private akcs_template = { "akcs", NULL, }; struct akcs_private *priv; /* new akcs_private structure */ /* copy the template private data */ priv = (struct akcs_private *)xmalloc(sizeof(*priv)); (void) memcpy((char *)priv, (char *)&akcs_template, sizeof(*priv)); dp->private = (char *)priv; /* fill in the attributes of the private data */ error = fill_attributes((char *)priv, attrs, &dp->flags, akcs_attributes, end_akcs_attributes); if (error) { return error; } else { if (priv->transport == NULL) { return "transport attribute required"; } if (find_transport(priv->transport) == NULL) { return xprintf("unknown transport: %s", priv->transport); } return NULL; } } /* * akcs_user_valid - is the address given valid? * * if the passed field matches a username, return non-zero. * */ int akcs_user_valid(addr) char *addr; /* addr to check */ { char tmp[512]; /* Temporary space */ char usr[32]; /* User space */ FILE *fid, *fid2; char basedir[132]; /* get the AKCS password entry if one exists */ if ((fid = fopen("/etc/akcsparams", "r")) == NULL) { return(0); /* Pass on this one... */ } while (fgets(tmp, 132, fid) != NULL) { if (sscanf(tmp, "Base: %[!-z]", basedir)) { sprintf(tmp, "%s/AKCS.p.users", basedir); if ((fid2 = fopen(tmp, "r")) == NULL) { /* Open user file */ fclose(fid); /* Close parameter file */ return(0); } while (fgets(tmp, 512, fid2) != NULL) { if (!strcmp(usr, addr)) { fclose(fid); /* Close parameter file */ fclose(fid2); return(-1); /* It's ok */ } } fclose(fid2); } } fclose(fid); return(0); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.