Пример #1
0
Файл: sla.c Проект: simta/simta
    int
main( int argc, char *argv[] )
{
    SNET                        *snet;
    char                        *hold = NULL;
    char                        *line;

    if ( argc < 2 ) {
        exit( 1 );
    }

    if (( snet = snet_open( argv[ 1 ], O_RDONLY, 0,
            1024 * 1024 )) == NULL ) {
        fprintf( stderr, "%s: snet_open %s: ", argv[ 0 ], argv[ 1 ] );
        perror( NULL );
    }

    while (( line = snet_getline( snet, NULL )) != NULL ) {
        if (( hold != NULL ) && ( strncmp( hold, line, 16 ) != 0 )) {
            if ( strcmp( hold, line ) != 0 ) {
                printf( "%s\n", hold );
            }

            printf( "%s\n", line );
        }

        free( hold );
        hold = strdup( line );
    }

    exit( 0 );
}
Пример #2
0
/* sets command file for connected host */
    int
command_k( char *path_config, int depth )
{
    SNET	*sn;
    char	**av, *line, *p;
    char	*valid_host;
    char	temp[ MAXPATHLEN ];
    int		ac;
    int		rc = -1;
    int		linenum = 0;

    if (( sn = snet_open( path_config, O_RDONLY, 0, 0 )) == NULL ) {
        syslog( LOG_ERR, "command_k: snet_open: %s: %m", path_config );
	return( -1 );
    }

    while (( line = snet_getline( sn, NULL )) != NULL ) {
	linenum++;

        if (( ac = argcargv( line, &av )) < 0 ) {
	    syslog( LOG_ERR, "argvargc: %m" );
	    goto command_k_done;
	}

	if ( ( ac == 0 ) || ( *av[ 0 ] == '#' ) ) {
	    continue;
	}
	if ( ac < 2 ) {
	    syslog( LOG_ERR, "%s: line %d: invalid number of arguments",
			path_config, linenum );
	    continue;
	}
	if ( strcmp( av[ 0 ], "@include" ) == 0 ) {
	    if ( depth >= RADMIND_MAX_INCLUDE_DEPTH ) {
		syslog( LOG_ERR, "%s: line %d: include %s exceeds max depth",
			path_config, linenum, av[ 1 ] );
		goto command_k_done;
	    }
	    if ( ac > 3 ) {
		syslog( LOG_ERR, "%s: line %d: invalid number of arguments",
			path_config, linenum );
		continue;
	    } else if ( ac == 3 ) {
		if ( match_config_entry( av[ 2 ] ) == NULL ) {
		    /* connecting host doesn't match pattern, skip include. */
		    continue;
		}
	    }
	    if ( command_k( av[ 1 ], depth + 1 ) != 0 ) {
		continue;
	    }

	    rc = 0;
	    goto command_k_done;
	}

        if (( ac > 2 ) && ( *av[ 2 ] != '#' )) { 
	    syslog( LOG_ERR, "%s: line %d: invalid number of arguments",
		    path_config, linenum );
	    continue;
	}

	if (( p = strrchr( av[ 1 ], '/' )) == NULL ) {
	    sprintf( special_dir, "special" );
	} else {
	    *p = '\0';
	    if ( snprintf( special_dir, MAXPATHLEN, "special/%s", av[ 1 ] )
		    >= MAXPATHLEN ) {
		syslog( LOG_ERR, "config file: line %d: path too long\n",
		    linenum );
		continue;
	    }
	    *p = '/';
	}

	if (( valid_host = match_config_entry( av[ 0 ] )) != NULL ) {
	    if ( strlen( av[ 1 ] ) >= MAXPATHLEN ) {
		syslog( LOG_ERR,
		    "config file: line %d: command file too long\n", linenum );
		continue;
	    }
	    strcpy( command_file, av[ 1 ] );
	    if ( snprintf( temp, MAXPATHLEN, "%s/%s", special_dir,
		    valid_host ) >= MAXPATHLEN ) {
		syslog( LOG_ERR, "config file: line %d: special dir too long\n",
		    linenum );
		continue;
	    }
	    strcpy( special_dir, temp );
	    rc = 0;
	    goto command_k_done;
	}
    }

    /* If we get here, the host that connected is not in the config
       file. So screw him. */
    syslog( LOG_ERR, "host %s not in config file %s",
		remote_host, path_config );

command_k_done:
    snet_close( sn );
    return( rc );
}
Пример #3
0
    int
read_scookie( char *path, struct sinfo *si, void *s )
{
    SNET	*sn;
    struct stat	st;
    char	*p, *line;

    memset( si, 0, sizeof( struct sinfo ));

    if (( sn = snet_open( path, O_RDONLY, 0, 0 )) == NULL ) {
	if ( errno != ENOENT ) {
	    perror( path );
	}
	return( 1 );
    }

    if ( fstat( snet_fd( sn ), &st ) != 0 ) {
	(void)snet_close( sn );
	perror( path );
	return( -1 );
    }

    si->si_itime = st.st_mtime;

    while (( line = snet_getline( sn, NULL )) != NULL ) {
	p = line + 1;

	switch( line[0] ) {

	case 'v':
	    errno = 0;
            si->si_protocol = strtol( p, (char **)NULL, 10 );
            if ( errno ) {
                cosign_log( APLOG_NOTICE, s, "mod_cosign: read_scookie: "
                            "invalid protocol version %s, "
                            "falling back to protocol v0.", p );
                si->si_protocol = 0;
            }
	    break;

	case 'i':
	    strcpy( si->si_ipaddr, p );
	    break;

	case 'p':
	    strcpy( si->si_user, p );
	    break;

	case 'r':
	    strcpy( si->si_realm, p );
	    break;

	case 'f':
	    strcpy( si->si_factor, p );
	    break;
#ifdef KRB
	case 'k':
	    strcpy( si->si_krb5tkt, p );
	    break;
#endif /* KRB */

	default:
	    cosign_log( APLOG_ERR, s,
		    "mod_cosign: read_scookie: unknown key %c", line[0] );
	    (void)snet_close( sn );
	    return( -1 );
	}
    }

    if ( snet_close( sn ) != 0 ) {
	cosign_log( APLOG_ERR, s, "mod_cosign: read_scookie: %s", path );
	return( -1 );
    }
    return( 0 );
}
Пример #4
0
    int
