diff options
| author | Gregory Neil Shapiro <gshapiro@FreeBSD.org> | 2020-07-14 21:40:53 +0000 |
|---|---|---|
| committer | Gregory Neil Shapiro <gshapiro@FreeBSD.org> | 2020-07-14 21:40:53 +0000 |
| commit | cee0d44ab388e12fbd62fdb134d295c58901148a (patch) | |
| tree | fbe464b241337077b941be7126ad3f3f78b19f7f /makemap | |
| parent | 1c3e417caf2d11608f10043b7e70b6e7ed8711ff (diff) | |
Diffstat (limited to 'makemap')
| -rw-r--r-- | makemap/Makefile | 2 | ||||
| -rw-r--r-- | makemap/Makefile.m4 | 1 | ||||
| -rw-r--r-- | makemap/makemap.0 | 88 | ||||
| -rw-r--r-- | makemap/makemap.8 | 15 | ||||
| -rw-r--r-- | makemap/makemap.c | 316 |
5 files changed, 311 insertions, 111 deletions
diff --git a/makemap/Makefile b/makemap/Makefile index 953d28b37e7e..301a639d437e 100644 --- a/makemap/Makefile +++ b/makemap/Makefile @@ -8,6 +8,8 @@ all: FRC $(SHELL) $(BUILD) $(OPTIONS) $@ clean: FRC $(SHELL) $(BUILD) $(OPTIONS) $@ +check: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ install: FRC $(SHELL) $(BUILD) $(OPTIONS) $@ diff --git a/makemap/Makefile.m4 b/makemap/Makefile.m4 index c6dffd0f57f5..9ff01cd25491 100644 --- a/makemap/Makefile.m4 +++ b/makemap/Makefile.m4 @@ -21,4 +21,5 @@ bldPRODUCT_START(`manpage', `makemap') define(`bldSOURCES', `makemap.8') bldPRODUCT_END + bldFINISH diff --git a/makemap/makemap.0 b/makemap/makemap.0 index 73d6ef09a37e..61f4d6f868dc 100644 --- a/makemap/makemap.0 +++ b/makemap/makemap.0 @@ -2,20 +2,20 @@ MAKEMAP(8) MAKEMAP(8) -NNAAMMEE +[1mNAME[0m makemap - create database maps for sendmail -SSYYNNOOPPSSIISS - mmaakkeemmaapp [--CC _f_i_l_e] [--NN] [--cc _c_a_c_h_e_s_i_z_e] [--dd] [--DD _c_o_m_m_e_n_t_c_h_a_r] [--ee] [--ff] - [--ll] [--oo] [--rr] [--ss] [--tt _d_e_l_i_m] [--uu] [--vv] _m_a_p_t_y_p_e _m_a_p_n_a_m +[1mSYNOPSIS[0m + [1mmakemap [22m[[1m-C [4m[22mfile[24m] [[1m-N[22m] [[1m-c [4m[22mcachesize[24m] [[1m-d[22m] [[1m-D [4m[22mcommentchar[24m] [[1m-e[22m] [[1m-f[22m] + [[1m-l[22m] [[1m-o[22m] [[1m-r[22m] [[1m-s[22m] [[1m-t [4m[22mdelim[24m] [[1m-u[22m] [[1m-v[22m] [4mmaptype[24m [4mmapnam[0m -DDEESSCCRRIIPPTTIIOONN - MMaakkeemmaapp creates the database maps used by the keyed map lookups in +[1mDESCRIPTION[0m + [1mMakemap [22mcreates the database maps used by the keyed map lookups in sendmail(8). It reads input from the standard input and outputs them - to the indicated _m_a_p_n_a_m_e_. + to the indicated [4mmapname.[0m - Depending on how it is compiled, mmaakkeemmaapp handles up to three different - database formats, selected using the _m_a_p_t_y_p_e parameter. They may be + Depending on how it is compiled, [1mmakemap [22mhandles different database + formats, selected using the [4mmaptype[24m parameter. They may be dbm DBM format maps. This requires the ndbm(3) library. @@ -23,67 +23,79 @@ DDEESSCCRRIIPPTTIIOONN hash Hash format maps. This also requires the Berkeley DB library. - In all cases, mmaakkeemmaapp reads lines from the standard input consisting of + cdb CDB (Constant DataBase) format maps. This requires the tinycdb + library. + + implicit + The first available format in the following order: hash, dbm, + and cdb. + + In all cases, [1mmakemap [22mreads lines from the standard input consisting of two words separated by white space. The first is the database key, the - second is the value. The value may contain ``%_n'' strings to indicate + second is the value. The value may contain ``%[4mn[24m'' strings to indicate parameter substitution. Literal percents should be doubled (``%%''). Blank lines and lines beginning with ``#'' are ignored. - Notice: do nnoott use mmaakkeemmaapp to create the aliases data base, but - nneewwaalliiaasseess which puts a special token into the data base that is - required by sseennddmmaaiill.. + Notice: do [1mnot [22muse [1mmakemap [22mto create the aliases data base, but + [1mnewaliases [22mwhich puts a special token into the data base that is + required by [1msendmail.[0m - If the _T_r_u_s_t_e_d_U_s_e_r option is set in the sendmail configuration file and - mmaakkeemmaapp is invoked as root, the generated files will be owned by the - specified _T_r_u_s_t_e_d_U_s_e_r_. + If the [4mTrustedUser[24m option is set in the sendmail configuration file and + [1mmakemap [22mis invoked as root, the generated files will be owned by the + specified [4mTrustedUser.[0m - FFllaaggss - --CC Use the specified sseennddmmaaiill configuration file for looking up the + [1mFlags[0m + [1m-C [22mUse the specified [1msendmail [22mconfiguration file for looking up the TrustedUser option. - --NN Include the null byte that terminates strings in the map. This + [1m-N [22mInclude the null byte that terminates strings in the map. This must match the -N flag in the sendmail.cf ``K'' line. - --cc Use the specified hash and B-Tree cache size. + [1m-c [22mUse the specified hash and B-Tree cache size. - --DD Use to specify the character to use to indicate a comment (which + [1m-D [22mUse to specify the character to use to indicate a comment (which is ignored) instead of the default of '#'. - --dd Allow duplicate keys in the map. This is only allowed on B-Tree + [1m-d [22mAllow duplicate keys in the map. This is only allowed on B-Tree format maps. If two identical keys are read, they will both be inserted into the map. - --ee Allow empty value (right hand side). + [1m-e [22mAllow empty value (right hand side). - --ff Normally all upper case letters in the key are folded to lower + [1m-f [22mNormally all upper case letters in the key are folded to lower case. This flag disables that behaviour. This is intended to - mesh with the -f flag in the KK line in sendmail.cf. The value + mesh with the -f flag in the [1mK [22mline in sendmail.cf. The value is never case folded. - --ll List supported map types. + [1m-l [22mList supported map types. - --oo Append to an old file. This allows you to augment an existing - file. + [1m-o [22mAppend to an old file. This allows you to augment an existing + file. Note: this might not be supported by all database types, + e.g., cdb. - --rr Allow replacement of existing keys. Normally mmaakkeemmaapp complains + [1m-r [22mAllow replacement of existing keys. Normally [1mmakemap [22mcomplains if you repeat a key, and does not do the insert. - --ss Ignore safety checks on maps being created. This includes - checking for hard or symbolic links in world writable directo- + [1m-s [22mIgnore safety checks on maps being created. This includes + checking for hard or symbolic links in world writable directo- ries. - --tt Use the specified delimiter instead of white space (also for + [1m-t [22mUse the specified delimiter instead of white space (also for dumping a map). - --uu dump (unmap) the content of the database to standard output. + [1m-u [22mdump (unmap) the content of the database to standard output. + + [1m-v [22mVerbosely print what it is doing. + - --vv Verbosely print what it is doing. +[1mExample[0m + makemap hash /etc/mail/access < /etc/mail/access -SSEEEE AALLSSOO +[1mSEE ALSO[0m sendmail(8), newaliases(1) -HHIISSTTOORRYY - The mmaakkeemmaapp command appeared in 4.4BSD. +[1mHISTORY[0m + The [1mmakemap [22mcommand appeared in 4.4BSD. diff --git a/makemap/makemap.8 b/makemap/makemap.8 index a6bfd21462c4..fa250109b842 100644 --- a/makemap/makemap.8 +++ b/makemap/makemap.8 @@ -46,7 +46,7 @@ and outputs them to the indicated .PP Depending on how it is compiled, .B makemap -handles up to three different database formats, +handles different database formats, selected using the .I maptype parameter. @@ -67,6 +67,14 @@ hash Hash format maps. This also requires the Berkeley DB library. +.TP +cdb +CDB (Constant DataBase) format maps. +This requires the tinycdb library. +.TP +implicit +The first available format in the following order: +hash, dbm, and cdb. .PP In all cases, .B makemap @@ -142,6 +150,8 @@ List supported map types. .B \-o Append to an old file. This allows you to augment an existing file. +Note: this might not be supported by all database types, +e.g., cdb. .TP .B \-r Allow replacement of existing keys. @@ -164,6 +174,9 @@ dump (unmap) the content of the database to standard output. .TP .B \-v Verbosely print what it is doing. +.P +.SH Example +makemap hash /etc/mail/access < /etc/mail/access .SH SEE ALSO sendmail(8), newaliases(1) .SH HISTORY diff --git a/makemap/makemap.c b/makemap/makemap.c index cf1f62c8ea9e..4aa8d6ddab38 100644 --- a/makemap/makemap.c +++ b/makemap/makemap.c @@ -26,15 +26,16 @@ SM_IDSTR(id, "@(#)$Id: makemap.c,v 8.183 2013-11-22 20:51:52 ca Exp $") #include <sys/types.h> #ifndef ISC_UNIX # include <sys/file.h> -#endif /* ! ISC_UNIX */ +#endif #include <ctype.h> #include <stdlib.h> #include <unistd.h> #ifdef EX_OK # undef EX_OK /* unistd.h may have another use for this */ -#endif /* EX_OK */ +#endif #include <sysexits.h> #include <sendmail/sendmail.h> +#include <sm/path.h> #include <sendmail/pathnames.h> #include <libsmdb/smdb.h> @@ -50,13 +51,15 @@ uid_t TrustedUid = 0; BITMAP256 DontBlameSendmail; #define BUFSIZE 1024 -#define ISSEP(c) (sep == '\0' ? isascii(c) && isspace(c) : (c) == sep) +#define ISASCII(c) isascii((unsigned char)(c)) +#define ISSEP(c) (sep == '\0' ? ISASCII(c) && isspace(c) : (c) == sep) -static void usage __P((char *)); +static void usage __P((const char *)); +static char *readcf __P((const char *, char *, bool)); static void usage(progname) - char *progname; + const char *progname; { sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "Usage: %s [-C cffile] [-N] [-c cachesize] [-D commentchar]\n", @@ -70,6 +73,181 @@ usage(progname) exit(EX_USAGE); } +/* +** READCF -- read some settings from configuration file. +** +** Parameters: +** cfile -- configuration file name. +** mapfile -- file name of map to look up (if not NULL/empty) +** Note: this finds the first match, so in case someone +** uses the same map file for different maps, they are +** hopefully using the same map type. +** fullpath -- compare the full paths or just the "basename"s? +** (even excluding any .ext !) +** +** Returns: +** pointer to map class name (static!) +*/ + +static char * +readcf(cfile, mapfile, fullpath) + const char *cfile; + char *mapfile; + bool fullpath; +{ + SM_FILE_T *cfp; + char buf[MAXLINE]; + static char classbuf[MAXLINE]; + char *classname; + char *p; + + if ((cfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, cfile, + SM_IO_RDONLY, NULL)) == NULL) + { + sm_io_fprintf(smioerr, SM_TIME_DEFAULT, + "makemap: %s: %s\n", + cfile, sm_errstring(errno)); + exit(EX_NOINPUT); + } + classname = NULL; + classbuf[0] = '\0'; + + if (!fullpath && mapfile != NULL) + { + p = strrchr(mapfile, '/'); + if (p != NULL) + mapfile = ++p; + p = strrchr(mapfile, '.'); + if (p != NULL) + *p = '\0'; + } + + while (sm_io_fgets(cfp, SM_TIME_DEFAULT, buf, sizeof(buf)) >= 0) + { + char *b; + + if ((b = strchr(buf, '\n')) != NULL) + *b = '\0'; + + b = buf; + switch (*b++) + { + case 'O': /* option */ +#if HASFCHOWN + if (strncasecmp(b, " TrustedUser", 12) == 0 && + !(ISASCII(b[12]) && isalnum(b[12]))) + { + b = strchr(b, '='); + if (b == NULL) + continue; + while (ISASCII(*++b) && isspace(*b)) + continue; + if (ISASCII(*b) && isdigit(*b)) + TrustedUid = atoi(b); + else + { + struct passwd *pw; + + TrustedUid = 0; + pw = getpwnam(b); + if (pw == NULL) + (void) sm_io_fprintf(smioerr, + SM_TIME_DEFAULT, + "TrustedUser: unknown user %s\n", b); + else + TrustedUid = pw->pw_uid; + } + +# ifdef UID_MAX + if (TrustedUid > UID_MAX) + { + (void) sm_io_fprintf(smioerr, + SM_TIME_DEFAULT, + "TrustedUser: uid value (%ld) > UID_MAX (%ld)", + (long) TrustedUid, + (long) UID_MAX); + TrustedUid = 0; + } +# endif /* UID_MAX */ + } +#endif /* HASFCHOWN */ + break; + + case 'K': /* Keyfile (map) */ + if (classname != NULL) /* found it already */ + continue; + if (mapfile == NULL || *mapfile == '\0') + continue; + + /* cut off trailing spaces */ + for (p = buf + strlen(buf) - 1; ISASCII(*p) && isspace(*p) && p > buf; p--) + *p = '\0'; + + /* find the last argument */ + p = strrchr(buf, ' '); + if (p == NULL) + continue; + b = strstr(p, mapfile); + if (b == NULL) + continue; + if (b <= buf) + continue; + if (!fullpath) + { + p = strrchr(b, '.'); + if (p != NULL) + *p = '\0'; + } + + /* allow trailing white space? */ + if (strcmp(mapfile, b) != 0) + continue; + /* SM_ASSERT(b > buf); */ + --b; + if (!ISASCII(*b)) + continue; + if (!isspace(*b) && fullpath) + continue; + if (!fullpath && !(SM_IS_DIR_DELIM(*b) || isspace(*b))) + continue; + + /* basically from readcf.c */ + for (b = buf + 1; ISASCII(*b) && isspace(*b); b++) + ; + if (!(ISASCII(*b) && isalnum(*b))) + { + /* syserr("readcf: config K line: no map name"); */ + return NULL; + } + + while ((ISASCII(*++b) && isalnum(*b)) || *b == '_' || *b == '.') + ; + if (*b != '\0') + *b++ = '\0'; + while (ISASCII(*b) && isspace(*b)) + b++; + if (!(ISASCII(*b) && isalnum(*b))) + { + /* syserr("readcf: config K line, map %s: no map class", b); */ + return NULL; + } + classname = b; + while (ISASCII(*++b) && isalnum(*b)) + ; + if (*b != '\0') + *b++ = '\0'; + (void) sm_strlcpy(classbuf, classname, sizeof classbuf); + break; + + default: + continue; + } + } + (void) sm_io_close(cfp, SM_TIME_DEFAULT); + + return classbuf; +} + int main(argc, argv) int argc; @@ -84,11 +262,13 @@ main(argc, argv) bool verbose = false; bool foldcase = true; bool unmake = false; + bool didreadcf = false; char sep = '\0'; char comment = '#'; int exitstat; int opt; char *typename = NULL; + char *fallback = NULL; char *mapname = NULL; unsigned int lineno; int st; @@ -103,10 +283,6 @@ main(argc, argv) SMDB_DBPARAMS params; SMDB_USER_INFO user_info; char ibuf[BUFSIZE]; -#if HASFCHOWN - SM_FILE_T *cfp; - char buf[MAXLINE]; -#endif /* HASFCHOWN */ static char rnamebuf[MAXNAME]; /* holds RealUserName */ extern char *optarg; extern int optind; @@ -136,7 +312,7 @@ main(argc, argv) (void) sm_strlcpy(user_info.smdbu_name, RunAsUserName, SMDB_MAX_USER_NAME_LEN); -#define OPTIONS "C:D:Nc:deflorst:uv" +#define OPTIONS "C:D:Nc:defi:Llorst:uvx" while ((opt = getopt(argc, argv, OPTIONS)) != -1) { switch (opt) @@ -165,12 +341,23 @@ main(argc, argv) foldcase = false; break; + case 'i': + fallback =optarg; + break; + case 'D': comment = *optarg; break; + case 'L': + smdb_print_available_types(false); + sm_io_fprintf(smioout, SM_TIME_DEFAULT, + "cf\nCF\n"); + exit(EX_OK); + break; + case 'l': - smdb_print_available_types(); + smdb_print_available_types(false); exit(EX_OK); break; @@ -206,6 +393,11 @@ main(argc, argv) case 'v': verbose = true; break; + + case 'x': + smdb_print_available_types(true); + exit(EX_OK); + break; default: usage(progname); @@ -233,68 +425,18 @@ main(argc, argv) mapname = argv[1]; } +#define TYPEFROMCF (strcasecmp(typename, "cf") == 0) +#define FULLPATHFROMCF (strcmp(typename, "cf") == 0) + #if HASFCHOWN - /* Find TrustedUser value in sendmail.cf */ - if ((cfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, cfile, SM_IO_RDONLY, - NULL)) == NULL) + if (geteuid() == 0) { - sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "makemap: %s: %s\n", - cfile, sm_errstring(errno)); - exit(EX_NOINPUT); - } - while (sm_io_fgets(cfp, SM_TIME_DEFAULT, buf, sizeof(buf)) >= 0) - { - register char *b; - - if ((b = strchr(buf, '\n')) != NULL) - *b = '\0'; - - b = buf; - switch (*b++) - { - case 'O': /* option */ - if (strncasecmp(b, " TrustedUser", 12) == 0 && - !(isascii(b[12]) && isalnum(b[12]))) - { - b = strchr(b, '='); - if (b == NULL) - continue; - while (isascii(*++b) && isspace(*b)) - continue; - if (isascii(*b) && isdigit(*b)) - TrustedUid = atoi(b); - else - { - TrustedUid = 0; - pw = getpwnam(b); - if (pw == NULL) - (void) sm_io_fprintf(smioerr, - SM_TIME_DEFAULT, - "TrustedUser: unknown user %s\n", b); - else - TrustedUid = pw->pw_uid; - } - -# ifdef UID_MAX - if (TrustedUid > UID_MAX) - { - (void) sm_io_fprintf(smioerr, - SM_TIME_DEFAULT, - "TrustedUser: uid value (%ld) > UID_MAX (%ld)", - (long) TrustedUid, - (long) UID_MAX); - TrustedUid = 0; - } -# endif /* UID_MAX */ - break; - } - - - default: - continue; - } + if (TYPEFROMCF) + typename = readcf(cfile, mapname, FULLPATHFROMCF); + else + (void) readcf(cfile, NULL, false); + didreadcf = true; } - (void) sm_io_close(cfp, SM_TIME_DEFAULT); #endif /* HASFCHOWN */ if (!params.smdbp_allow_dup && !allowreplace) @@ -318,6 +460,36 @@ main(argc, argv) params.smdbp_num_elements = 4096; + if (!didreadcf && TYPEFROMCF) + { + typename = readcf(cfile, mapname, FULLPATHFROMCF); + didreadcf = true; + } + if (didreadcf && (typename == NULL || *typename == '\0')) + { + if (fallback != NULL && *fallback != '\0') + { + typename = fallback; + if (verbose) + (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, + "%s: mapfile %s: not found in %s, using fallback %s\n", + progname, mapname, cfile, fallback); + } + else + { + (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, + "%s: mapfile %s: not found in %s\n", + progname, mapname, cfile); + exit(EX_DATAERR); + } + } + + /* + ** Note: if "implicit" is selected it does not work like + ** sendmail: it will just use the first available DB type, + ** it won't try several (for -u) to find one that "works". + */ + errno = smdb_open_database(&database, mapname, mode, smode, sff, typename, &user_info, ¶ms); if (errno != SMDBE_OK) @@ -417,7 +589,7 @@ main(argc, argv) if (ibuf[0] == '\0' || ibuf[0] == comment) continue; - if (sep == '\0' && isascii(ibuf[0]) && isspace(ibuf[0])) + if (sep == '\0' && ISASCII(ibuf[0]) && isspace(ibuf[0])) { (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "%s: %s: line %u: syntax error (leading space)\n", @@ -432,7 +604,7 @@ main(argc, argv) for (p = ibuf; *p != '\0' && !(ISSEP(*p)); p++) { - if (foldcase && isascii(*p) && isupper(*p)) + if (foldcase && ISASCII(*p) && isupper(*p)) *p = tolower(*p); } db_key.size = p - ibuf; |
