📄 udb.c
字号:
/* * Copyright (c) 1983 Eric P. Allman * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#include "sendmail.h"#ifndef lint#ifdef USERDBstatic char sccsid [] = "@(#)udb.c 8.8 (Berkeley) 4/14/94 (with USERDB)";#elsestatic char sccsid [] = "@(#)udb.c 8.8 (Berkeley) 4/14/94 (without USERDB)";#endif#endif#ifdef USERDB#include <errno.h>#include <netdb.h>#include <db.h>#ifdef HESIOD#include <hesiod.h>#endif /* HESIOD *//*** UDB.C -- interface between sendmail and Berkeley User Data Base.**** This depends on the 4.4BSD db package.*/struct udbent{ char *udb_spec; /* string version of spec */ int udb_type; /* type of entry */ char *udb_default; /* default host for outgoing mail */ union { /* type UE_REMOTE -- do remote call for lookup */ struct { struct sockaddr_in _udb_addr; /* address */ int _udb_timeout; /* timeout */ } udb_remote;#define udb_addr udb_u.udb_remote._udb_addr#define udb_timeout udb_u.udb_remote._udb_timeout /* type UE_FORWARD -- forward message to remote */ struct { char *_udb_fwdhost; /* name of forward host */ } udb_forward;#define udb_fwdhost udb_u.udb_forward._udb_fwdhost /* type UE_FETCH -- lookup in local database */ struct { char *_udb_dbname; /* pathname of database */ DB *_udb_dbp; /* open database ptr */ } udb_lookup;#define udb_dbname udb_u.udb_lookup._udb_dbname#define udb_dbp udb_u.udb_lookup._udb_dbp } udb_u;};#define UDB_EOLIST 0 /* end of list */#define UDB_SKIP 1 /* skip this entry */#define UDB_REMOTE 2 /* look up in remote database */#define UDB_DBFETCH 3 /* look up in local database */#define UDB_FORWARD 4 /* forward to remote host */#define UDB_HESIOD 5 /* look up via hesiod */#define MAXUDBENT 10 /* maximum number of UDB entries */struct option{ char *name; char *val;};/*** UDBEXPAND -- look up user in database and expand**** Parameters:** a -- address to expand.** sendq -- pointer to head of sendq to put the expansions in.**** Returns:** EX_TEMPFAIL -- if something "odd" happened -- probably due** to accessing a file on an NFS server that is down.** EX_OK -- otherwise.**** Side Effects:** Modifies sendq.*/int UdbPort = 1616;int UdbTimeout = 10;struct udbent UdbEnts[MAXUDBENT + 1];int UdbSock = -1;bool UdbInitialized = FALSE;intudbexpand(a, sendq, e) register ADDRESS *a; ADDRESS **sendq; register ENVELOPE *e;{ int i; register char *p; DBT key; DBT info; bool breakout; register struct udbent *up; int keylen; int naddrs; char keybuf[MAXKEY]; char buf[BUFSIZ]; if (tTd(28, 1)) printf("udbexpand(%s)\n", a->q_paddr); /* make certain we are supposed to send to this address */ if (bitset(QDONTSEND|QVERIFIED, a->q_flags)) return EX_OK; e->e_to = a->q_paddr; /* on first call, locate the database */ if (!UdbInitialized) { extern int _udbx_init(); if (_udbx_init() == EX_TEMPFAIL) return EX_TEMPFAIL; } /* short circuit the process if no chance of a match */ if (UdbSpec == NULL || UdbSpec[0] == '\0') return EX_OK; /* short circuit name begins with '\\' since it can't possibly match */ if (a->q_user[0] == '\\') return EX_OK; /* if name is too long, assume it won't match */ if (strlen(a->q_user) > sizeof keybuf - 12) return EX_OK; /* if name begins with a colon, it indicates our metadata */ if (a->q_user[0] == ':') return EX_OK; /* build actual database key */ (void) strcpy(keybuf, a->q_user); (void) strcat(keybuf, ":maildrop"); keylen = strlen(keybuf); breakout = FALSE; for (up = UdbEnts; !breakout; up++) { char *user; /* ** Select action based on entry type. ** ** On dropping out of this switch, "class" should ** explain the type of the data, and "user" should ** contain the user information. */ switch (up->udb_type) { case UDB_DBFETCH: key.data = keybuf; key.size = keylen; if (tTd(28, 80)) printf("udbexpand: trying %s (%d) via db\n", keybuf, keylen); i = (*up->udb_dbp->seq)(up->udb_dbp, &key, &info, R_CURSOR); if (i > 0 || info.size <= 0) { if (tTd(28, 2)) printf("udbexpand: no match on %s (%d)\n", keybuf, keylen); continue; } if (tTd(28, 80)) printf("udbexpand: match %.*s: %.*s\n", key.size, key.data, info.size, info.data); naddrs = 0; a->q_flags &= ~QSELFREF; while (i == 0 && key.size == keylen && bcmp(key.data, keybuf, keylen) == 0) { if (bitset(EF_VRFYONLY, e->e_flags)) { a->q_flags |= QVERIFIED; e->e_nrcpts++; return EX_OK; } breakout = TRUE; if (info.size < sizeof buf) user = buf; else user = xalloc(info.size + 1); bcopy(info.data, user, info.size); user[info.size] = '\0'; message("expanded to %s", user);#ifdef LOG if (LogLevel >= 10) syslog(LOG_INFO, "%s: expand %s => %s", e->e_id, e->e_to, user);#endif AliasLevel++; naddrs += sendtolist(user, a, sendq, e); AliasLevel--; if (user != buf) free(user); /* get the next record */ i = (*up->udb_dbp->seq)(up->udb_dbp, &key, &info, R_NEXT); } /* if nothing ever matched, try next database */ if (!breakout) continue; if (naddrs > 0 && !bitset(QSELFREF, a->q_flags)) { if (tTd(28, 5)) { printf("udbexpand: QDONTSEND "); printaddr(a, FALSE); } a->q_flags |= QDONTSEND; } if (i < 0) { syserr("udbexpand: db-get %.*s stat %d", key.size, key.data, i); return EX_TEMPFAIL; } /* ** If this address has a -request address, reflect ** it into the envelope. */ (void) strcpy(keybuf, a->q_user); (void) strcat(keybuf, ":mailsender"); keylen = strlen(keybuf); key.data = keybuf; key.size = keylen; i = (*up->udb_dbp->get)(up->udb_dbp, &key, &info, 0); if (i != 0 || info.size <= 0) break; a->q_owner = xalloc(info.size + 1); bcopy(info.data, a->q_owner, info.size); a->q_owner[info.size] = '\0'; /* announce delivery; NORECEIPT bit set later */ if (e->e_xfp != NULL) { fprintf(e->e_xfp, "Message delivered to mailing list %s\n", a->q_paddr); e->e_flags |= EF_SENDRECEIPT; } break;#ifdef HESIOD case UDB_HESIOD: key.data = keybuf; key.size = keylen; if (tTd(28, 80)) printf("udbexpand: trying %s (%d) via hesiod\n", keybuf, keylen); /* look up the key via hesiod */ i = hes_udb_get(&key, &info); if (i > 0 || info.size <= 0) { if (tTd(28, 2)) printf("udbexpand: no match on %s (%d)\n", keybuf, keylen); continue; } if (tTd(28, 80)) printf("udbexpand: match %.*s: %.*s\n", key.size, key.data, info.size, info.data); a->q_flags &= ~QSELFREF; if (bitset(EF_VRFYONLY, e->e_flags)) { a->q_flags |= QVERIFIED; e->e_nrcpts++; free(info.data); return EX_OK; } breakout = TRUE; if (info.size < sizeof buf) user = buf; else user = xalloc(info.size + 1); bcopy(info.data, user, info.size); user[info.size] = '\0'; free(info.data); message("hesioded to %s", user);#ifdef LOG if (LogLevel >= 10) syslog(LOG_INFO, "%s: hesiod %s => %s", e->e_id, e->e_to, user);#endif AliasLevel++; naddrs = sendtolist(user, a, sendq, e); AliasLevel--; if (user != buf) free(user); if (naddrs > 0 && !bitset(QSELFREF, a->q_flags)) { if (tTd(28, 5)) { printf("udbexpand: QDONTSEND "); printaddr(a, FALSE); } a->q_flags |= QDONTSEND; } if (i < 0) { syserr("udbexpand: hesiod-get %.*s stat %d", key.size, key.data, i); return EX_TEMPFAIL; } /* ** If this address has a -request address, reflect ** it into the envelope. */ (void) strcpy(keybuf, a->q_user); (void) strcat(keybuf, ":mailsender"); keylen = strlen(keybuf); key.data = keybuf; key.size = keylen; i = hes_udb_get(&key, &info); if (i != 0 || info.size <= 0) break; a->q_owner = xalloc(info.size + 1); bcopy(info.data, a->q_owner, info.size); a->q_owner[info.size] = '\0'; free(info.data); break;#endif /* HESIOD */ case UDB_REMOTE: /* not yet implemented */ continue; case UDB_FORWARD: if (bitset(EF_VRFYONLY, e->e_flags)) return EX_OK; i = strlen(up->udb_fwdhost) + strlen(a->q_user) + 1; if (i < sizeof buf) user = buf; else user = xalloc(i + 1); (void) sprintf(user, "%s@%s", a->q_user, up->udb_fwdhost); message("expanded to %s", user); a->q_flags &= ~QSELFREF; AliasLevel++; naddrs = sendtolist(user, a, sendq, e); AliasLevel--; if (naddrs > 0 && !bitset(QSELFREF, a->q_flags)) { if (tTd(28, 5)) { printf("udbexpand: QDONTSEND "); printaddr(a, FALSE); } a->q_flags |= QDONTSEND; } if (user != buf) free(user); breakout = TRUE; break; case UDB_EOLIST: breakout = TRUE; continue; default: /* unknown entry type */ continue; } } return EX_OK;}/*** UDBSENDER -- return canonical external name of sender, given local name**** Parameters:** sender -- the name of the sender on the local machine.**** Returns:** The external name for this sender, if derivable from the** database.** NULL -- if nothing is changed from the database.**** Side Effects:** none.*/char *udbsender(sender) char *sender;{ extern char *udbmatch(); return udbmatch(sender, "mailname");}char *udbmatch(user, field) char *user; char *field;{ register char *p; register struct udbent *up; int i; int keylen; DBT key, info; char keybuf[MAXKEY]; if (tTd(28, 1)) printf("udbmatch(%s, %s)\n", user, field); if (!UdbInitialized) { if (_udbx_init() == EX_TEMPFAIL) return NULL; } /* short circuit if no spec */ if (UdbSpec == NULL || UdbSpec[0] == '\0') return NULL; /* short circuit name begins with '\\' since it can't possibly match */ if (user[0] == '\\') return NULL; /* long names can never match and are a pain to deal with */ if ((strlen(user) + strlen(field)) > sizeof keybuf - 4) return NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -