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: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 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