int f_retr( SNET *sn, int ac, char **av ) { ssize_t readlen; struct stat st; struct timeval tv; char buf[8192]; char path[ MAXPATHLEN ]; char *d_path, *d_tran; int fd; switch ( keyword( ac, av )) { case K_COMMAND: if ( ac == 2 ) { if ( snprintf( path, MAXPATHLEN, "command/%s", command_file ) >= MAXPATHLEN ) { syslog( LOG_ERR, "f_retr: 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_retr: 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_retr: 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_retr: 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_retr: 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_retr: 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_retr: special path too long" ); snet_writef( sn, "%d Path too long\r\n", 540 ); return( 1 ); } break; case K_FILE: if (( d_path = decode( av[ 3 ] )) == NULL ) { syslog( LOG_ERR, "f_retr: 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_retr: strdup: %s: %m", d_path ); return( -1 ); } if (( d_tran = decode( av[ 2 ] )) == NULL ) { syslog( LOG_ERR, "f_retr: 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:%s\r\n", 540, d_tran, d_path ); return( 1 ); } if ( snprintf( path, MAXPATHLEN, "file/%s/%s", d_tran, d_path ) >= MAXPATHLEN ) { syslog( LOG_ERR, "f_retr: file path too long" ); snet_writef( sn, "%d Path too long\r\n", 540 ); return( 1 ); } free( d_path ); break; default: snet_writef( sn, "%d RETR Syntax error\r\n", 540 ); return( 1 ); } if (( fd = open( path, O_RDONLY, 0 )) < 0 ) { syslog( LOG_ERR, "open: %s: %m", path ); snet_writef( sn, "%d Unable to access %s.\r\n", 543, path ); return( 1 ); } /* dump file info */ if ( fstat( fd, &st ) < 0 ) { syslog( LOG_ERR, "f_retr: fstat: %m" ); snet_writef( sn, "%d Access Error: %s\r\n", 543, path ); if ( close( fd ) < 0 ) { syslog( LOG_ERR, "close: %m" ); return( -1 ); } return( 1 ); } /* * Here's a problem. Do we need to add long long support to * snet_writef? */ snet_writef( sn, "240 Retrieving file\r\n%" PRIofft "d\r\n", st.st_size ); /* dump file */ while (( readlen = read( fd, buf, sizeof( buf ))) > 0 ) { tv.tv_sec = 60 ; tv.tv_usec = 0; if ( snet_write( sn, buf, readlen, &tv ) != readlen ) { syslog( LOG_ERR, "snet_write: %m" ); return( -1 ); } } if ( readlen < 0 ) { syslog( LOG_ERR, "read: %m" ); return( -1 ); } snet_writef( sn, ".\r\n" ); if ( close( fd ) < 0 ) { syslog( LOG_ERR, "close: %m" ); return( -1 ); } syslog( LOG_DEBUG, "f_retr: 'file' %s retrieved", path ); return( 0 ); }
static int retr_ticket( SNET *sn, struct servicelist *sl, char *krbpath ) { struct stat st; int fd; ssize_t readlen; char buf[ 8192 ]; struct timeval tv; /* S: 240 Retrieving file * S: [size] * S: [data] * S: . */ if (( sl->sl_flag & SL_TICKET ) == 0 ) { syslog( LOG_ERR, "%s not allowed to retrieve tkts", sl->sl_auth->al_hostname ); snet_writef( sn, "%d RETR: %s not allowed to retrieve tkts.\r\n", 441, sl->sl_auth->al_hostname ); return( 1 ); } if (( fd = open( krbpath, O_RDONLY, 0 )) < 0 ) { syslog( LOG_ERR, "open: %s: %m", krbpath ); snet_writef( sn, "%d Unable to access %s.\r\n", 547, krbpath ); return( 1 ); } if ( fstat( fd, &st ) < 0 ) { syslog( LOG_ERR, "f_retr: fstat: %m" ); snet_writef( sn, "%d Access Error: %s\r\n", 548, krbpath ); if ( close( fd ) < 0 ) { syslog( LOG_ERR, "close: %m" ); return( -1 ); } return( 1 ); } snet_writef( sn, "%d Retrieving file\r\n", 240 ); snet_writef( sn, "%d\r\n", (int)st.st_size ); while (( readlen = read( fd, buf, sizeof( buf ))) > 0 ) { tv = cosign_net_timeout; if ( snet_write( sn, buf, (int)readlen, &tv ) != readlen ) { syslog( LOG_ERR, "snet_write: %m" ); return( -1 ); } } if ( readlen < 0 ) { syslog( LOG_ERR, "read: %m" ); close( fd ); return( -1 ); } if ( close( fd ) < 0 ) { syslog( LOG_ERR, "close: %m" ); return( -1 ); } snet_writef( sn, ".\r\n" ); return( 0 ); }