env_read( int mode, struct envelope *env, SNET **s_lock )
{
    char			*line;
    SNET			*snet;
    char			filename[ MAXPATHLEN + 1 ];
    char			*hostname;
    int				ret = 1;
    ino_t			dinode;
    int				version;
    int				exp_level;
    int				jail;
    int				line_no = 1;
    struct dll_entry		*e_dll;

    switch ( mode ) {
    default:
	syslog( LOG_ERR, "Envelope.read unknown mode: %d", mode );
	return( 1 );

    case READ_QUEUE_INFO:
	if ( s_lock != NULL ) {
	    syslog( LOG_ERR,
		    "Envelope.read no lock allowed in READ_QUEUE_INFO mode" );
	    return( 1 );
	}
	break;

    case READ_DELIVER_INFO:
    case READ_JAIL_INFO:
	break;
    }

    sprintf( filename, "%s/E%s", env->e_dir, env->e_id );

    if (( snet = snet_open( filename, O_RDWR, 0, 1024 * 1024 )) == NULL ) {
	if ( errno != ENOENT ) {
	    syslog( LOG_ERR, "Syserror: env_read snet_open %s: %m", filename );
	}
	return( 1 );
    }

    switch ( mode ) {
    default:
	syslog( LOG_ERR, "Envelope.read invalid mode change: %d", mode );
	goto cleanup;

    case READ_QUEUE_INFO:
	/* test to see if env is locked by a q_runner */
	if ( lockf( snet_fd( snet ), F_TEST, 0 ) != 0 ) {
	    syslog( LOG_ERR, "Syserror: env_read lockf %s: %m", filename );
	    goto cleanup;
	}
	break;

    case READ_DELIVER_INFO:
    case READ_JAIL_INFO:
	if ( s_lock != NULL ) {
	    *s_lock = snet;

	    /* lock envelope fd */
	    if ( lockf( snet_fd( snet ), F_TLOCK, 0 ) != 0 ) {
		if ( errno != EAGAIN ) {
		    /* file not locked by a diferent process */
		    syslog( LOG_ERR, "Syserror: env_read lockf %s: %m",
			    filename );
		}
		goto cleanup;
	    }
	}
	break;
    }

    /* Vsimta-version */
    if ((( line = snet_getline( snet, NULL )) == NULL ) || ( *line != 'V' )) {
	syslog( LOG_ERR, "Envelope.read %s %d: expected version syntax",
		filename, line_no );
	goto cleanup;
    }
    sscanf( line + 1, "%d", &version );
    if (( version < 1 ) || ( version > SIMTA_EFILE_VERSION )) {
	syslog( LOG_ERR,
		"Envelope.read %s %d: unsupported efile version %d",
		filename, line_no, version );
	goto cleanup;
    }

    if ( version >= 2 ) {
	/* Emessage-id */
	line_no++;
	if ((( line = snet_getline( snet, NULL )) == NULL ) || 
		( *line != 'E' )) {
	    syslog( LOG_ERR,
		    "Envelope.read %s %d: expected Equeue-id syntax",
		    filename, line_no );
	    goto cleanup;
	}
	if ( strcmp( line + 1, env->e_id ) != 0 ) {
	    syslog( LOG_WARNING,
		    "Envelope.read %s %d: queue-id mismatch: %s",
		    filename, line_no, line + 1 );
	    goto cleanup;
	}
    }

    line_no++;
    if (( line = snet_getline( snet, NULL )) == NULL ) {
	syslog( LOG_ERR,
		"Envelope.read %s %d: expected Dinode syntax", filename,
			line_no );
	goto cleanup;
    }

    /* ignore optional M for now */
    if ( *line == 'M' ) {
	line_no++;
	if (( line = snet_getline( snet, NULL )) == NULL ) {
	    syslog( LOG_ERR,
		    "Envelope.read %s %d: expected Dinode syntax",
		    filename, line_no );
	    goto cleanup;
	}
    }

    /* Dinode info */
    if ( *line != 'I' ) {
	syslog( LOG_ERR, "Envelope.read %s %d: expected Dinode syntax",
		filename, line_no );
	goto cleanup;
    }

    sscanf( line + 1, "%lu", &dinode );

    switch ( mode ) {
    default:
	syslog( LOG_ERR, "Envelope.read invalid mode change: %d", mode );
	goto cleanup;

    case READ_JAIL_INFO:
    case READ_DELIVER_INFO:
	if ( dinode != env->e_dinode ) {
	    syslog( LOG_WARNING,
		    "Envelope.read %s %d: Dinode reread mismatch: "
		    "old %d new %d, ignoring", filename, line_no,
		    (int)env->e_dinode, (int)dinode );
	}
	break;

    case READ_QUEUE_INFO:
	if ( dinode == 0 ) {
	    syslog( LOG_WARNING, "Envelope.read %s %d: Dinode is 0",
		    filename, line_no );
	}
	env->e_dinode = dinode;
	break;
    }

    /* expansion info */
    if ( version >= 3 ) {
	line_no++;
	if ((( line = snet_getline( snet, NULL )) == NULL ) ||
		( *line != 'X' )) {
	    syslog( LOG_ERR,
		    "Envelope.read %s %d: expected Xpansion syntax",
		    filename, line_no );
	    goto cleanup;
	}

	if ( sscanf( line + 1, "%d", &exp_level) != 1 ) {
	    syslog( LOG_ERR, "Envelope.read %s %d: bad Xpansion syntax",
		    filename, line_no );
	    goto cleanup;
	}

	switch ( mode ) {
	default:
	    syslog( LOG_ERR, "Envelope.read: invalid mode change: %d", mode );
	    goto cleanup;

	case READ_DELIVER_INFO:
	case READ_JAIL_INFO:
	    if ( exp_level == env->e_n_exp_level ) {
		break;
	    }
	    syslog( LOG_WARNING, "Envelope.read %s %d: Xpansion mismatch: "
		    "old %d new %d, ignoring", filename, line_no,
		    env->e_n_exp_level, exp_level );
	    break;

	case READ_QUEUE_INFO:
	    env->e_n_exp_level = exp_level;
	    break;
	}
    }

    /* Jail info */
    if ( version >= 5 ) {
	line_no++;
	if ((( line = snet_getline( snet, NULL )) == NULL ) ||
		( *line != 'J' )) {
	    syslog( LOG_ERR, "Envelope.read %s %d: expected Jail syntax",
		    filename, line_no );
	    goto cleanup;
	}

	if ( sscanf( line + 1, "%d", &jail) != 1 ) {
	    syslog( LOG_ERR, "Envelope.read %s %d: bad Jail syntax",
		    filename, line_no );
	    goto cleanup;
	}

	switch ( mode ) {
	default:
	    syslog( LOG_ERR, "Envelope.read: invalid mode change: %d", mode );
	    goto cleanup;

	case READ_JAIL_INFO:
	case READ_DELIVER_INFO:
	    if ( env->e_jail == jail ) {
		break;
	    }
	    syslog( LOG_WARNING, "Envelope.read %s %d: Jail mismatch: "
		    "old %d new %d, ignoring", filename, line_no,
		    env->e_jail, jail );
	    break;

	case READ_QUEUE_INFO:
	    env_jail_set( env, jail );
	    break;
	}
    }

    line_no++;
    if ((( line = snet_getline( snet, NULL )) == NULL ) || ( *line != 'H' )) {
	syslog( LOG_ERR,
		"Envelope.read %s %d: expected host syntax",
		filename, line_no );
	goto cleanup;
    }

    hostname = line + 1;

    switch ( mode ) {
    default:
	syslog( LOG_ERR, "Envelope.read: invalid mode change: %d", mode );
	goto cleanup;

    case READ_DELIVER_INFO:
    case READ_JAIL_INFO:
	if ( env->e_hostname == NULL ) {
	    if ( *hostname != '\0' ) {
		syslog( LOG_ERR,
			"Envelope.read %s %d: hostname reread mismatch, "
			"old \"\" new \"%s\"", filename, line_no, hostname );
		goto cleanup;
	    }
	} else if ( strcasecmp( hostname, env->e_hostname ) != 0 ) {
	    syslog( LOG_ERR,
		    "Envelope.read %s %d: hostname reread mismatch, "
		    "old \"%s\" new \"%s\"", filename, line_no,
		    env->e_hostname, hostname );
	    goto cleanup;
	}
	break;

    case READ_QUEUE_INFO:
	if ( env_hostname( env, hostname ) != 0 ) {
	    goto cleanup;
	}
	break;
    }

    /* Dattributes */
    if ( version >= 4 ) {
	line_no++;
	if (( line = snet_getline( snet, NULL )) == NULL ) {
	    syslog( LOG_ERR, "Envelope.read %s: unexpected EOF", filename );
	    goto cleanup;
	}

	if ( *line != 'D' ) {
	    syslog( LOG_ERR, "Envelope.read %s: expected Dattributes syntax",
		    filename );
	    goto cleanup;
	}

	if ( sscanf( line + 1, "%d", &exp_level) != 1 ) {
	    syslog( LOG_ERR, "Envelope.read %s: bad Dattributes syntax",
		    filename );
	    goto cleanup;
	}

	if ( mode == READ_QUEUE_INFO ) {
	    env->e_attributes = exp_level;
	} else if ( exp_level != env->e_attributes ) {
	    syslog( LOG_WARNING, "Envelope.read %s: "
		    "Dattributes reread mismatch old %d new %d",
		    filename, env->e_attributes, exp_level );
	}
    }

    /* Ffrom-address */
    line_no++;
    if ((( line = snet_getline( snet, NULL )) == NULL ) || ( *line != 'F' )) {
	syslog( LOG_ERR, "Envelope.read %s %d: expected Ffrom syntax",
		filename, line_no );
	goto cleanup;
    }

    switch ( mode ) {
    default:
	syslog( LOG_ERR, "Envelope.read: invalid mode change: %d", mode );
	goto cleanup;

    case READ_QUEUE_INFO:
	if ( env_sender( env, line + 1 ) == 0 ) {
	    ret = 0;
	}
	goto cleanup;

    case READ_JAIL_INFO:
    case READ_DELIVER_INFO:
	if ( strcmp( env->e_mail, line + 1 ) != 0 ) {
	    syslog( LOG_ERR, "Envelope.read %s %d: bad sender re-read: "
		    "old <%s> new <%s>",
		    filename, line_no, env->e_mail, line + 1 );
	    goto cleanup;
	}
	break;
    }

    /* Rto-addresses */
    for ( line_no++; ( line = snet_getline( snet, NULL )) != NULL;
	    line_no++ ) {
	if ( *line != 'R' ) {
	    syslog( LOG_ERR, "Envelope.read %s %d: expected Recipient syntax",
		    filename, line_no );
	    goto cleanup;
	}

	if ( env_recipient( env, line + 1 ) != 0 ) {
	    goto cleanup;
	}
    }

    if ( env->e_rcpt == NULL ) {
	syslog( LOG_ERR, "Envelope.read %s %d: no recipients",
		filename, line_no );
	goto cleanup;
    }

    ret = 0;

    /* close snet if no need to maintain lock */
    if ( s_lock == NULL ) {
cleanup:
	if ( snet_close( snet ) < 0 ) {
	    syslog( LOG_ERR, "Liberror: env_read snet_close %s: %m",
		    filename );
	    ret = 1;
	}
    }

    if (( simta_mid_list_enable != 0 ) && ( ret == 0 )) {
	if (( e_dll = dll_lookup_or_create( &simta_env_list,
		env->e_id, 0 )) == NULL ) {
	    return( 1 );
	}

	if ( e_dll->dll_data == NULL ) {
	    e_dll->dll_data = env;
	    env->e_env_list_entry = e_dll;
	}
    }

    if (( simta_sender_list_enable != 0 ) && ( ret == 0 )) {
	if ( sender_list_add( env ) != 0 ) {
	    return( 1 );
	}
    }

    return( ret );
}
Пример #5
0
    yastr
