Ejemplo n.º 1
0
Archivo: sla.c Proyecto: 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 );
}
Ejemplo n.º 2
0
    int
main( int argc, char *argv[])
{
    int				fd;
    SNET			*snet;
    char			*line;
    u_int			line_len;
    struct message_digest       md;

    if ( argc != 3 ) {
	fprintf( stderr, "Usage: %s <checksum_algorithm> <file>\n", argv[ 0 ]);
	return( 1 );
    }

    /* OpenSSL 1.1.0 added auto-init */
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
    OpenSSL_add_all_digests();
#endif /* OpenSSL < 1.1.0 */
    simta_checksum_md = EVP_get_digestbyname((const char*)(argv[ 1 ]));

    if ( simta_checksum_md == NULL ) {
	fprintf( stderr, "%s: unknown checksum algorithm\n", argv[ 1 ]);
	return( 1 );
    }

    md_init( &md );
    md_reset( &md );

    if (( fd = open( argv[ 2 ], O_RDONLY, 0 )) < 0 ) {
	perror( "open" );
	exit( 1 );
    }

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

    while (( line = snet_getline( snet, NULL )) != NULL ) {
	line_len = strlen( line );
        md_update( &md, line, line_len );
    }

    md_finalize( &md );
    md_cleanup( &md );

    if ( snet_close( snet ) != 0 ) {
	perror( "snet_close" );
	return( 1 );
    }

    printf( "\nChecksum: %s\n", md.md_b16 );

    return( 0 );
}
Ejemplo n.º 3
0
    int
f_stor( SNET *sn, int ac, char *av[] )
{
    char 		*sizebuf;
    char		xscriptdir[ MAXPATHLEN ];
    char		upload[ MAXPATHLEN ];
    char		buf[ 8192 ];
    char		*line;
    char		*d_tran, *d_path;
    int			fd;
    int			zero = 0;
    off_t		len;
    ssize_t		rc;
    struct timeval	tv;
    struct protoent	*proto;

    if ( !prevstor ) {
	/* Turn off TCP_NODELAY for stores */
	if (( proto = getprotobyname( "tcp" )) == NULL ) {
	    syslog( LOG_ERR, "f_stor: getprotobyname: %m" );
	    return( -1 );
	}

	if ( setsockopt( snet_fd( sn ), proto->p_proto, TCP_NODELAY, &zero,
		sizeof( zero )) != 0 ) {
	    syslog( LOG_ERR, "f_stor: snet_setopt: %m" );
	    return( -1 );
	}
	prevstor = 1;
    }

    if ( checkuser && ( !authorized )) {
	snet_writef( sn, "%d Not logged in\r\n", 551 );
	exit( 1 );
    }
    /* decode() uses static mem, so strdup() */
    if (( d_tran = decode( av[ 2 ] )) == NULL ) {
	syslog( LOG_ERR, "f_stor: decode: buffer too small" );
	snet_writef( sn, "%d Line too long\r\n", 540 );
	return( 1 );
    } 
    if (( d_tran = strdup( d_tran )) == NULL ) {
	syslog( LOG_ERR, "f_stor: strdup: %s: %m", d_tran );
	return( -1 );
    }

    switch ( keyword( ac, av )) {

    case K_TRANSCRIPT:
        if ( snprintf( xscriptdir, MAXPATHLEN, "tmp/file/%s", d_tran )
		>= MAXPATHLEN ) {
	    syslog( LOG_ERR, "f_stor: xscriptdir path too long" );
	    snet_writef( sn, "%d Path too long\r\n", 540 );
	    return( 1 );
	}
        if ( snprintf( upload, MAXPATHLEN, "tmp/transcript/%s", d_tran )
		>= MAXPATHLEN ) {
	    syslog( LOG_ERR, "f_stor: upload path too long" );
	    snet_writef( sn, "%d Path too long\r\n", 540 );
	    return( 1 );
	}

	/* keep encoded transcript name, since it will just be
	 * used later to compare in a stor file.
	 */
	if ( strlen( av[ 2 ] ) >= MAXPATHLEN ) {
	    syslog( LOG_ERR, "f_stor: upload_xscript path too long" );
	    snet_writef( sn, "%d Path too long\r\n", 540 );
	    return( 1 );
	}
	strcpy( upload_xscript, av[ 2 ] );

	/* make the directory for the files of this xscript to live in. */
	if ( mkdir( xscriptdir, 0777 ) < 0 ) {
	    if ( errno == EEXIST ) {
	        snet_writef( sn, "%d Transcript exists\r\n", 551 );
		exit( 1 );
	    }
	    snet_writef( sn, "%d %s: %s\r\n",
		    551, xscriptdir, strerror( errno ));
	    exit( 1 );
	}
	break;

    case K_FILE:
	/* client must have provided a transcript name before giving 
	 * files in that transcript
	 */
	if (( strcmp( upload_xscript, av[ 2 ] ) != 0 )) {
	    snet_writef( sn, "%d Incorrect Transcript %s\r\n", 552, av[ 2 ] );
	    exit( 1 );
	}

	/* decode() uses static mem, so strdup() */
	if (( d_path = decode( av[ 3 ] )) == NULL ) {
	    syslog( LOG_ERR, "f_stor: decode: buffer too small" );
	    snet_writef( sn, "%d Line too long\r\n", 540 );
	    return( 1 );
	} 
	if (( d_path = strdup( d_path )) == NULL ) {
	    syslog( LOG_ERR, "f_stor: strdup: %s: %m", d_path );
	    return( -1 );
	}

	if ( d_path[ 0 ] == '/' ) {
	    if ( snprintf( upload, MAXPATHLEN, "tmp/file/%s%s", d_tran,
		    d_path ) >= MAXPATHLEN ) {
		syslog( LOG_ERR, "f_stor: upload path too long" );
		snet_writef( sn, "%d Path too long\r\n", 540 );
		return( 1 );
	    }
	} else {
	    if ( snprintf( upload, MAXPATHLEN, "tmp/file/%s/%s", d_tran,
		    d_path ) >= MAXPATHLEN ) {
		syslog( LOG_ERR, "f_stor: upload path too long" );
		snet_writef( sn, "%d Path too long\r\n", 540 );
		return( 1 );
	    }
	}
	free( d_path );
	free( d_tran );
	break;

    default:
        snet_writef( sn, "%d STOR Syntax error\r\n", 550 );
	exit( 1 ); 
    }

    if (( fd = open( upload, O_CREAT|O_EXCL|O_WRONLY, 0666 )) < 0 ) {
	if ( mkdirs( upload ) < 0 ) {
	    syslog( LOG_ERR, "f_stor: mkdir: %s: %m", upload );
	    snet_writef( sn, "%d %s: %s\r\n", 555, upload, strerror( errno ));
	    exit( 1 );
	}
	if (( fd = open( upload, O_CREAT|O_EXCL|O_WRONLY, 0666 )) < 0 ) {
	    syslog( LOG_ERR, "f_stor: open: %s: %m", upload );
	    snet_writef( sn, "%d %s: %s\r\n", 555, upload, strerror( errno ));
	    exit( 1 );
	}
    }


    snet_writef( sn, "%d Storing file\r\n", 350 );

    tv.tv_sec = 60;
    tv.tv_usec = 0;
    if ( ( sizebuf = snet_getline( sn, &tv ) ) == NULL ) {
	syslog( LOG_ERR, "f_stor: snet_getline: %m" );
	return( -1 );
    }
    /* Will there be a limit? */
    len = strtoofft( sizebuf, NULL, 10 );

    for ( ; len > 0; len -= rc ) {
	tv.tv_sec = 60;
	tv.tv_usec = 0;
	if (( rc = snet_read(
		sn, buf, MIN( len, sizeof( buf )), &tv )) <= 0 ) {
	    if ( snet_eof( sn )) {
		syslog( LOG_ERR, "f_stor: snet_read: eof" );
	    } else {
		syslog( LOG_ERR, "f_stor: snet_read: %m" );
	    }
	    return( -1 );
	}

	if ( write( fd, buf, rc ) != rc ) {
	    snet_writef( sn, "%d %s: %s\r\n", 555, upload, strerror( errno ));
	    exit( 1 );
	}
    }

    if ( len != 0 ) {
	syslog( LOG_ERR, "f_stor: len is %" PRIofft "d", len );
	snet_writef( sn, "%d %s: internal error!\r\n", 555, upload );
	exit( 1 );
    }

    if ( close( fd ) < 0 ) {
	snet_writef( sn, "%d %s: %s\r\n", 555, upload, strerror( errno ));
	exit( 1 );
    }

    syslog( LOG_DEBUG, "f_stor: file %s stored", upload );

    tv.tv_sec = 60;
    tv.tv_usec = 0;
    if (( line = snet_getline( sn, &tv )) == NULL ) {
        syslog( LOG_ERR, "f_stor: snet_getline: %m" );
	return( -1 );
    }

    /* make sure client agrees we're at the end */
    if ( strcmp( line, "." ) != 0 ) {
        syslog( LOG_ERR, "f_stor: line is: %s", line );
	snet_writef( sn, "%d Length doesn't match sent data %s\r\n",
		555, upload );
	(void)unlink( upload );
	exit( 1 );
    }

    snet_writef( sn, "%d File stored\r\n", 250 );
    return( 0 );
}
Ejemplo n.º 4
0
    int
