]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/sendmail/praliases/praliases.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / sendmail / praliases / praliases.c
1 /*
2  * Copyright (c) 1998-2001, 2008 Sendmail, 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 Sendmail, 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.97 2013/03/12 15:24:51 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 /* EX_OK */
32 #include <sysexits.h>
33
34
35 #ifndef NOT_SENDMAIL
36 # define NOT_SENDMAIL
37 #endif /* ! NOT_SENDMAIL */
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                     strcmp(db_type, "hash") != 0 &&
278                     strcmp(db_type, "btree") != 0 &&
279                     strcmp(db_type, "dbm") != 0)
280                 {
281                         sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
282                                       "praliases: Skipping non-file based alias type %s\n",
283                                 db_type);
284                         return;
285                 }
286         }
287
288         if (*db_name == '\0' || (db_type != NULL && *db_type == '\0'))
289         {
290                 if (colon != NULL)
291                         *colon = ':';
292                 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
293                     "praliases: illegal alias specification: %s\n", filename);
294                 goto fatal;
295         }
296
297         memset(&params, '\0', sizeof params);
298         params.smdbp_cache_size = 1024 * 1024;
299
300         user_info.smdbu_id = RunAsUid;
301         user_info.smdbu_group_id = RunAsGid;
302         (void) sm_strlcpy(user_info.smdbu_name, RunAsUserName,
303                           SMDB_MAX_USER_NAME_LEN);
304
305         result = smdb_open_database(&database, db_name, O_RDONLY, 0,
306                                     SFF_ROOTOK, db_type, &user_info, &params);
307         if (result != SMDBE_OK)
308         {
309                 sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
310                               "praliases: %s: open: %s\n",
311                               db_name, sm_errstring(result));
312                 goto fatal;
313         }
314
315         if (argc == 0)
316         {
317                 memset(&db_key, '\0', sizeof db_key);
318                 memset(&db_value, '\0', sizeof db_value);
319
320                 result = database->smdb_cursor(database, &cursor, 0);
321                 if (result != SMDBE_OK)
322                 {
323                         (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
324                             "praliases: %s: set cursor: %s\n", db_name,
325                             sm_errstring(result));
326                         goto fatal;
327                 }
328
329                 while ((result = cursor->smdbc_get(cursor, &db_key, &db_value,
330                                                    SMDB_CURSOR_GET_NEXT)) ==
331                                                    SMDBE_OK)
332                 {
333 #if 0
334                         /* skip magic @:@ entry */
335                         if (db_key.size == 2 &&
336                             db_key.data[0] == '@' &&
337                             db_key.data[1] == '\0' &&
338                             db_value.size == 2 &&
339                             db_value.data[0] == '@' &&
340                             db_value.data[1] == '\0')
341                                 continue;
342 #endif /* 0 */
343
344                         (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
345                                              "%.*s:%.*s\n",
346                                              (int) db_key.size,
347                                              (char *) db_key.data,
348                                              (int) db_value.size,
349                                              (char *) db_value.data);
350                 }
351
352                 if (result != SMDBE_OK && result != SMDBE_LAST_ENTRY)
353                 {
354                         (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
355                                 "praliases: %s: get value at cursor: %s\n",
356                                 db_name, sm_errstring(result));
357                         goto fatal;
358                 }
359         }
360         else for (; *argv != NULL; ++argv)
361         {
362                 int get_res;
363
364                 memset(&db_key, '\0', sizeof db_key);
365                 memset(&db_value, '\0', sizeof db_value);
366                 db_key.data = *argv;
367                 db_key.size = strlen(*argv);
368                 get_res = database->smdb_get(database, &db_key, &db_value, 0);
369                 if (get_res == SMDBE_NOT_FOUND)
370                 {
371                         db_key.size++;
372                         get_res = database->smdb_get(database, &db_key,
373                                                      &db_value, 0);
374                 }
375                 if (get_res == SMDBE_OK)
376                 {
377                         (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
378                                              "%.*s:%.*s\n",
379                                              (int) db_key.size,
380                                              (char *) db_key.data,
381                                              (int) db_value.size,
382                                              (char *) db_value.data);
383                 }
384                 else
385                         (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
386                                              "%s: No such key\n",
387                                              (char *)db_key.data);
388         }
389
390  fatal:
391         if (cursor != NULL)
392                 (void) cursor->smdbc_close(cursor);
393         if (database != NULL)
394                 (void) database->smdb_close(database);
395         if (colon != NULL)
396                 *colon = ':';
397         return;
398 }