env_dkim_sign( struct envelope *env )
{
    char	    df[ MAXPATHLEN + 1 ];
    DKIM_LIB	    *libhandle;
    unsigned int    flags;
    DKIM	    *dkim;
    DKIM_STAT	    result;
    yastr	    signature = NULL;
    yastr	    key = NULL;
    yastr	    tmp = NULL;
    yastr	    *split = NULL;
    size_t	    tok_count = 0;
    char	    buf[ 1024 * 1024 ];
    unsigned char   *dkim_header;
    SNET	    *snet;
    ssize_t	    chunk;

    sprintf( df, "%s/D%s", env->e_dir, env->e_id );

    if (( snet = snet_open( simta_dkim_key, O_RDONLY, 0,
	    1024 * 1024 )) == NULL ) {
	syslog( LOG_ERR, "Liberror: env_dkim_sign snet_open %s: %m",
		simta_dkim_key );
	return( NULL );
    }
    key = yaslempty();
    while (( chunk = snet_read( snet, buf, 1024 * 1024, NULL )) > 0 ) {
	key = yaslcatlen( key, buf, chunk );
    }
    snet_close( snet );

    if (( libhandle = dkim_init( NULL, NULL )) == NULL ) {
	syslog( LOG_ERR, "Liberror: env_dkim_sign dkim_init" );
	return( NULL );
    }

    /* Data is stored in UNIX format, so tell libopendkim to fix
     * CRLF issues.
     */
    flags = DKIM_LIBFLAGS_FIXCRLF;
    dkim_options( libhandle, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags,
	    sizeof( flags ));

    /* Only sign the headers recommended by RFC 6376 */
    dkim_options( libhandle, DKIM_OP_SETOPT, DKIM_OPTS_SIGNHDRS,
	    dkim_should_signhdrs, sizeof( unsigned char ** ));

    if (( dkim = dkim_sign( libhandle, (unsigned char *)(env->e_id), NULL,
	    (unsigned char *)key, (unsigned char *)simta_dkim_selector,
	    (unsigned char *)simta_dkim_domain,
	    DKIM_CANON_RELAXED, DKIM_CANON_RELAXED, DKIM_SIGN_RSASHA256,
	    -1, &result )) == NULL ) {
	syslog( LOG_NOTICE, "Liberror: env_dkim_sign dkim_sign: %s",
		dkim_getresultstr( result ));
	goto error;
    }

    if (( snet = snet_open( df, O_RDONLY, 0, 1024 * 1024 )) == NULL ) {
	syslog( LOG_ERR, "Liberror: env_dkim_sign snet_open %s: %m",
		buf );
	goto error;
    }

    while (( chunk = snet_read( snet, buf, 1024 * 1024, NULL )) > 0 ) {
	if (( result = dkim_chunk( dkim, (unsigned char *)buf,
		chunk )) != 0 ) {
	    syslog( LOG_NOTICE, "Liberror: env_dkim_sign dkim_chunk: %s: %s",
		    dkim_getresultstr( result ),
		    dkim_geterror( dkim ));
	    snet_close( snet );
	    goto error;
	}
    }

    snet_close( snet );

    if (( result = dkim_chunk( dkim, NULL, 0 )) != 0 ) {
	syslog( LOG_NOTICE, "Liberror: env_dkim_sign dkim_chunk: %s: %s",
		dkim_getresultstr( result ),
		dkim_geterror( dkim ));
	goto error;
    }
    if (( result = dkim_eom( dkim, NULL )) != 0 ) {
	syslog( LOG_NOTICE, "Liberror: env_dkim_sign dkim_eom: %s: %s",
		dkim_getresultstr( result ),
		dkim_geterror( dkim ));
	goto error;
    }
    if (( result = dkim_getsighdr_d( dkim, 16, &dkim_header,
	    (size_t *)&chunk )) != 0 ) {
	syslog( LOG_NOTICE,
		"Liberror: env_dkim_sign dkim_getsighdr_d: %s: %s",
		dkim_getresultstr( result ),
		dkim_geterror( dkim ));
	goto error;
    }

    /* Get rid of carriage returns in libopendkim output */
    split = yaslsplitlen( (const char *)dkim_header,
	    strlen( (const char *)dkim_header ), "\r", 1, &tok_count );
    tmp = yasljoinyasl( split, tok_count, "", 0 );
    signature = yaslcatyasl( yaslauto( "DKIM-Signature: " ), tmp );

error:
    yaslfree( tmp );
    yaslfreesplitres( split, tok_count );
    yaslfree( key );
    dkim_free( dkim );
    dkim_close( libhandle );

    return( signature );
}
Пример #6
0
    ino_t
