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