cmdloop( int fd, struct sockaddr_in *sin )
{
    SNET		*sn;
    struct hostent	*hp;
    char		*p;
    int			ac, i;
    int			one = 1;
    unsigned int	n;
    char		**av, *line;
    struct timeval	tv;
    extern char		*version;
    extern int		connections;
    extern int		maxconnections;
    extern int		rap_extensions;

    if ( authlevel == 0 ) {
	commands = noauth;
	ncommands = sizeof( noauth ) / sizeof( noauth[ 0 ] );
    } else {
	commands = notls;
	ncommands = sizeof( notls ) / sizeof( notls[ 0 ] );
    }

    if (( sn = snet_attach( fd, 1024 * 1024 )) == NULL ) {
	syslog( LOG_ERR, "snet_attach: %m" );
	exit( 1 );
    }
    remote_addr = strdup( inet_ntoa( sin->sin_addr ));

    if (( hp = gethostbyaddr( (char *)&sin->sin_addr,
	    sizeof( struct in_addr ), AF_INET )) == NULL ) {
	remote_host = strdup( remote_addr );
    } else {
	/* set global remote_host for retr command */
	remote_host = strdup( hp->h_name );
	for ( p = remote_host; *p != '\0'; p++ ) {
	    *p = tolower( *p );
	}
    }

    syslog( LOG_INFO, "child for [%s] %s",
	    inet_ntoa( sin->sin_addr ), remote_host );

    if ( setsockopt( fd, 6, TCP_NODELAY, &one, sizeof( one )) < 0 ) {
	syslog( LOG_ERR, "setsockopt: %m" );
    }

    if ( maxconnections != 0 ) {
	if ( connections > maxconnections ) {
	    syslog( LOG_INFO, "%s: connection refused: server busy\r\n",
		    remote_host );
	    snet_writef( sn, "%d Server busy\r\n", 420 );
	    exit( 1 );
	}
    }

    if (( access_list = list_new( )) == NULL ) {
	syslog( LOG_ERR, "new_list: %m" );
	snet_writef( sn,
	    "%d Service not available, closing transmission channel\r\n", 421 );
	return( -1 );
    }
    
    if ( authlevel == 0 ) {
	/* lookup proper command file based on the hostname, IP or CN */
	if ( command_k( "config", 0 ) < 0 ) {
	    syslog( LOG_INFO, "%s: Access denied: Not in config file",
		remote_host );
	    snet_writef( sn, "%d No access for %s\r\n", 500, remote_host );
	    exit( 1 );
	} else {
	    if ( read_kfile( sn, command_file ) != 0 ) {
		/* error message given in read_kfile */
		exit( 1 );
	    }
	    commands = auth;
	    ncommands = sizeof( auth ) / sizeof( auth[ 0 ] );
	}
    }

    if ( gethostname( hostname, MAXHOSTNAMELEN ) < 0 ) {
	syslog( LOG_ERR, "gethostname: %m" );
	exit( 1 );
    }

    snet_writef( sn, "200%sRAP 1 %s %s radmind access protocol\r\n",
	rap_extensions ? "-" : " ", hostname, version );
    if ( rap_extensions ) {
	snet_writef( sn, "200 CAPA" ); 
#ifdef HAVE_ZLIB
	if ( max_zlib_level > 0 ) {
	    snet_writef( sn, " ZLIB" ); 
	}
#endif /* HAVE_ZLIB */
	snet_writef( sn, " REPO" ); 
	snet_writef( sn, "\r\n" ); 
    }

    /*
     * 60 minutes
     * To make fsdiff | lapply work, when fsdiff will take a long time,
     * we allow the server to wait a long time.
     */
    tv.tv_sec = 60 * 60;
    tv.tv_usec = 0 ;
    while (( line = snet_getline( sn, &tv )) != NULL ) {
	tv.tv_sec = 60 * 60;
	tv.tv_usec = 0; 

	if ( debug ) {
	    fprintf( stderr, "<<< %s\n", line );
	}

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

	if ( ac == 0 ) {
	    snet_writef( sn, "%d Illegal null command\r\n", 501 );
	    continue;
	}

	for ( i = 0; i < ncommands; i++ ) {
	    n = MAX( strlen( av[ 0 ] ), 4 );
	    if ( strncasecmp( av[ 0 ], commands[ i ].c_name, n ) == 0 ) {
		break;
	    }
	}
	if ( i >= ncommands ) {
	    snet_writef( sn, "%d Command %s unrecognized\r\n", 500, av[ 0 ] );
	    continue;
	}
	if ( (*(commands[ i ].c_func))( sn, ac, av ) < 0 ) {
	    break;
	}

    }

    snet_writef( sn, "%d Server closing connection\r\n", 444 );

    if ( line == NULL ) {
	syslog( LOG_ERR, "snet_getline: %m" );
    }
    return( 0 );
}
Ejemplo n.º 5
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 );
}
Ejemplo n.º 6
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 );
}
Ejemplo n.º 7
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 );
}
Ejemplo n.º 8
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 );
}
Ejemplo n.º 9
0
    int