env_dfile_copy( struct envelope *env, char *source, char *header )
{
    int			dfile_fd = -1;
    ino_t		retval = 0;
    FILE		*dfile = NULL;
    struct stat         sbuf;
    SNET		*snet = NULL;
    char		*line;
    char		df[ MAXPATHLEN + 1 ];

    /* If the tfile has already been written it has incorrect Dinode
     * information.
     */
    if ( env->e_flags & ENV_FLAG_TFILE ) {
	env_tfile_unlink( env );
    }

    if ( source == NULL ) {
	if ( ! ( env->e_flags & ENV_FLAG_DFILE )) {
	    syslog( LOG_ERR, "env_dfile_copy: no source" );
	    return( 0 );
	}

	sprintf( df, "%s/D%s", env->e_dir, env->e_id );
	if (( snet = snet_open( df, O_RDONLY, 0, 1024 * 1024 )) != NULL ) {
	    if ( unlink( df )) {
		syslog( LOG_ERR, "Syserror: env_dfile_copy unlink %s: %m", df );
		goto error;
	    }
	}
    } else {
	snet = snet_open( source, O_RDONLY, 0, 1024 * 1024 );
    }

    if ( snet == NULL ) {
	syslog( LOG_ERR, "Liberror: env_dfile_copy snet_open: %m" );
	return( 0 );
    }

    if (( dfile_fd = env_dfile_open( env )) < 0 ) {
	goto error;
    }

    if (( dfile = fdopen( dfile_fd, "w" )) == NULL ) {
	syslog( LOG_ERR, "Syserror: env_dfile_copy fdopen: %m" );
	if ( close( dfile_fd ) != 0 ) {
	    syslog( LOG_ERR, "Syserror: env_dfile_copy close: %m" );
	}
	goto error;
    }

    if ( header ) {
	if ( fprintf( dfile, "%s\n", header ) < 0 ) {
	    syslog( LOG_ERR, "Syserror: env_dfile_copy fprintf: %m" );
	    goto error;
	}
    }

    while (( line = snet_getline( snet, NULL )) != NULL ) {
	if ( fprintf( dfile, "%s\n", line ) < 0 ) {
	    syslog( LOG_ERR, "Syserror: env_dfile_copy fprintf: %m" );
	    goto error;
	}
    }

    if ( fstat( dfile_fd, &sbuf ) == 0 ) {
	retval = sbuf.st_ino;
    } else {
	syslog( LOG_ERR, "Syserror: env_dfile_copy fstat: %m" );
    }

error:
    if ( dfile != NULL && ( fclose( dfile ) != 0 )) {
	syslog( LOG_ERR, "Syserror: env_dfile_copy fclose: %m" );
    }

    if ( snet != NULL && ( snet_close( snet ) != 0 )) {
	syslog( LOG_ERR, "Liberror: env_dfile_copy snet_close: %m" );
    }

    if ( retval == 0 ) {
	env_dfile_unlink( env );
    }

    return( retval );
}
Пример #7
0
    int
