/* * main.c: for rcpt500 (X.500 email query responder) * * 16 June 1992 by Mark C Smith * Copyright (c) 1992 The Regents of The University of Michigan * All Rights Reserved */ #include #include #include #include #include #include "portable.h" #include "ldapconfig.h" #include "rcpt500.h" #ifdef ultrix extern char *strdup(); #endif int dosyslog = 0; #ifdef CLDAP int do_cldap = 0; #endif /* CLDAP */ int derefaliases = 1; int sizelimit = RCPT500_SIZELIMIT; int rdncount = RCPT500_RDNCOUNT; int ldapport = 0; char *ldaphost = LDAPHOST; char *searchbase = RCPT500_BASE; char *dapuser = RCPT500_BINDDN; char *filterfile = FILTERFILE; char *templatefile = TEMPLATEFILE; char reply[ MAXSIZE * RCPT500_LISTLIMIT ]; /* * functions */ int read_msg(); char *read_hdr(); int send_reply(); /* * main is invoked by sendmail via the alias file * the entire incoming message gets piped to our standard input */ main( argc, argv ) int argc; char **argv; { char *prog, *usage = "%s [-l] [-U] [-h ldaphost] [-p ldapport] [-b searchbase] [-a] [-z sizelimit] [-u dapuser] [-f filterfile] [-t templatefile] [-c rdncount]\n"; struct msginfo msg; int c, errflg; char *replytext; extern int optind; extern char *optarg; *reply = '\0'; if (( prog = strrchr( argv[ 0 ], '/' )) == NULL ) { prog = strdup( argv[ 0 ] ); } else { prog = strdup( prog + 1 ); } errflg = 0; while (( c = getopt( argc, argv, "alUh:b:s:z:f:t:p:c:" )) != EOF ) { switch( c ) { case 'a': derefaliases = 0; break; case 'l': dosyslog = 1; break; case 'U': #ifdef CLDAP do_cldap = 1; #else /* CLDAP */ fprintf( stderr, "Compile with -DCLDAP for -U support\n" ); #endif /* CLDAP */ break; case 'b': searchbase = optarg; break; case 'h': ldaphost = optarg; break; case 'p': ldapport = atoi( optarg ); break; case 'z': sizelimit = atoi( optarg ); break; case 'u': dapuser = optarg; break; case 'f': filterfile = optarg; break; case 't': templatefile = optarg; break; case 'c': rdncount = atoi( optarg ); break; default: ++errflg; } } if ( errflg || optind < argc ) { fprintf( stderr, usage, prog ); exit( 1 ); } if ( dosyslog ) { /* * if syslogging requested, initialize */ #ifdef LOG_DAEMON openlog( prog, OPENLOG_OPTIONS, LOG_DAEMON ); #else openlog( prog, OPENLOG_OPTIONS ); #endif } if ( read_msg( stdin, &msg ) < 0 ) { if ( dosyslog ) { syslog( LOG_INFO, "unparseable message ignored" ); } exit( 0 ); /* so as not to give sendmail an error */ } if ( dosyslog ) { syslog( LOG_INFO, "processing command \"%s %s\" from %s", ( msg.msg_command < 0 ) ? "Unknown" : cmds[ msg.msg_command ].cmd_text, ( msg.msg_arg == NULL ) ? "" : msg.msg_arg, msg.msg_replyto ); } if ( msg.msg_command < 0 ) { msg.msg_command = 0; /* unknown command == help command */ } /* sprintf( reply, "Your request was interpreted as: %s %s\n\n", cmds[ msg.msg_command ].cmd_text, msg.msg_arg ); */ (*cmds[ msg.msg_command ].cmd_handler)( &msg, reply ); if ( send_reply( &msg, reply ) < 0 ) { if ( dosyslog ) { syslog( LOG_INFO, "reply failed: %m" ); } exit( 0 ); /* so as not to give sendmail an error */ } if ( dosyslog ) { syslog( LOG_INFO, "reply OK" ); } exit( 0 ); } int read_msg( fp, msgp ) FILE *fp; struct msginfo *msgp; { char buf[ MAXSIZE ], *line; int command = -1; msgp->msg_replyto = msgp->msg_date = msgp->msg_subject = NULL; line = NULL; while( 1 ) { if ( line == NULL ) { if (( line = fgets( buf, MAXSIZE, fp )) == NULL ) { break; } buf[ strlen( buf ) - 1 ] = '\0'; /* remove trailing newline */ } if ( *buf == '\0' ) { /* start of message body */ break; } if ( strncasecmp( buf, "Reply-To:", 9 ) == 0 ) { if ( msgp->msg_replyto != NULL ) { free( msgp->msg_replyto ); } msgp->msg_replyto = read_hdr( fp, 9, buf, MAXSIZE, &line ); } else if ( strncasecmp( buf, "From:", 5 ) == 0 && msgp->msg_replyto == NULL ) { msgp->msg_replyto = read_hdr( fp, 5, buf, MAXSIZE, &line ); } else if ( strncasecmp( buf, "Date:", 5 ) == 0 ) { msgp->msg_date = read_hdr( fp, 5, buf, MAXSIZE, &line ); } else if ( strncasecmp( buf, "Message-ID:", 5 ) == 0 ) { msgp->msg_messageid = read_hdr( fp, 11, buf, MAXSIZE, &line ); } else if ( strncasecmp( buf, "Subject:", 8 ) == 0 ) { if (( msgp->msg_subject = read_hdr( fp, 8, buf, MAXSIZE, &line )) != NULL ) { command = find_command( msgp->msg_subject, &msgp->msg_arg ); } } else { line = NULL; /* discard current line */ } } while ( command < 0 && line != NULL ) { /* * read the body of the message, looking for commands */ if (( line = fgets( buf, MAXSIZE, fp )) != NULL ) { buf[ strlen( buf ) - 1 ] = '\0'; /* remove trailing newline */ command = find_command( buf, &msgp->msg_arg ); } } if ( msgp->msg_replyto == NULL ) { return( -1 ); } msgp->msg_command = command; return( 0 ); } char * read_hdr( fp, offset, buf, MAXSIZEe, linep ) FILE *fp; int offset; char *buf; int MAXSIZEe; char **linep; { char *hdr; for ( hdr = buf + offset; isspace( *hdr ); ++hdr ) { ; } if (( hdr = strdup( hdr )) == NULL ) { if ( dosyslog ) { syslog( LOG_ERR, "strdup: %m" ); } exit( 1 ); } while ( 1 ) { *linep = fgets( buf, MAXSIZE, fp ); buf[ strlen( buf ) - 1 ] = '\0'; /* remove trailing newline */ if ( *linep == NULL || !isspace( **linep )) { break; } if (( hdr = realloc( hdr, strlen( hdr ) + strlen( *linep ) + 3 )) == NULL) { if ( dosyslog ) { syslog( LOG_ERR, "realloc: %m" ); } exit( 1 ); } strcat( hdr, "\n" ); strcat( hdr, *linep ); } return( hdr ); } int send_reply( msgp, body ) struct msginfo *msgp; char *body; { char buf[ MAXSIZE ]; FILE *cmdpipe; int rc; if (( cmdpipe = popen( RCPT500_PIPEMAILCMD, "w" )) == NULL ) { if ( dosyslog ) { syslog( LOG_ERR, "popen pipemailcmd failed: %m" ); } return( -1 ); } /* * send the headers */ sprintf( buf, "From: %s\n", RCPT500_FROM ); rc = fwrite( buf, strlen( buf ), 1, cmdpipe ); if ( rc == 1 ) { if ( msgp->msg_subject != NULL ) { sprintf( buf, "Subject: Re: %s\n", msgp->msg_subject ); } else { sprintf( buf, "Subject: query response\n" ); } rc = fwrite( buf, strlen( buf ), 1, cmdpipe ); } if ( rc == 1 && msgp->msg_date != NULL ) { /* * add "In-reply-to:" header */ if ( msgp->msg_messageid == NULL ) { sprintf( buf, "In-reply-to: Your message of \"%s\"\n", msgp->msg_date ); } else { sprintf( buf, "In-reply-to: Your message of \"%s\"\n %s\n", msgp->msg_date, msgp->msg_messageid ); } rc = fwrite( buf, strlen( buf ), 1, cmdpipe ); } if ( rc == 1 ) { sprintf( buf, "To: %s\n", msgp->msg_replyto ); rc = fwrite( buf, strlen( buf ), 1, cmdpipe ); } /* * send the header/body separator (blank line) */ if ( rc == 1 ) { rc = fwrite( "\n", 1, 1, cmdpipe ); } /* * send the body */ if ( rc == 1 ) { rc = fwrite( body, strlen( body ), 1, cmdpipe ); } if ( rc != 1 && dosyslog ) { syslog( LOG_ERR, "write to binmail failed: %m" ); } if ( pclose( cmdpipe ) < 0 ) { if ( dosyslog ) { syslog( LOG_ERR, "pclose binmail failed: %m" ); } return( -1 ); } return( rc == 1 ? 0 : -1 ); } int find_command( text, argp ) char *text; char **argp; { int i; char *s, *p; static char argbuf[ MAXSIZE ]; p = text; for ( s = argbuf; *p != '\0'; ++p ) { *s++ = tolower( *p ); } *s = '\0'; for ( i = 0; cmds[ i ].cmd_text != NULL; ++i ) { if (( s = strstr( argbuf, cmds[ i ].cmd_text )) != NULL && isspace( *(s + strlen( cmds[ i ].cmd_text )))) { strcpy( argbuf, text + (s - argbuf) + strlen( cmds[ i ].cmd_text )); *argp = argbuf; while ( isspace( **argp )) { ++(*argp); } return( i ); } } return( -1 ); }