示例#1
0
文件: command.c 项目: Radmind/radmind
    int
f_stat( SNET *sn, int ac, char *av[] )
{

    char 		path[ MAXPATHLEN ];
    char		cksum_b64[ SZ_BASE64_E( EVP_MAX_MD_SIZE ) ];
    struct stat		st;
    int			key;
    char		*enc_file, *d_tran, *d_path;

    switch ( key = keyword( ac, av )) {
    case K_COMMAND:
	if ( ac == 2 ) { 
	    if ( snprintf( path, MAXPATHLEN, "command/%s", command_file )
		    >= MAXPATHLEN ) {
		syslog( LOG_ERR, "f_stat: command/%s: path too long",
		    command_file );
		snet_writef( sn, "%d Path too long\r\n", 540 );
		return( 1 );
	    }
	} else {
	    if (( d_path = decode( av[ 2 ] )) == NULL ) {
		syslog( LOG_ERR, "f_stat: decode: buffer too small" );
		snet_writef( sn, "%d Line too long\r\n", 540 );
		return( 1 );
	    } 

	    /* Check for access */
	    if ( !list_check( access_list, d_path )) {
		syslog( LOG_WARNING | LOG_AUTH, "attempt to access: %s",
		    d_path );
		snet_writef( sn, "%d No access for %s\r\n", 540, d_path );
		return( 1 );
	    }

	    if ( snprintf( path, MAXPATHLEN, "command/%s", d_path )
		    >= MAXPATHLEN ) {
		syslog( LOG_ERR, "f_stat: command path too long" );
		snet_writef( sn, "%d Path too long\r\n", 540 );
		return( 1 );
	    }
	}
	break;

    case K_TRANSCRIPT:
	if (( d_tran = decode( av[ 2 ] )) == NULL ) {
	    syslog( LOG_ERR, "f_stat: decode: buffer too small" );
	    snet_writef( sn, "%d Line too long\r\n", 540 );
	    return( 1 );
	} 

	/* Check for access */
	if ( !list_check( access_list, d_tran )) {
	    syslog( LOG_WARNING | LOG_AUTH, "attempt to access: %s", d_tran );
	    snet_writef( sn, "%d No access for %s\r\n", 540, d_tran );
	    return( 1 );
	}

	if ( snprintf( path, MAXPATHLEN, "transcript/%s", d_tran )
		>= MAXPATHLEN ) {
	    syslog( LOG_ERR, "f_stat: transcript path too long" );
	    snet_writef( sn, "%d Path too long\r\n", 540 );
	    return( 1 );
	}
	break;

    case K_SPECIAL:
	if (( d_path = decode( av[ 2 ] )) == NULL ) {
	    syslog( LOG_ERR, "f_stat: decode: buffer too small" );
	    snet_writef( sn, "%d Line too long\r\n", 540 );
	    return( 1 );
	} 

	if ( snprintf( path, MAXPATHLEN, "%s/%s", special_dir, d_path) 
		>= MAXPATHLEN ) {
	    syslog( LOG_ERR, "f_stat: special path too long" );
	    snet_writef( sn, "%d Path too long\r\n", 540 );
	    return( 1 );
	}
	break;

    default:
	snet_writef( sn, "%d STAT Syntax error\r\n", 530 );
	return( 1 );
    }
        
    syslog( LOG_DEBUG, "f_stat: returning infomation for %s", path );

    if ( stat( path, &st ) < 0 ) {
        syslog( LOG_ERR, "f_stat: stat: %m" );
	snet_writef( sn, "%d Access Error: %s\r\n", 531, path );
	return( 1 );
    }

    /* XXX cksums here, totally the wrong place to do this! */
    OpenSSL_add_all_digests();
    md = EVP_get_digestbyname( "sha1" );
    if ( !md ) {
	/* XXX */
	fprintf( stderr, "%s: unsupported checksum\n", "sha1" );
	exit( 1 );
    }
    if ( do_cksum( path, cksum_b64 ) < 0 ) {
	syslog( LOG_ERR, "do_cksum: %s: %m", path );
	snet_writef( sn, "%d Checksum Error: %s: %m\r\n", 500, path );
	return( 1 );
    }

    snet_writef( sn, "%d Returning STAT information\r\n", 230 );
    switch ( key ) {
    case K_COMMAND:
	if ( ac == 2 ) {
	    snet_writef( sn, RADMIND_STAT_FMT,
		"f", "command", DEFAULT_MODE, DEFAULT_UID, DEFAULT_GID,
		st.st_mtime, st.st_size, cksum_b64 );
	} else {
	    snet_writef( sn, RADMIND_STAT_FMT,
		"f", av[ 2 ], DEFAULT_MODE, DEFAULT_UID, DEFAULT_GID,
		st.st_mtime, st.st_size, cksum_b64 );
	}
	return( 0 );
        
		    
    case K_TRANSCRIPT:
	snet_writef( sn, RADMIND_STAT_FMT,
		"f", av[ 2 ], 
		DEFAULT_MODE, DEFAULT_UID, DEFAULT_GID,
		st.st_mtime, st.st_size, cksum_b64 );
	return( 0 );
    
    case K_SPECIAL:
	/*
	 * store value of av[ 2 ], because argcargv will be called
	 * from special_t(), and that will blow away the current values
	 * for av[ 2 ].
	 */
	if (( enc_file = strdup( av[ 2 ] )) == NULL ) {
	    syslog( LOG_ERR, "f_stat: strdup: %s %m", av[ 2 ] );
	    return( -1 );
	}

	if (( av = special_t( path, enc_file )) == NULL ) {
	    /* no special transcript match found, return defaults. */
	    snet_writef( sn, RADMIND_STAT_FMT,
		    "f", enc_file, 
		    DEFAULT_MODE, DEFAULT_UID, DEFAULT_GID, 
		    st.st_mtime, st.st_size, cksum_b64 );
	    free( enc_file );
	    return( 0 );
	}
	snet_writef( sn, RADMIND_STAT_FMT,
		av[ 0 ], enc_file,
		av[ 2 ], av[ 3 ], av[ 4 ],
		st.st_mtime, st.st_size, cksum_b64 );

	free( enc_file );
	return( 0 );

    default:
        return( 1 );
    }
}
示例#2
0
    int