expand( struct envelope *unexpanded_env )
{
    struct expand               exp;
    struct envelope             *base_error_env;
    struct envelope             *env_dead = NULL;
    struct envelope             *env;
    struct envelope             **env_p;
    struct recipient            *rcpt;
    struct expand_output        *host_stab = NULL;
    struct expand_output        *eo;
    struct expand_output        *eo_free;
    struct exp_addr             *e_addr;
    struct exp_addr             *next_e_addr;
    struct simta_red            *hq_red;
    char                        *domain;
    SNET                        *snet = NULL;
    int                         n_rcpts;
    int                         return_value = 1;
    int                         env_out = 0;
    int                         fast_file_start;
    int                         sendermatch;
    char                        e_original[ MAXPATHLEN ];
    char                        d_original[ MAXPATHLEN ];
    char                        d_out[ MAXPATHLEN ];
    /* RFC 5321 4.5.3.1.3.  Path
     * The maximum total length of a reverse-path or forward-path is 256
     * octets (including the punctuation and element separators).
     */
    char                        header[ 270 ];
#ifdef HAVE_LDAP
    char                        *p;
    int                         loop_color = 1;
    struct exp_link             *memonly;
    struct exp_link             *parent;
#endif /* HAVE_LDAP */

    if ( unexpanded_env->e_hostname != NULL ) {
        syslog( LOG_INFO, "Expand env <%s>: already expanded for host %s",
                unexpanded_env->e_id, unexpanded_env->e_hostname );
        return_value = 0;
        goto done;
    }

    memset( &exp, 0, sizeof( struct expand ));
    exp.exp_env = unexpanded_env;
    fast_file_start = simta_fast_files;

    /* call address_expand on each address in the expansion list.
     *
     * if an address is expandable, the address(es) that it expands to will
     * be added to the expansion list. These non-terminal addresses must
     * have their st_data set to NULL to specify that they are not to be
     * included in the terminal expansion list.
     *
     * Any address in the expansion list whose st_data is not NULL is
     * considered a terminal address and will be written out as one
     * of the addresses in expanded envelope(s).
     */

    if (( base_error_env = address_bounce_create( &exp )) == NULL ) {
        syslog( LOG_ERR, "Expand env <%s>: address_bounce_create: %m",
                unexpanded_env->e_id );
        goto done;
    }

    if ( env_recipient( base_error_env, unexpanded_env->e_mail ) != 0 ) {
        syslog( LOG_ERR, "Expand env <%s>: env_recipient: %m",
                unexpanded_env->e_id );
        goto done;
    }

    /* add all of the original recipients to the expansion list */
    for ( rcpt = unexpanded_env->e_rcpt; rcpt != NULL; rcpt = rcpt->r_next ) {
        if ( add_address( &exp, rcpt->r_rcpt, base_error_env,
                ADDRESS_TYPE_EMAIL, exp.exp_env->e_mail ) != 0 ) {
            /* add_address syslogs errors */
            goto cleanup1;
        }
    }

    /* process the expansion list */
    for ( exp.exp_addr_cursor = exp.exp_addr_head;
            exp.exp_addr_cursor != NULL;
            exp.exp_addr_cursor = exp.exp_addr_cursor->e_addr_next ) {
        switch ( address_expand( &exp )) {
        case ADDRESS_EXCLUDE:
            exp.exp_addr_cursor->e_addr_terminal = 0;
            /* the address is not a terminal local address */
            break;

        case ADDRESS_FINAL:
            exp.exp_addr_cursor->e_addr_terminal = 1;
            break;

        case ADDRESS_SYSERROR:
            goto cleanup1;

        default:
            panic( "Expand: address_expand out of range" );
        }
    }

#ifdef HAVE_LDAP
    /* Members-only processing */
    for ( memonly = exp.exp_memonly; memonly != NULL;
            memonly = memonly->el_next ) {
        if ((( p = parent_permitted( memonly->el_exp_addr )) != NULL ) ||
                ( sender_is_child( memonly->el_exp_addr->e_addr_children,
                loop_color++ ))) {
            if ( p != NULL ) {
                syslog( LOG_INFO, "Expand env <%s>: members-only group %s OK: "
                        "parent %s permitted",
                        unexpanded_env->e_id, memonly->el_exp_addr->e_addr, p );

            } else {
                syslog( LOG_INFO, "Expand env <%s>: members-only group %s OK: "
                        "sender is child",
                        unexpanded_env->e_id, memonly->el_exp_addr->e_addr );
            }
            memonly->el_exp_addr->e_addr_ldap_flags =
                    ( memonly->el_exp_addr->e_addr_ldap_flags &
                    ( ~STATUS_LDAP_MEMONLY ));
            if ( memonly->el_exp_addr->e_addr_env_moderated != NULL ) {
                env_free( memonly->el_exp_addr->e_addr_env_moderated );
                memonly->el_exp_addr->e_addr_env_moderated = NULL;
            }

        } else {
            syslog( LOG_NOTICE,
                    "Expand env <%s>: members-only group %s suppressed",
                    unexpanded_env->e_id, memonly->el_exp_addr->e_addr );
            memonly->el_exp_addr->e_addr_ldap_flags |= STATUS_LDAP_SUPPRESSOR;
            suppress_addrs( memonly->el_exp_addr->e_addr_children,
                    loop_color++ );
        }
    }
#endif /* HAVE_LDAP */

    sprintf( d_original, "%s/D%s", unexpanded_env->e_dir,
            unexpanded_env->e_id );

    /* Create one expanded envelope for every host we expanded address for */
    for ( e_addr = exp.exp_addr_head; e_addr != NULL;
            e_addr = e_addr->e_addr_next ) {

#ifdef HAVE_LDAP
        if ((( e_addr->e_addr_ldap_flags & STATUS_LDAP_SUPPRESSED ) != 0 ) &&
                ( !unblocked_path_to_root( e_addr, loop_color++ ))) {
            if ( simta_expand_debug != 0 ) {
                printf( "Suppressed: %s\n", e_addr->e_addr );
            }
            continue;
        }
        if ( e_addr->e_addr_env_gmailfwd != NULL ) {
            e_addr->e_addr_env_gmailfwd->e_attributes =
                    unexpanded_env->e_attributes | ENV_ATTR_ARCHIVE_ONLY;

            if ( simta_expand_debug != 0 ) {
                printf( "Group mail forwarding: %s\n", e_addr->e_addr );
                env_stdout( e_addr->e_addr_env_gmailfwd );
                continue;
            }

            sprintf( d_out, "%s/D%s", e_addr->e_addr_env_gmailfwd->e_dir,
                    e_addr->e_addr_env_gmailfwd->e_id );
            if ( env_dfile_copy( e_addr->e_addr_env_gmailfwd, d_original,
                    NULL ) == 0 ) {
                syslog( LOG_ERR, "Expand env <%s>: %s: env_dfile_copy failed",
                        unexpanded_env->e_id,
                        e_addr->e_addr_env_gmailfwd->e_id );
                goto cleanup3;
            }

            simta_debuglog( 2, "Expand env <%s>: group mail env %s dinode %d",
                    unexpanded_env->e_id,
                    e_addr->e_addr_env_gmailfwd->e_id,
                    (int)e_addr->e_addr_env_gmailfwd->e_dinode );

            sendermatch = !strcasecmp( unexpanded_env->e_mail,
                    e_addr->e_addr_env_gmailfwd->e_mail );

            n_rcpts = 0;
            for ( rcpt = e_addr->e_addr_env_gmailfwd->e_rcpt; rcpt != NULL;
                    rcpt = rcpt->r_next ) {
                n_rcpts++;
                if ( sendermatch ) {
                    syslog( LOG_INFO, "Expand env <%s>: %s: To <%s> From <%s>",
                            unexpanded_env->e_id,
                            e_addr->e_addr_env_gmailfwd->e_id, rcpt->r_rcpt,
                            e_addr->e_addr_env_gmailfwd->e_mail );
                } else {
                    syslog( LOG_INFO,
                            "Expand env <%s>: %s: To <%s> From <%s> (%s)",
                            unexpanded_env->e_id,
                            e_addr->e_addr_env_gmailfwd->e_id, rcpt->r_rcpt,
                            e_addr->e_addr_env_gmailfwd->e_mail,
                            unexpanded_env->e_mail );
                }

            }
            syslog( LOG_INFO,
                    "Expand env <%s>: %s: Expanded %d group mail forwarders",
                    unexpanded_env->e_id, e_addr->e_addr_env_gmailfwd->e_id,
                    n_rcpts );

            if ( env_outfile( e_addr->e_addr_env_gmailfwd ) != 0 ) {
                /* env_outfile syslogs errors */
                if ( unlink( d_out ) != 0 ) {
                    syslog( LOG_ERR, "Syserror: expand unlink %s: %m", d_out );
                }
                goto cleanup3;
            }
            env_out++;
            queue_envelope( e_addr->e_addr_env_gmailfwd );
            continue;

        }

        if ( e_addr->e_addr_env_moderated != NULL ) {
            e_addr->e_addr_env_moderated->e_attributes =
                    unexpanded_env->e_attributes;

            if ( simta_expand_debug != 0 ) {
                printf( "Moderated: %s\n", e_addr->e_addr );
                env_stdout( e_addr->e_addr_env_moderated );
                continue;
            }

            sprintf( d_out, "%s/D%s", e_addr->e_addr_env_moderated->e_dir,
                    e_addr->e_addr_env_moderated->e_id );
            if ( env_dfile_copy( e_addr->e_addr_env_moderated, d_original,
                    NULL ) == 0 ) {
                syslog( LOG_ERR, "Expand env <%s>: %s: env_dfile_copy failed",
                        unexpanded_env->e_id,
                        e_addr->e_addr_env_moderated->e_id );
                goto cleanup3;
            }

            simta_debuglog( 2, "Expand env <%s>: %s: moderation env dinode %d",
                    unexpanded_env->e_id, e_addr->e_addr_env_moderated->e_id,
                    (int)e_addr->e_addr_env_moderated->e_dinode );

            sendermatch = !strcasecmp( unexpanded_env->e_mail,
                    e_addr->e_addr_env_moderated->e_mail );

            n_rcpts = 0;
            for ( rcpt = e_addr->e_addr_env_moderated->e_rcpt; rcpt != NULL;
                    rcpt = rcpt->r_next ) {
                n_rcpts++;
                if ( sendermatch ) {
                    syslog( LOG_INFO, "Expand env <%s>: %s: To <%s> From <%s>",
                            unexpanded_env->e_id,
                            e_addr->e_addr_env_moderated->e_id, rcpt->r_rcpt,
                            e_addr->e_addr_env_moderated->e_mail );
                } else {
                    syslog( LOG_INFO,
                            "Expand env <%s>: %s: To <%s> From <%s> (%s)",
                            unexpanded_env->e_id,
                            e_addr->e_addr_env_moderated->e_id, rcpt->r_rcpt,
                            e_addr->e_addr_env_moderated->e_mail,
                            unexpanded_env->e_mail );
                }

            }
            syslog( LOG_INFO,
                    "Expand env <%s>: %s: Expanded %d moderators",
                    unexpanded_env->e_id, e_addr->e_addr_env_moderated->e_id,
                    n_rcpts );

            if ( env_outfile( e_addr->e_addr_env_moderated ) != 0 ) {
                /* env_outfile syslogs errors */
                if ( unlink( d_out ) != 0 ) {
                    syslog( LOG_ERR, "expand unlink %s: %m", d_out );
                }
                goto cleanup3;
            }
            env_out++;
            queue_envelope( e_addr->e_addr_env_moderated );
            continue;

        } else if ( e_addr->e_addr_ldap_flags & STATUS_LDAP_SUPPRESSOR ) {
            for ( parent = e_addr->e_addr_parents; parent != NULL;
                    parent = parent->el_next ) {
                if ( parent->el_exp_addr == NULL ) {
                    if ( bounce_text( base_error_env, TEXT_ERROR,
                            "Members only group conditions not met: ",
                            e_addr->e_addr, NULL ) != 0 ) {
                        goto cleanup3;
                    }

                    if ( bounce_text( base_error_env, TEXT_ERROR,
            "If you have any questions, please contact the group owner: ",
                            e_addr->e_addr_owner, NULL ) != 0 ) {
                        goto cleanup3;
                    }

                } else if (( e_addr->e_addr_ldap_flags &
                        STATUS_LDAP_PRIVATE ) == 0 ) {
                    if ( bounce_text( parent->el_exp_addr->e_addr_errors,
                            TEXT_ERROR,
                            "Members only group conditions not met: ",
                            e_addr->e_addr, NULL ) != 0 ) {
                        goto cleanup3;
                    }

                    if ( bounce_text( parent->el_exp_addr->e_addr_errors,
                            TEXT_ERROR,
            "If you have any questions, please contact the group owner: ",
                            e_addr->e_addr_owner, NULL ) != 0 ) {
                        goto cleanup3;
                    }
                }
            }

            continue;
        }
#endif /* HAVE_LDAP */

        if ( e_addr->e_addr_terminal == 0 ) {
            if ( simta_expand_debug != 0 ) {
                printf( "Non-terminal: %s\n", e_addr->e_addr );
            }
            /* not a terminal expansion, do not add */
            continue;
        }

        if ( simta_expand_debug != 0 ) {
            printf( "Terminal: %s\n", e_addr->e_addr );
        }

        switch ( e_addr->e_addr_type ) {
        case ADDRESS_TYPE_EMAIL:
            if (( domain = strchr( e_addr->e_addr, '@' )) == NULL ) {
                syslog( LOG_ERR, "Expand env <%s>: strchr blivet",
                        unexpanded_env->e_id );
                goto cleanup3;
            }
            domain++;
            env = eo_lookup( host_stab, domain, e_addr->e_addr_from );
            break;

        case ADDRESS_TYPE_DEAD:
            domain = NULL;
            env = env_dead;
            break;

        default:
            panic( "expand: address type out of range" );
        }

        if ( env == NULL ) {
            /* Create envelope and add it to list */
            if (( env = env_create( domain ? simta_dir_fast : simta_dir_dead,
                    NULL, e_addr->e_addr_from, unexpanded_env )) == NULL ) {
                syslog( LOG_ERR, "Expand env <%s>: env_create: %m",
                        unexpanded_env->e_id );
                goto cleanup3;
            }

            simta_debuglog( 2, "Expand env <%s>: %s: expansion env dinode %d",
                    unexpanded_env->e_id, env->e_id, (int)env->e_dinode );

            /* fill in env */
            env->e_attributes = unexpanded_env->e_attributes;
            if ( domain != NULL ) {
                if ( env_hostname( env, domain ) != 0 ) {
                    env_free( env );
                    goto cleanup3;
                }
            } else {
                env_dead = env;
            }

            /* Add env to host_stab */
            if ( eo_insert( &host_stab, env ) != 0 ) {
                syslog( LOG_ERR, "Expand env <%s>: eo_insert %s failed: %m",
                        unexpanded_env->e_id, env->e_id );
                env_free( env );
                goto cleanup3;
            }
        }

        if ( env_recipient( env, e_addr->e_addr ) != 0 ) {
            goto cleanup3;
        }

        syslog( LOG_NOTICE,
                "Expand env <%s>: %s: recipient <%s> added to env for host %s",
                unexpanded_env->e_id, env->e_id, e_addr->e_addr,
                env->e_hostname ? env->e_hostname : "NULL" );
    }

    /* Write out all expanded envelopes and place them in to the host_q */
    for ( eo = host_stab; eo != NULL; eo = eo->eo_next ) {
        env = eo->eo_env;

        if ( simta_expand_debug == 0 ) {
            sprintf( d_out, "%s/D%s", env->e_dir, env->e_id );

            /* RFC 5321 4.4 Trace Information
             * When the delivery SMTP server makes the "final delivery" of a
             * message, it inserts a return-path line at the beginning of the
             * mail data.  This use of return-path is required; mail systems
             * MUST support it.  The return-path line preserves the
             * information in the <reverse-path> from the MAIL command.
             * Here, final delivery means the message has left the SMTP
             * environment.
             */
            if ((( hq_red = red_host_lookup( eo->eo_hostname )) != NULL ) &&
                    ( hq_red->red_deliver_type == RED_DELIVER_BINARY )) {
                if ( snprintf( header, 270,
                        "Return-Path: <%s>", env->e_mail ) >= 270 ) {
                    syslog( LOG_ERR,
                            "Expand env <%s>: %s: return path is too large",
                            unexpanded_env->e_id, env->e_id );
                }
                if ( env_dfile_copy( env, d_original, header ) == 0 ) {
                    syslog( LOG_ERR, "Expand env <%s>: %s: env_dfile_copy failed",
                            unexpanded_env->e_id, env->e_id );
                    goto cleanup4;
                }
            } else {
                /* Dfile: link Dold_id env->e_dir/Dnew_id */
                if ( link( d_original, d_out ) != 0 ) {
                    syslog( LOG_ERR, "Syserror: expand link %s %s: %m",
                            d_original, d_out );
                    goto cleanup4;
                }
            }

            sendermatch = !strcasecmp( unexpanded_env->e_mail, env->e_mail );

            n_rcpts = 0;
            for ( rcpt = env->e_rcpt; rcpt != NULL; rcpt = rcpt->r_next ) {
                n_rcpts++;
                if ( sendermatch ) {
                    syslog( LOG_INFO, "Expand env <%s>: %s: To <%s> From <%s>",
                            unexpanded_env->e_id, env->e_id, rcpt->r_rcpt,
                            env->e_mail );
                } else {
                    syslog( LOG_INFO,
                            "Expand env <%s>: %s: To <%s> From <%s> (%s)",
                            unexpanded_env->e_id, env->e_id, rcpt->r_rcpt,
                            env->e_mail, unexpanded_env->e_mail );
                }
            }

            syslog( LOG_INFO,
                    "Expand env <%s>: %s: Expanded %d recipients",
                    unexpanded_env->e_id, env->e_id, n_rcpts );

            /* Efile: write env->e_dir/Enew_id for all recipients at host */
            syslog( LOG_NOTICE, "Expand env <%s>: %s: writing Efile for %s",
                    unexpanded_env->e_id, env->e_id,
                    env->e_hostname ? env->e_hostname : "NULL" );
            if ( env_outfile( env ) != 0 ) {
                /* env_outfile syslogs errors */
                if ( unlink( d_out ) != 0 ) {
                    syslog( LOG_ERR, "Syserror: expand unlink %s: %m", d_out );
                }
                goto cleanup4;
            }

            env_out++;
            queue_envelope( env );

        } else {
            printf( "\n" );
            env_stdout( env );
        }
    }

    if ( env_out == 0 ) {
        syslog( LOG_NOTICE, "Expand env <%s>: no terminal recipients, "
                "deleting message", unexpanded_env->e_id );
    }

    /* write errors out to disk */
    env_p = &(exp.exp_errors);
    while (( env = *env_p ) != NULL ) {
        if ( simta_expand_debug == 0 ) {
            if ( env->e_error != 0 ) {
                env_p = &(env->e_next);

                if ( snet == NULL ) {
                    if (( snet = snet_open( d_original, O_RDONLY, 0,
                            1024 * 1024 )) == NULL ) {
                        syslog( LOG_ERR, "Liberror: expand snet_open %s: %m",
                                d_original );
                        goto cleanup5;
                    }
                } else {
                    if ( lseek( snet_fd( snet ), (off_t)0, SEEK_SET ) != 0 ) {
                        syslog( LOG_ERR, "Syserror: q_deliver lseek: %m" );
                        panic( "q_deliver lseek fail" );
                    }
                }

                /* write out error text, get Dfile inode */
                if ( bounce_dfile_out( env, snet ) == 0 ) {
                    if ( snet != NULL ) {
                        if ( snet_close( snet ) != 0 ) {
                            syslog( LOG_ERR,
                                    "Liberror: expand snet_close %s: %m",
                                    d_original );
                        }
                    }

                    goto cleanup5;
                }

                simta_debuglog( 2, "Expand env <%s>: %s: errors env dinode %d",
                        unexpanded_env->e_id, env->e_id, (int)env->e_dinode );

                line_file_free( env->e_err_text );
                env->e_err_text = NULL;
                env->e_error = 0;

                if ( env_outfile( env ) != 0 ) {
                    /* env_outfile syslogs errors */
                    sprintf( d_out, "%s/D%s", env->e_dir, env->e_id );
                    if ( unlink( d_out ) != 0 ) {
                        syslog( LOG_ERR, "Syserror: expand unlink %s: %m",
                                d_out );
                    }
                    goto cleanup5;
                }

                sendermatch = !strcasecmp( unexpanded_env->e_mail,
                        env->e_mail );

                n_rcpts = 0;
                for ( rcpt = env->e_rcpt; rcpt != NULL; rcpt = rcpt->r_next ) {
                    n_rcpts++;
                    if ( sendermatch ) {
                        syslog( LOG_INFO,
                                "Expand env <%s>: %s: To <%s> From <%s>",
                                unexpanded_env->e_id, env->e_id, rcpt->r_rcpt,
                                env->e_mail );
                    } else {
                        syslog( LOG_INFO,
                                "Expand env <%s>: %s: To <%s> From <%s> (%s)",
                                unexpanded_env->e_id, env->e_id, rcpt->r_rcpt,
                                env->e_mail, unexpanded_env->e_mail );
                    }
                }

                syslog( LOG_NOTICE, "Expand env <%s>: %s: Expanded %d bounces",
                        unexpanded_env->e_id, env->e_id, n_rcpts );

                queue_envelope( env );

            } else {
                *env_p = env->e_next;
                env_free( env );
            }

        } else {
            *env_p = env->e_next;
            bounce_stdout( env );
            env_free( env );
        }
    }

    if ( snet != NULL ) {
        if ( snet_close( snet ) != 0 ) {
            syslog( LOG_ERR, "Liberror: expand snet_close %s: %m", d_original );
            sprintf( d_out, "%s/D%s", env->e_dir, env->e_id );
            if ( unlink( d_out ) != 0 ) {
                syslog( LOG_ERR, "Syserror: expand unlink %s: %m", d_out );
            }
            goto cleanup5;
        }
        snet = NULL;
    }

    syslog( LOG_INFO, "Expand env <%s>: Metric %d entries %d levels",
            unexpanded_env->e_id, exp.exp_entries, exp.exp_max_level );

    if ( simta_expand_debug != 0 ) {
        return_value = 0;
        goto cleanup2;
    }

    if ( utime( d_original, NULL ) != 0 ) {
        syslog( LOG_ERR, "Syserror: expand utime %s: %m", d_original );
        goto cleanup5;
    }

    if ( unexpanded_env->e_dir != simta_dir_fast ) {
        /* truncate orignal Efile */
        sprintf( e_original, "%s/E%s", unexpanded_env->e_dir,
                unexpanded_env->e_id );

        if ( truncate( e_original, (off_t)0 ) != 0 ) {
            syslog( LOG_ERR, "Syserror: expand truncate %s: %m", e_original );
            goto cleanup5;
        }
    }

    /* delete original message */
    if ( env_unlink( unexpanded_env ) != 0 ) {
        syslog( LOG_ERR,
                "Expand env <%s>: Expansion complete, can't delete message",
                unexpanded_env->e_id );
    } else {
        syslog( LOG_INFO,
                "Expand env <%s>: Expansion complete, message deleted",
                unexpanded_env->e_id );
    }

    return_value = 0;
    goto cleanup2;

cleanup5:
    cleanup_envelope_list( &exp.exp_errors );
#ifdef HAVE_LDAP
    cleanup_envelope_list( &exp.exp_gmailfwding );
#endif /* HAVE_LDAP */

cleanup4:
    for ( eo = host_stab; eo != NULL; eo = eo->eo_next ) {
        env = eo->eo_env;
        eo->eo_env = NULL;

        if (( env->e_flags & ENV_FLAG_EFILE ) != 0 ) {
            queue_remove_envelope( env );
            if ( env_unlink( env ) == 0 ) {
                syslog( LOG_WARNING, "Expand env <%s>: Message Deleted: "
                        "System error, unwinding expansion", env->e_id );
            } else {
                syslog( LOG_ERR, "Expand env <%s>: "
                        "System error, can't unwind expansion", env->e_id );
            }
        }

        env_free( env );
    }

cleanup3:
#ifdef HAVE_LDAP
    for ( memonly = exp.exp_memonly; memonly != NULL;
            memonly = memonly->el_next ) {
        if (( memonly->el_exp_addr->e_addr_env_moderated != NULL ) &&
                (( memonly->el_exp_addr->e_addr_env_moderated->e_flags &
                ENV_FLAG_EFILE ) != 0 )) {
            env_unlink( memonly->el_exp_addr->e_addr_env_moderated );
            env_free( memonly->el_exp_addr->e_addr_env_moderated );
            memonly->el_exp_addr->e_addr_env_moderated = NULL;
        }
    }
#endif /* HAVE_LDAP */

    if ( simta_fast_files != fast_file_start ) {
        syslog( LOG_ERR, "Expand env <%s>: could not unwind expansion",
                unexpanded_env->e_id );
        return_value = 1;
    }

cleanup2:
    /* free host_stab */
    eo = host_stab;
    while ( eo != NULL ) {
        eo_free = eo;
        eo = eo->eo_next;
        free( eo_free );
    }

cleanup1:
#ifdef HAVE_LDAP
    exp_addr_link_free( exp.exp_memonly );
#endif /* HAVE_LDAP */

    /* free the expansion list */
    for ( e_addr = exp.exp_addr_head; e_addr != NULL; e_addr = next_e_addr ) {
        next_e_addr = e_addr->e_addr_next;

#ifdef HAVE_LDAP
        exp_addr_link_free( e_addr->e_addr_parents );
        exp_addr_link_free( e_addr->e_addr_children );
        permitted_destroy( e_addr );
        if (( e_addr->e_addr_env_moderated != NULL ) &&
                (( e_addr->e_addr_env_moderated->e_flags &
                ENV_FLAG_EFILE ) == 0 )) {
            env_free( e_addr->e_addr_env_moderated );
        }

        if ( e_addr->e_addr_owner ) {
            free( e_addr->e_addr_owner );
        }

        if ( e_addr->e_addr_dn ) {
            free( e_addr->e_addr_dn );
        }
#endif

        free( e_addr->e_addr );
        free( e_addr->e_addr_from );
        free( e_addr );
    }

done:
    if ( return_value != 0 ) {
        syslog( LOG_ERR, "Expand env <%s>: Expansion failed",
                unexpanded_env->e_id );
    }

    return( return_value );
}
Пример #8
0
    int