f_time( SNET *sn, int ac, char *av[], SNET *pushersn )
{
    struct utimbuf	new_time;
    struct stat		st;
    struct timeval	tv;
    int			timestamp, state;
    int			total = 0, fail = 0;
    char		*line, path[ MAXPATHLEN ];

    /* TIME */
    /* 3xx */
    /* login_cookie timestamp state */
    /* . */

    if ( al->al_key != CGI ) {
	syslog( LOG_ERR, "%s not allowed to tell time", al->al_hostname );
	snet_writef( sn, "%d TIME: %s not allowed to propogate time.\r\n",
		460, al->al_hostname );
	return( 1 );
    }

    if ( ac != 1 ) {
	syslog( LOG_ERR, "f_time: expected 1 argument, got %d", ac );
	snet_writef( sn, "%d TIME: Wrong number of args.\r\n", 560 );
	return( 1 );
    }

    snet_writef( sn, "%d TIME: Send timestamps.\r\n", 360 );

    tv = cosign_net_timeout;
    while (( line = snet_getline( sn, &tv )) != NULL ) {
	tv = cosign_net_timeout;
	if (( ac = argcargv( line, &av )) < 0 ) {
	    syslog( LOG_ERR, "argcargv: %m" );
	    break;
	}

	if ( strcmp( line, "." ) == 0 ) {
	    break;
	}

	if ( ac != 3 ) {
	    syslog( LOG_ERR, "f_time: wrong number of args" );
	    continue;
	}

	if ( strncmp( av[ 0 ], "cosign=", 7 ) != 0 ) {
	    syslog( LOG_ERR, "f_time: cookie name malformat" );
	    continue;
	}

	if ( mkcookiepath( NULL, hashlen, av[ 0 ], path, sizeof( path )) < 0 ) {
	    syslog( LOG_ERR, "f_time: path name malformat" );
	    continue;
	}

	total++;
	if ( stat( path, &st ) != 0 ) {
	    /* record a missing cookie here */
	    fail++;
	    continue;
	}

	timestamp = atoi( av[ 1 ] ); 
	if ( timestamp > st.st_mtime ) {
	    new_time.modtime = timestamp;
	    utime( path, &new_time );
	}

	state = atoi( av[ 2 ] );
	if (( state == 0 ) && (( st.st_mode & S_ISGID ) != 0 )) {
	    if ( do_logout( path ) < 0 ) {
		syslog( LOG_ERR, "f_time: %s should be logged out!", path );
	    }
	}
    }

    if ( total != 0 ) {
	syslog( LOG_NOTICE, "STATS TIME %s: %d tried, %d%% success",
		al->al_hostname, total, 100 * ( total - fail ) / total );
    }
    snet_writef( sn, "%d TIME successful: we are now up-to-date\r\n", 260 );
    return( 0 );
}
Ejemplo n.º 10
0
    int
