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.20 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 pw = finduser(buf); 236 if (pw == NULL) 237 { 238 a->q_flags |= QBADADDR; 239 giveresponse(EX_NOUSER, TRUE, m); 240 } 241 else 242 { 243 if (strcmp(a->q_user, pw->pw_name) != 0) 244 { 245 a->q_user = newstr(pw->pw_name); 246 strcpy(buf, pw->pw_name); 247 } 248 a->q_home = newstr(pw->pw_dir); 249 a->q_uid = pw->pw_uid; 250 a->q_gid = pw->pw_gid; 251 a->q_flags |= QGOODUID; 252 if (!quoted) 253 forward(a); 254 } 255 } 256 } 257 } 258 /* 259 ** FINDUSER -- find the password entry for a user. 260 ** 261 ** This looks a lot like getpwnam, except that it may want to 262 ** do some fancier pattern matching in /etc/passwd. 263 ** 264 ** Parameters: 265 ** name -- the name to match against. 266 ** 267 ** Returns: 268 ** A pointer to a pw struct. 269 ** NULL if name is unknown or ambiguous. 270 ** 271 ** Side Effects: 272 ** none. 273 */ 274 275 struct passwd * 276 finduser(name) 277 char *name; 278 { 279 extern struct passwd *getpwent(); 280 register struct passwd *pw; 281 282 setpwent(); 283 while ((pw = getpwent()) != NULL) 284 { 285 char buf[MAXNAME]; 286 register char *p; 287 extern bool sameword(); 288 bool gotaspace; 289 290 if (strcmp(pw->pw_name, name) == 0) 291 return (pw); 292 buildfname(pw->pw_gecos, pw->pw_name, buf); 293 gotaspace = FALSE; 294 for (p = buf; (p = index(p, ' ')) != NULL; ) 295 { 296 *p++ = SPACESUB & 0177; 297 gotaspace = TRUE; 298 } 299 if (gotaspace && sameword(buf, name)) 300 { 301 if (Verbose) 302 message(Arpa_Info, "sending to login name %s", 303 pw->pw_name); 304 return (pw); 305 } 306 } 307 return (NULL); 308 } 309 /* 310 ** WRITABLE -- predicate returning if the file is writable. 311 ** 312 ** This routine must duplicate the algorithm in sys/fio.c. 313 ** Unfortunately, we cannot use the access call since we 314 ** won't necessarily be the real uid when we try to 315 ** actually open the file. 316 ** 317 ** Notice that ANY file with ANY execute bit is automatically 318 ** not writable. This is also enforced by mailfile. 319 ** 320 ** Parameters: 321 ** s -- pointer to a stat struct for the file. 322 ** 323 ** Returns: 324 ** TRUE -- if we will be able to write this file. 325 ** FALSE -- if we cannot write this file. 326 ** 327 ** Side Effects: 328 ** none. 329 */ 330 331 bool 332 writable(s) 333 register struct stat *s; 334 { 335 int euid, egid; 336 int bits; 337 338 if (bitset(0111, s->st_mode)) 339 return (FALSE); 340 euid = getruid(); 341 egid = getrgid(); 342 if (geteuid() == 0) 343 { 344 if (bitset(S_ISUID, s->st_mode)) 345 euid = s->st_uid; 346 if (bitset(S_ISGID, s->st_mode)) 347 egid = s->st_gid; 348 } 349 350 if (euid == 0) 351 return (TRUE); 352 bits = S_IWRITE; 353 if (euid != s->st_uid) 354 { 355 bits >>= 3; 356 if (egid != s->st_gid) 357 bits >>= 3; 358 } 359 return ((s->st_mode & bits) != 0); 360 } 361 /* 362 ** INCLUDE -- handle :include: specification. 363 ** 364 ** Parameters: 365 ** fname -- filename to include. 366 ** msg -- message to print in verbose mode. 367 ** ctladdr -- address template to use to fill in these 368 ** addresses -- effective user/group id are 369 ** the important things. 370 ** 371 ** Returns: 372 ** none. 373 ** 374 ** Side Effects: 375 ** reads the :include: file and sends to everyone 376 ** listed in that file. 377 */ 378 379 include(fname, msg, ctladdr) 380 char *fname; 381 char *msg; 382 ADDRESS *ctladdr; 383 { 384 char buf[MAXLINE]; 385 register FILE *fp; 386 char *oldto = To; 387 388 fp = fopen(fname, "r"); 389 if (fp == NULL) 390 { 391 usrerr("Cannot open %s", fname); 392 return; 393 } 394 if (getctladdr(ctladdr) == NULL) 395 { 396 struct stat st; 397 398 if (fstat(fileno(fp), &st) < 0) 399 syserr("Cannot fstat %s!", fname); 400 ctladdr->q_uid = st.st_uid; 401 ctladdr->q_gid = st.st_gid; 402 ctladdr->q_flags |= QGOODUID; 403 } 404 405 /* read the file -- each line is a comma-separated list. */ 406 while (fgets(buf, sizeof buf, fp) != NULL) 407 { 408 register char *p = index(buf, '\n'); 409 410 if (p != NULL) 411 *p = '\0'; 412 if (buf[0] == '\0') 413 continue; 414 To = oldto; 415 if (Verbose) 416 message(Arpa_Info, "%s to %s", msg, buf); 417 AliasLevel++; 418 sendto(buf, 1, ctladdr); 419 AliasLevel--; 420 } 421 422 (void) fclose(fp); 423 } 424 /* 425 ** SENDTOARGV -- send to an argument vector. 426 ** 427 ** Parameters: 428 ** argv -- argument vector to send to. 429 ** 430 ** Returns: 431 ** none. 432 ** 433 ** Side Effects: 434 ** puts all addresses on the argument vector onto the 435 ** send queue. 436 */ 437 438 sendtoargv(argv) 439 register char **argv; 440 { 441 register char *p; 442 extern bool sameword(); 443 444 while ((p = *argv++) != NULL) 445 { 446 if (argv[0] != NULL && argv[1] != NULL && sameword(argv[0], "at")) 447 { 448 char nbuf[MAXNAME]; 449 450 if (strlen(p) + strlen(argv[1]) + 2 > sizeof nbuf) 451 usrerr("address overflow"); 452 else 453 { 454 (void) strcpy(nbuf, p); 455 (void) strcat(nbuf, "@"); 456 (void) strcat(nbuf, argv[1]); 457 p = newstr(nbuf); 458 argv += 2; 459 } 460 } 461 sendto(p, 0, NULL); 462 } 463 } 464 /* 465 ** GETCTLADDR -- get controlling address from an address header. 466 ** 467 ** If none, get one corresponding to the effective userid. 468 ** 469 ** Parameters: 470 ** a -- the address to find the controller of. 471 ** 472 ** Returns: 473 ** the controlling address. 474 ** 475 ** Side Effects: 476 ** none. 477 */ 478 479 ADDRESS * 480 getctladdr(a) 481 register ADDRESS *a; 482 { 483 while (a != NULL && !bitset(QGOODUID, a->q_flags)) 484 a = a->q_alias; 485 return (a); 486 } 487