main( int argc, char *argv[] )
{
    SNET		*in;
    SNET		*out;
    char		*line;
    int			x;
    struct timeval	tv;
    char		path[ MAXPATHLEN ];
    int			c;

    if ( simta_gettimeofday( &tv ) != 0 ) {
	perror( "gettimeofday" );
	return( 1 );
    }

    /* XXX hard path */
    sprintf( path, "%s/%ld.%ld", "/var/simta/log", tv.tv_sec, tv.tv_usec );

    if (( in = snet_attach( 0, 1024 * 1024 )) == NULL ) {
	perror( "snet_attach" );
	exit( 1 );
    }

    if (( out = snet_open( path, O_CREAT | O_WRONLY,
	    S_IRUSR | S_IRGRP | S_IROTH, 1024 * 1024 )) == NULL ) {
	perror( "snet_open" );
	exit( 1 );
    }

    snet_writef( out, "%s", argv[ 0 ] );

    for ( x = 1; x < argc; x++ ) {
	snet_writef( out, " %s", argv[ x ] );
    }
    snet_writef( out, "\n\n" );

    opterr = 0;

    while (( c = getopt( argc, argv, "b:" )) != -1 ) {
	switch ( c ) {
	case 'b':
	    if ( strlen( optarg ) == 1 ) {
		switch ( *optarg ) {
		case 'a':
		    /* -ba ARPANET mode */
		case 'd':
		    /* -bd Daemon mode, background */
		case 's':
		    /* 501 Permission denied */
		    printf( "501 Mode not supported\r\n" );
		    exit( 1 );
		}
	    }
	    break;

	default:
	    break;
	}
    }

    while (( line = snet_getline( in, NULL )) != NULL ) {
	snet_writef( out, "%s\n", line );
    }

    if ( snet_close( in ) != 0 ) {
	perror( "snet_close" );
	exit( 1 );
    }

    if ( snet_close( out ) != 0 ) {
	perror( "snet_close" );
	exit( 1 );
    }

    return( 0 );
}