f_login( SNET *sn, int ac, char *av[], SNET *pushersn )
{
    FILE		*tmpfile;
    ACAV		*facav;
    char		tmppath[ MAXCOOKIELEN ], path[ MAXPATHLEN ];
    char		tmpkrb[ 16 ], krbpath [ MAXPATHLEN ];
    char                *sizebuf, *line;
    char                buf[ 8192 ];
    char		**fv;
    int			fd, i, j, fc, already_krb = 0;
    int			krb = 0, err = 1, addinfo = 0, newinfo = 0;
    struct timeval	tv;
    struct cinfo	ci;
    unsigned int        len, rc;
    extern int		errno;

    /*
     * C: LOGIN login_cookie ip principal factor [factor2]
     * S: 200 LOGIN successful: Cookie Stored.
     */

    /*
     * C: LOGIN login_cookie ip principal factor "kerberos"
     * S: 300 LOGIN: Send length then file.
     * C: [length]
     * C: [data]
     * C: .
     */

    if ( al->al_key != CGI ) {
	syslog( LOG_ERR, "%s not allowed to login", al->al_hostname );
	snet_writef( sn, "%d LOGIN: %s not allowed to login.\r\n",
		400, al->al_hostname );
	return( 1 );
    }

    if ( ac < 5 ) {
	syslog( LOG_ERR, "f_login: got %d args, need at least 5", ac );
	snet_writef( sn, "%d LOGIN: Wrong number of args.\r\n", 500 );
	return( 1 );
    }

    if ( ac >= 6 ) {
	if ( strcmp( av[ ac - 1 ], "kerberos" ) == 0 ) {
	    krb = 1;
	    ac--;
	    if ( mkcookie( sizeof( tmpkrb ), tmpkrb ) != 0 ) {
		syslog( LOG_ERR, "f_login: mkcookie error." );
		return( -1 );
	    }
	    if ( snprintf( krbpath, sizeof( krbpath ), "%s/%s",
		    cosign_tickets, tmpkrb ) >= sizeof( krbpath )) {
		syslog( LOG_ERR, "f_login: krbpath too long." );
		return( -1 );
	    }
	}
    }

    if ( mkcookiepath( NULL, hashlen, av[ 1 ], path, sizeof( path )) < 0 ) {
	syslog( LOG_ERR, "f_login: mkcookiepath error" );
	snet_writef( sn, "%d LOGIN: Invalid cookie path.\r\n", 501 );
	return( 1 );
    }

    if ( read_cookie( path, &ci ) == 0 ) {
	addinfo = 1;
	if ( ci.ci_state == 0 ) {
	    syslog( LOG_ERR,
		    "f_login: %s already logged out", av[ 1 ] );
	    snet_writef( sn, "%d LOGIN: Already logged out\r\n", 505 );
	    return( 1 );
	}
	if ( strcmp( av[ 3 ], ci.ci_user ) != 0 ) {
	    syslog( LOG_ERR, "%s in cookie %s does not match %s",
		    ci.ci_user, av[ 1 ], av[ 3 ] );
	    snet_writef( sn,
		"%d user name given does not match cookie\r\n", 402 );
	    return( 1 );
	}
    }

    if ( gettimeofday( &tv, NULL ) != 0 ) {
	syslog( LOG_ERR, "f_login: gettimeofday: %m" );
	return( -1 );
    }

    if ( snprintf( tmppath, sizeof( tmppath ), "%x%x.%i",
	    (int)tv.tv_sec, (int)tv.tv_usec, (int)getpid()) >=
	    sizeof( tmppath )) {
	syslog( LOG_ERR, "f_login: tmppath too long" );
	return( -1 );
    }

    if (( fd = open( tmppath, O_CREAT|O_EXCL|O_WRONLY, 0644 )) < 0 ) {
	syslog( LOG_ERR, "f_login: open: %s: %m", tmppath );
	return( -1 );
    }

    if (( tmpfile = fdopen( fd, "w" )) == NULL ) {
	/* close */
	if ( unlink( tmppath ) != 0 ) {
	    syslog( LOG_ERR, "f_login: unlink: %m" );
	}
	syslog( LOG_ERR, "f_login: fdopen: %m" );
	return( -1 );
    }

    fprintf( tmpfile, "v2\n" );
    fprintf( tmpfile, "s1\n" );	 /* 1 is logged in, 0 is logged out */

    if ( strlen( av[ 2 ] ) >= sizeof( ci.ci_ipaddr )) {
	goto file_err;
    }
    if ( addinfo ) {
	fprintf( tmpfile, "i%s\n", ci.ci_ipaddr );
    } else {
	fprintf( tmpfile, "i%s\n", av[ 2 ] );
    }

    if ( addinfo ) {
	if ( strcmp( ci.ci_ipaddr_cur, av[ 2 ] ) != 0 ) {
	    newinfo = 1;
	}
    }
    if ( strlen( av[ 2 ] ) >= sizeof( ci.ci_ipaddr_cur )) {
	goto file_err;
    }
    fprintf( tmpfile, "j%s\n", av[ 2 ] );

    if ( strlen( av[ 3 ] ) >= sizeof( ci.ci_user )) {
	goto file_err;
    }
    fprintf( tmpfile, "p%s\n", av[ 3 ] );
    if ( strlen( av[ 4 ] ) >= sizeof( ci.ci_realm )) {
	goto file_err;
    }

    if ( addinfo ) {
	if (( facav = acav_alloc()) == NULL ) {
	    syslog( LOG_ERR, "acav_alloc: %m" );
	    goto file_err;
	}
	if (( fc = acav_parse( facav, ci.ci_realm, &fv )) < 0 ) {
	    syslog( LOG_ERR, "acav_parse: %m" );
	    goto file_err;
	}
	fprintf( tmpfile, "r%s", fv[ 0 ] );
	for ( i = 1; i < fc; i++ ) {
	    fprintf( tmpfile, " %s", fv[ i ] );
	}
	for ( i = 4; i < ac; i++ ) {
	    for ( j = 0; j < fc; j++ ) {
		if ( strcmp( fv[ j ], av[ i ] ) == 0 ) {
		    break;
		}
	    }
	    if ( j >= fc ) {
		fprintf( tmpfile, " %s", av[ i ] );
		newinfo = 1;
	    }
	}
	if ( newinfo == 0 ) {
	    snet_writef( sn, "%d LOGIN Cookie Already Stored.\r\n", 202 );
	    if ( fclose ( tmpfile ) != 0 ) {
		syslog( LOG_ERR, "f_login: fclose: %m" );
	    }
	    if ( unlink( tmppath ) != 0 ) {
		syslog( LOG_ERR, "f_login: unlink %s: %m", tmppath );
	    }
	    return( 0 );
	}
    } else {
	fprintf( tmpfile, "r%s", av[ 4 ] );
	for ( i = 5; i < ac; i++ ) {
	    fprintf( tmpfile, " %s", av[ i ] );
	}
    }
    fprintf( tmpfile, "\n" );

    if ( addinfo ) {
	fprintf( tmpfile, "t%lu\n", ci.ci_itime);
    } else {
	fprintf( tmpfile, "t%lu\n", tv.tv_sec );
    }

    if ( krb ) {
	if (( addinfo ) && ( *ci.ci_krbtkt != '\0' )) {
	    fprintf( tmpfile, "k%s\n", ci.ci_krbtkt );
	    already_krb = 1;
	} else {
	    fprintf( tmpfile, "k%s\n", krbpath );
	}
    } else if ( *ci.ci_krbtkt != '\0' ) {
	fprintf( tmpfile, "k%s\n", ci.ci_krbtkt );
	already_krb = 1;
    }

    if ( fclose ( tmpfile ) != 0 ) {
	if ( unlink( tmppath ) != 0 ) {
	    syslog( LOG_ERR, "f_login: unlink %s: %m", tmppath );
	}
	syslog( LOG_ERR, "f_login: fclose: %m" );
	return( -1 );
    }

    if ( addinfo ) {
	if ( rename( tmppath, path ) != 0 ) {
	    syslog( LOG_ERR, "f_login: rename %s to %s: %m", tmppath, path );
	    err = -1;
	    goto file_err2;
	}
    } else {
	if ( link( tmppath, path ) != 0 ) {
	    syslog( LOG_ERR, "f_login: link %s to %s: %m", tmppath, path );
	    err = -1;
	    goto file_err2;
	}
	if ( unlink( tmppath ) != 0 ) {
	    syslog( LOG_ERR, "f_login: unlink %s: %m", tmppath );
	}
    }

    if (( !krb ) || ( already_krb )) {
	snet_writef( sn, "%d LOGIN successful: Cookie Stored.\r\n", 200 );
	if (( pushersn != NULL ) && ( !replicated )) {
	    snet_writef( pushersn, "LOGIN %s %s %s %s\r\n",
		    av[ 1 ], av[ 2 ], av[ 3 ], av[ 4 ]);
	}
	if ( !replicated ) {
	    syslog( LOG_INFO, "LOGIN %s %s %s", av[ 3 ], av [ 4 ], av [ 2 ] );
	}
	return( 0 );
    }

    snet_writef( sn, "%d LOGIN: Send length then file.\r\n", 300 );

    if (( fd = open( krbpath, O_CREAT|O_EXCL|O_WRONLY, 0644 )) < 0 ) {
	syslog( LOG_ERR, "f_login: open: %s: %m", krbpath );
	return( -1 );
    }

    tv = cosign_net_timeout;
    if (( sizebuf = snet_getline( sn, &tv )) == NULL ) {
        syslog( LOG_ERR, "f_login: snet_getline: %m" );
        return( -1 );
    }

    for ( len = atoi( sizebuf ); len > 0; len -= rc ) {
        tv = cosign_net_timeout;
        if (( rc = snet_read(
                sn, buf, (int)MIN( len, sizeof( buf )), &tv )) <= 0 ) {
            syslog( LOG_ERR, "f_login: snet_read: %m" );
            return( -1 );
        }

        if ( write( fd, buf, rc ) != rc ) {
	    syslog( LOG_ERR, "f_login: write to %s: %m", krbpath );
            snet_writef( sn, "%d %s: %s\r\n", 504, krbpath, strerror( errno ));
            return( 1 );
        }
    }

    if ( close( fd ) < 0 ) {
	syslog( LOG_ERR, "f_login: close %s: %m", krbpath );
        snet_writef( sn, "%d %s: %s\r\n", 504, krbpath, strerror( errno ));
        return( 1 );
    }


    tv = cosign_net_timeout;
    tv.tv_usec = 0;
    if (( line = snet_getline( sn, &tv )) == NULL ) {
        syslog( LOG_ERR, "f_login: snet_getline: %m" );
        return( -1 );
    }

    /* make sure client agrees we're at the end */
    if ( strcmp( line, "." ) != 0 ) {
        snet_writef( sn, "%d Length doesn't match sent data\r\n", 505 );
        (void)unlink( krbpath );

	/* if the krb tkt didn't store, unlink the cookie as well */
	if ( unlink( av[ 1 ] ) != 0 ) {
	    syslog( LOG_ERR, "f_login: unlink: %m" );
	}

        tv = cosign_net_timeout;
        tv.tv_usec = 0;
        for (;;) {
            if (( line = snet_getline( sn, &tv )) == NULL ) {
                syslog( LOG_ERR, "f_login: snet_getline: %m" );
                exit( 1 );
            }
            if ( strcmp( line, "." ) == 0 ) {
                break;
            }
        }
        exit( 1 );
    }


    snet_writef( sn, "%d LOGIN successful: Cookie & Ticket Stored.\r\n", 201 );
    if (( pushersn != NULL ) && ( !replicated )) {
	snet_writef( pushersn, "LOGIN %s %s %s %s %s\r\n",
		av[ 1 ], av[ 2 ], av[ 3 ], av[ 4 ], av[ 5 ]);
    }
    if ( !replicated ) {
	syslog( LOG_INFO, "LOGIN %s %s %s", av[ 3 ], av [ 4 ], av [ 2 ] );
    }
    return( 0 );

file_err:
    (void)fclose( tmpfile );
    if ( unlink( tmppath ) != 0 ) {
	syslog( LOG_ERR, "f_login: unlink: %m" );
    }
    syslog( LOG_ERR, "f_login: bad file format" );
    snet_writef( sn, "%d LOGIN Syntax Error: Bad File Format\r\n", 504 );
    return( 1 );

file_err2:
    if ( unlink( tmppath ) != 0 ) {
	syslog( LOG_ERR, "f_login: unlink: %m" );
    }
    return( err );
}
Ejemplo n.º 11
0
    int
