ok, here's the news forger.. two caveats on this one:

caveat #1: newer nntp servers insist on creating their own 
"NNTP-Posting-Host:" header and will balk the post if you
try to forge it.. this header, while not usually displayed
by most readers, is distributed in a post and usually contains
the correct pseudo-authenticated machine that the socket 
connection was made from originally..

caveat #2: on one level, it seems that this is no better than sendmail
or the forgepost no better than your run of the mill news poster - as
it furthers people ability to ignore the mechanisms of things
around them... further your mind and read the rfc's..  

take care, loki
(argh thru_ : contribute to the Process)

-----news_forgery.h--------

/* written by Loki D. Quaeler (copyfree 1995) 
   v1.0 */

/* #define DBUG */

#include <stdio.h>
#include <strings.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

#define NEWSPORT		119
#define	MAXLEN			256
#define NNTP_INITIATE		"POST"
#define NNTP_CLOSE		"QUIT"
#define ORGANIZATION		"Organization:"
#define FROM			"From:"
#define SUBJECT			"Subject:"
#define NEWSGROUPS		"Newsgroups:"
#define DISTRIBUTION		"Distribution:"
#define MSGID			"Message-ID:"
#define NNTP_EODATA		"."
#define GOOD_CONNECT_STR	"ready"
#define GOOD_POST_ACK		"240"
#define BAD_NEWS		"no posting"
#define GOOD_DISCONNECT		"205"

#define QUIT_EXEC		"quit"

#define DIST_DEFAULT		"world"

#define MAX_HOSTLEN		64

#define null(type)		(type) 0L
#define NULL_STRING		""

#ifndef YES
#define YES			1
#define NO			0
#endif

int s;					/* socket number */ 
char buf[BUFSIZ+1];			/* global text data buffer     */
char nntpHost[MAX_HOSTLEN];
char newsgroups[MAXLEN];
char pseudoSender[MAXLEN];
char organization[MAXLEN];
char subjectLine[MAXLEN];
char distribution[MAXLEN];
char messageID[MAXLEN];
char *body;

-----news_forgery.c--------
/* by Loki D. Quaeler - copyfree 1995 */

#include "news_forgery.h"

/*~~[ call_socket ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  Connect to port MAILPORT on host 'hostname', returning the socket
  value.  Return -1 on any errors.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
int call_socket(hostname)
  char *hostname;
{
	struct sockaddr_in sa;
	struct hostent *hp;
	int a, sock;

#ifdef DBUG
  printf("Entered call_socket, hostname = %s\n", hostname);
#endif

	if ((hp=gethostbyname(hostname))==NULL)
		{ errno=ECONNREFUSED;
		  return(-1); }
	bzero(&sa, sizeof(sa));
	bcopy(hp->h_addr, (char *)&sa.sin_addr, hp->h_length);
	sa.sin_family = hp->h_addrtype;
	sa.sin_port = htons((u_short)NEWSPORT);

	if((sock=socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0)
		return(-1);
	if(connect(sock, &sa, sizeof(sa)) < 0)
		{ close(sock);
		  return(-1); }
#ifdef DBUG
  printf("Exiting call_socket correctly, socket = %d\n", sock);
#endif
	return(sock);
}

/*~~~[ readln ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  Read all characters from socket s until a newline.  Put resulting
  string in buf, ignoring all after the BUFSIZ'th character.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
int readln(buf)
  char *buf;
{
	int to=0;
	char c;
	
#ifdef DBUG
  printf("Entering readln\n");
#endif 

	do {
		if(read(s, &c, 1)<1) 
			return(0);
		if((c >= ' ') || (c <= 126))
			if(to<BUFSIZ-1) 
				buf[to++] = c;
	} while (c != '\n');

	buf[to] = '\0';
   
#ifdef DBUG
  printf("buf = %s", buf);
  printf("Exiting readln correctly\n");
#endif

	return(1);
}

/*~~[ writeln ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  Send contents of buf to socket s.  Return 0 if the entire buf 
  wasn't written.  Return 1 on a successful write.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
int writeln(buf)
  char *buf;
{
	int to=0;

#ifdef DBUG
  printf("Entered writeln\n");
  printf("buf = %s\n", buf);
#endif

/*	buf[BUFSIZ] = '\0'; */
	if( write(s, buf, strlen(buf)) < to )
		return(0);

#ifdef DBUG
   printf("Exited writeln correctly.\n");
#endif

	return(1);
}

