1 # include <pwd.h> 2 # include <sys/types.h> 3 # include <sys/stat.h> 4 # include "sendmail.h" 5 6 static char SccsId[] = "@(#)recipient.c 3.21 09/16/81"; 7 8 /* 9 ** SENDTO -- Designate a send list. 10 ** 11 ** The parameter is a comma-separated list of people to send to. 12 ** This routine arranges to send to all of them. 13 ** 14 ** Parameters: 15 ** list -- the send list. 16 ** copyf -- the copy flag; passed to parse. 17 ** ctladdr -- the address template for the person to 18 ** send to -- effective uid/gid are important. 19 ** 20 ** Returns: 21 ** none 22 ** 23 ** Side Effects: 24 ** none. 25 */ 26 27 # define MAXRCRSN 10 28 29 sendto(list, copyf, ctladdr) 30 char *list; 31 int copyf; 32 ADDRESS *ctladdr; 33 { 34 register char *p; 35 bool more; /* set if more addresses to send to */ 36 ADDRESS *al; /* list of addresses to send to */ 37 38 # ifdef DEBUG 39 if (Debug > 1) 40 printf("sendto: %s\n", list); 41 # endif DEBUG 42 43 more = TRUE; 44 al = NULL; 45 for (p = list; more; ) 46 { 47 register char *q; 48 register char c; 49 ADDRESS *a; 50 51 /* find the end of this address */ 52 while (*p == ' ' || *p == '\t') 53 p++; 54 q = p; 55 while ((c = *p++) != '\0' && c != ',' && c != '\n') 56 continue; 57 more = c != '\0'; 58 *--p = '\0'; 59 if (more) 60 p++; 61 if (*q == '\0') 62 continue; 63 64 /* parse the address */ 65 if ((a = parse(q, (ADDRESS *) NULL, copyf)) == NULL) 66 continue; 67 68 /* put it on the local send list */ 69 a->q_next = al; 70 a->q_alias = ctladdr; 71 al = a; 72 } 73 74 /* arrange to send to everyone on the local send list */ 75 while (al != NULL) 76 { 77 register ADDRESS *a = al; 78 79 al = a->q_next; 80 recipient(a); 81 } 82 83 To = NULL; 84 } 85 /* 86 ** RECIPIENT -- Designate a message recipient 87 ** 88 ** Saves the named person for future mailing. 89 ** 90 ** Parameters: 91 ** a -- the (preparsed) address header for the recipient. 92 ** 93 ** Returns: 94 ** none. 95 ** 96 ** Side Effects: 97 ** none. 98 */ 99 100 recipient(a) 101 register ADDRESS *a; 102 { 103 register ADDRESS *q; 104 ADDRESS **pq; 105 register struct mailer *m; 106 extern ADDRESS *getctladdr(); 107 108 To = a->q_paddr; 109 m = Mailer[a->q_mailer]; 110 errno = 0; 111 # ifdef DEBUG 112 if (Debug) 113 printf("recipient(%s)\n", To); 114 # endif DEBUG 115 116 /* break aliasing loops */ 117 if (AliasLevel > MAXRCRSN) 118 { 119 usrerr("aliasing/forwarding loop broken"); 120 return; 121 } 122 123 /* 124 ** Do sickly crude mapping for program mailing, etc. 125 */ 126 127 if (a->q_mailer == MN_LOCAL) 128 { 129 if (a->q_user[0] == '|') 130 { 131 a->q_mailer = MN_PROG; 132 m = Mailer[MN_PROG]; 133 a->q_user++; 134 if (a->q_alias == NULL && Debug == 0) 135 { 136 usrerr("Cannot mail directly to programs"); 137 a->q_flags |= QDONTSEND; 138 } 139 } 140 } 141 142 /* 143 ** Look up this person in the recipient list. If they 144 ** are there already, return, otherwise continue. 145 ** If the list is empty, just add it. 146 */ 147 148 for (pq = &m->m_sendq; (q = *pq) != NULL; pq = &q->q_next) 149 { 150 if (!ForceMail && sameaddr(q, a, FALSE)) 151 { 152 # ifdef DEBUG 153 if (Debug) 154 printf("(%s in sendq)\n", a->q_paddr); 155 # endif DEBUG 156 if (Verbose && !bitset(QDONTSEND, a->q_flags)) 157 message(Arpa_Info, "duplicate suppressed"); 158 return; 159 } 160 } 161 162 /* add address on list */ 163 *pq = a; 164 a->q_next = NULL; 165 if (DontSend) 166 a->q_flags |= QDONTSEND; 167 168 /* 169 ** Alias the name and handle :include: specs. 170 */ 171 172 if (a->q_mailer == MN_LOCAL) 173 { 174 if (strncmp(a->q_user, ":include:", 9) == 0) 175 { 176 a->q_flags |= QDONTSEND; 177 if (a->q_alias == NULL && Debug == 0) 178 usrerr("Cannot mail directly to :include:s"); 179 else 180 { 181 if (Verbose) 182 message(Arpa_Info, "including file %s", &a->q_user[9]); 183 include(&a->q_user[9], " sending", a); 184 } 185 } 186 else 187 alias(a); 188 } 189 190 /* 191 ** If the user is local and still being sent, verify that 192 ** the address is good. If it is, try to forward. 193 ** If the address is already good, we have a forwarding 194 ** loop. This can be broken by just sending directly to 195 ** the user (which is probably correct anyway). 196 */ 197 198 if (!bitset(QDONTSEND, a->q_flags) && a->q_mailer == MN_LOCAL) 199 { 200 char buf[MAXNAME]; 201 register char *p; 202 struct stat stb; 203 extern bool writable(); 204 bool quoted = FALSE; 205 206 strcpy(buf, a->q_user); 207 for (p = buf; *p != '\0' && !quoted; p++) 208 { 209 if (!isascii(*p)) 210 quoted = TRUE; 211 } 212 stripquotes(buf, TRUE); 213 214 /* see if this is to a file */ 215 if ((p = rindex(buf, '/')) != NULL) 216 { 217 /* check if writable or creatable */ 218 if (a->q_alias == NULL && Debug == 0) 219 { 220 usrerr("Cannot mail directly to files"); 221 a->q_flags |= QDONTSEND; 222 } 223 else if ((stat(buf, &stb) >= 0) ? (!writable(&stb)) : 224 (*p = '\0', access(buf, 3) < 0)) 225 { 226 a->q_flags |= QBADADDR; 227 giveresponse(EX_CANTCREAT, TRUE, m); 228 } 229 } 230 else 231 { 232 register struct passwd *pw; 233 extern struct passwd *finduser(); 234 235 /* warning -- finduser may trash buf */ 236 pw = finduser(buf); 237 if (pw == NULL) 238 { 239 a->q_flags |= QBADADDR; 240 giveresponse(EX_NOUSER, TRUE, m); 241 } 242 else 243 { 244 if (strcmp(a->q_user, pw->pw_name) != 0) 245 { 246 a->q_user = newstr(pw->pw_name); 247 strcpy(buf, pw->pw_name); 248 } 249 a->q_home = newstr(pw->pw_dir); 250 a->q_uid = pw->pw_uid; 251 a->q_gid = pw->pw_gid; 252 a->q_flags |= QGOODUID; 253 if (!quoted) 254 forward(a); 255 } 256 } 257 } 258 } 259 /* 260 ** FINDUSER -- find the password entry for a user. 261 ** 262 ** This looks a lot like getpwnam, except that it may want to 263 ** do some fancier pattern matching in /etc/passwd. 264 ** 265 ** Parameters: 266 ** name -- the name to match against. 267 ** 268 ** Returns: 269 ** A pointer to a pw struct. 270 ** NULL if name is unknown or ambiguous. 271 ** 272 ** Side Effects: 273 ** may modify name. 274 */ 275 276 struct passwd * 277 finduser(name) 278 char *name; 279 { 280 extern struct passwd *getpwent(); 281 register struct passwd *pw; 282 register char *p; 283 284 /* 285 ** Make name canonical. 286 */ 287 288 for (p = name; *p != '\0'; p++) 289 { 290 if (*p == (SPACESUB & 0177) || *p == '_') 291 *p = ' '; 292 } 293 294 setpwent(); 295 while ((pw = getpwent()) != NULL) 296 { 297 char buf[MAXNAME]; 298 extern bool sameword(); 299 300 if (strcmp(pw->pw_name, name) == 0) 301 return (pw); 302 buildfname(pw->pw_gecos, pw->pw_name, buf); 303 if (index(buf, ' ') != NULL && sameword(buf, name)) 304 { 305 if (Verbose) 306 message(Arpa_Info, "sending to login name %s", 307 pw->pw_name); 308 return (pw); 309 } 310 } 311 return (NULL); 312 } 313 /* 314 ** WRITABLE -- predicate returning if the file is writable. 315 ** 316 ** This routine must duplicate the algorithm in sys/fio.c. 317 ** Unfortunately, we cannot use the access call since we 318 ** won't necessarily be the real uid when we try to 319 ** actually open the file. 320 ** 321 ** Notice that ANY file with ANY execute bit is automatically 322 ** not writable. This is also enforced by mailfile. 323 ** 324 ** Parameters: 325 ** s -- pointer to a stat struct for the file. 326 ** 327 ** Returns: 328 ** TRUE -- if we will be able to write this file. 329 ** FALSE -- if we cannot write this file. 330 ** 331 ** Side Effects: 332 ** none. 333 */ 334 335 bool 336 writable(s) 337 register struct stat *s; 338 { 339 int euid, egid; 340 int bits; 341 342 if (bitset(0111, s->st_mode)) 343 return (FALSE); 344 euid = getruid(); 345 egid = getrgid(); 346 if (geteuid() == 0) 347 { 348 if (bitset(S_ISUID, s->st_mode)) 349 euid = s->st_uid; 350 if (bitset(S_ISGID, s->st_mode)) 351 egid = s->st_gid; 352 } 353 354 if (euid == 0) 355 return (TRUE); 356 bits = S_IWRITE; 357 if (euid != s->st_uid) 358 { 359 bits >>= 3; 360 if (egid != s->st_gid) 361 bits >>= 3; 362 } 363 return ((s->st_mode & bits) != 0); 364 } 365 /* 366 ** INCLUDE -- handle :include: specification. 367 ** 368 ** Parameters: 369 ** fname -- filename to include. 370 ** msg -- message to print in verbose mode. 371 ** ctladdr -- address template to use to fill in these 372 ** addresses -- effective user/group id are 373 ** the important things. 374 ** 375 ** Returns: 376 ** none. 377 ** 378 ** Side Effects: 379 ** reads the :include: file and sends to everyone 380 ** listed in that file. 381 */ 382 383 include(fname, msg, ctladdr) 384 char *fname; 385 char *msg; 386 ADDRESS *ctladdr; 387 { 388 char buf[MAXLINE]; 389 register FILE *fp; 390 char *oldto = To; 391 392 fp = fopen(fname, "r"); 393 if (fp == NULL) 394 { 395 usrerr("Cannot open %s", fname); 396 return; 397 } 398 if (getctladdr(ctladdr) == NULL) 399 { 400 struct stat st; 401 402 if (fstat(fileno(fp), &st) < 0) 403 syserr("Cannot fstat %s!", fname); 404 ctladdr->q_uid = st.st_uid; 405 ctladdr->q_gid = st.st_gid; 406 ctladdr->q_flags |= QGOODUID; 407 } 408 409 /* read the file -- each line is a comma-separated list. */ 410 while (fgets(buf, sizeof buf, fp) != NULL) 411 { 412 register char *p = index(buf, '\n'); 413 414 if (p != NULL) 415 *p = '\0'; 416 if (buf[0] == '\0') 417 continue; 418 To = oldto; 419 if (Verbose) 420 message(Arpa_Info, "%s to %s", msg, buf); 421 AliasLevel++; 422 sendto(buf, 1, ctladdr); 423 AliasLevel--; 424 } 425 426 (void) fclose(fp); 427 } 428 /* 429 ** SENDTOARGV -- send to an argument vector. 430 ** 431 ** Parameters: 432 ** argv -- argument vector to send to. 433 ** 434 ** Returns: 435 ** none. 436 ** 437 ** Side Effects: 438 ** puts all addresses on the argument vector onto the 439 ** send queue. 440 */ 441 442 sendtoargv(argv) 443 register char **argv; 444 { 445 register char *p; 446 extern bool sameword(); 447 448 while ((p = *argv++) != NULL) 449 { 450 if (argv[0] != NULL && argv[1] != NULL && sameword(argv[0], "at")) 451 { 452 char nbuf[MAXNAME]; 453 454 if (strlen(p) + strlen(argv[1]) + 2 > sizeof nbuf) 455 usrerr("address overflow"); 456 else 457 { 458 (void) strcpy(nbuf, p); 459 (void) strcat(nbuf, "@"); 460 (void) strcat(nbuf, argv[1]); 461 p = newstr(nbuf); 462 argv += 2; 463 } 464 } 465 sendto(p, 0, NULL); 466 } 467 } 468 /* 469 ** GETCTLADDR -- get controlling address from an address header. 470 ** 471 ** If none, get one corresponding to the effective userid. 472 ** 473 ** Parameters: 474 ** a -- the address to find the controller of. 475 ** 476 ** Returns: 477 ** the controlling address. 478 ** 479 ** Side Effects: 480 ** none. 481 */ 482 483 ADDRESS * 484 getctladdr(a) 485 register ADDRESS *a; 486 { 487 while (a != NULL && !bitset(QGOODUID, a->q_flags)) 488 a = a->q_alias; 489 return (a); 490 } 491