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