/*~~[ main ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  Yes, main.  amazing.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
main()
{
	char inputString[BUFSIZ],outputString[BUFSIZ];
	char *dataBody;
	int goodConnect = 0;
	
	printf("\n\nWelcome the news forgery Process...\n");
	printf("\t-  After all data is entered, a confirmation entry will be\n\t\tasked for before the actual connection is made.\n\n");
	
	do {
		printf("~ Please enter NNTP server machine name\n\tor %s to exec program: ", QUIT_EXEC);
		gets(nntpHost);
		if (strcmp(nntpHost, QUIT_EXEC))
			{ goodConnect = contact_relay();
			  switch (goodConnect)
			  	{ case 0: printf("** Could not reach host\n"); break;
				  case 1: printf("** Host does not accept posting\n"); close(s); break;
				  default: close(s); break; } }
		else
			exit(0);
	} while (goodConnect != 2);

	

	printf("~ Pseudonym (anything, any format): ");
	gets(pseudoSender);
	printf("~ Newsgroups to post to, multiple groups seperated\n\tby commas: ");
	gets(newsgroups);
	printf("~ Subject: ");
	gets(subjectLine);
	printf("~ Organization: ");
	gets(organization);
	printf("~ The distribution is defaulted to %s, enter a different one or\n\thit return: ", DIST_DEFAULT);
	gets(distribution);
	printf("~ Message-ID (ex: 23.23@ninth.circle.hell - *warning* some nntp\n\tservers do not like having this assigned for\n\tthem and will not correctly post because of\n\tit; hit return to skip this item) : ");
	gets(messageID);

	printf("~ Enter the body below, enter ctrl-d on a blank line to end text entry.\n---------\n");
	body = (char *)malloc(2);
	sprintf(body,"\n");
	while (gets(inputString) != NULL)
		{ if (! strcmp(inputString, NNTP_EODATA))
			sprintf(inputString,"%s.", NNTP_EODATA);
		  body = (char *)realloc(body,((strlen(body) + strlen(inputString) + 2) * sizeof(char)));
		  strcat(body,inputString);
		  strcat(body,"\n"); }
	clearerr(stdin);

	printf("\n---------\n**This is the last chance to back out.\n\tContinue with the forgery Process (yes/no)? [no]:");
	gets(inputString);
	if (strcmp(inputString,"yes"))
		{ printf("Process was aborted.\n");
		  exit(0); }
	
	printf("-----\nContinuing...\n");
	
	/* build data body chunk */

	printf("  Building data body...\n");

	sprintf(inputString,"%s %s\n%s %s\n%s %s\n%s %s\n%s %s\n",FROM, pseudoSender,NEWSGROUPS, newsgroups,SUBJECT,subjectLine, ORGANIZATION, organization, DISTRIBUTION, ((strcmp(distribution,NULL_STRING)) ? distribution : DIST_DEFAULT ));
	dataBody = (char*)malloc((strlen(inputString) + 1) * sizeof(char));	
	strcat(dataBody,inputString);

	if (strcmp(messageID, NULL_STRING))
		{ sprintf(inputString,"%s <%s>\n", MSGID, messageID);
		  dataBody = (char*)realloc(dataBody,(strlen(dataBody) + strlen(inputString) + 1) * sizeof(char));	
		  strcat(dataBody,inputString); }
	
	dataBody = (char*)realloc(dataBody,(strlen(dataBody) + strlen(body) + 1) * sizeof(char));	
	strcat(dataBody,body);

	printf(" Contacting nntp server...\n");
	
	contact_relay();
	
		/* speak that protocol slang */

	printf("  Exchanging protocol slang...\n");

	sprintf(buf,"%s\n", NNTP_INITIATE);
	writeln(buf);
	readln(outputString);

		/* monitor force feed of body into buf.... */

	printf("  Passing the body of mail...\n");

	writeln(dataBody);
	
	sprintf(buf,"\n%s\n", NNTP_EODATA);
	writeln(buf);
	readln(outputString);

	if (! strstr(outputString, GOOD_POST_ACK))
		printf("   Server didn't send good post acknowledgment. Post probably failed.\n");

	printf("  Closing connection...\n");
	
	sprintf(buf,"%s\n", NNTP_CLOSE);
	writeln(buf);
	readln(outputString);
	if (strstr(outputString,GOOD_DISCONNECT))
		printf("Received good acknowldegment\n");
	else
		printf("\t ~~ Unrecognized command at socket closure.\n");

	close(s);
	
	printf("------\nFinished... copy of sent message follows\n------\n%s\n------\n",dataBody);
	
	exit(0);
}

int contact_relay()
{  /* 0:host unreachable; 1:host connect but no posting allowed; 2: good host connect */
	char serverSpew[BUFSIZ];
	int i;

	if ((s=call_socket(nntpHost))==-1)
			return 0;

	do {
		readln(serverSpew);
	} while (! strstr(serverSpew,GOOD_CONNECT_STR));
	
	if (strstr(serverSpew,BAD_NEWS))
		return 1;
	else
		return 2;
}

