mirror of
https://git.openldap.org/openldap/openldap.git
synced 2024-12-15 03:01:09 +08:00
b5494457d8
This could cause problems on odd systems. The generic headers should be extended as needed to include necessary system headers or, if necessary, make explicit declarations. Extended ac/string.h header to look for string.h/strings.h if STDC_HEADERS is not defined. Also provide basic declarations for str*() functions. This could cause problems on odd systems. Extended ac/unistd.h header to define basic declaration for misc functions that might be missing from headers. This includes externs for getenv(), getopt(), mktemp(), tempname(). Protect fax500.h from multiple inclusion. Moved includes of system/generic headers back to source files. Made mail500 helper functions static. Fixed includes of ctype.h, signal.h, etc. to use generics. lutil/tempname.c: was including stdlib.h twice, one should stdio.h. Wrapped <sys/resource.h> with HAVE_SYS_RESOURCE_H. lber/io.c/ber_get_next(): Changed noctets back to signed. Used with BerRead which expects signed int as second arg and returns signed int.
371 lines
8.2 KiB
C
371 lines
8.2 KiB
C
/*
|
|
* 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 "portable.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <ac/ctype.h>
|
|
#include <ac/string.h>
|
|
#include <ac/syslog.h>
|
|
#include <ac/unistd.h>
|
|
|
|
#include "ldapconfig.h"
|
|
#include "rcpt500.h"
|
|
|
|
int dosyslog = 0;
|
|
#ifdef LDAP_CONNECTIONLESS
|
|
int do_cldap = 0;
|
|
#endif /* LDAP_CONNECTIONLESS */
|
|
|
|
int derefaliases = 1;
|
|
int sizelimit = RCPT500_SIZELIMIT;
|
|
int rdncount = RCPT500_RDNCOUNT;
|
|
int ldapport = 0;
|
|
char *ldaphost = NULL;
|
|
char *searchbase = NULL;
|
|
char *dapuser = NULL;
|
|
char *filterfile = FILTERFILE;
|
|
char *templatefile = TEMPLATEFILE;
|
|
static char reply[ MAXSIZE * RCPT500_LISTLIMIT ];
|
|
|
|
|
|
/*
|
|
* functions
|
|
*/
|
|
static int read_msg(FILE *fp, struct msginfo *msgp);
|
|
static char *read_hdr(FILE *fp, int off, char *buf, int MAXSIZEe, char **ln_p);
|
|
static int send_reply(struct msginfo *msgp, char *body);
|
|
static int find_command(char *text, char **argp);
|
|
|
|
/*
|
|
* main is invoked by sendmail via the alias file
|
|
* the entire incoming message gets piped to our standard input
|
|
*/
|
|
int
|
|
main( 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;
|
|
|
|
*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 LDAP_CONNECTIONLESS
|
|
do_cldap = 1;
|
|
#else /* LDAP_CONNECTIONLESS */
|
|
fprintf( stderr,
|
|
"Compile with -DLDAP_CONNECTIONLESS for -U support\n" );
|
|
#endif /* LDAP_CONNECTIONLESS */
|
|
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 );
|
|
}
|
|
|
|
|
|
static int
|
|
read_msg( 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 );
|
|
}
|
|
|
|
|
|
static char *
|
|
read_hdr( 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 );
|
|
}
|
|
|
|
|
|
static int
|
|
send_reply( 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 );
|
|
}
|
|
|
|
|
|
static int
|
|
find_command( 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 );
|
|
}
|