|
|
1.1 root 1: /*
2: * This software is Copyright (c) 1986 by Rick Adams.
3: *
4: * Permission is hereby granted to copy, reproduce, redistribute or
5: * otherwise use this software as long as: there is no monetary
6: * profit gained specifically from the use or reproduction or this
7: * software, it is not sold, rented, traded or otherwise marketed, and
8: * this copyright notice is included prominently in any copy
9: * made.
10: *
11: * The author make no claims as to the fitness or correctness of
12: * this software for any use whatsoever, and it is provided as is.
13: * Any use of this software is at the user's own risk.
14: *
15: * Control message handling code. Deal with messages which are to be
16: * acted on by netnews itself rather than by people.
17: *
18: * See defs.h "news_version" for the real version of netnews.
19: */
20:
21: #ifdef SCCSID
22: static char *SccsId = "@(#)control.c 2.43 3/19/86";
23: #endif /* SCCSID */
24:
25: #include "iparams.h"
26:
27: #define eq(msg) (strcmp(msg, cargv[0]) == 0)
28:
29: int cargc;
30: char **cargv;
31:
32: FILE *hfopen();
33: FILE *popen(), *mhopen(), *mailhdr();
34:
35: char *senderof();
36: #ifdef u370
37: static struct hbuf htmp;
38: #endif /* u370 */
39:
40: control(h)
41: struct hbuf *h;
42: {
43: register char *ctlmsgtext;
44:
45: if (strncmp(h->title, "cmsg ", 5) == 0) {
46: register char *cp1, *cp2;
47: cp1 = h->title;
48: cp2 = h->title + 5;
49: while (*cp1++ = *cp2++)
50: ;
51: }
52:
53: if (*h->ctlmsg)
54: ctlmsgtext = h->ctlmsg;
55: else
56: ctlmsgtext = h->title;
57: log("Ctl Msg %s from %s: %s", h->nbuf, h->path, ctlmsgtext);
58: /*
59: * Control messages have the standard format
60: * command [args]
61: * much like shell commands. Each site has the option
62: * of customizing this code to deal with control messages
63: * as they see fit, but we would like to buy back the
64: * code, ifdeffed or otherwise parameterized, to simplify
65: * the maintenence issues.
66: */
67: argparse(ctlmsgtext);
68:
69: if (eq("cancel"))
70: return c_cancel(cargc, cargv);
71: else if (eq("newgroup"))
72: c_newgroup(cargc, cargv);
73: else if (eq("ihave"))
74: c_ihave(cargc, cargv);
75: else if (eq("sendme"))
76: c_sendme(cargc, cargv);
77: else if (eq("sendbad"))
78: c_sendme(cargc, cargv);
79: else if (eq("rmgroup"))
80: c_rmgroup(cargc, cargv);
81: else if (eq("sendsys"))
82: c_sendsys(cargc, cargv);
83: else if (eq("senduuname"))
84: c_senduuname(cargc, cargv);
85: else if (eq("version"))
86: c_version(cargc, cargv);
87: else if (eq("checkgroups"))
88: c_checkgroups(cargc, cargv);
89: else if (eq("delsub"))
90: c_unimp(cargc, cargv);
91: else
92: c_unknown(h, ctlmsgtext);
93: return 0;
94: }
95:
96: /*
97: * Parse the string str into separate words in cargc and cargv
98: * as per the usual UNIX convention. Nothing fancy here, just
99: * blanks and tabs separating words.
100: */
101: argparse(str)
102: char *str;
103: {
104: static char *cavpbuf[20];
105: static char cavbuf[256];
106: char *nextfree = cavbuf;
107:
108: if (str == '\0')
109: xerror("Control message %s has no title", header.ident);
110: cargc = (*str != '\0');
111: cargv = cavpbuf;
112: cargv[0] = cavbuf;
113:
114: while (*str) {
115: if (*str <= ' ') {
116: *nextfree++ = 0;
117: cargv[cargc] = nextfree;
118: cargc++;
119: /* skip over white space */
120: while (*str != '\0' && *str <= ' ')
121: str++;
122: if (*str == '\0') /* line ends in white space */
123: return;
124: } else
125: *nextfree++ = *str++;
126: }
127: }
128:
129: /*
130: * ihave <artid> <remotesys>
131: * The other system is telling you it has article <artid>, in case
132: * you decide you want it to transmit it to you.
133: */
134: c_ihave(argc, argv)
135: char **argv;
136: {
137: char tl[256], ng[256];
138: #ifndef u370
139: struct hbuf htmp;
140: #endif /* !u370 */
141:
142: if (argc < 2)
143: xerror("ihave: Not enough arguments.");
144: /*
145: * Check that we haven't already seen it (history)
146: * and then send back a "sendme" message if we subscribe.
147: */
148: (void) strncpy(htmp.ident, argv[1], BUFLEN);
149: if (history(&htmp) == 0) {
150: /* Should probably check SUBFILE here. */
151: (void) sprintf(tl, "sendme %s %s", argv[1], FULLSYSNAME);
152: (void) sprintf(ng, "to.%s.ctl", argv[2]);
153: xmitmsg(argv[2], tl, ng);
154: }
155: }
156:
157: /*
158: * sendme <artid> ... <remotesys>
159: * The other system wants me to send him article <artid>.
160: */
161: c_sendme(argc, argv)
162: char **argv;
163: {
164: int i;
165: FILE *fp;
166: struct srec srec;
167: #ifndef u370
168: struct hbuf htmp;
169: #endif /* !u370 */
170:
171: if (argc < 2)
172: xerror("sendme: Not enough arguments.");
173: /* Don't ask for it from myself */
174: if (strncmp(FULLSYSNAME, argv[argc], SNLN) == 0)
175: return;
176: /* Find the sys record */
177: s_openr();
178: while (s_read(&srec)) {
179: if (strncmp(srec.s_name, argv[argc], SNLN))
180: continue;
181: /* It's the right one. Send them. */
182: for (i=1; i<argc; i++) {
183: fp = hfopen(argv[i]);
184: htmp.unrec[0] = NULL;
185: if (hread(&htmp, fp, TRUE) == NULL) {
186: if (bfr[0] == '/') {
187: fp = xfopen(bfr, "r");
188: if (hread(&htmp, fp, TRUE) == NULL)
189: xerror("Article %s is garbled.", bfr);
190: } else
191: xerror("Article %s is garbled.", argv[i]);
192: }
193: (void) fseek(fp, 0L, 0);
194: if (strcmp(argv[0], "sendme") == 0) {
195: /* check that other sys subscribes. */
196: if (!ngmatch(htmp.nbuf, srec.s_nbuf) ||
197: !(htmp.distribution[0] == '\0' ||
198: ngmatch(htmp.distribution, srec.s_nbuf)))
199: continue;
200: }
201: transmit(&srec, fp, 0, (char **)0, 0);
202: /* transmit does fclose(fp) */
203: }
204: return;
205: }
206: xerror("Cannot find system %s to send article %s to.", argv[argc],
207: argv[1]);
208: }
209:
210: /*
211: * newgroup <groupname>
212: * A new newsgroup has been created.
213: * The body of the article, if present, is a description of the
214: * purpose of the newsgroup.
215: *
216: */
217: c_newgroup(argc, argv)
218: char **argv;
219: {
220: FILE *fd;
221: int didcreate = 0;
222:
223: if (argc < 1)
224: xerror("newgroup: Not enough arguments.");
225: if (validng(argv[1]))
226: return;
227: if (header.approved[0] == '\0')
228: xerror("newgroup: %s not approved", argv[1]);
229:
230: #ifndef NONEWGROUPS
231: #ifdef ORGDISTRIB
232: if (!strcmp(ORGDISTRIB, header.distribution)) {
233: didcreate++;
234: #endif /* ORGDISTRIB */
235: actfp = xfopen(ACTIVE, "a");
236: fprintf(actfp, "%s 00000 00001 y\n", argv[1]);
237: (void) fclose(actfp);
238: #ifdef ORGDISTRIB
239: }
240: #endif /* ORGDISTRIB */
241: #endif /* !NONEWGROUPS */
242:
243: #ifdef NOTIFY
244: fd = mailhdr((struct hbuf *)NULL, "creation of new newsgroup");
245: if (fd != NULL) {
246: if (didcreate)
247: fprintf(fd, "A new newsgroup called '%s' has been created by %s.\n",
248: argv[1], header.path);
249: else
250: fprintf(fd, "%s requested that a new newsgroup called '%s' be created.\n",
251: header.path, argv[1]);
252: fprintf(fd, "It was approved by %s\n\n", header.approved);
253: #ifdef ORGDISTRIB
254: fprintf(fd, "You can accomplish this by sending a newgroup control message with a\n");
255: fprintf(fd, "distribution code of %s; in other words, by executing the command:\n", ORGDISTRIB);
256: fprintf(fd, "%s/inews -n net.news -d %s -t \"cmsg newgroup %s\"\n",
257: LIB, ORGDISTRIB, argv[1]);
258: #endif /* ORGDISTRIB */
259: (void) mclose(fd);
260: }
261: }
262: #endif /* NOTIFY */
263:
264:
265: /*
266: * rmgroup <groupname>
267: * An old newsgroup is being cancelled on a network wide basis.
268: */
269: c_rmgroup(argc, argv)
270: char **argv;
271: {
272: FILE *fd;
273: int shouldremove = 0;
274:
275: if (argc < 1)
276: xerror("rmgroup: Not enough arguments.");
277: if (!validng(argv[1]))
278: return;
279: if (header.approved[0] == '\0')
280: xerror("rmgroup: %s not approved", argv[1]);
281:
282: #ifndef MANUALLY
283: #ifdef ORGDISTRIB
284: if (!strcmp(ORGDISTRIB, header.distribution))
285: #endif /* ORGDISTRIB */
286: shouldremove++;
287: #endif /* !MANUALLY */
288: #ifdef NOTIFY
289: fd = mailhdr((struct hbuf *)NULL, "rmgroup control message");
290: if (fd != NULL) {
291: if (shouldremove) {
292: fprintf(fd, "A newsgroup called '%s' has been removed by %s.\n\n",
293: argv[1], header.path);
294: # ifdef USG
295: fprintf(fd, "You may need to remove the directory %s by hand\n",
296: dirname(argv[1]));
297: # endif
298: } else {
299: fprintf(fd, "%s has requested that newsgroup %s be removed.\n",
300: header.path, argv[1]);
301: fprintf(fd, "You should remove it by hand\n");
302: fprintf(fd, "To do this, execute the command\n");
303: fprintf(fd, "\t%s/rmgroup %s\n", LIB, argv[1]);
304: }
305: (void) mclose(fd);
306: }
307: #endif /* NOTIFY */
308:
309: if (shouldremove) {
310: int rc;
311: /* We let the shell do all the work.
312: * See the rmgrp shell script. */
313: (void) setuid(geteuid()); /* otherwise it won't rmdir the dir */
314: (void) sprintf(bfr, "exec %s/rmgroup %s", LIB, argv[1]);
315: rc = system(bfr);
316: log("system(%s) status %d", bfr, rc);
317: }
318: }
319:
320: /*
321: * cancel <artid>
322: * Cancel the named article
323: */
324: c_cancel(argc, argv)
325: char **argv;
326: {
327: char *line, *p, *q, *r, *poster;
328: char *findhist();
329: register FILE *fp;
330: char whatsisname[BUFLEN], nfilename[BUFLEN];
331: time_t t;
332: int su = 0;
333: #ifndef u370
334: struct hbuf htmp;
335: #endif /* !u370 */
336:
337: if (argc < 1)
338: xerror("cancel: Not enough arguments.");
339: (void) strcpy(whatsisname, senderof(&header));
340: line = findhist(argv[1]);
341: if (line == NULL) {
342: struct tm *tm;
343: log("Can't cancel %s: non-existent", argv[1]);
344: (void) time(&t);
345: tm = localtime(&t);
346: #ifdef USG
347: sprintf(bfr,"%s\t%2.2d/%2.2d/%d %2.2d:%2.2d\tcancelled",
348: #else /* !USG */
349: sprintf(bfr,"%s\t%02d/%02d/%d %02d:%02d\tcancelled",
350: #endif /* !USG */
351: argv[1], tm->tm_mon+1, tm->tm_mday, tm->tm_year, tm->tm_hour,
352: tm->tm_min);
353: savehist(bfr);
354: return 1;
355: }
356:
357: q = index(line, '\t');
358: p = index(q+1, '\t');
359: if (p == NULL || *++p == '\0' || *p == '\n') {
360: *q = '\0';
361: log("Expired article %s", line);
362: return 1;
363: }
364: if (strcmp(p, "cancelled") == 0) {
365: *q = '\0';
366: log("Already Cancelled %s", line);
367: return 1;
368: } else
369: log("Cancelling %s", line);
370: if ((uid == ROOTID||uid == 0) && strcmp(header.distribution, "local") == 0)
371: su = 1;
372: while (*p) {
373: q = index(p, ' ');
374: if (q)
375: *q = '\0';
376: (void) strcpy(nfilename, dirname(p));
377: fp = fopen(nfilename, "r");
378: if (fp == NULL) {
379: log("Already Cancelled %s", line);
380: return 1;
381: }
382: htmp.unrec[0] = NULL;
383: if (hread(&htmp, fp, TRUE) == NULL) {
384: if (bfr[0] == '/') {
385: fp = fopen(bfr, "r");
386: if (fp == NULL
387: || hread(&htmp, fp, TRUE) == NULL)
388: xerror("Article is garbled.");
389: } else
390: xerror("Article is garbled.");
391: }
392: (void) fclose(fp);
393: poster = senderof(&htmp);
394: /* only compare up to '.' or ' ' */
395: r = index(poster,'.');
396: if (r == NULL)
397: r = index(poster,' ');
398: if (r != NULL)
399: *r = '\0';
400: if (!su && strncmp(whatsisname, poster,strlen(poster))) {
401: xerror("Not contributor: posted by %s, and you are %s", poster, whatsisname);
402: }
403:
404: (void) unlink(nfilename);
405: p = q+1;
406: }
407: return 0;
408: }
409:
410: /*
411: * sendsys (no arguments)
412: *
413: * Mail the sys file to the person submitting the article.
414: * POLICY: the contents of your sys file are public information
415: * and as such, you should not change this code. You may feel
416: * free to arrange for it to manually notify you, in the event
417: * that you want to do something to clean it up before it goes out.
418: * Secret sites on the net are expressly frowned on.
419: *
420: * The purpose of this command is for making a network map. The
421: * details of your link and which newsgroups are forwarded are not
422: * important, in case you want to sanitize them. Since the definition
423: * of USENET is those sites getting net.announce, you can disable this
424: * on sites not getting net articles, but if you take out the list of
425: * forwarded newsgroups, and you have sites that only get local newsgroups,
426: * you should make this clear, or remove those sites from what you send out.
427: */
428: /* ARGSUSED */
429: c_sendsys(argc, argv)
430: char **argv;
431: {
432: register FILE *f, *u;
433: int c;
434:
435: #ifdef NOTIFY
436: f = mailhdr((struct hbuf *)NULL, "sendsys control message");
437: if (f != NULL) {
438: fprintf(f, "%s requested your %s/sys file.\n", header.path, LIB);
439: fprintf(f, "It has been sent.\n");
440: (void) mclose(f);
441: }
442: #endif
443: f = mailhdr(&header, "response to your sendsys request");
444: u = fopen(SUBFILE, "r");
445: if (f != NULL && u != NULL) {
446: while ((c=getc(u)) != EOF)
447: putc(c, f);
448: (void) fclose(u);
449: (void) mclose(f);
450: }
451: }
452:
453: /*
454: * senduuname (no arguments)
455: *
456: * Run the "uuname" command and send it back to the person who submitted
457: * the article. The purpose of this control message is for attempting to
458: * make a uucp net map.
459: *
460: * POLICY: If you view this information as not public (because you have
461: * a connection you consider secret, or know a site that considers itself
462: * secret) you can feel free to change this code in whatever way is
463: * appropriate, so long as it sends some response back to the sender. If
464: * you don't run uucp, this code does not make sense, and so an error
465: * message (or garbage, such as "research") will be mailed back.
466: *
467: * If you wish to add or remove sites from the output of uuname, you
468: * may wish to use the euuname.sh shell script here.
469: */
470: /* ARGSUSED */
471: c_senduuname(argc, argv)
472: char **argv;
473: {
474: char buf[256];
475: FILE *fd, *u;
476: int c;
477:
478: #ifdef NOTIFY
479: fd = mailhdr((struct hbuf *)NULL, "uuname control message");
480: fprintf(fd, "%s requested your uuname output\n", header.path);
481: (void) mclose(fd);
482: #endif
483: fd = mailhdr(&header, "response to your senduuname request");
484: #ifdef UUPROG
485: if (UUPROG[0] == '/')
486: (void) strcpy(buf, UUPROG);
487: else
488: (void) sprintf(buf, "%s/%s", LIB, UUPROG);
489: #else
490: (void) strcpy(buf, "uuname");
491: #endif
492: u = popen(buf, "r");
493: if (fd != NULL && u != NULL) {
494: while ((c=getc(u)) != EOF)
495: putc(c, fd);
496: (void) pclose(u);
497: (void) mclose(fd);
498: }
499: }
500:
501: /*
502: * Send the version number to the right person.
503: */
504: /* ARGSUSED */
505: c_version(argc, argv)
506: char **argv;
507: {
508: register FILE *f;
509:
510: f = mailhdr(&header, "Our news version");
511: if (f == NULL)
512: xerror("Cannot send back error message");
513: fprintf(f, "Currently running news version %s.\n\n", news_version);
514: fprintf(f, "The header of your message follows:\n\n");
515: (void) hwrite(&header, f);
516: (void) mclose(f);
517: }
518:
519: /*
520: * Check the active file for old or missing newsgroups
521: * Body of article is list of valid groups
522: */
523: /* ARGSUSED */
524: c_checkgroups(argc, argv)
525: char **argv;
526: {
527: int rc;
528:
529: (void) setuid(geteuid());
530: /* dont change the cat %s| to < %s, it breaks some "unix" systems */
531: (void) sprintf(bfr, "cat %s | %s/checkgroups %s", INFILE, LIB,
532: #ifdef NOTIFY
533: (TELLME && *TELLME) ? TELLME : NEWSUSR );
534: #else /* !NOTIFY */
535: NEWSUSR);
536: #endif /* !NOTIFY */
537: rc = system(bfr);
538: log("system(%s) status %d", bfr, rc);
539: }
540:
541: /*
542: * An unknown control message has been received.
543: */
544: c_unknown(h, ctlmsgtext)
545: struct hbuf *h;
546: char *ctlmsgtext;
547: {
548: register FILE *f;
549:
550: log("UNKNOWN Ctl Msg %s from %s", ctlmsgtext, h->path);
551: #ifdef NOTIFY
552: f = mailhdr((struct hbuf *)NULL, "Unrecognized Control Message");
553: if (f != NULL) {
554: fprintf(f, "Currently running news version %s.\n\n", news_version);
555: fprintf(f, "The header of the message follows:\n\n");
556: (void) hwrite(h, f);
557: (void) mclose(f);
558: }
559: #endif /* NOTIFY */
560: }
561:
562: /* ARGSUSED */
563: c_unimp(argc, argv)
564: char **argv;
565: {
566: register FILE *f;
567:
568: #ifdef NOTIFY
569: f = mailhdr((struct hbuf*)NULL, "Unimplemented Control Message");
570: if (f != NULL) {
571: fprintf(f, "Currently running news version B %s.\n\n", news_version);
572: fprintf(f, "The header of the message follows:\n\n");
573: (void) hwrite(&header, f);
574: (void) mclose(f);
575: }
576: #endif /* NOTIFY */
577: }
578:
579: xmitmsg(tosys, title, ng)
580: char *tosys, *title, *ng;
581: {
582: #ifndef u370
583: struct hbuf htmp;
584: #endif /* !u370 */
585: struct srec srec;
586: FILE *tfp;
587: char *fname;
588:
589: /* Make an article called ARTICLE */
590: (void) sprintf(htmp.from, "%s@%s%s", "usenet", FULLSYSNAME, MYDOMAIN);
591: (void) strcpy(htmp.path, NEWSUSR);
592: (void) strcpy(htmp.nbuf, ng);
593: (void) strcpy(htmp.title, title);
594: (void) strcpy(htmp.ctlmsg, title);
595: (void) strcpy(htmp.subdate, "");
596: (void) strcpy(htmp.expdate, "");
597: getident(&htmp);
598: dates(&htmp);
599: tfp = xfopen(fname = mktemp("/tmp/xmsgXXXXXX"), "w");
600: hwrite(&htmp, tfp);
601: (void) fclose(tfp);
602:
603: /* Find the sys record */
604: s_openr();
605: while (s_read(&srec)) {
606: if (strncmp(srec.s_name, tosys, SNLN))
607: continue;
608: tfp = xfopen(fname, "r");
609: (void) transmit(&srec, tfp, 0, (char **)0, 0);
610: (void) unlink(fname);
611: return;
612: }
613: log("Can't find sys record for %s", tosys);
614: xerror("Cannot find sys record");
615: }
616:
617: /*
618: * This is a modified version of popen, made more secure. Rather than
619: * forking off a shell, you get a bare process. You must have exactly
620: * one argument, and the command must be mail (or sendmail if you have it).
621: */
622: #define RDR 0
623: #define WTR 1
624: static int mopen_pid[20];
625: char *replyname();
626:
627: FILE *
628: mhopen(hptr)
629: struct hbuf *hptr;
630: {
631: int p[2];
632: register myside, hisside, pid;
633: char *sendto = "usenet";
634:
635: if (hptr)
636: sendto = replyname(hptr);
637: else {
638: #ifdef NOTIFY
639: if (TELLME && *TELLME)
640: sendto = TELLME;
641: #endif /* NOTIFY */
642: if (sendto == NULL)
643: return NULL;
644: }
645: verifyname(sendto);
646: if(pipe(p) < 0)
647: return NULL;
648: myside = p[WTR];
649: hisside = p[RDR];
650: if((pid = fork()) == 0) {
651: /* myside and hisside reverse roles in child */
652: (void) close(myside);
653: (void) close(0);
654: (void) dup(hisside);
655: (void) close(hisside);
656: (void) setgid(gid);
657: (void) setuid(uid);
658: #ifdef SENDMAIL
659: execl(SENDMAIL, "sendmail", "-oi", "-oeq", sendto, (char *)NULL);
660: #endif /* SENDMAIL */
661: #ifdef MMDF
662: execl(MMDF, "inews-mail", "-smuxto,cc*", (char *)NULL);
663: #endif /* MMDF */
664: execl("/bin/mail", "mail", sendto, (char *)NULL);
665: execl("/usr/bin/mail", "mail", sendto, (char *)NULL);
666: execl("/usr/ucb/mail", "mail", sendto, (char *)NULL);
667: _exit(1);
668: }
669: if(pid == -1)
670: return NULL;
671: mopen_pid[myside] = pid;
672: (void) close(hisside);
673: return(fdopen(myside, "w"));
674: }
675:
676: mclose(ptr)
677: FILE *ptr;
678: {
679: register f, r, (*hstat)(), (*istat)(), (*qstat)();
680: int status;
681:
682: f = fileno(ptr);
683: (void) fclose(ptr);
684: istat = signal(SIGINT, SIG_IGN);
685: qstat = signal(SIGQUIT, SIG_IGN);
686: hstat = signal(SIGHUP, SIG_IGN);
687: while((r = wait(&status)) != mopen_pid[f] && r != -1)
688: ;
689: if(r == -1)
690: status = -1;
691: signal(SIGINT, istat);
692: signal(SIGQUIT, qstat);
693: signal(SIGHUP, hstat);
694: return status;
695: }
696:
697: /*
698: * mhopen a pipe to mail, write out a std header, and return the file ptr.
699: *
700: * We don't include a From: field because this is probably uucp, i.e.
701: * explicitly routed. Leave it up to the recipient's mailer.
702: * Always include the To: field because if we ge back failed mail, we
703: * might be able to deliver it by hand if we know to wom it was addressed.
704: * By convention, hptr==NULL means to send the message to the local contact person.
705: */
706: FILE *
707: mailhdr(hptr, subject)
708: struct hbuf *hptr;
709: char *subject;
710: {
711: FILE *fp;
712: time_t now;
713: char *to = "usenet";
714:
715: #ifdef NOTIFY
716: if (TELLME && *TELLME)
717: to = TELLME;
718: #endif /* NOTIFY */
719: if (hptr)
720: to = replyname(hptr);
721:
722: if ((fp = mhopen(hptr)) != NULL) {
723: (void) time(&now);
724: fprintf(fp, "Date: %s\n", arpadate(&now));
725: #ifdef MMDF
726: fprintf(fp, "From: The News System <usenet@%s%s>\n",
727: FULLSYSNAME, MYDOMAIN);
728: #endif /* MMDF */
729: fprintf(fp, "To: %s\n", to);
730: fprintf(fp, "Subject: %s\n", subject);
731: #ifdef HIDDENNET
732: if (strcmp(LOCALSYSNAME, FULLSYSNAME))
733: fprintf(fp, "Responding-System: %s.%s%s\n\n",
734: LOCALSYSNAME, FULLSYSNAME, MYDOMAIN);
735: #endif /* !HIDDENNET */
736: fprintf(fp, "Responding-System: %s%s\n\n",
737: FULLSYSNAME, MYDOMAIN);
738: }
739: return fp;
740: }
741:
742: /*
743: * verify that the name mail is being sent to does not contain any
744: * nasty hooks to invoke funny functions from the shell or the like.
745: */
746: verifyname(sendto)
747: char *sendto;
748: {
749: /* Be sure we DO allow alphabetics, !, :, ., -, @. *. */
750: char *nasty = "\"'\\`^|;& <>/~";
751: register char *p;
752:
753: if (sendto[0] <= ' ') {
754: log("nasty mail name %s from %s", sendto, header.path);
755: xxit(1);
756: }
757: for (p=sendto; *p; p++) {
758: if (*p == ' ') {
759: *p = 0;
760: break;
761: }
762: }
763: if (strpbrk(sendto, nasty) != NULL)
764: xerror("nasty mail name %s from %s", sendto, header.path);
765:
766: for (nasty = sendto; (nasty = index(nasty, '.')) != NULL; ) {
767: if (*++nasty == '.') /* check for .. */
768: xerror("nasty mail name %s from %s", sendto, header.path);
769: }
770: }
771:
772: /*
773: * Checks to make sure the control message is OK to post.
774: */
775: ctlcheck()
776: {
777: char msg[BUFLEN];
778: char *p;
779:
780: if (!is_ctl)
781: return;
782:
783: if (header.ctlmsg[0])
784: (void) strcpy(msg, header.ctlmsg);
785: else
786: (void) strcpy(msg, header.title);
787:
788: p = index(msg, ' ');
789: if (p)
790: *p = 0;
791:
792: if (strcmp(msg, "ihave") == 0) {
793: } else if (strcmp(msg, "sendme") == 0) {
794: return; /* no restrictions */
795: } else if (strcmp(msg, "newgroup") == 0) {
796: suser();
797: } else if (strcmp(msg, "rmgroup") == 0) {
798: suser();
799: } else if (strcmp(msg, "sendsys") == 0) {
800: suser();
801: } else if (strcmp(msg, "senduuname") == 0) {
802: suser();
803: } else if (strcmp(msg, "checkgroups") == 0) {
804: suser();
805: } else if (strcmp(msg, "version") == 0) {
806: return; /* no restrictions */
807: } else if (strcmp(msg, "cancel") == 0) {
808: return; /* no restrictions at this level */
809: } else if (strcmp(msg, "delsub") == 0) {
810: if (!prefix(header.nbuf, "to.")) {
811: printf("Must be in a 'to.system' newsgroup.");
812: xxit(0);
813: }
814: return;
815: } else {
816: printf("Unrecognized control message - %s\n", msg);
817: xxit(0);
818: }
819: }
820:
821: /* Make sure this guy is special. */
822: suser()
823: {
824: if (uid == 0 || uid == ROOTID)
825: return;
826: /*
827: * We assume that since our real uid is the same as NEWSUSR
828: * (the euid) we were run by rootid and it did a setuid.
829: * Too bad we can't set just the effective uid like suid does.
830: */
831: if (uid == geteuid())
832: return;
833: #ifdef IHCC
834: printf("Please use the command:\n\ttoolnews providers\n");
835: printf("then call one of the news people.\n");
836: #else
837: printf("Get your local netnews contact to do it for you.\n");
838: #endif
839: xxit(0);
840: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.