command( int fd, SNET *pushersn )
{
    SNET				*snet;
    int					ac, i, zero = 0;
    char				**av, *line;
    struct timeval			tv;
    extern int				errno;
    double				rate;
    struct protoent			*proto;

    if (( proto = getprotobyname( "tcp" )) != NULL ) {
	if ( setsockopt( fd, proto->p_proto, TCP_NODELAY,
		&zero, sizeof( zero )) < 0 ) {
	    syslog( LOG_ERR, "setsockopt TCP_NODELAY: %m" );
	}
    }

    if (( snet = snet_attach( fd, 1024 * 1024 )) == NULL ) {
	syslog( LOG_ERR, "snet_attach: %m" );
	exit( 1 );
    }

    /* for debugging, TLS not required but still available. we
     * need to do the authlist look up here b/c it normally happens
     * in the starttls code which we may not even call. All the
     * f_cmds require an "al".
     */

    if ( tlsopt ) {
	commands = auth_commands;
	ncommands = sizeof( auth_commands ) / sizeof( auth_commands[ 0 ] );
	if (( al = authlist_find( "NOTLS" )) == NULL ) {
	    syslog( LOG_ERR, "No debugging access" );
	    snet_writef( snet, "%d No NOTLS access\r\n", 508 );
	    exit( 1 );
	}
    }

    /*
     * because of problems with legacy client protocol checks, we return a
     * list of capabilities on the same line as the banner. a multi-line
     * banner would be more in the SMTP-like vernacular, but the IIS & Java
     * legacy clients don't handle multi-line banner output gracefully.
     * 
     * 220 2 Collaborative Web Single Sign-On [ CAPA1 CAPA2 ... ]\r\n
     */
    banner( snet );

    tv = cosign_net_timeout;
    while (( line = snet_getline( snet, &tv )) != NULL ) {
	/* log everything we get to stdout if we're debugging */
	tv = cosign_net_timeout;
	if ( debug ) {
	    printf( "debug: %s\n", line );
	}
	if (( ac = argcargv( line, &av )) < 0 ) {
	    syslog( LOG_ERR, "argcargv: %m" );
	    break;
	}

	if ( ac == 0 ) {
	    snet_writef( snet, "%d Command unrecognized\r\n", 501 );
	    continue;
	}

	for ( i = 0; i < ncommands; i++ ) {
	    if ( strcasecmp( av[ 0 ], commands[ i ].c_name ) == 0 ) {
		break;
	    }
	}
	if ( i >= ncommands ) {
	    snet_writef( snet, "%d Command %s unregcognized\r\n",
		    500, av[ 0 ] );
	    continue;
	}

	if ( (*(commands[ i ].c_func))( snet, ac, av, pushersn ) < 0 ) {
	    break;
	}
    }

    if (( rate = rate_get( &checkpass )) != 0.0 ) {
	syslog( LOG_NOTICE, "STATS CHECK %s: PASS %.5f / sec",
		inet_ntoa( cosign_sin.sin_addr), rate );
    }
    if (( rate = rate_get( &checkfail )) != 0.0 ) {
	syslog( LOG_NOTICE, "STATS CHECK %s: FAIL %.5f / sec",
		inet_ntoa( cosign_sin.sin_addr), rate );
    }
    if (( rate = rate_get( &checkunknown )) != 0.0 ) {
	syslog( LOG_NOTICE, "STATS CHECK %s: UNKNOWN %.5f / sec",
		inet_ntoa( cosign_sin.sin_addr), rate );
    }

    if ( line != NULL ) {
	snet_writef( snet,
		"491 Service not available, closing transmission channel\r\n" );
    } else {
	if ( snet_eof( snet )) {
	    exit( 0 );
	} else if ( errno == ETIMEDOUT ) {
	    exit( 0 );
	} else {
	    syslog( LOG_ERR, "snet_getline: %m" );
	}
    }

    exit( 1 );

}
Ejemplo n.º 12
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 );
}
Ejemplo n.º 13
0
    static int
