praliases.c revision 266692
1193323Sed/* 2193323Sed * Copyright (c) 1998-2001, 2008 Proofpoint, Inc. and its suppliers. 3193323Sed * All rights reserved. 4193323Sed * Copyright (c) 1983 Eric P. Allman. All rights reserved. 5193323Sed * Copyright (c) 1988, 1993 6193323Sed * The Regents of the University of California. All rights reserved. 7193323Sed * 8193323Sed * By using this file, you agree to the terms and conditions set 9193323Sed * forth in the LICENSE file which can be found at the top level of 10193323Sed * the sendmail distribution. 11193323Sed * 12193323Sed */ 13193323Sed 14193323Sed#include <sm/gen.h> 15193323Sed 16193323SedSM_IDSTR(copyright, 17193323Sed"@(#) Copyright (c) 1998-2001 Proofpoint, Inc. and its suppliers.\n\ 18234353Sdim All rights reserved.\n\ 19198396Srdivacky Copyright (c) 1983 Eric P. Allman. All rights reserved.\n\ 20193323Sed Copyright (c) 1988, 1993\n\ 21193323Sed The Regents of the University of California. All rights reserved.\n") 22193323Sed 23193323SedSM_IDSTR(id, "@(#)$Id: praliases.c,v 8.98 2013-11-22 20:51:53 ca Exp $") 24263508Sdim 25263508Sdim#include <sys/types.h> 26263508Sdim#include <ctype.h> 27263508Sdim#include <stdlib.h> 28263508Sdim#include <unistd.h> 29263508Sdim#ifdef EX_OK 30263508Sdim# undef EX_OK /* unistd.h may have another use for this */ 31263508Sdim#endif /* EX_OK */ 32263508Sdim#include <sysexits.h> 33263508Sdim 34263508Sdim 35263508Sdim#ifndef NOT_SENDMAIL 36263508Sdim# define NOT_SENDMAIL 37263508Sdim#endif /* ! NOT_SENDMAIL */ 38234353Sdim#include <sendmail/sendmail.h> 39263508Sdim#include <sendmail/pathnames.h> 40193323Sed#include <libsmdb/smdb.h> 41251662Sdim 42251662Sdimstatic void praliases __P((char *, int, char **)); 43251662Sdim 44251662Sdimuid_t RealUid; 45251662Sdimgid_t RealGid; 46251662Sdimchar *RealUserName; 47251662Sdimuid_t RunAsUid; 48251662Sdimgid_t RunAsGid; 49251662Sdimchar *RunAsUserName; 50251662Sdimint Verbose = 2; 51251662Sdimbool DontInitGroups = false; 52251662Sdimuid_t TrustedUid = 0; 53251662SdimBITMAP256 DontBlameSendmail; 54251662Sdim 55251662Sdim# define DELIMITERS " ,/" 56251662Sdim# define PATH_SEPARATOR ':' 57251662Sdim 58251662Sdimint 59251662Sdimmain(argc, argv) 60251662Sdim int argc; 61251662Sdim char **argv; 62251662Sdim{ 63251662Sdim char *cfile; 64251662Sdim char *filename = NULL; 65251662Sdim SM_FILE_T *cfp; 66251662Sdim int ch; 67251662Sdim char afilebuf[MAXLINE]; 68251662Sdim char buf[MAXLINE]; 69251662Sdim struct passwd *pw; 70251662Sdim static char rnamebuf[MAXNAME]; 71251662Sdim extern char *optarg; 72251662Sdim extern int optind; 73251662Sdim 74251662Sdim clrbitmap(DontBlameSendmail); 75251662Sdim RunAsUid = RealUid = getuid(); 76251662Sdim RunAsGid = RealGid = getgid(); 77251662Sdim pw = getpwuid(RealUid); 78251662Sdim if (pw != NULL) 79251662Sdim { 80251662Sdim if (strlen(pw->pw_name) > MAXNAME - 1) 81251662Sdim pw->pw_name[MAXNAME] = 0; 82251662Sdim sm_snprintf(rnamebuf, sizeof rnamebuf, "%s", pw->pw_name); 83234353Sdim } 84234353Sdim else 85234353Sdim (void) sm_snprintf(rnamebuf, sizeof rnamebuf, 86234353Sdim "Unknown UID %d", (int) RealUid); 87234353Sdim RunAsUserName = RealUserName = rnamebuf; 88234353Sdim 89234353Sdim cfile = getcfname(0, 0, SM_GET_SENDMAIL_CF, NULL); 90234353Sdim while ((ch = getopt(argc, argv, "C:f:")) != -1) 91234353Sdim { 92234353Sdim switch ((char)ch) { 93234353Sdim case 'C': 94234353Sdim cfile = optarg; 95234353Sdim break; 96234353Sdim case 'f': 97234353Sdim filename = optarg; 98234353Sdim break; 99234353Sdim case '?': 100234353Sdim default: 101234353Sdim (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, 102239462Sdim "usage: praliases [-C cffile] [-f aliasfile]" 103239462Sdim " [key ...]\n"); 104239462Sdim exit(EX_USAGE); 105239462Sdim } 106239462Sdim } 107239462Sdim argc -= optind; 108239462Sdim argv += optind; 109234353Sdim 110234353Sdim if (filename != NULL) 111234353Sdim { 112234353Sdim praliases(filename, argc, argv); 113234353Sdim exit(EX_OK); 114234353Sdim } 115234353Sdim 116234353Sdim if ((cfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, cfile, SM_IO_RDONLY, 117234353Sdim NULL)) == NULL) 118234353Sdim { 119234353Sdim (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, 120234353Sdim "praliases: %s: %s\n", cfile, 121234353Sdim sm_errstring(errno)); 122234353Sdim exit(EX_NOINPUT); 123234353Sdim } 124234353Sdim 125234353Sdim while (sm_io_fgets(cfp, SM_TIME_DEFAULT, buf, sizeof(buf)) >= 0) 126234353Sdim { 127234353Sdim register char *b, *p; 128234353Sdim 129234353Sdim b = strchr(buf, '\n'); 130234353Sdim if (b != NULL) 131234353Sdim *b = '\0'; 132234353Sdim 133234353Sdim b = buf; 134234353Sdim switch (*b++) 135234353Sdim { 136234353Sdim case 'O': /* option -- see if alias file */ 137234353Sdim if (sm_strncasecmp(b, " AliasFile", 10) == 0 && 138234353Sdim !(isascii(b[10]) && isalnum(b[10]))) 139234353Sdim { 140234353Sdim /* new form -- find value */ 141234353Sdim b = strchr(b, '='); 142234353Sdim if (b == NULL) 143234353Sdim continue; 144234353Sdim while (isascii(*++b) && isspace(*b)) 145239462Sdim continue; 146239462Sdim } 147239462Sdim else if (*b++ != 'A') 148239462Sdim { 149239462Sdim /* something else boring */ 150239462Sdim continue; 151239462Sdim } 152239462Sdim 153239462Sdim /* this is the A or AliasFile option -- save it */ 154239462Sdim if (sm_strlcpy(afilebuf, b, sizeof afilebuf) >= 155239462Sdim sizeof afilebuf) 156239462Sdim { 157234353Sdim (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, 158234353Sdim "praliases: AliasFile filename too long: %.30s\n", 159234353Sdim b); 160234353Sdim (void) sm_io_close(cfp, SM_TIME_DEFAULT); 161234353Sdim exit(EX_CONFIG); 162234353Sdim } 163234353Sdim b = afilebuf; 164239462Sdim 165251662Sdim for (p = b; p != NULL; ) 166234353Sdim { 167239462Sdim while (isascii(*p) && isspace(*p)) 168251662Sdim p++; 169239462Sdim if (*p == '\0') 170234353Sdim break; 171239462Sdim b = p; 172234353Sdim 173234353Sdim p = strpbrk(p, DELIMITERS); 174251662Sdim 175251662Sdim /* find end of spec */ 176251662Sdim if (p != NULL) 177234353Sdim { 178239462Sdim bool quoted = false; 179234353Sdim 180251662Sdim for (; *p != '\0'; p++) 181234353Sdim { 182234353Sdim /* 183234353Sdim ** Don't break into a quoted 184234353Sdim ** string. 185234353Sdim */ 186234353Sdim 187234353Sdim if (*p == '"') 188234353Sdim quoted = !quoted; 189239462Sdim else if (*p == ',' && !quoted) 190239462Sdim break; 191239462Sdim } 192249423Sdim 193249423Sdim /* No more alias specs follow */ 194249423Sdim if (*p == '\0') 195249423Sdim { 196234353Sdim /* chop trailing whitespace */ 197234353Sdim while (isascii(*p) && 198234353Sdim isspace(*p) && 199234353Sdim p > b) 200234353Sdim p--; 201234353Sdim *p = '\0'; 202234353Sdim p = NULL; 203234353Sdim } 204234353Sdim } 205234353Sdim 206234353Sdim if (p != NULL) 207234353Sdim { 208234353Sdim char *e = p - 1; 209234353Sdim 210263508Sdim /* chop trailing whitespace */ 211263508Sdim while (isascii(*e) && 212263508Sdim isspace(*e) && 213263508Sdim e > b) 214263508Sdim e--; 215263508Sdim *++e = '\0'; 216263508Sdim *p++ = '\0'; 217263508Sdim } 218263508Sdim praliases(b, argc, argv); 219263508Sdim } 220263508Sdim 221263508Sdim default: 222263508Sdim continue; 223263508Sdim } 224234353Sdim } 225234353Sdim (void) sm_io_close(cfp, SM_TIME_DEFAULT); 226234353Sdim exit(EX_OK); 227234353Sdim /* NOTREACHED */ 228234353Sdim return EX_OK; 229234353Sdim} 230234353Sdim 231234353Sdimstatic void 232234353Sdimpraliases(filename, argc, argv) 233234353Sdim char *filename; 234234353Sdim int argc; 235234353Sdim char **argv; 236234353Sdim{ 237234353Sdim int result; 238234353Sdim char *colon; 239234353Sdim char *db_name; 240234353Sdim char *db_type; 241234353Sdim SMDB_DATABASE *database = NULL; 242234353Sdim SMDB_CURSOR *cursor = NULL; 243234353Sdim SMDB_DBENT db_key, db_value; 244234353Sdim SMDB_DBPARAMS params; 245249423Sdim SMDB_USER_INFO user_info; 246249423Sdim 247249423Sdim colon = strchr(filename, PATH_SEPARATOR); 248249423Sdim if (colon == NULL) 249249423Sdim { 250249423Sdim db_name = filename; 251249423Sdim db_type = SMDB_TYPE_DEFAULT; 252249423Sdim } 253249423Sdim else 254249423Sdim { 255234353Sdim *colon = '\0'; 256234353Sdim db_name = colon + 1; 257234353Sdim db_type = filename; 258234353Sdim } 259234353Sdim 260234353Sdim /* clean off arguments */ 261234353Sdim for (;;) 262234353Sdim { 263234353Sdim while (isascii(*db_name) && isspace(*db_name)) 264234353Sdim db_name++; 265234353Sdim 266234353Sdim if (*db_name != '-') 267234353Sdim break; 268234353Sdim while (*db_name != '\0' && 269234353Sdim !(isascii(*db_name) && isspace(*db_name))) 270234353Sdim db_name++; 271234353Sdim } 272234353Sdim 273234353Sdim /* Skip non-file based DB types */ 274239462Sdim if (db_type != NULL && *db_type != '\0') 275239462Sdim { 276239462Sdim if (db_type != SMDB_TYPE_DEFAULT && 277239462Sdim strcmp(db_type, "hash") != 0 && 278239462Sdim strcmp(db_type, "btree") != 0 && 279239462Sdim strcmp(db_type, "dbm") != 0) 280239462Sdim { 281239462Sdim sm_io_fprintf(smioerr, SM_TIME_DEFAULT, 282239462Sdim "praliases: Skipping non-file based alias type %s\n", 283239462Sdim db_type); 284239462Sdim return; 285239462Sdim } 286234353Sdim } 287234353Sdim 288234353Sdim if (*db_name == '\0' || (db_type != NULL && *db_type == '\0')) 289234353Sdim { 290234353Sdim if (colon != NULL) 291234353Sdim *colon = ':'; 292234353Sdim (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, 293234353Sdim "praliases: illegal alias specification: %s\n", filename); 294234353Sdim goto fatal; 295234353Sdim } 296234353Sdim 297234353Sdim memset(¶ms, '\0', sizeof params); 298234353Sdim params.smdbp_cache_size = 1024 * 1024; 299234353Sdim 300234353Sdim user_info.smdbu_id = RunAsUid; 301234353Sdim user_info.smdbu_group_id = RunAsGid; 302234353Sdim (void) sm_strlcpy(user_info.smdbu_name, RunAsUserName, 303234353Sdim SMDB_MAX_USER_NAME_LEN); 304234353Sdim 305249423Sdim result = smdb_open_database(&database, db_name, O_RDONLY, 0, 306249423Sdim SFF_ROOTOK, db_type, &user_info, ¶ms); 307249423Sdim if (result != SMDBE_OK) 308249423Sdim { 309249423Sdim sm_io_fprintf(smioerr, SM_TIME_DEFAULT, 310234353Sdim "praliases: %s: open: %s\n", 311234353Sdim db_name, sm_errstring(result)); 312234353Sdim goto fatal; 313234353Sdim } 314234353Sdim 315234353Sdim if (argc == 0) 316234353Sdim { 317234353Sdim memset(&db_key, '\0', sizeof db_key); 318234353Sdim memset(&db_value, '\0', sizeof db_value); 319234353Sdim 320234353Sdim result = database->smdb_cursor(database, &cursor, 0); 321234353Sdim if (result != SMDBE_OK) 322234353Sdim { 323234353Sdim (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, 324239462Sdim "praliases: %s: set cursor: %s\n", db_name, 325239462Sdim sm_errstring(result)); 326234353Sdim goto fatal; 327239462Sdim } 328263508Sdim 329263508Sdim while ((result = cursor->smdbc_get(cursor, &db_key, &db_value, 330239462Sdim SMDB_CURSOR_GET_NEXT)) == 331239462Sdim SMDBE_OK) 332234353Sdim { 333234353Sdim#if 0 334234353Sdim /* skip magic @:@ entry */ 335234353Sdim if (db_key.size == 2 && 336234353Sdim db_key.data[0] == '@' && 337234353Sdim db_key.data[1] == '\0' && 338234353Sdim db_value.size == 2 && 339239462Sdim db_value.data[0] == '@' && 340234353Sdim db_value.data[1] == '\0') 341234353Sdim continue; 342234353Sdim#endif /* 0 */ 343234353Sdim 344234353Sdim (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 345249423Sdim "%.*s:%.*s\n", 346249423Sdim (int) db_key.size, 347249423Sdim (char *) db_key.data, 348249423Sdim (int) db_value.size, 349249423Sdim (char *) db_value.data); 350263508Sdim } 351249423Sdim 352193323Sed if (result != SMDBE_OK && result != SMDBE_LAST_ENTRY) 353193323Sed { 354193323Sed (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, 355212904Sdim "praliases: %s: get value at cursor: %s\n", 356193323Sed db_name, sm_errstring(result)); 357193323Sed goto fatal; 358193323Sed } 359193323Sed } 360193323Sed else for (; *argv != NULL; ++argv) 361212904Sdim { 362206124Srdivacky int get_res; 363206124Srdivacky 364206124Srdivacky memset(&db_key, '\0', sizeof db_key); 365193323Sed memset(&db_value, '\0', sizeof db_value); 366234353Sdim db_key.data = *argv; 367212904Sdim db_key.size = strlen(*argv); 368193323Sed get_res = database->smdb_get(database, &db_key, &db_value, 0); 369234353Sdim if (get_res == SMDBE_NOT_FOUND) 370212904Sdim { 371193323Sed db_key.size++; 372218893Sdim get_res = database->smdb_get(database, &db_key, 373218893Sdim &db_value, 0); 374218893Sdim } 375234353Sdim if (get_res == SMDBE_OK) 376234353Sdim { 377234353Sdim (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 378234353Sdim "%.*s:%.*s\n", 379234353Sdim (int) db_key.size, 380193323Sed (char *) db_key.data, 381193323Sed (int) db_value.size, 382193323Sed (char *) db_value.data); 383212904Sdim } 384212904Sdim else 385239462Sdim (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 386239462Sdim "%s: No such key\n", 387239462Sdim (char *)db_key.data); 388239462Sdim } 389218893Sdim 390218893Sdim fatal: 391218893Sdim if (cursor != NULL) 392234353Sdim (void) cursor->smdbc_close(cursor); 393193323Sed if (database != NULL) 394193323Sed (void) database->smdb_close(database); 395212904Sdim if (colon != NULL) 396193323Sed *colon = ':'; 397234353Sdim return; 398234353Sdim} 399226633Sdim