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 ); } }
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 ); } }