connect_sn( struct connlist *cl, cosign_host_config *cfg, void *s )
{
    int			sock, zero = 0, ac = 0, state, i;
    char		*line, buf[ 1024 ], **av;
    X509		*peer;
    struct timeval      tv;
    struct protoent	*proto;

    if (( sock = socket( PF_INET, SOCK_STREAM, 0 )) < 0 ) {
	cosign_log( APLOG_ERR, s, "mod_cosign: connect_sn: socket" );
	return( -1 );
    }

    if (( proto = getprotobyname( "tcp" )) != NULL ) {
	if ( setsockopt( sock, proto->p_proto, TCP_NODELAY,
		&zero, sizeof( zero )) < 0 ) {
	    cosign_log( APLOG_ERR, s,
		    "mod_cosign: connect_sn: setsockopt: TCP_NODELAY" );
	}
    }

    if ( connect( sock, ( struct sockaddr *)&cl->conn_sin,
	    sizeof( struct sockaddr_in )) != 0 ) {
	cosign_log( APLOG_ERR, s, "mod_cosign: connect_sn: connect" );
	(void)close( sock );
	return( -1 );
    }

    if (( cl->conn_sn = snet_attach( sock, 1024 * 1024 ) ) == NULL ) {
	cosign_log( APLOG_ERR, s,
		"mod_cosign: connect_sn: snet_attach failed" );
	(void)close( sock );
	return( -1 );
    }

    tv = timeout;
    if (( line = snet_getline( cl->conn_sn, &tv )) == NULL ) {
	cosign_log( APLOG_ERR, s,
	    "mod_cosign: connect_sn: snet_getline failed" );
	goto done;
    }

    if ( *line != '2' ) {
	cosign_log( APLOG_ERR, s, "mod_cosign: connect_sn: %s", line );
	goto done;
    }

    if (( ac = argcargv( line, &av )) < 4 ) {
	cosign_log( APLOG_ERR, s, "mod_cosign: argcargv: %s", line );
	goto done;
    }

    errno = 0;
    cl->conn_proto = strtol( av[ 1 ], (char **)NULL, 10 );
    if ( errno ) {
	cosign_log( APLOG_ERR, s, "mod_cosign: unrecognized protocol "
		    "version %s, falling back to protocol v0", av[1]);
	cl->conn_proto = COSIGN_PROTO_V0;
    }
    if ( cfg->reqfc > 0 && !COSIGN_PROTO_SUPPORTS_FACTORS( cl->conn_proto )) {
	cosign_log( APLOG_ERR, s, "mod_cosign: required v2 or greater "
		    "protocol unsupported by server "
		    "(server protocol version: %s)", av[ 1 ] );
	goto done;
    }
	   
    cl->conn_capa = COSIGN_CAPA_DEFAULTS;
    if ( ac > 6 ) {
	/* "220 2 Collaborative Web Single Sign-On [COSIGNv3 REKEY ...]" */
	ac -= 6;
	av += 6;
	
	if ( capa_parse( ac, av, cl, s ) < 0 ) {
	    cosign_log( APLOG_ERR, s, "mod_cosign: failed to parse server "
			"capabilities" );
	    goto done;
	}
    } else {
	/* pre-3.1: "220 2 Collaborative Web Single Sign-On" */
	if ( COSIGN_PROTO_SUPPORTS_FACTORS( cl->conn_proto )) {
	    cl->conn_capa |= COSIGN_CAPA_FACTORS;
	}
    }
    if ( cl->conn_proto >= COSIGN_PROTO_V2 ) {
	if ( snet_writef( cl->conn_sn, "STARTTLS %d\r\n",
		cl->conn_proto ) < 0 ) {
	    cosign_log( APLOG_ERR, s,
		    "mod_cosign: connect_sn: starttls 2 failed" );
	    goto done;
	}
    } else {
	if ( snet_writef( cl->conn_sn, "STARTTLS\r\n" ) < 0 ) {
	    cosign_log( APLOG_ERR, s,
		    "mod_cosign: connect_sn: starttls failed" );
	    goto done;
	}
    }

    tv = timeout;
    if (( line = snet_getline_multi( cl->conn_sn, logger, &tv )) == NULL ) {
	cosign_log( APLOG_ERR, s,
		"mod_cosign: connect_sn: snet_getline_multi failed" );
	goto done;
    }

    if ( snet_starttls( cl->conn_sn, cfg->ctx, 0 ) != 1 ) {
	cosign_log( APLOG_ERR, s, "mod_cosign: snet_starttls: %s",
		ERR_error_string( ERR_get_error(), NULL ));
	goto done;
    }

    if (( peer = SSL_get_peer_certificate( cl->conn_sn->sn_ssl )) == NULL ) {
	cosign_log( APLOG_ERR, s, "mod_cosign: connect_sn: no certificate" );
	goto done;
    }

    X509_NAME_get_text_by_NID( X509_get_subject_name( peer ), NID_commonName,
	    buf, sizeof( buf ));
    X509_free( peer );

    /* cn and host must match */
    if ( strcasecmp( buf, cfg->host ) != 0 ) {
	cosign_log( APLOG_ERR, s, "mod_cosign: connect_sn: cn=%s & host=%s " 
		"don't match!", buf, cfg->host );
	goto done;
    }

    if ( cl->conn_proto >= COSIGN_PROTO_V2 ) {
	tv = timeout;
	if (( line = snet_getline_multi( cl->conn_sn, logger, &tv )) == NULL ) {
	    cosign_log( APLOG_ERR, s,
		    "mod_cosign: connect_sn: snet_getline_multi failed" );
	    goto done;
	}
	if ( *line != '2' ) {
	    cosign_log( APLOG_ERR, s, "mod_cosign: starttls 2: %s", line );
	    goto done;
	}
    }

    return( 0 );
done:
    if ( snet_close( cl->conn_sn ) != 0 ) {
	cosign_log( APLOG_ERR, s, "mod_cosign: connect_sn: snet_close failed" );
    }
    cl->conn_sn = NULL;
    cl->conn_proto = COSIGN_PROTO_V0;

    return( -1 );
}
Ejemplo n.º 14
0
    static int
