udb.c
上传用户:xu_441
上传日期:2007-01-04
资源大小:1640k
文件大小:29k
源码类别:

Email客户端

开发平台:

Unix_Linux

  1. /*
  2.  * Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers.
  3.  * All rights reserved.
  4.  * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
  5.  * Copyright (c) 1988, 1993
  6.  * The Regents of the University of California.  All rights reserved.
  7.  *
  8.  * By using this file, you agree to the terms and conditions set
  9.  * forth in the LICENSE file which can be found at the top level of
  10.  * the sendmail distribution.
  11.  *
  12.  */
  13. #include <sendmail.h>
  14. #ifndef lint
  15. # if USERDB
  16. static char id[] = "@(#)$Id: udb.c,v 8.111 1999/11/16 02:04:04 gshapiro Exp $ (with USERDB)";
  17. # else /* USERDB */
  18. static char id[] = "@(#)$Id: udb.c,v 8.111 1999/11/16 02:04:04 gshapiro Exp $ (without USERDB)";
  19. # endif /* USERDB */
  20. #endif /* ! lint */
  21. #if USERDB
  22. # ifdef NEWDB
  23. #  include <db.h>
  24. #  ifndef DB_VERSION_MAJOR
  25. #   define DB_VERSION_MAJOR 1
  26. #  endif /* ! DB_VERSION_MAJOR */
  27. # else /* NEWDB */
  28. #  define DBT struct _data_base_thang_
  29. DBT
  30. {
  31. void *data; /* pointer to data */
  32. size_t size; /* length of data */
  33. };
  34. # endif /* NEWDB */
  35. /*
  36. **  UDB.C -- interface between sendmail and Berkeley User Data Base.
  37. **
  38. ** This depends on the 4.4BSD db package.
  39. */
  40. struct udbent
  41. {
  42. char *udb_spec; /* string version of spec */
  43. int udb_type; /* type of entry */
  44. pid_t udb_pid; /* PID of process which opened db */
  45. char *udb_default; /* default host for outgoing mail */
  46. union
  47. {
  48. # if NETINET || NETINET6
  49. /* type UE_REMOTE -- do remote call for lookup */
  50. struct
  51. {
  52. SOCKADDR _udb_addr; /* address */
  53. int _udb_timeout; /* timeout */
  54. } udb_remote;
  55. #  define udb_addr udb_u.udb_remote._udb_addr
  56. #  define udb_timeout udb_u.udb_remote._udb_timeout
  57. # endif /* NETINET || NETINET6 */
  58. /* type UE_FORWARD -- forward message to remote */
  59. struct
  60. {
  61. char *_udb_fwdhost; /* name of forward host */
  62. } udb_forward;
  63. # define udb_fwdhost udb_u.udb_forward._udb_fwdhost
  64. # ifdef NEWDB
  65. /* type UE_FETCH -- lookup in local database */
  66. struct
  67. {
  68. char *_udb_dbname; /* pathname of database */
  69. DB *_udb_dbp; /* open database ptr */
  70. } udb_lookup;
  71. #  define udb_dbname udb_u.udb_lookup._udb_dbname
  72. #  define udb_dbp udb_u.udb_lookup._udb_dbp
  73. # endif /* NEWDB */
  74. } udb_u;
  75. };
  76. # define UDB_EOLIST 0 /* end of list */
  77. # define UDB_SKIP 1 /* skip this entry */
  78. # define UDB_REMOTE 2 /* look up in remote database */
  79. # define UDB_DBFETCH 3 /* look up in local database */
  80. # define UDB_FORWARD 4 /* forward to remote host */
  81. # define UDB_HESIOD 5 /* look up via hesiod */
  82. # define MAXUDBENT 10 /* maximum number of UDB entries */
  83. struct udb_option
  84. {
  85. char *udbo_name;
  86. char *udbo_val;
  87. };
  88. # ifdef HESIOD
  89. static int hes_udb_get __P((DBT *, DBT *));
  90. # endif /* HESIOD */
  91. static char *udbmatch __P((char *, char *));
  92. static int _udbx_init __P((ENVELOPE *));
  93. static int _udb_parsespec __P((char *, struct udb_option [], int));
  94. /*
  95. **  UDBEXPAND -- look up user in database and expand
  96. **
  97. ** Parameters:
  98. ** a -- address to expand.
  99. ** sendq -- pointer to head of sendq to put the expansions in.
  100. ** aliaslevel -- the current alias nesting depth.
  101. ** e -- the current envelope.
  102. **
  103. ** Returns:
  104. ** EX_TEMPFAIL -- if something "odd" happened -- probably due
  105. ** to accessing a file on an NFS server that is down.
  106. ** EX_OK -- otherwise.
  107. **
  108. ** Side Effects:
  109. ** Modifies sendq.
  110. */
  111. static struct udbent UdbEnts[MAXUDBENT + 1];
  112. static bool UdbInitialized = FALSE;
  113. int
  114. udbexpand(a, sendq, aliaslevel, e)
  115. register ADDRESS *a;
  116. ADDRESS **sendq;
  117. int aliaslevel;
  118. register ENVELOPE *e;
  119. {
  120. int i;
  121. DBT key;
  122. DBT info;
  123. bool breakout;
  124. register struct udbent *up;
  125. int keylen;
  126. int naddrs;
  127. char *user;
  128. char keybuf[MAXKEY];
  129. memset(&key, '', sizeof key);
  130. memset(&info, '', sizeof info);
  131. if (tTd(28, 1))
  132. dprintf("udbexpand(%s)n", a->q_paddr);
  133. /* make certain we are supposed to send to this address */
  134. if (!QS_IS_SENDABLE(a->q_state))
  135. return EX_OK;
  136. e->e_to = a->q_paddr;
  137. /* on first call, locate the database */
  138. if (!UdbInitialized)
  139. {
  140. if (_udbx_init(e) == EX_TEMPFAIL)
  141. return EX_TEMPFAIL;
  142. }
  143. /* short circuit the process if no chance of a match */
  144. if (UdbSpec == NULL || UdbSpec[0] == '')
  145. return EX_OK;
  146. /* extract user to do userdb matching on */
  147. user = a->q_user;
  148. /* short circuit name begins with '\' since it can't possibly match */
  149. /* (might want to treat this as unquoted instead) */
  150. if (user[0] == '\')
  151. return EX_OK;
  152. /* if name is too long, assume it won't match */
  153. if (strlen(user) > (SIZE_T) sizeof keybuf - 12)
  154. return EX_OK;
  155. /* if name begins with a colon, it indicates our metadata */
  156. if (user[0] == ':')
  157. return EX_OK;
  158. /* build actual database key */
  159. (void) strlcpy(keybuf, user, sizeof keybuf);
  160. (void) strlcat(keybuf, ":maildrop", sizeof keybuf);
  161. keylen = strlen(keybuf);
  162. breakout = FALSE;
  163. for (up = UdbEnts; !breakout; up++)
  164. {
  165. int usersize;
  166. int userleft;
  167. char userbuf[MEMCHUNKSIZE];
  168. # if defined(HESIOD) && defined(HES_GETMAILHOST)
  169. char pobuf[MAXNAME];
  170. # endif /* defined(HESIOD) && defined(HES_GETMAILHOST) */
  171. # if defined(NEWDB) && DB_VERSION_MAJOR > 1
  172. DBC *dbc = NULL;
  173. # endif /* defined(NEWDB) && DB_VERSION_MAJOR > 1 */
  174. user = userbuf;
  175. userbuf[0] = '';
  176. usersize = sizeof userbuf;
  177. userleft = sizeof userbuf - 1;
  178. /*
  179. **  Select action based on entry type.
  180. **
  181. ** On dropping out of this switch, "class" should
  182. ** explain the type of the data, and "user" should
  183. ** contain the user information.
  184. */
  185. switch (up->udb_type)
  186. {
  187. # ifdef NEWDB
  188.   case UDB_DBFETCH:
  189. key.data = keybuf;
  190. key.size = keylen;
  191. if (tTd(28, 80))
  192. dprintf("udbexpand: trying %s (%d) via dbn",
  193. keybuf, keylen);
  194. #  if DB_VERSION_MAJOR < 2
  195. i = (*up->udb_dbp->seq)(up->udb_dbp, &key, &info, R_CURSOR);
  196. #  else /* DB_VERSION_MAJOR < 2 */
  197. i = 0;
  198. if (dbc == NULL &&
  199. #   if DB_VERSION_MAJOR > 2 || DB_VERSION_MINOR >= 6
  200.     (errno = (*up->udb_dbp->cursor)(up->udb_dbp,
  201.     NULL, &dbc, 0)) != 0)
  202. #   else /* DB_VERSION_MAJOR > 2 || DB_VERSION_MINOR >= 6 */
  203.     (errno = (*up->udb_dbp->cursor)(up->udb_dbp,
  204.     NULL, &dbc)) != 0)
  205. #   endif /* DB_VERSION_MAJOR > 2 || DB_VERSION_MINOR >= 6 */
  206. i = -1;
  207. if (i != 0 || dbc == NULL ||
  208.     (errno = dbc->c_get(dbc, &key,
  209. &info, DB_SET)) != 0)
  210. i = 1;
  211. #  endif /* DB_VERSION_MAJOR < 2 */
  212. if (i > 0 || info.size <= 0)
  213. {
  214. if (tTd(28, 2))
  215. dprintf("udbexpand: no match on %s (%d)n",
  216. keybuf, keylen);
  217. #  if DB_VERSION_MAJOR > 1
  218. if (dbc != NULL)
  219. {
  220. (void) dbc->c_close(dbc);
  221. dbc = NULL;
  222. }
  223. #  endif /* DB_VERSION_MAJOR > 1 */
  224. break;
  225. }
  226. if (tTd(28, 80))
  227. dprintf("udbexpand: match %.*s: %.*sn",
  228. (int) key.size, (char *) key.data,
  229. (int) info.size, (char *) info.data);
  230. a->q_flags &= ~QSELFREF;
  231. while (i == 0 && key.size == keylen &&
  232.        memcmp(key.data, keybuf, keylen) == 0)
  233. {
  234. char *p;
  235. if (bitset(EF_VRFYONLY, e->e_flags))
  236. {
  237. a->q_state = QS_VERIFIED;
  238. #  if DB_VERSION_MAJOR > 1
  239. if (dbc != NULL)
  240. {
  241. (void) dbc->c_close(dbc);
  242. dbc = NULL;
  243. }
  244. #  endif /* DB_VERSION_MAJOR > 1 */
  245. return EX_OK;
  246. }
  247. breakout = TRUE;
  248. if (info.size >= userleft - 1)
  249. {
  250. char *nuser;
  251. int size = MEMCHUNKSIZE;
  252. if (info.size > MEMCHUNKSIZE)
  253. size = info.size;
  254. nuser = xalloc(usersize + size);
  255. memmove(nuser, user, usersize);
  256. if (user != userbuf)
  257. free(user);
  258. user = nuser;
  259. usersize += size;
  260. userleft += size;
  261. }
  262. p = &user[strlen(user)];
  263. if (p != user)
  264. {
  265. *p++ = ',';
  266. userleft--;
  267. }
  268. memmove(p, info.data, info.size);
  269. p[info.size] = '';
  270. userleft -= info.size;
  271. /* get the next record */
  272. #  if DB_VERSION_MAJOR < 2
  273. i = (*up->udb_dbp->seq)(up->udb_dbp, &key, &info, R_NEXT);
  274. #  else /* DB_VERSION_MAJOR < 2 */
  275. i = 0;
  276. if ((errno = dbc->c_get(dbc, &key,
  277. &info, DB_NEXT)) != 0)
  278. i = 1;
  279. #  endif /* DB_VERSION_MAJOR < 2 */
  280. }
  281. #  if DB_VERSION_MAJOR > 1
  282. if (dbc != NULL)
  283. {
  284. (void) dbc->c_close(dbc);
  285. dbc = NULL;
  286. }
  287. #  endif /* DB_VERSION_MAJOR > 1 */
  288. /* if nothing ever matched, try next database */
  289. if (!breakout)
  290. break;
  291. message("expanded to %s", user);
  292. if (LogLevel > 10)
  293. sm_syslog(LOG_INFO, e->e_id,
  294.   "expand %.100s => %s",
  295.   e->e_to,
  296.   shortenstring(user, MAXSHORTSTR));
  297. naddrs = sendtolist(user, a, sendq, aliaslevel + 1, e);
  298. if (naddrs > 0 && !bitset(QSELFREF, a->q_flags))
  299. {
  300. if (tTd(28, 5))
  301. {
  302. dprintf("udbexpand: QS_EXPANDED ");
  303. printaddr(a, FALSE);
  304. }
  305. a->q_state = QS_EXPANDED;
  306. }
  307. if (i < 0)
  308. {
  309. syserr("udbexpand: db-get %.*s stat %d",
  310. (int) key.size, (char *) key.data, i);
  311. return EX_TEMPFAIL;
  312. }
  313. /*
  314. **  If this address has a -request address, reflect
  315. **  it into the envelope.
  316. */
  317. memset(&key, '', sizeof key);
  318. memset(&info, '', sizeof info);
  319. (void) strlcpy(keybuf, a->q_user, sizeof keybuf);
  320. (void) strlcat(keybuf, ":mailsender", sizeof keybuf);
  321. keylen = strlen(keybuf);
  322. key.data = keybuf;
  323. key.size = keylen;
  324. #  if DB_VERSION_MAJOR < 2
  325. i = (*up->udb_dbp->get)(up->udb_dbp, &key, &info, 0);
  326. #  else /* DB_VERSION_MAJOR < 2 */
  327. i = errno = (*up->udb_dbp->get)(up->udb_dbp, NULL,
  328. &key, &info, 0);
  329. #  endif /* DB_VERSION_MAJOR < 2 */
  330. if (i != 0 || info.size <= 0)
  331. break;
  332. a->q_owner = xalloc(info.size + 1);
  333. memmove(a->q_owner, info.data, info.size);
  334. a->q_owner[info.size] = '';
  335. /* announce delivery; NORECEIPT bit set later */
  336. if (e->e_xfp != NULL)
  337. {
  338. fprintf(e->e_xfp,
  339. "Message delivered to mailing list %sn",
  340. a->q_paddr);
  341. }
  342. e->e_flags |= EF_SENDRECEIPT;
  343. a->q_flags |= QDELIVERED|QEXPANDED;
  344. break;
  345. # endif /* NEWDB */
  346. # ifdef HESIOD
  347.   case UDB_HESIOD:
  348. key.data = keybuf;
  349. key.size = keylen;
  350. if (tTd(28, 80))
  351. dprintf("udbexpand: trying %s (%d) via hesiodn",
  352. keybuf, keylen);
  353. /* look up the key via hesiod */
  354. i = hes_udb_get(&key, &info);
  355. if (i < 0)
  356. {
  357. syserr("udbexpand: hesiod-get %.*s stat %d",
  358. (int) key.size, (char *) key.data, i);
  359. return EX_TEMPFAIL;
  360. }
  361. else if (i > 0 || info.size <= 0)
  362. {
  363. #  if HES_GETMAILHOST
  364. struct hes_postoffice *hp;
  365. #  endif /* HES_GETMAILHOST */
  366. if (tTd(28, 2))
  367. dprintf("udbexpand: no match on %s (%d)n",
  368. (char *) keybuf, (int) keylen);
  369. #  if HES_GETMAILHOST
  370. if (tTd(28, 8))
  371. dprintf("  ... trying hes_getmailhost(%s)n",
  372. a->q_user);
  373. hp = hes_getmailhost(a->q_user);
  374. if (hp == NULL)
  375. {
  376. if (hes_error() == HES_ER_NET)
  377. {
  378. syserr("udbexpand: hesiod-getmail %s stat %d",
  379. a->q_user, hes_error());
  380. return EX_TEMPFAIL;
  381. }
  382. if (tTd(28, 2))
  383. dprintf("hes_getmailhost(%s): %dn",
  384. a->q_user, hes_error());
  385. break;
  386. }
  387. if (strlen(hp->po_name) + strlen(hp->po_host) >
  388.     sizeof pobuf - 2)
  389. {
  390. if (tTd(28, 2))
  391. dprintf("hes_getmailhost(%s): expansion too long: %.30s@%.30sn",
  392. a->q_user,
  393. hp->po_name,
  394. hp->po_host);
  395. break;
  396. }
  397. info.data = pobuf;
  398. snprintf(pobuf, sizeof pobuf, "%s@%s",
  399. hp->po_name, hp->po_host);
  400. info.size = strlen(info.data);
  401. #  else /* HES_GETMAILHOST */
  402. break;
  403. #  endif /* HES_GETMAILHOST */
  404. }
  405. if (tTd(28, 80))
  406. dprintf("udbexpand: match %.*s: %.*sn",
  407. (int) key.size, (char *) key.data,
  408. (int) info.size, (char *) info.data);
  409. a->q_flags &= ~QSELFREF;
  410. if (bitset(EF_VRFYONLY, e->e_flags))
  411. {
  412. a->q_state = QS_VERIFIED;
  413. return EX_OK;
  414. }
  415. breakout = TRUE;
  416. if (info.size >= usersize)
  417. user = xalloc(info.size + 1);
  418. memmove(user, info.data, info.size);
  419. user[info.size] = '';
  420. message("hesioded to %s", user);
  421. if (LogLevel > 10)
  422. sm_syslog(LOG_INFO, e->e_id,
  423.   "hesiod %.100s => %s",
  424.   e->e_to,
  425.   shortenstring(user, MAXSHORTSTR));
  426. naddrs = sendtolist(user, a, sendq, aliaslevel + 1, e);
  427. if (naddrs > 0 && !bitset(QSELFREF, a->q_flags))
  428. {
  429. if (tTd(28, 5))
  430. {
  431. dprintf("udbexpand: QS_EXPANDED ");
  432. printaddr(a, FALSE);
  433. }
  434. a->q_state = QS_EXPANDED;
  435. }
  436. /*
  437. **  If this address has a -request address, reflect
  438. **  it into the envelope.
  439. */
  440. (void) strlcpy(keybuf, a->q_user, sizeof keybuf);
  441. (void) strlcat(keybuf, ":mailsender", sizeof keybuf);
  442. keylen = strlen(keybuf);
  443. key.data = keybuf;
  444. key.size = keylen;
  445. i = hes_udb_get(&key, &info);
  446. if (i != 0 || info.size <= 0)
  447. break;
  448. a->q_owner = xalloc(info.size + 1);
  449. memmove(a->q_owner, info.data, info.size);
  450. a->q_owner[info.size] = '';
  451. break;
  452. # endif /* HESIOD */
  453.   case UDB_REMOTE:
  454. /* not yet implemented */
  455. break;
  456.   case UDB_FORWARD:
  457. if (bitset(EF_VRFYONLY, e->e_flags))
  458. {
  459. a->q_state = QS_VERIFIED;
  460. return EX_OK;
  461. }
  462. i = strlen(up->udb_fwdhost) + strlen(a->q_user) + 1;
  463. if (i >= usersize)
  464. {
  465. usersize = i + 1;
  466. user = xalloc(usersize);
  467. }
  468. (void) snprintf(user, usersize, "%s@%s",
  469. a->q_user, up->udb_fwdhost);
  470. message("expanded to %s", user);
  471. a->q_flags &= ~QSELFREF;
  472. naddrs = sendtolist(user, a, sendq, aliaslevel + 1, e);
  473. if (naddrs > 0 && !bitset(QSELFREF, a->q_flags))
  474. {
  475. if (tTd(28, 5))
  476. {
  477. dprintf("udbexpand: QS_EXPANDED ");
  478. printaddr(a, FALSE);
  479. }
  480. a->q_state = QS_EXPANDED;
  481. }
  482. breakout = TRUE;
  483. break;
  484.   case UDB_EOLIST:
  485. breakout = TRUE;
  486. break;
  487.   default:
  488. /* unknown entry type */
  489. break;
  490. }
  491. if (user != userbuf)
  492. free(user);
  493. }
  494. return EX_OK;
  495. }
  496. /*
  497. **  UDBSENDER -- return canonical external name of sender, given local name
  498. **
  499. ** Parameters:
  500. ** sender -- the name of the sender on the local machine.
  501. **
  502. ** Returns:
  503. ** The external name for this sender, if derivable from the
  504. ** database.
  505. ** NULL -- if nothing is changed from the database.
  506. **
  507. ** Side Effects:
  508. ** none.
  509. */
  510. char *
  511. udbsender(sender)
  512. char *sender;
  513. {
  514. return udbmatch(sender, "mailname");
  515. }
  516. /*
  517. **  UDBMATCH -- match user in field, return result of lookup.
  518. **
  519. ** Parameters:
  520. ** user -- the name of the user.
  521. ** field -- the field to lookup.
  522. **
  523. ** Returns:
  524. ** The external name for this sender, if derivable from the
  525. ** database.
  526. ** NULL -- if nothing is changed from the database.
  527. **
  528. ** Side Effects:
  529. ** none.
  530. */
  531. static char *
  532. udbmatch(user, field)
  533. char *user;
  534. char *field;
  535. {
  536. register char *p;
  537. register struct udbent *up;
  538. int i;
  539. int keylen;
  540. DBT key, info;
  541. char keybuf[MAXKEY];
  542. if (tTd(28, 1))
  543. dprintf("udbmatch(%s, %s)n", user, field);
  544. if (!UdbInitialized)
  545. {
  546. if (_udbx_init(CurEnv) == EX_TEMPFAIL)
  547. return NULL;
  548. }
  549. /* short circuit if no spec */
  550. if (UdbSpec == NULL || UdbSpec[0] == '')
  551. return NULL;
  552. /* short circuit name begins with '\' since it can't possibly match */
  553. if (user[0] == '\')
  554. return NULL;
  555. /* long names can never match and are a pain to deal with */
  556. i = strlen(field);
  557. if (i < sizeof "maildrop")
  558. i = sizeof "maildrop";
  559. if ((strlen(user) + i) > sizeof keybuf - 4)
  560. return NULL;
  561. /* names beginning with colons indicate metadata */
  562. if (user[0] == ':')
  563. return NULL;
  564. /* build database key */
  565. (void) snprintf(keybuf, sizeof keybuf, "%s:%s", user, field);
  566. keylen = strlen(keybuf);
  567. for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
  568. {
  569. /*
  570. **  Select action based on entry type.
  571. */
  572. switch (up->udb_type)
  573. {
  574. # ifdef NEWDB
  575.   case UDB_DBFETCH:
  576. memset(&key, '', sizeof key);
  577. memset(&info, '', sizeof info);
  578. key.data = keybuf;
  579. key.size = keylen;
  580. #  if DB_VERSION_MAJOR < 2
  581. i = (*up->udb_dbp->get)(up->udb_dbp, &key, &info, 0);
  582. #  else /* DB_VERSION_MAJOR < 2 */
  583. i = errno = (*up->udb_dbp->get)(up->udb_dbp, NULL,
  584. &key, &info, 0);
  585. #  endif /* DB_VERSION_MAJOR < 2 */
  586. if (i != 0 || info.size <= 0)
  587. {
  588. if (tTd(28, 2))
  589. dprintf("udbmatch: no match on %s (%d) via dbn",
  590. keybuf, keylen);
  591. continue;
  592. }
  593. p = xalloc(info.size + 1);
  594. memmove(p, info.data, info.size);
  595. p[info.size] = '';
  596. if (tTd(28, 1))
  597. dprintf("udbmatch ==> %sn", p);
  598. return p;
  599. # endif /* NEWDB */
  600. # ifdef HESIOD
  601.   case UDB_HESIOD:
  602. key.data = keybuf;
  603. key.size = keylen;
  604. i = hes_udb_get(&key, &info);
  605. if (i != 0 || info.size <= 0)
  606. {
  607. if (tTd(28, 2))
  608. dprintf("udbmatch: no match on %s (%d) via hesiodn",
  609. keybuf, keylen);
  610. continue;
  611. }
  612. p = xalloc(info.size + 1);
  613. memmove(p, info.data, info.size);
  614. p[info.size] = '';
  615. if (tTd(28, 1))
  616. dprintf("udbmatch ==> %sn", p);
  617. return p;
  618. # endif /* HESIOD */
  619. }
  620. }
  621. if (strcmp(field, "mailname") != 0)
  622. return NULL;
  623. /*
  624. **  Nothing yet.  Search again for a default case.  But only
  625. **  use it if we also have a forward (:maildrop) pointer already
  626. **  in the database.
  627. */
  628. /* build database key */
  629. (void) strlcpy(keybuf, user, sizeof keybuf);
  630. (void) strlcat(keybuf, ":maildrop", sizeof keybuf);
  631. keylen = strlen(keybuf);
  632. for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
  633. {
  634. switch (up->udb_type)
  635. {
  636. # ifdef NEWDB
  637.   case UDB_DBFETCH:
  638. /* get the default case for this database */
  639. if (up->udb_default == NULL)
  640. {
  641. memset(&key, '', sizeof key);
  642. memset(&info, '', sizeof info);
  643. key.data = ":default:mailname";
  644. key.size = strlen(key.data);
  645. #  if DB_VERSION_MAJOR < 2
  646. i = (*up->udb_dbp->get)(up->udb_dbp,
  647. &key, &info, 0);
  648. #  else /* DB_VERSION_MAJOR < 2 */
  649. i = errno = (*up->udb_dbp->get)(up->udb_dbp,
  650. NULL, &key,
  651. &info, 0);
  652. #  endif /* DB_VERSION_MAJOR < 2 */
  653. if (i != 0 || info.size <= 0)
  654. {
  655. /* no default case */
  656. up->udb_default = "";
  657. continue;
  658. }
  659. /* save the default case */
  660. up->udb_default = xalloc(info.size + 1);
  661. memmove(up->udb_default, info.data, info.size);
  662. up->udb_default[info.size] = '';
  663. }
  664. else if (up->udb_default[0] == '')
  665. continue;
  666. /* we have a default case -- verify user:maildrop */
  667. memset(&key, '', sizeof key);
  668. memset(&info, '', sizeof info);
  669. key.data = keybuf;
  670. key.size = keylen;
  671. #  if DB_VERSION_MAJOR < 2
  672. i = (*up->udb_dbp->get)(up->udb_dbp, &key, &info, 0);
  673. #  else /* DB_VERSION_MAJOR < 2 */
  674. i = errno = (*up->udb_dbp->get)(up->udb_dbp, NULL,
  675. &key, &info, 0);
  676. #  endif /* DB_VERSION_MAJOR < 2 */
  677. if (i != 0 || info.size <= 0)
  678. {
  679. /* nope -- no aliasing for this user */
  680. continue;
  681. }
  682. /* they exist -- build the actual address */
  683. i = strlen(user) + strlen(up->udb_default) + 2;
  684. p = xalloc(i);
  685. (void) snprintf(p, i, "%s@%s", user, up->udb_default);
  686. if (tTd(28, 1))
  687. dprintf("udbmatch ==> %sn", p);
  688. return p;
  689. # endif /* NEWDB */
  690. # ifdef HESIOD
  691.   case UDB_HESIOD:
  692. /* get the default case for this database */
  693. if (up->udb_default == NULL)
  694. {
  695. key.data = ":default:mailname";
  696. key.size = strlen(key.data);
  697. i = hes_udb_get(&key, &info);
  698. if (i != 0 || info.size <= 0)
  699. {
  700. /* no default case */
  701. up->udb_default = "";
  702. continue;
  703. }
  704. /* save the default case */
  705. up->udb_default = xalloc(info.size + 1);
  706. memmove(up->udb_default, info.data, info.size);
  707. up->udb_default[info.size] = '';
  708. }
  709. else if (up->udb_default[0] == '')
  710. continue;
  711. /* we have a default case -- verify user:maildrop */
  712. key.data = keybuf;
  713. key.size = keylen;
  714. i = hes_udb_get(&key, &info);
  715. if (i != 0 || info.size <= 0)
  716. {
  717. /* nope -- no aliasing for this user */
  718. continue;
  719. }
  720. /* they exist -- build the actual address */
  721. i = strlen(user) + strlen(up->udb_default) + 2;
  722. p = xalloc(i);
  723. (void) snprintf(p, i, "%s@%s", user, up->udb_default);
  724. if (tTd(28, 1))
  725. dprintf("udbmatch ==> %sn", p);
  726. return p;
  727. break;
  728. # endif /* HESIOD */
  729. }
  730. }
  731. /* still nothing....  too bad */
  732. return NULL;
  733. }
  734. /*
  735. **  UDB_MAP_LOOKUP -- look up arbitrary entry in user database map
  736. **
  737. ** Parameters:
  738. ** map -- the map being queried.
  739. ** name -- the name to look up.
  740. ** av -- arguments to the map lookup.
  741. ** statp -- to get any error status.
  742. **
  743. ** Returns:
  744. ** NULL if name not found in map.
  745. ** The rewritten name otherwise.
  746. */
  747. /* ARGSUSED3 */
  748. char *
  749. udb_map_lookup(map, name, av, statp)
  750. MAP *map;
  751. char *name;
  752. char **av;
  753. int *statp;
  754. {
  755. char *val;
  756. char *key;
  757. char keybuf[MAXNAME + 1];
  758. if (tTd(28, 20) || tTd(38, 20))
  759. dprintf("udb_map_lookup(%s, %s)n", map->map_mname, name);
  760. if (bitset(MF_NOFOLDCASE, map->map_mflags))
  761. {
  762. key = name;
  763. }
  764. else
  765. {
  766. int keysize = strlen(name);
  767. if (keysize > sizeof keybuf - 1)
  768. keysize = sizeof keybuf - 1;
  769. memmove(keybuf, name, keysize);
  770. keybuf[keysize] = '';
  771. makelower(keybuf);
  772. key = keybuf;
  773. }
  774. val = udbmatch(key, map->map_file);
  775. if (val == NULL)
  776. return NULL;
  777. if (bitset(MF_MATCHONLY, map->map_mflags))
  778. return map_rewrite(map, name, strlen(name), NULL);
  779. else
  780. return map_rewrite(map, val, strlen(val), av);
  781. }
  782. /*
  783. **  _UDBX_INIT -- parse the UDB specification, opening any valid entries.
  784. **
  785. ** Parameters:
  786. ** e -- the current envelope.
  787. **
  788. ** Returns:
  789. ** EX_TEMPFAIL -- if it appeared it couldn't get hold of a
  790. ** database due to a host being down or some similar
  791. ** (recoverable) situation.
  792. ** EX_OK -- otherwise.
  793. **
  794. ** Side Effects:
  795. ** Fills in the UdbEnts structure from UdbSpec.
  796. */
  797. # define MAXUDBOPTS 27
  798. static int
  799. _udbx_init(e)
  800. ENVELOPE *e;
  801. {
  802. int ents = 0;
  803. register char *p;
  804. register struct udbent *up;
  805. if (UdbInitialized)
  806. return EX_OK;
  807. # ifdef UDB_DEFAULT_SPEC
  808. if (UdbSpec == NULL)
  809. UdbSpec = UDB_DEFAULT_SPEC;
  810. # endif /* UDB_DEFAULT_SPEC */
  811. p = UdbSpec;
  812. up = UdbEnts;
  813. while (p != NULL)
  814. {
  815. char *spec;
  816. int l;
  817. struct udb_option opts[MAXUDBOPTS + 1];
  818. while (*p == ' ' || *p == 't' || *p == ',')
  819. p++;
  820. if (*p == '')
  821. break;
  822. spec = p;
  823. p = strchr(p, ',');
  824. if (p != NULL)
  825. *p++ = '';
  826. if (ents >= MAXUDBENT)
  827. {
  828. syserr("Maximum number of UDB entries exceeded");
  829. break;
  830. }
  831. /* extract options */
  832. (void) _udb_parsespec(spec, opts, MAXUDBOPTS);
  833. /*
  834. **  Decode database specification.
  835. **
  836. ** In the sendmail tradition, the leading character
  837. ** defines the semantics of the rest of the entry.
  838. **
  839. ** @hostname -- forward email to the indicated host.
  840. ** This should be the last in the list,
  841. ** since it always matches the input.
  842. ** /dbname  -- search the named database on the local
  843. ** host using the Berkeley db package.
  844. ** Hesiod -- search the named database with BIND
  845. ** using the MIT Hesiod package.
  846. */
  847. switch (*spec)
  848. {
  849.   case '@': /* forward to remote host */
  850. up->udb_type = UDB_FORWARD;
  851. up->udb_pid = getpid();
  852. up->udb_fwdhost = spec + 1;
  853. ents++;
  854. up++;
  855. break;
  856. # ifdef HESIOD
  857.   case 'h': /* use hesiod */
  858.   case 'H':
  859. if (strcasecmp(spec, "hesiod") != 0)
  860. goto badspec;
  861. up->udb_type = UDB_HESIOD;
  862. up->udb_pid = getpid();
  863. ents++;
  864. up++;
  865. break;
  866. # endif /* HESIOD */
  867. # ifdef NEWDB
  868.   case '/': /* look up remote name */
  869. l = strlen(spec);
  870. if (l > 3 && strcmp(&spec[l - 3], ".db") == 0)
  871. {
  872. up->udb_dbname = spec;
  873. }
  874. else
  875. {
  876. up->udb_dbname = xalloc(l + 4);
  877. (void) strlcpy(up->udb_dbname, spec, l + 4);
  878. (void) strlcat(up->udb_dbname, ".db", l + 4);
  879. }
  880. errno = 0;
  881. #  if DB_VERSION_MAJOR < 2
  882. up->udb_dbp = dbopen(up->udb_dbname, O_RDONLY,
  883.      0644, DB_BTREE, NULL);
  884. #  else /* DB_VERSION_MAJOR < 2 */
  885. {
  886. int flags = DB_RDONLY;
  887. #  if DB_VERSION_MAJOR > 2
  888. int ret;
  889. #  endif /* DB_VERSION_MAJOR > 2 */
  890. #  if !HASFLOCK && defined(DB_FCNTL_LOCKING)
  891. flags |= DB_FCNTL_LOCKING;
  892. #  endif /* !HASFLOCK && defined(DB_FCNTL_LOCKING) */
  893. up->udb_dbp = NULL;
  894. #  if DB_VERSION_MAJOR > 2
  895. ret = db_create(&up->udb_dbp, NULL, 0);
  896. if (ret != 0)
  897. {
  898. (void) up->udb_dbp->close(up->udb_dbp,
  899.   0);
  900. up->udb_dbp = NULL;
  901. }
  902. else
  903. {
  904. ret = up->udb_dbp->open(up->udb_dbp,
  905. up->udb_dbname,
  906. NULL,
  907. DB_BTREE,
  908. flags,
  909. 0644);
  910. if (ret != 0)
  911. {
  912. (void) up->udb_dbp->close(up->udb_dbp, 0);
  913. up->udb_dbp = NULL;
  914. }
  915. }
  916. errno = ret;
  917. #  else /* DB_VERSION_MAJOR > 2 */
  918. errno = db_open(up->udb_dbname, DB_BTREE,
  919. flags, 0644, NULL,
  920. NULL, &up->udb_dbp);
  921. #  endif /* DB_VERSION_MAJOR > 2 */
  922. }
  923. #  endif /* DB_VERSION_MAJOR < 2 */
  924. if (up->udb_dbp == NULL)
  925. {
  926. if (tTd(28, 1))
  927. {
  928. int save_errno = errno;
  929. #  if DB_VERSION_MAJOR < 2
  930. dprintf("dbopen(%s): %sn",
  931. #  else /* DB_VERSION_MAJOR < 2 */
  932. dprintf("db_open(%s): %sn",
  933. #  endif /* DB_VERSION_MAJOR < 2 */
  934. up->udb_dbname,
  935. errstring(errno));
  936. errno = save_errno;
  937. }
  938. if (errno != ENOENT && errno != EACCES)
  939. {
  940. if (LogLevel > 2)
  941. sm_syslog(LOG_ERR, e->e_id,
  942. #  if DB_VERSION_MAJOR < 2
  943.   "dbopen(%s): %s",
  944. #  else /* DB_VERSION_MAJOR < 2 */
  945.   "db_open(%s): %s",
  946. #  endif /* DB_VERSION_MAJOR < 2 */
  947.   up->udb_dbname,
  948.   errstring(errno));
  949. up->udb_type = UDB_EOLIST;
  950. if (up->udb_dbname != spec)
  951. free(up->udb_dbname);
  952. goto tempfail;
  953. }
  954. if (up->udb_dbname != spec)
  955. free(up->udb_dbname);
  956. break;
  957. }
  958. if (tTd(28, 1))
  959. {
  960. #  if DB_VERSION_MAJOR < 2
  961. dprintf("_udbx_init: dbopen(%s)n",
  962. #  else /* DB_VERSION_MAJOR < 2 */
  963. dprintf("_udbx_init: db_open(%s)n",
  964. #  endif /* DB_VERSION_MAJOR < 2 */
  965. up->udb_dbname);
  966. }
  967. up->udb_type = UDB_DBFETCH;
  968. up->udb_pid = getpid();
  969. ents++;
  970. up++;
  971. break;
  972. # endif /* NEWDB */
  973.   default:
  974. # ifdef HESIOD
  975. badspec:
  976. # endif /* HESIOD */
  977. syserr("Unknown UDB spec %s", spec);
  978. break;
  979. }
  980. }
  981. up->udb_type = UDB_EOLIST;
  982. if (tTd(28, 4))
  983. {
  984. for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
  985. {
  986. switch (up->udb_type)
  987. {
  988. # if DAEMON
  989.   case UDB_REMOTE:
  990. dprintf("REMOTE: addr %s, timeo %dn",
  991. anynet_ntoa((SOCKADDR *) &up->udb_addr),
  992. up->udb_timeout);
  993. break;
  994. # endif /* DAEMON */
  995.   case UDB_DBFETCH:
  996. # ifdef NEWDB
  997. dprintf("FETCH: file %sn",
  998. up->udb_dbname);
  999. # else /* NEWDB */
  1000. dprintf("FETCHn");
  1001. # endif /* NEWDB */
  1002. break;
  1003.   case UDB_FORWARD:
  1004. dprintf("FORWARD: host %sn",
  1005. up->udb_fwdhost);
  1006. break;
  1007.   case UDB_HESIOD:
  1008. dprintf("HESIODn");
  1009. break;
  1010.   default:
  1011. dprintf("UNKNOWNn");
  1012. break;
  1013. }
  1014. }
  1015. }
  1016. UdbInitialized = TRUE;
  1017. errno = 0;
  1018. return EX_OK;
  1019. /*
  1020. **  On temporary failure, back out anything we've already done
  1021. */
  1022.   tempfail:
  1023. # ifdef NEWDB
  1024. for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
  1025. {
  1026. if (up->udb_type == UDB_DBFETCH)
  1027. {
  1028. #  if DB_VERSION_MAJOR < 2
  1029. (*up->udb_dbp->close)(up->udb_dbp);
  1030. #  else /* DB_VERSION_MAJOR < 2 */
  1031. errno = (*up->udb_dbp->close)(up->udb_dbp, 0);
  1032. #  endif /* DB_VERSION_MAJOR < 2 */
  1033. if (tTd(28, 1))
  1034. dprintf("_udbx_init: db->close(%s)n",
  1035. up->udb_dbname);
  1036. }
  1037. }
  1038. # endif /* NEWDB */
  1039. return EX_TEMPFAIL;
  1040. }
  1041. static int
  1042. _udb_parsespec(udbspec, opt, maxopts)
  1043. char *udbspec;
  1044. struct udb_option opt[];
  1045. int maxopts;
  1046. {
  1047. register char *spec;
  1048. register char *spec_end;
  1049. register int optnum;
  1050. spec_end = strchr(udbspec, ':');
  1051. for (optnum = 0; optnum < maxopts && (spec = spec_end) != NULL; optnum++)
  1052. {
  1053. register char *p;
  1054. while (isascii(*spec) && isspace(*spec))
  1055. spec++;
  1056. spec_end = strchr(spec, ':');
  1057. if (spec_end != NULL)
  1058. *spec_end++ = '';
  1059. opt[optnum].udbo_name = spec;
  1060. opt[optnum].udbo_val = NULL;
  1061. p = strchr(spec, '=');
  1062. if (p != NULL)
  1063. opt[optnum].udbo_val = ++p;
  1064. }
  1065. return optnum;
  1066. }
  1067. /*
  1068. **  _UDBX_CLOSE -- close all file based UDB entries.
  1069. **
  1070. ** Parameters:
  1071. ** none
  1072. **
  1073. ** Returns:
  1074. ** none
  1075. */
  1076. void
  1077. _udbx_close()
  1078. {
  1079. pid_t pid;
  1080. struct udbent *up;
  1081. if (!UdbInitialized)
  1082. return;
  1083. pid = getpid();
  1084. for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
  1085. {
  1086. if (up->udb_pid != pid)
  1087. continue;
  1088. # ifdef NEWDB
  1089. if (up->udb_type == UDB_DBFETCH)
  1090. {
  1091. #  if DB_VERSION_MAJOR < 2
  1092. (*up->udb_dbp->close)(up->udb_dbp);
  1093. #  else /* DB_VERSION_MAJOR < 2 */
  1094. errno = (*up->udb_dbp->close)(up->udb_dbp, 0);
  1095. #  endif /* DB_VERSION_MAJOR < 2 */
  1096. }
  1097. if (tTd(28, 1))
  1098. dprintf("_udbx_init: db->close(%s)n",
  1099. up->udb_dbname);
  1100. # endif /* NEWDB */
  1101. }
  1102. }
  1103. # ifdef HESIOD
  1104. static int
  1105. hes_udb_get(key, info)
  1106. DBT *key;
  1107. DBT *info;
  1108. {
  1109. char *name, *type;
  1110. char **hp;
  1111. char kbuf[MAXKEY + 1];
  1112. if (strlcpy(kbuf, key->data, sizeof kbuf) >= (SIZE_T) sizeof kbuf)
  1113. return 0;
  1114. name = kbuf;
  1115. type = strrchr(name, ':');
  1116. if (type == NULL)
  1117. return 1;
  1118. *type++ = '';
  1119. if (strchr(name, '@') != NULL)
  1120. return 1;
  1121. if (tTd(28, 1))
  1122. dprintf("hes_udb_get(%s, %s)n", name, type);
  1123. /* make the hesiod query */
  1124. #  ifdef HESIOD_INIT
  1125. if (HesiodContext == NULL && hesiod_init(&HesiodContext) != 0)
  1126. return -1;
  1127. hp = hesiod_resolve(HesiodContext, name, type);
  1128. #  else /* HESIOD_INIT */
  1129. hp = hes_resolve(name, type);
  1130. #  endif /* HESIOD_INIT */
  1131. *--type = ':';
  1132. #  ifdef HESIOD_INIT
  1133. if (hp == NULL)
  1134. return 1;
  1135. if (*hp == NULL)
  1136. {
  1137. hesiod_free_list(HesiodContext, hp);
  1138. if (errno == ECONNREFUSED || errno == EMSGSIZE)
  1139. return -1;
  1140. return 1;
  1141. }
  1142. #  else /* HESIOD_INIT */
  1143. if (hp == NULL || hp[0] == NULL)
  1144. {
  1145. /* network problem or timeout */
  1146. if (hes_error() == HES_ER_NET)
  1147. return -1;
  1148. return 1;
  1149. }
  1150. #  endif /* HESIOD_INIT */
  1151. else
  1152. {
  1153. /*
  1154. **  If there are multiple matches, just return the
  1155. **  first one.
  1156. **
  1157. **  XXX These should really be returned; for example,
  1158. **  XXX it is legal for :maildrop to be multi-valued.
  1159. */
  1160. info->data = hp[0];
  1161. info->size = (size_t) strlen(info->data);
  1162. }
  1163. if (tTd(28, 80))
  1164. dprintf("hes_udb_get => %sn", *hp);
  1165. return 0;
  1166. }
  1167. # endif /* HESIOD */
  1168. #else /* USERDB */
  1169. int
  1170. udbexpand(a, sendq, aliaslevel, e)
  1171. ADDRESS *a;
  1172. ADDRESS **sendq;
  1173. int aliaslevel;
  1174. ENVELOPE *e;
  1175. {
  1176. return EX_OK;
  1177. }
  1178. #endif /* USERDB */