f_stat( SNET *sn, int ac, char *av[] )
{

    char 		path[ MAXPATHLEN ];
    char		cksum_b64[ SZ_BASE64_E( EVP_MAX_MD_SIZE ) ];
    struct stat		st;
    int			key;
    char		*enc_file, *d_tran, *d_path;

    switch ( key = keyword( ac, av )) {
    case K_COMMAND:
	if ( ac == 2 ) { 
	    if ( snprintf( path, MAXPATHLEN, "command/%s", command_file )
		    >= MAXPATHLEN ) {
		syslog( LOG_ERR, "f_stat: command/%s: path too long",
		    command_file );
		snet_writef( sn, "%d Path too long\r\n", 540 );
		return( 1 );
	    }
	} else {
	    if (( d_path = decode( av[ 2 ] )) == NULL ) {
		syslog( LOG_ERR, "f_stat: decode: buffer too small" );
		snet_writef( sn, "%d Line too long\r\n", 540 );
		return( 1 );
	    } 

	    /* Check for access */
	    if ( !list_check( access_list, d_path )) {
		syslog( LOG_WARNING | LOG_AUTH, "attempt to access: %s",
		    d_path );
		snet_writef( sn, "%d No access for %s\r\n", 540, d_path );
		return( 1 );
	    }

	    if ( snprintf( path, MAXPATHLEN, "command/%s", d_path )
		    >= MAXPATHLEN ) {
		syslog( LOG_ERR, "f_stat: command path too long" );
		snet_writef( sn, "%d Path too long\r\n", 540 );
		return( 1 );
	    }
	}
	break;

    case K_TRANSCRIPT:
	if (( d_tran = decode( av[ 2 ] )) == NULL ) {
	    syslog( LOG_ERR, "f_stat: decode: buffer too small" );
	    snet_writef( sn, "%d Line too long\r\n", 540 );
	    return( 1 );
	} 

	/* Check for access */
	if ( !list_check( access_list, d_tran )) {
	    syslog( LOG_WARNING | LOG_AUTH, "attempt to access: %s", d_tran );
	    snet_writef( sn, "%d No access for %s\r\n", 540, d_tran );
	    return( 1 );
	}

	if ( snprintf( path, MAXPATHLEN, "transcript/%s", d_tran )
		>= MAXPATHLEN ) {
	    syslog( LOG_ERR, "f_stat: transcript path too long" );
	    snet_writef( sn, "%d Path too long\r\n", 540 );
	    return( 1 );
	}
	break;

    case K_SPECIAL:
	if (( d_path = decode( av[ 2 ] )) == NULL ) {
	    syslog( LOG_ERR, "f_stat: decode: buffer too small" );
	    snet_writef( sn, "%d Line too long\r\n", 540 );
	    return( 1 );
	} 

	if ( snprintf( path, MAXPATHLEN, "%s/%s", special_dir, d_path) 
		>= MAXPATHLEN ) {
	    syslog( LOG_ERR, "f_stat: special path too long" );
	    snet_writef( sn, "%d Path too long\r\n", 540 );
	    return( 1 );
	}
	break;

    default:
	snet_writef( sn, "%d STAT Syntax error\r\n", 530 );
	return( 1 );
    }
        
    syslog( LOG_DEBUG, "f_stat: returning infomation for %s", path );

    if ( stat( path, &st ) < 0 ) {
        syslog( LOG_ERR, "f_stat: stat: %m" );
	snet_writef( sn, "%d Access Error: %s\r\n", 531, path );
	return( 1 );
    }

    /* XXX cksums here, totally the wrong place to do this! */
    OpenSSL_add_all_digests();
    md = EVP_get_digestbyname( "sha1" );
    if ( !md ) {
	/* XXX */
	fprintf( stderr, "%s: unsupported checksum\n", "sha1" );
	exit( 1 );
    }
    if ( do_cksum( path, cksum_b64 ) < 0 ) {
	syslog( LOG_ERR, "do_cksum: %s: %m", path );
	snet_writef( sn, "%d Checksum Error: %s: %m\r\n", 500, path );
	return( 1 );
    }

    snet_writef( sn, "%d Returning STAT information\r\n", 230 );
    switch ( key ) {
    case K_COMMAND:
	if ( ac == 2 ) {
	    snet_writef( sn, "%s %s %o %d %d %d %" PRIofft "d %s\r\n",
		"f", "command", DEFAULT_MODE, DEFAULT_UID, DEFAULT_GID,
		st.st_mtime, st.st_size, cksum_b64 );
	} else {
	    snet_writef( sn, "%s %s %o %d %d %d %" PRIofft "d %s\r\n",
		"f", av[ 2 ], DEFAULT_MODE, DEFAULT_UID, DEFAULT_GID,
		st.st_mtime, st.st_size, cksum_b64 );
	}
	return( 0 );
        
		    
    case K_TRANSCRIPT:
	snet_writef( sn, "%s %s %o %d %d %d %" PRIofft "d %s\r\n",
		"f", av[ 2 ], 
		DEFAULT_MODE, DEFAULT_UID, DEFAULT_GID,
		st.st_mtime, st.st_size, cksum_b64 );
	return( 0 );
    
    case K_SPECIAL:
	/*  status on a special file comes from 1 of three cases:
	 *  1. A transcript in the special file directory
	 *  2. A transcript in the Transcript dir with .T appended
	 *  3. No transcript is found, and constants are returned
	 */

        /* look for transcript containing the information */
	if ( ( strlen( path ) + 2 ) > MAXPATHLEN ) {
	    syslog( LOG_WARNING, 
		"f_stat: transcript path longer than MAXPATHLEN" );

	    /* return constants */
	    snet_writef( sn, "%s %s %o %d %d %d %" PRIofft "d %s\r\n",
		    "f", av[ 2 ], 
		    DEFAULT_MODE, DEFAULT_UID, DEFAULT_GID,
		    st.st_mtime, st.st_size, cksum_b64 );
	    return( 0 );
	}

	/* if allowable, check for transcript in the special file directory */

	strcat( path, ".T" );

	/* store value of av[ 2 ], because argcargv will be called
	 * from special_t(), and that will blow away the current values
	 * for av[ 2 ]
	 *
	 * Could just use new argvargc API... XXX  Notice how we never free
	 * env_file...
	 */

	if (( enc_file = strdup( av[ 2 ] )) == NULL ) {
	    syslog( LOG_ERR, "f_stat: strdup: %s %m", av[ 2 ] );
	    return( -1 );
	}

	if (( av = special_t( path, enc_file )) == NULL ) {
	    if (( av = special_t( "transcript/special.T", enc_file ))
		    == NULL ) {
		snet_writef( sn, "%s %s %o %d %d %d %" PRIofft "d %s\r\n",
			"f", enc_file, 
			DEFAULT_MODE, DEFAULT_UID, DEFAULT_GID, 
			st.st_mtime, st.st_size, cksum_b64 );
		free( enc_file );
		return( 0 );
	    }
	}
	snet_writef( sn, "%s %s %s %s %s %d %" PRIofft "d %s\r\n",
		av[ 0 ], enc_file,
		av[ 2 ], av[ 3 ], av[ 4 ],
		st.st_mtime, st.st_size, cksum_b64 );

	free( enc_file );
	return( 0 );

    default:
        return( 1 );
    }
}