netretr_ticket( char *scookie, struct sinfo *si, SNET *sn, char *tkt_prefix,
	void *s )
{
    char		*line;
    char                tmpkrb[ 16 ], krbpath [ MAXPATHLEN ];
    char		buf[ 8192 ];
    int			fd; 
    size_t              size = 0;
    ssize_t             rr;
    struct timeval      tv;
    extern int		errno;

    /* clear it, in case we can't get it later */
    *si->si_krb5tkt = '\0';

    /* RETR service-cookie TicketType */
    if ( snet_writef( sn, "RETR %s tgt\r\n", scookie ) < 0 ) {
	cosign_log( APLOG_ERR, s,
		"mod_cosign: netretr_ticket: snet_writef failed");
	return( COSIGN_ERROR );
    }

    tv = timeout;
    if (( line = snet_getline_multi( sn, logger, &tv )) == NULL ) {
	cosign_log( APLOG_ERR, s,
		"mod_cosign: netretr_ticket: %s", strerror( errno ));
	return( COSIGN_ERROR );
    }

    switch( *line ) {
    case '2':
	break;

    case '4':
	cosign_log( APLOG_ERR, s, "mod_cosign: netretr_ticket: %s", line );
	return( COSIGN_LOGGED_OUT );

    case '5':
	/* choose another connection */
	cosign_log( APLOG_ERR, s, "mod_cosign: netretr_ticket: 5xx" );
	return( COSIGN_RETRY );

    default:
	cosign_log( APLOG_ERR, s, "mod_cosign: netretr_ticket: %s", line );
	return( COSIGN_ERROR );
    }

    if ( mkcookie( sizeof( tmpkrb ), tmpkrb ) != 0 ) {
	cosign_log( APLOG_ERR, s,
		"mod_cosign: netretr_ticket: mkcookie failed" );
	return( COSIGN_ERROR );
    }

    if ( snprintf( krbpath, sizeof( krbpath ), "%s/%s",
	    tkt_prefix, tmpkrb ) >= sizeof( krbpath )) {
	cosign_log( APLOG_ERR, s,
		"mod_cosign: netretr_ticket: krbpath too long" );
	return( COSIGN_ERROR );
    }

    tv = timeout;
    if (( line = snet_getline( sn, &tv )) == NULL ) {
	cosign_log( APLOG_ERR, s,
		"mod_cosign: netretr_ticket: failed for %s", scookie );
        return( COSIGN_ERROR );
    }
    size = atoi( line );

    if (( fd = open( krbpath, O_WRONLY | O_CREAT | O_EXCL, 0600 )) < 0 ) {
        perror( krbpath );
        return( COSIGN_ERROR );
    }

    /* Get file from server */
    while ( size > 0 ) {
        tv = timeout;
        if (( rr = snet_read( sn, buf, (int)MIN( sizeof( buf ), size ),
                &tv )) <= 0 ) {
	    cosign_log( APLOG_ERR, s,
		    "mod_cosign: retrieve tgt failed: %s", strerror( errno ));
            goto error2;
        }
        if ( write( fd, buf, (size_t)rr ) != rr ) {
            perror( krbpath );
            goto error2;
        }
        size -= rr;
    }
    if ( close( fd ) != 0 ) {
        perror( krbpath );
        goto error1;
    }
    if ( size != 0 ) {
	cosign_log( APLOG_ERR, s,
		    "mod_cosign: retrieve tickets: size from server did "
		    "not match size read from server" );
	goto error1;
    }

    tv = timeout;
    if (( line = snet_getline( sn, &tv )) == NULL ) {
	cosign_log( APLOG_ERR, s, "mod_cosign: retrieve for %s failed: %s",
		scookie, strerror( errno ));
        goto error1;
    }
    if ( strcmp( line, "." ) != 0 ) {
	cosign_log( APLOG_ERR, s, "mod_cosign: netretr_ticket: %s", line );
        goto error1;
    }

    /* copy the path to the ticket file */
    if ( strlen( krbpath ) >= sizeof( si->si_krb5tkt )) {
	cosign_log( APLOG_ERR, s,
		"mod_cosign: netretr_ticket: krb5tkt path too long" );
	goto error1;
    }
    strcpy( si->si_krb5tkt, krbpath );

    return( COSIGN_OK );

error2:
    close( fd );
error1:
    unlink( krbpath );
    return( COSIGN_ERROR );
}
Ejemplo n.º 15
0
    static int
