]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/sendmail/praliases/praliases.c
Merge sendmail 8.16.1 to HEAD: See contrib/sendmail/RELEASE_NOTES for details
[FreeBSD/FreeBSD.git] / contrib / sendmail / praliases / praliases.c
1 /*
2  * Copyright (c) 1998-2001, 2008 Proofpoint, Inc. and its suppliers.
3  *      All rights reserved.
4  * Copyright (c) 1983 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
14 #include <sm/gen.h>
15
16 SM_IDSTR(copyright,
17 "@(#) Copyright (c) 1998-2001 Proofpoint, Inc. and its suppliers.\n\
18         All rights reserved.\n\
19      Copyright (c) 1983 Eric P. Allman.  All rights reserved.\n\
20      Copyright (c) 1988, 1993\n\
21         The Regents of the University of California.  All rights reserved.\n")
22
23 SM_IDSTR(id, "@(#)$Id: praliases.c,v 8.98 2013-11-22 20:51:53 ca Exp $")
24
25 #include <sys/types.h>
26 #include <ctype.h>
27 #include <stdlib.h>
28 #include <unistd.h>
29 #ifdef EX_OK
30 # undef EX_OK           /* unistd.h may have another use for this */
31 #endif
32 #include <sysexits.h>
33
34
35 #ifndef NOT_SENDMAIL
36 # define NOT_SENDMAIL
37 #endif
38 #include <sendmail/sendmail.h>
39 #include <sendmail/pathnames.h>
40 #include <libsmdb/smdb.h>
41
42 static void praliases __P((char *, int, char **));
43
44 uid_t   RealUid;
45 gid_t   RealGid;
46 char    *RealUserName;
47 uid_t   RunAsUid;
48 gid_t   RunAsGid;
49 char    *RunAsUserName;
50 int     Verbose = 2;
51 bool    DontInitGroups = false;
52 uid_t   TrustedUid = 0;
53 BITMAP256 DontBlameSendmail;
54
55 # define DELIMITERS             " ,/"
56 # define PATH_SEPARATOR         ':'
57
58 int
59 main(argc, argv)
60         int argc;
61         char **argv;
62 {
63         char *cfile;
64         char *filename = NULL;
65         SM_FILE_T *cfp;
66         int ch;
67         char afilebuf[MAXLINE];
68         char buf[MAXLINE];
69         struct passwd *pw;
70         static char rnamebuf[MAXNAME];
71         extern char *optarg;
72         extern int optind;
73
74         clrbitmap(DontBlameSendmail);
75         RunAsUid = RealUid = getuid();
76         RunAsGid = RealGid = getgid();
77         pw = getpwuid(RealUid);
78         if (pw != NULL)
79         {
80                 if (strlen(pw->pw_name) > MAXNAME - 1)
81                         pw->pw_name[MAXNAME] = 0;
82                 sm_snprintf(rnamebuf, sizeof rnamebuf, "%s", pw->pw_name);
83         }
84         else
85                 (void) sm_snprintf(rnamebuf, sizeof rnamebuf,
86                     "Unknown UID %d", (int) RealUid);
87         RunAsUserName = RealUserName = rnamebuf;
88
89         cfile = getcfname(0, 0, SM_GET_SENDMAIL_CF, NULL);
90         while ((ch = getopt(argc, argv, "C:f:")) != -1)
91         {
92                 switch ((char)ch) {
93                 case 'C':
94                         cfile = optarg;
95                         break;
96                 case 'f':
97                         filename = optarg;
98                         break;
99                 case '?':
100                 default:
101                         (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
102                             "usage: praliases [-C cffile] [-f aliasfile]"
103                             " [key ...]\n");
104                         exit(EX_USAGE);
105                 }
106         }
107         argc -= optind;
108         argv += optind;
109
110         if (filename != NULL)
111         {
112                 praliases(filename, argc, argv);
113                 exit(EX_OK);
114         }
115
116         if ((cfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, cfile, SM_IO_RDONLY,
117                               NULL)) == NULL)
118         {
119                 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
120                                      "praliases: %s: %s\n", cfile,
121                                      sm_errstring(errno));
122                 exit(EX_NOINPUT);
123         }
124
125         while (sm_io_fgets(cfp, SM_TIME_DEFAULT, buf, sizeof(buf)) >= 0)
126         {
127                 register char *b, *p;
128
129                 b = strchr(buf, '\n');
130                 if (b != NULL)
131                         *b = '\0';
132
133                 b = buf;
134                 switch (*b++)
135                 {
136                   case 'O':             /* option -- see if alias file */
137                         if (sm_strncasecmp(b, " AliasFile", 10) == 0 &&
138                             !(isascii(b[10]) && isalnum(b[10])))
139                         {
140                                 /* new form -- find value */
141                                 b = strchr(b, '=');
142                                 if (b == NULL)
143                                         continue;
144                                 while (isascii(*++b) && isspace(*b))
145                                         continue;
146                         }
147                         else if (*b++ != 'A')
148                         {
149                                 /* something else boring */
150                                 continue;
151                         }
152
153                         /* this is the A or AliasFile option -- save it */
154                         if (sm_strlcpy(afilebuf, b, sizeof afilebuf) >=
155                             sizeof afilebuf)
156                         {
157                                 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
158                                     "praliases: AliasFile filename too long: %.30s\n",
159                                         b);
160                                 (void) sm_io_close(cfp, SM_TIME_DEFAULT);
161                                 exit(EX_CONFIG);
162                         }
163                         b = afilebuf;
164
165                         for (p = b; p != NULL; )
166                         {
167                                 while (isascii(*p) && isspace(*p))
168                                         p++;
169                                 if (*p == '\0')
170                                         break;
171                                 b = p;
172
173                                 p = strpbrk(p, DELIMITERS);
174
175                                 /* find end of spec */
176                                 if (p != NULL)
177                                 {
178                                         bool quoted = false;
179
180                                         for (; *p != '\0'; p++)
181                                         {
182                                                 /*
183                                                 **  Don't break into a quoted
184                                                 **  string.
185                                                 */
186
187                                                 if (*p == '"')
188                                                         quoted = !quoted;
189                                                 else if (*p == ',' && !quoted)
190                                                         break;
191                                         }
192
193                                         /* No more alias specs follow */
194                                         if (*p == '\0')
195                                         {
196                                                 /* chop trailing whitespace */
197                                                 while (isascii(*p) &&
198                                                        isspace(*p) &&
199                                                        p > b)
200                                                         p--;
201                                                 *p = '\0';
202                                                 p = NULL;
203                                         }
204                                 }
205
206                                 if (p != NULL)
207                                 {
208                                         char *e = p - 1;
209
210                                         /* chop trailing whitespace */
211                                         while (isascii(*e) &&
212                                                isspace(*e) &&
213                                                e > b)
214                                                 e--;
215                                         *++e = '\0';
216                                         *p++ = '\0';
217                                 }
218                                 praliases(b, argc, argv);
219                         }
220
221                   default:
222                         continue;
223                 }
224         }
225         (void) sm_io_close(cfp, SM_TIME_DEFAULT);
226         exit(EX_OK);
227         /* NOTREACHED */
228         return EX_OK;
229 }
230
231 static void
232 praliases(filename, argc, argv)
233         char *filename;
234         int argc;
235         char **argv;
236 {
237         int result;
238         char *colon;
239         char *db_name;
240         char *db_type;
241         SMDB_DATABASE *database = NULL;
242         SMDB_CURSOR *cursor = NULL;
243         SMDB_DBENT db_key, db_value;
244         SMDB_DBPARAMS params;
245         SMDB_USER_INFO user_info;
246
247         colon = strchr(filename, PATH_SEPARATOR);
248         if (colon == NULL)
249         {
250                 db_name = filename;
251                 db_type = SMDB_TYPE_DEFAULT;
252         }
253         else
254         {
255                 *colon = '\0';
256                 db_name = colon + 1;
257                 db_type = filename;
258         }
259
260         /* clean off arguments */
261         for (;;)
262         {
263                 while (isascii(*db_name) && isspace(*db_name))
264                         db_name++;
265
266                 if (*db_name != '-')
267                         break;
268                 while (*db_name != '\0' &&
269                        !(isascii(*db_name) && isspace(*db_name)))
270                         db_name++;
271         }
272
273         /* Skip non-file based DB types */
274         if (db_type != NULL && *db_type != '\0')
275         {
276                 if (db_type != SMDB_TYPE_DEFAULT &&
277                     !smdb_is_db_type(db_type))
278                 {
279                         sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
280                                       "praliases: Skipping non-file based alias type %s\n",
281                                 db_type);
282                         return;
283                 }
284         }
285
286         if (*db_name == '\0' || (db_type != NULL && *db_type == '\0'))
287         {
288                 if (colon != NULL)
289                         *colon = ':';
290                 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
291                     "praliases: illegal alias specification: %s\n", filename);
292                 goto fatal;
293         }
294
295         memset(&params, '\0', sizeof params);
296         params.smdbp_cache_size = 1024 * 1024;
297
298         user_info.smdbu_id = RunAsUid;
299         user_info.smdbu_group_id = RunAsGid;
300         (void) sm_strlcpy(user_info.smdbu_name, RunAsUserName,
301                           SMDB_MAX_USER_NAME_LEN);
302
303         result = smdb_open_database(&database, db_name, O_RDONLY, 0,
304                                     SFF_ROOTOK, db_type, &user_info, &params);
305         if (result != SMDBE_OK)
306         {
307                 sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
308                               "praliases: %s: open: %s\n",
309                               db_name, sm_errstring(result));
310                 goto fatal;
311         }
312
313         if (argc == 0)
314         {
315                 memset(&db_key, '\0', sizeof db_key);
316                 memset(&db_value, '\0', sizeof db_value);
317
318                 result = database->smdb_cursor(database, &cursor, 0);
319                 if (result != SMDBE_OK)
320                 {
321                         (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
322                             "praliases: %s: set cursor: %s\n", db_name,
323                             sm_errstring(result));
324                         goto fatal;
325                 }
326
327                 while ((result = cursor->smdbc_get(cursor, &db_key, &db_value,
328                                                    SMDB_CURSOR_GET_NEXT)) ==
329                                                    SMDBE_OK)
330                 {
331 #if 0
332                         /* skip magic @:@ entry */
333                         if (db_key.size == 2 &&
334                             db_key.data[0] == '@' &&
335                             db_key.data[1] == '\0' &&
336                             db_value.size == 2 &&
337                             db_value.data[0] == '@' &&
338                             db_value.data[1] == '\0')
339                                 continue;
340 #endif /* 0 */
341
342                         (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
343                                              "%.*s:%.*s\n",
344                                              (int) db_key.size,
345                                              (char *) db_key.data,
346                                              (int) db_value.size,
347                                              (char *) db_value.data);
348                 }
349
350                 if (result != SMDBE_OK && result != SMDBE_LAST_ENTRY)
351                 {
352                         (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
353                                 "praliases: %s: get value at cursor: %s\n",
354                                 db_name, sm_errstring(result));
355                         goto fatal;
356                 }
357         }
358         else for (; *argv != NULL; ++argv)
359         {
360                 int get_res;
361
362                 memset(&db_key, '\0', sizeof db_key);
363                 memset(&db_value, '\0', sizeof db_value);
364                 db_key.data = *argv;
365                 db_key.size = strlen(*argv);
366                 get_res = database->smdb_get(database, &db_key, &db_value, 0);
367                 if (get_res == SMDBE_NOT_FOUND)
368                 {
369                         db_key.size++;
370                         get_res = database->smdb_get(database, &db_key,
371                                                      &db_value, 0);
372                 }
373                 if (get_res == SMDBE_OK)
374                 {
375                         (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
376                                              "%.*s:%.*s\n",
377                                              (int) db_key.size,
378                                              (char *) db_key.data,
379                                              (int) db_value.size,
380                                              (char *) db_value.data);
381                 }
382                 else
383                         (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
384                                              "%s: No such key\n",
385                                              (char *)db_key.data);
386         }
387
388  fatal:
389         if (cursor != NULL)
390                 (void) cursor->smdbc_close(cursor);
391         if (database != NULL)
392                 (void) database->smdb_close(database);
393         if (colon != NULL)
394                 *colon = ':';
395         return;
396 }