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
main(argc,argv)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:l")) != -1)
91 {
92 switch ((char)ch) {
93 case 'C':
94 cfile = optarg;
95 break;
96 case 'f':
97 filename = optarg;
98 break;
99
100 case 'l':
101 smdb_print_available_types(false);
102 exit(EX_OK);
103 break;
104 case '?':
105 default:
106 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
107 "usage: praliases [-C cffile] [-f aliasfile]"
108 " [key ...]\n");
109 exit(EX_USAGE);
110 }
111 }
112 argc -= optind;
113 argv += optind;
114
115 if (filename != NULL)
116 {
117 praliases(filename, argc, argv);
118 exit(EX_OK);
119 }
120
121 if ((cfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, cfile, SM_IO_RDONLY,
122 NULL)) == NULL)
123 {
124 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
125 "praliases: %s: %s\n", cfile,
126 sm_errstring(errno));
127 exit(EX_NOINPUT);
128 }
129
130 while (sm_io_fgets(cfp, SM_TIME_DEFAULT, buf, sizeof(buf)) >= 0)
131 {
132 register char *b, *p;
133
134 b = strchr(buf, '\n');
135 if (b != NULL)
136 *b = '\0';
137
138 b = buf;
139 switch (*b++)
140 {
141 case 'O': /* option -- see if alias file */
142 if (sm_strncasecmp(b, " AliasFile", 10) == 0 &&
143 !(isascii(b[10]) && isalnum(b[10])))
144 {
145 /* new form -- find value */
146 b = strchr(b, '=');
147 if (b == NULL)
148 continue;
149 while (isascii(*++b) && isspace(*b))
150 continue;
151 }
152 else if (*b++ != 'A')
153 {
154 /* something else boring */
155 continue;
156 }
157
158 /* this is the A or AliasFile option -- save it */
159 if (sm_strlcpy(afilebuf, b, sizeof afilebuf) >=
160 sizeof afilebuf)
161 {
162 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
163 "praliases: AliasFile filename too long: %.30s\n",
164 b);
165 (void) sm_io_close(cfp, SM_TIME_DEFAULT);
166 exit(EX_CONFIG);
167 }
168 b = afilebuf;
169
170 for (p = b; p != NULL; )
171 {
172 while (isascii(*p) && isspace(*p))
173 p++;
174 if (*p == '\0')
175 break;
176 b = p;
177
178 p = strpbrk(p, DELIMITERS);
179
180 /* find end of spec */
181 if (p != NULL)
182 {
183 bool quoted = false;
184
185 for (; *p != '\0'; p++)
186 {
187 /*
188 ** Don't break into a quoted
189 ** string.
190 */
191
192 if (*p == '"')
193 quoted = !quoted;
194 else if (*p == ',' && !quoted)
195 break;
196 }
197
198 /* No more alias specs follow */
199 if (*p == '\0')
200 {
201 /* chop trailing whitespace */
202 while (isascii(*p) &&
203 isspace(*p) &&
204 p > b)
205 p--;
206 *p = '\0';
207 p = NULL;
208 }
209 }
210
211 if (p != NULL)
212 {
213 char *e = p - 1;
214
215 /* chop trailing whitespace */
216 while (isascii(*e) &&
217 isspace(*e) &&
218 e > b)
219 e--;
220 *++e = '\0';
221 *p++ = '\0';
222 }
223 praliases(b, argc, argv);
224 }
225
226 default:
227 continue;
228 }
229 }
230 (void) sm_io_close(cfp, SM_TIME_DEFAULT);
231 exit(EX_OK);
232 /* NOTREACHED */
233 return EX_OK;
234 }
235
236 static void
praliases(filename,argc,argv)237 praliases(filename, argc, argv)
238 char *filename;
239 int argc;
240 char **argv;
241 {
242 int result;
243 char *colon;
244 char *db_name;
245 char *db_type;
246 SMDB_DATABASE *database = NULL;
247 SMDB_CURSOR *cursor = NULL;
248 SMDB_DBENT db_key, db_value;
249 SMDB_DBPARAMS params;
250 SMDB_USER_INFO user_info;
251
252 colon = strchr(filename, PATH_SEPARATOR);
253 if (colon == NULL)
254 {
255 db_name = filename;
256 db_type = SMDB_TYPE_DEFAULT;
257 }
258 else
259 {
260 *colon = '\0';
261 db_name = colon + 1;
262 db_type = filename;
263 }
264
265 /* clean off arguments */
266 for (;;)
267 {
268 while (isascii(*db_name) && isspace(*db_name))
269 db_name++;
270
271 if (*db_name != '-')
272 break;
273 while (*db_name != '\0' &&
274 !(isascii(*db_name) && isspace(*db_name)))
275 db_name++;
276 }
277
278 /* Skip non-file based DB types */
279 if (db_type != NULL && *db_type != '\0')
280 {
281 if (db_type != SMDB_TYPE_DEFAULT &&
282 !smdb_is_db_type(db_type))
283 {
284 sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
285 "praliases: Skipping non-file based alias type %s\n",
286 db_type);
287 return;
288 }
289 }
290
291 if (*db_name == '\0' || (db_type != NULL && *db_type == '\0'))
292 {
293 if (colon != NULL)
294 *colon = ':';
295 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
296 "praliases: illegal alias specification: %s\n", filename);
297 goto fatal;
298 }
299
300 memset(¶ms, '\0', sizeof params);
301 params.smdbp_cache_size = 1024 * 1024;
302
303 user_info.smdbu_id = RunAsUid;
304 user_info.smdbu_group_id = RunAsGid;
305 (void) sm_strlcpy(user_info.smdbu_name, RunAsUserName,
306 SMDB_MAX_USER_NAME_LEN);
307
308 result = smdb_open_database(&database, db_name, O_RDONLY, 0,
309 SFF_ROOTOK, db_type, &user_info, ¶ms);
310 if (result != SMDBE_OK)
311 {
312 sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
313 "praliases: %s: open: %s\n",
314 db_name, sm_errstring(result));
315 goto fatal;
316 }
317
318 if (argc == 0)
319 {
320 memset(&db_key, '\0', sizeof db_key);
321 memset(&db_value, '\0', sizeof db_value);
322
323 result = database->smdb_cursor(database, &cursor, 0);
324 if (result != SMDBE_OK)
325 {
326 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
327 "praliases: %s: set cursor: %s\n", db_name,
328 sm_errstring(result));
329 goto fatal;
330 }
331
332 while ((result = cursor->smdbc_get(cursor, &db_key, &db_value,
333 SMDB_CURSOR_GET_NEXT)) ==
334 SMDBE_OK)
335 {
336 #if 0
337 /* skip magic @:@ entry */
338 if (db_key.size == 2 &&
339 db_key.data[0] == '@' &&
340 db_key.data[1] == '\0' &&
341 db_value.size == 2 &&
342 db_value.data[0] == '@' &&
343 db_value.data[1] == '\0')
344 continue;
345 #endif /* 0 */
346
347 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
348 "%.*s:%.*s\n",
349 (int) db_key.size,
350 (char *) db_key.data,
351 (int) db_value.size,
352 (char *) db_value.data);
353 }
354
355 if (result != SMDBE_OK && result != SMDBE_LAST_ENTRY)
356 {
357 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
358 "praliases: %s: get value at cursor: %s\n",
359 db_name, sm_errstring(result));
360 goto fatal;
361 }
362 }
363 else for (; *argv != NULL; ++argv)
364 {
365 int get_res;
366
367 memset(&db_key, '\0', sizeof db_key);
368 memset(&db_value, '\0', sizeof db_value);
369 db_key.data = *argv;
370 db_key.size = strlen(*argv);
371 get_res = database->smdb_get(database, &db_key, &db_value, 0);
372 if (get_res == SMDBE_NOT_FOUND)
373 {
374 db_key.size++;
375 get_res = database->smdb_get(database, &db_key,
376 &db_value, 0);
377 }
378 if (get_res == SMDBE_OK)
379 {
380 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
381 "%.*s:%.*s\n",
382 (int) db_key.size,
383 (char *) db_key.data,
384 (int) db_value.size,
385 (char *) db_value.data);
386 }
387 else
388 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
389 "%s: No such key\n",
390 (char *)db_key.data);
391 }
392
393 fatal:
394 if (cursor != NULL)
395 (void) cursor->smdbc_close(cursor);
396 if (database != NULL)
397 (void) database->smdb_close(database);
398 if (colon != NULL)
399 *colon = ':';
400 return;
401 }
402