int test_chooser( struct line_list *servers, struct line_list *available, int *use_subserver ) { struct line_list *sp; char *s, *t, *pr; int i, n = -1; DEBUG1("test_chooser: servers %d, available %d", servers->count, available->count ); for( i = 0; i < available->count; ++i ){ s = available->list[i]; DEBUG1("test_chooser: avail[%d]='%s'", i, s ); if( (t = safestrpbrk(s,Value_sep)) ){ n = strtol(t+1,0,0); DEBUG1("test_chooser: '%s' index '%d'", s, n ); sp = (void *)servers->list[n]; pr = Find_str_value(sp,PRINTER,Value_sep); DEBUG1("test_chooser: available '%s'", pr ); if( i == 0 ){ *use_subserver = n; } } } return( 0 ); }
int Check_secure_perms( struct line_list *options, int from_server, char *error, int errlen ) { /* * line 1 - CLIENT=xxxx - client authentication * line 2 - SERVER=xxxx - server authentication * ... - FROM=xxxx - from * line 3 - INPUT=\00x - command line */ char *authfrom, *authuser; authfrom = Find_str_value(options,AUTHFROM); if( !authfrom ) authfrom = Find_str_value(options,FROM); authuser = Find_str_value(options,AUTHUSER); if( !from_server ){ if( !authuser && authfrom ) authuser = authfrom; } if( !authuser ) authuser = Find_str_value(options,CLIENT); Set_str_value(options, AUTHTYPE, Perm_check.authtype ); Set_str_value(options, AUTHFROM, authfrom ); Set_str_value(options, AUTHUSER, authuser ); Perm_check.authfrom = Find_str_value(options,AUTHFROM); Perm_check.authuser = authuser = Find_str_value(options,AUTHUSER); if( !authuser ){ plp_snprintf( error, errlen, "Printer %s@%s: missing authentication client id", Printer_DYN,Report_server_as_DYN?Report_server_as_DYN:ShortHost_FQDN ); return( JABORT ); } Perm_check.authca = Find_str_value(options,AUTHCA); DEBUGFC(DRECV1)Dump_line_list("Check_secure_perms - after",options); DEBUGFC(DRECV1)Dump_perm_check( "Check_secure_perms - checking", &Perm_check ); return(0); }
void send_to_logger( int send_to_status_fd, int send_to_mail_fd, struct job *job, const char *header, char *msg_b ) { char *s, *t; char *id, *tstr; int num,pid; char out_b[4*SMALLBUFFER]; struct line_list l; if( !Is_server || Doing_cleanup ) return; Init_line_list(&l); if(DEBUGL4){ char buffer[32]; plp_snprintf(buffer,sizeof(buffer)-5, "%s", msg_b ); if( msg_b ) safestrncat( buffer,"..."); LOGDEBUG("send_to_logger: Logger_fd fd %d, send_to_status_fd %d, send_to_mail fd %d, header '%s', body '%s'", Logger_fd, send_to_status_fd, send_to_mail_fd, header, buffer ); } if( send_to_status_fd <= 0 && send_to_mail_fd <= 0 && Logger_fd <= 0 ) return; s = t = id = tstr = 0; num = 0; if( job ){ Set_str_value(&l,IDENTIFIER, (id = Find_str_value(&job->info,IDENTIFIER)) ); Set_decimal_value(&l,NUMBER, (num = Find_decimal_value(&job->info,NUMBER)) ); } Set_str_value(&l,UPDATE_TIME,(tstr=Time_str(0,0))); Set_decimal_value(&l,PROCESS,(pid=getpid())); plp_snprintf( out_b, sizeof(out_b), "%s at %s ## %s=%s %s=%d %s=%d\n", msg_b, tstr, IDENTIFIER, id, NUMBER, num, PROCESS, pid ); if( send_to_status_fd > 0 && Write_fd_str( send_to_status_fd, out_b ) < 0 ){ DEBUG4("send_to_logger: write to send_to_status_fd %d failed - %s", send_to_status_fd, Errormsg(errno) ); } if( send_to_mail_fd > 0 && Write_fd_str( send_to_mail_fd, out_b ) < 0 ){ DEBUG4("send_to_logger: write to send_to_mail_fd %d failed - %s", send_to_mail_fd, Errormsg(errno) ); } if( Logger_fd > 0 ){ Set_str_value(&l,PRINTER,Printer_DYN); Set_str_value(&l,HOST,FQDNHost_FQDN); s = Escape(msg_b,1); Set_str_value(&l,VALUE,s); if(s) free(s); s = 0; t = Join_line_list(&l,"\n"); s = Escape(t,1); if(t) free(t); t = 0; t = safestrdup4(header,"=",s,"\n",__FILE__,__LINE__); Write_fd_str( Logger_fd, t ); if( s ) free(s); s = 0; if( t ) free(t); t = 0; } Free_line_list(&l); }
int Send_auth_transfer( int *sock, int transfer_timeout, struct job *job, struct job *logjob, char *error, int errlen, char *cmd, struct security *security, struct line_list *info ) { struct stat statb; int ack, len, n, fd; /* ACME! The best... */ int status = JFAIL; /* job status */ char *secure, *destination, *from, *client, *s; char *tempfile; char buffer[SMALLBUFFER]; errno = 0; secure = 0; fd = Make_temp_fd(&tempfile); if( cmd && (s = safestrrchr(cmd,'\n')) ) *s = 0; DEBUG1("Send_auth_transfer: cmd '%s'", cmd ); if(DEBUGL1)Dump_line_list("Send_auth_transfer: info ", info ); destination = Find_str_value(info, DESTINATION, Value_sep ); from = Find_str_value(info, FROM, Value_sep ); client = Find_str_value(info, CLIENT, Value_sep ); if( safestrcmp(security->config_tag, "kerberos") ){ Put_in_auth(fd,DESTINATION,destination); if( Is_server ) Put_in_auth(fd,SERVER,from); Put_in_auth(fd,CLIENT,client); if( cmd ){ Put_in_auth(fd,INPUT,cmd); } } else { if( cmd && (Write_fd_str(fd,cmd) < 0 || Write_fd_str(fd,"\n") < 0) ){ SNPRINTF(error, errlen) "Send_auth_transfer: '%s' write failed - %s", tempfile, Errormsg(errno) ); goto error; } if( Is_server && (Write_fd_str(fd,client) < 0 || Write_fd_str(fd,"\n") < 0) ){ SNPRINTF(error, errlen) "Send_auth_transfer: '%s' write failed - %s", tempfile, Errormsg(errno) ); goto error; }
/************************************************************************* * Receive_secure() - receive a secure transfer *************************************************************************/ int Receive_secure( int *sock, char *input ) { char *printername; char error[SMALLBUFFER]; /* error message */ char *authtype; char *cf, *s; char *jobsize = 0; char *user = 0; int tempfd = -1; int ack, status, from_server; struct line_list args, header_info, info; struct stat statb; char *tempfile = 0; const struct security *security = 0; Name = "RCVSEC"; memset( error, 0, sizeof(error)); ack = 0; status = 0; DEBUGF(DRECV1)("Receive_secure: input line '%s'", input ); Init_line_list( &args ); Init_line_list( &header_info ); Init_line_list( &info ); Split(&args,input+1,Whitespace,0,0,0,0,0,0); DEBUGFC(DRECV1)Dump_line_list("Receive_secure - input", &args); if( args.count != 5 && args.count != 4 ){ plp_snprintf( error+1, sizeof(error)-1, _("bad command line '%s'"), input ); ack = ACK_FAIL; /* no retry, don't send again */ status = JFAIL; goto error; } Check_max(&args,1); args.list[args.count] = 0; /* * \REQ_SECUREprintername C/F user authtype jobsize\n - receive a job * 0 1 2 3 4 */ printername = args.list[0]; cf = args.list[1]; user = args.list[2]; /* user is escape encoded */ Unescape(user); authtype = args.list[3]; Unescape(authtype); jobsize = args.list[4]; setproctitle( "lpd %s '%s'", Name, printername ); Perm_check.authtype = authtype; from_server = 0; if( *cf == 'F' ){ from_server = 1; } /* set up the authentication support information */ if( Is_clean_name( printername ) ){ plp_snprintf( error+1, sizeof(error)-1, _("bad printer name '%s'"), input ); ack = ACK_FAIL; /* no retry, don't send again */ status = JFAIL; goto error; } Set_DYN(&Printer_DYN,printername); if( Setup_printer( printername, error+1, sizeof(error)-1, 0 ) ){ if( jobsize ){ plp_snprintf( error+1, sizeof(error)-1, _("bad printer '%s'"), printername ); ack = ACK_FAIL; /* no retry, don't send again */ status = JFAIL; goto error; } } else { int db, dbf; db = Debug; dbf = DbgFlag; s = Find_str_value(&Spool_control,DEBUG); if(!s) s = New_debug_DYN; Parse_debug( s, 0 ); if( !(DRECVMASK & DbgFlag) ){ Debug = db; DbgFlag = dbf; } else { int tdb, tdbf; tdb = Debug; tdbf = DbgFlag; Debug = db; DbgFlag = dbf; if( Log_file_DYN ){ tempfd = Checkwrite( Log_file_DYN, &statb,0,0,0); if( tempfd > 0 && tempfd != 2 ){ dup2(tempfd,2); close(tempfd); } tempfd = -1; } Debug = tdb; DbgFlag = tdbf; LOGDEBUG("Receive_secure: socket fd %d", *sock); Dump_line_list("Receive_secure - input", &args); } DEBUGF(DRECV1)("Receive_secure: debug '%s', Debug %d, DbgFlag 0x%x", s, Debug, DbgFlag ); } if( !(security = Fix_receive_auth(authtype, &info)) ){ plp_snprintf( error+1, sizeof(error)-1, _("unsupported authentication '%s'"), authtype ); ack = ACK_FAIL; /* no retry, don't send again */ status = JFAIL; goto error; } if( !security->server_receive ){ plp_snprintf( error+1, sizeof(error)-1, _("no receive method supported for '%s'"), authtype ); ack = ACK_FAIL; /* no retry, don't send again */ status = JFAIL; goto error; } if( jobsize ){ double read_len; read_len = strtod(jobsize,0); DEBUGF(DRECV2)("Receive_secure: spooling_disabled %d", Sp_disabled(&Spool_control) ); if( Sp_disabled(&Spool_control) ){ plp_snprintf( error+1, sizeof(error)-1, _("%s: spooling disabled"), Printer_DYN ); ack = ACK_RETRY; /* retry */ status = JFAIL; goto error; } if( Max_job_size_DYN > 0 && (read_len+1023)/1024 > Max_job_size_DYN ){ plp_snprintf( error+1, sizeof(error)-1, _("%s: job size %0.0f is larger than %d K"), Printer_DYN, read_len, Max_job_size_DYN ); ack = ACK_RETRY; status = JFAIL; goto error; } else if( !Check_space( read_len, Minfree_DYN, Spool_dir_DYN ) ){ plp_snprintf( error+1, sizeof(error)-1, _("%s: insufficient file space"), Printer_DYN ); ack = ACK_RETRY; status = JFAIL; goto error; } } tempfd = Make_temp_fd(&tempfile); close(tempfd); tempfd = -1; DEBUGF(DRECV1)("Receive_secure: sock %d, user '%s', jobsize '%s'", *sock, user, jobsize ); status = security->server_receive( sock, Send_job_rw_timeout_DYN, user, jobsize, from_server, authtype, &info, error+1, sizeof(error)-1, &header_info, security, tempfile, Do_secure_work); error: DEBUGF(DRECV1)("Receive_secure: status %d, ack %d, error '%s'", status, ack, error+1 ); if( status ){ if( ack == 0 ) ack = ACK_FAIL; error[0] = ack; DEBUGF(DRECV1)("Receive_secure: sending '%s'", error ); (void)Link_send( ShortRemote_FQDN, sock, Send_query_rw_timeout_DYN, error, safestrlen(error), 0 ); Errorcode = JFAIL; } Free_line_list( &args ); Free_line_list( &header_info ); Free_line_list( &info ); close( *sock ); *sock = -1; Remove_tempfiles(); if( status == 0 && jobsize ){ /* start a new server */ DEBUGF(DRECV1)("Receive_secure: starting server"); if( Server_queue_name_DYN ){ Do_queue_jobs( Server_queue_name_DYN, 0 ); } else { Do_queue_jobs( Printer_DYN, 0 ); } } cleanup(0); }
static int Do_secure_work( char *jobsize, int from_server, char *tempfile, struct line_list *header_info ) { int n, len, linecount = 0, done = 0, fd, status = 0; char *s, *t; char buffer[SMALLBUFFER]; char error[SMALLBUFFER]; struct stat statb; error[0] = 0; if( (fd = Checkread(tempfile,&statb)) < 0 ){ status = JFAIL; plp_snprintf( error, sizeof(error), "Do_secure_work: reopen of '%s' failed - %s", tempfile, Errormsg(errno)); goto error; } buffer[0] = 0; n = 0; done = 0; linecount = 0; while( !done && n < (int)sizeof(buffer)-1 && (len = Read_fd_len_timeout( Send_query_rw_timeout_DYN, fd, buffer+n, sizeof(buffer)-1-n )) > 0 ){ buffer[n+len] = 0; DEBUGF(DRECV1)("Do_secure_work: read %d - '%s'", len, buffer ); while( !done && (s = safestrchr(buffer,'\n')) ){ *s++ = 0; if( safestrlen(buffer) == 0 ){ done = 1; break; } DEBUGF(DRECV1)("Do_secure_work: line [%d] '%s'", linecount, buffer ); if( (t = strchr(buffer,'=')) ){ *t++ = 0; Unescape(t); Set_str_value(header_info, buffer, t ); } else { switch( linecount ){ case 0: if( jobsize ){ if( from_server ){ Set_str_value(header_info,CLIENT,buffer); } done = 1; } else { Set_str_value(header_info,INPUT,buffer); break; } break; case 1: Set_str_value(header_info,CLIENT,buffer); done = 1; break; } } ++linecount; memmove(buffer,s,safestrlen(s)+1); n = safestrlen(buffer); } } if( fd >= 0 ) close(fd); fd = -1; DEBUGFC(DRECV1)Dump_line_list("Do_secure_work - header", header_info ); if( (status = Check_secure_perms( header_info, from_server, error, sizeof(error))) ){ goto error; } DEBUGFC(DRECV1)Dump_line_list("Do_secure_work - header after check", header_info ); buffer[0] = 0; if( jobsize ){ if( (fd = Checkread(tempfile, &statb) ) < 0 ){ status = JFAIL; plp_snprintf( error, sizeof(error), "Do_secure_work: reopen of '%s' for read failed - %s", tempfile, Errormsg(errno)); goto error; } status = Scan_block_file( fd, error, sizeof(error), header_info ); if( (fd = Checkwrite(tempfile,&statb,O_WRONLY|O_TRUNC,1,0)) < 0 ){ status = JFAIL; plp_snprintf( error, sizeof(error), "Do_secure_work: reopen of '%s' for write failed - %s", tempfile, Errormsg(errno)); goto error; } } else { if( (fd = Checkwrite(tempfile,&statb,O_WRONLY|O_TRUNC,1,0)) < 0 ){ status = JFAIL; plp_snprintf( error, sizeof(error), "Do_secure_work: reopen of '%s' for write failed - %s", tempfile, Errormsg(errno)); goto error; } if( (s = Find_str_value(header_info,INPUT)) ){ Dispatch_input( &fd, s, "from secure link" ); } } error: if( fd >= 0 ) close(fd); fd = -1; DEBUGF(DRECV1)("Do_secure_work: status %d, tempfile '%s', error '%s'", status, tempfile, error ); if( error[0] ){ DEBUGF(DRECV1)("Do_secure_work: updating tempfile '%s', error '%s'", tempfile, error ); if( (fd = Checkwrite(tempfile,&statb,O_WRONLY|O_TRUNC,1,0)) < 0 ){ Errorcode = JFAIL; logerr_die(LOG_INFO, "Do_secure_work: reopen of '%s' for write failed", tempfile ); } Write_fd_str(fd,error); close(fd); } DEBUGF(DRECV1)("Do_secure_work: returning %d", status ); return( status ); }
void Decode( char *in ) { struct line_list l, cf, info; char *s, *t, *header, *value; int i; Init_line_list(&l); Init_line_list(&cf); Init_line_list(&info); FPRINTF(STDOUT,"****\n"); if( debug )FPRINTF(STDOUT, "Decode: %s\n", in ); if((s = safestrpbrk(in,Value_sep)) ){ *s++ = 0; Unescape(s); Free_line_list(&l); Split(&l,s,Line_ends,1,Value_sep,1,1,1,0); for( i = 0; i < l.count; ++i ){ t = l.list[i]; if( debug || safestrncasecmp(t,VALUE,5) ){ FPRINTF(STDOUT,"%s\n", t ); } } s = Find_str_value(&l,VALUE,Value_sep); if( s ) Unescape(s); if( !safestrcasecmp(in,TRACE) ){ FPRINTF(STDOUT,"TRACE: '%s'\n", s ); } else if( !safestrcasecmp(in,UPDATE) ){ FPRINTF(STDOUT,"UPDATE: '%s'\n", s ); Split(&info,s,Line_ends,0,0,0,0,0,0); for( i = 0; i < info.count; ++i ){ header = info.list[i]; if( (value = safestrchr(header,'=')) ) *value++ = 0; Unescape(value); FPRINTF(STDOUT," [%d] %s='%s'\n", i, header, value ); } } else if( !safestrcasecmp(in,PRSTATUS) ){ FPRINTF(STDOUT,"PRSTATUS: '%s'\n", s ); } else if( !safestrcasecmp(in,QUEUE) ){ FPRINTF(STDOUT,"QUEUE: '%s'\n", s ); Split(&info,s,Line_ends,0,0,0,0,0,0); for( i = 0; i < info.count; ++i ){ header = info.list[i]; if( (value = safestrchr(header,'=')) ) *value++ = 0; Unescape(value); FPRINTF(STDOUT," [%d] %s='%s'\n", i, header, value ); } Free_line_list(&info); } else if( !safestrcasecmp(in,DUMP) ){ FPRINTF(STDOUT,"DUMP:\n"); Split(&info,s,Line_ends,0,0,0,0,0,0); for( i = 0; i < info.count; ++i ){ header = info.list[i]; if( (value = safestrchr(header,'=')) ) *value++ = 0; Unescape(value); if(debug) FPRINTF(STDOUT," [%d] %s='%s'\n", i, header, value ); if( !safestrcasecmp(header,QUEUE) ){ FPRINTF(STDOUT," EXTRACT QUEUE '%s'\n",value); } else if( !safestrcasecmp(header,UPDATE) ){ FPRINTF(STDOUT," EXTRACT UPDATE '%s'\n",value); } else { FPRINTF(STDOUT," EXTRACT '%s' '%s'\n",header, value); } } Free_line_list(&info); } else { FPRINTF(STDOUT,"%s: '%s'\n", in, s ); } } Free_line_list(&l); Free_line_list(&cf); Free_line_list(&info); FPRINTF(STDOUT,"\n"); }