netretr_proxy( char *scookie, struct sinfo *si, SNET *sn, char *proxydb,
	void *s )
{
    int			fd;
    char		*line;
    char                path[ MAXPATHLEN ], tmppath[ MAXPATHLEN ];
    struct timeval      tv;
    FILE                *tmpfile;

    /* RETR service-cookie cookies */
    if ( snet_writef( sn, "RETR %s cookies\r\n", scookie ) < 0 ) {
	cosign_log( APLOG_ERR, s,
		"mod_cosign: netretr_proxy: snet_writef failed");
	return( COSIGN_ERROR );
    }

    /* name our file and open tmp file */
    if ( snprintf( path, sizeof( path ), "%s/%s", proxydb, scookie ) >=
            sizeof( path )) {
	cosign_log( APLOG_ERR, s,
		"mod_cosign: netretr_proxy: cookie path too long");
        return( COSIGN_ERROR );
    }

    if ( gettimeofday( &tv, NULL ) < 0 ) {
	perror( "gettimeofday" );
	return( COSIGN_ERROR );
    }

    if ( snprintf( tmppath, sizeof( tmppath ), "%s/%x%x.%i",
	    proxydb, (int)tv.tv_sec, (int)tv.tv_usec, (int)getpid()) >=
	    sizeof( tmppath )) {
	cosign_log( APLOG_ERR, s,
		"mod_cosign: netretr_proxy: tmppath too long");
        return( COSIGN_ERROR );
    }

    if (( fd = open( tmppath, O_CREAT|O_EXCL|O_WRONLY, 0644 )) < 0 ) {
        perror( tmppath );
        return( COSIGN_ERROR );
    }

    if (( tmpfile = fdopen( fd, "w" )) == NULL ) {
        if ( unlink( tmppath ) != 0 ) {
            perror( tmppath );
        }
        perror( tmppath );
        return( COSIGN_ERROR );
    }

    tv = timeout;
    do {
	if (( line = snet_getline( sn, &tv )) == NULL ) {
	    cosign_log( APLOG_ERR, s,
		    "mod_cosign: netretr_proxy: snet_getline failed" );
	    return ( COSIGN_ERROR );
	}

	switch( *line ) {
	case '2':
	    break;

	case '4':
	    cosign_log( APLOG_ERR, s, "mod_cosign: netretr_proxy: %s", line );
	    return( COSIGN_LOGGED_OUT );

	case '5':
	    /* choose another connection */
	    cosign_log( APLOG_ERR, s, "mod_cosign: netretr_proxy: 5xx" );
	    return( COSIGN_RETRY );

	default:
	    cosign_log( APLOG_ERR, s, "mod_cosign: netretr_proxy: %s", line );
	    return( COSIGN_ERROR );
	}

	if ( strlen( line ) < 3 ) {
	    cosign_log( APLOG_ERR, s,
		    "mod_cosign: netretr_proxy: short line: %s", line );
	    return( COSIGN_ERROR );
	}
        if ( !isdigit( (int)line[ 1 ] ) ||
                !isdigit( (int)line[ 2 ] )) {
	    cosign_log( APLOG_ERR, s,
		    "mod_cosign: netretr_proxy: bad response: %s", line );
	    return( COSIGN_ERROR );
        }

	if ( line[ 3 ] != '\0' &&
		line[ 3 ] != ' ' &&
		line [ 3 ] != '-' ) {
	    cosign_log( APLOG_ERR, s,
		    "mod_cosign: netretr_proxy: bad response: %s", line );
	    return( COSIGN_ERROR );
	}

	if ( line[ 3 ] == '-' ) {
	    fprintf( tmpfile, "x%s\n", &line[ 4 ] );
	}

    } while ( line[ 3 ] == '-' );

    if ( fclose ( tmpfile ) != 0 ) {
        if ( unlink( tmppath ) != 0 ) {
            perror( tmppath );
        }
        perror( tmppath );
        return( COSIGN_ERROR );
    }

    if ( link( tmppath, path ) != 0 ) {
        if ( unlink( tmppath ) != 0 ) {
            perror( tmppath );
        }
        perror( tmppath );
        return( COSIGN_ERROR );
    }

    if ( unlink( tmppath ) != 0 ) {
        perror( tmppath );
    }

    return( COSIGN_OK );
}