1/*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License as
4 * published by the Free Software Foundation; either version 2 of
5 * the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
15 * MA 02111-1307 USA
16 */
17/***************************************************************************
18 * LPRng - An Extended Print Spooler System
19 *
20 * Copyright 1988-2003, Patrick Powell, San Diego, CA
21 *     papowell@lprng.com
22 * See LICENSE for conditions of use.
23 *
24 ***************************************************************************/
25
26 static char *const _id =
27"$Id: permission.c,v 1.1.1.1 2008/10/15 03:28:27 james26_jang Exp $";
28
29
30#include "lp.h"
31#include "fileopen.h"
32#include "globmatch.h"
33#include "gethostinfo.h"
34#include "getqueue.h"
35#include "permission.h"
36#include "linksupport.h"
37
38#undef HAVE_INNETGR
39
40/**** ENDINCLUDE ****/
41 struct keywords permwords[] = {
42
43{"ACCEPT", 0, P_ACCEPT,0,0,0,0},
44{"AUTH", 0, P_AUTH,0,0,0,0},
45{"AUTHFROM", 0, P_AUTHFROM,0,0,0,0},
46{"AUTHJOB", 0, P_AUTHJOB,0,0,0,0},
47{"AUTHSAMEUSER", 0, P_AUTHSAMEUSER,0,0,0,0},
48{"AUTHTYPE", 0, P_AUTHTYPE,0,0,0,0},
49{"AUTHUSER", 0, P_AUTHUSER,0,0,0,0},
50{"CONTROLLINE", 0, P_CONTROLLINE,0,0,0,0},
51{"DEFAULT", 0, P_DEFAULT,0,0,0,0},
52{"FORWARD", 0, P_FORWARD,0,0,0,0},
53{"GROUP", 0, P_GROUP,0,0,0,0},
54{"HOST", 0, P_HOST,0,0,0,0},
55{"IFIP", 0, P_IFIP,0,0,0,0},
56{"IP", 0, P_IP,0,0,0,0},
57{"LPC", 0, P_LPC,0,0,0,0},
58{"NOMATCHFOUND", 0, 0,0,0,0,0},
59{"NOT", 0, P_NOT,0,0,0,0},
60{"PORT", 0, P_PORT,0,0,0,0},
61{"PRINTER", 0, P_PRINTER,0,0,0,0},
62{"REJECT", 0, P_REJECT,0,0,0,0},
63{"REMOTEGROUP", 0, P_REMOTEGROUP,0,0,0,0},
64{"REMOTEHOST", 0, P_REMOTEHOST,0,0,0,0},
65{"REMOTEIP", 0, P_REMOTEIP,0,0,0,0},
66{"REMOTEPORT", 0, P_REMOTEPORT,0,0,0,0},
67{"REMOTEUSER", 0, P_REMOTEUSER,0,0,0,0},
68{"SAMEHOST", 0, P_SAMEHOST,0,0,0,0},
69{"SAMEUSER", 0, P_SAMEUSER,0,0,0,0},
70{"SERVER", 0, P_SERVER,0,0,0,0},
71{"SERVICE", 0, P_SERVICE,0,0,0,0},
72{"USER", 0, P_USER,0,0,0,0},
73{"UNIXSOCKET", 0, P_UNIXSOCKET,0,0,0,0},
74{"AUTHCA", 0, P_AUTHCA,0,0,0,0},
75
76{0,0,0,0,0,0,0}
77};
78
79char *perm_str( int n )
80{
81	return(Get_keystr(n,permwords));
82}
83int perm_val( char *s )
84{
85	if( !s )return(0);
86	if( safestrlen(s) == 1 && isupper(cval(s)) ){
87		return( P_CONTROLLINE );
88	}
89	return(Get_keyval(s,permwords));
90}
91
92
93/***************************************************************************
94 * Perms_check( struct line_list *perms, struct perm_check );
95 * - run down the list of permissions
96 * - do the check on each of them
97 * - if you get a distinct fail or success, return
98 * 1. the P_NOT field inverts the result of the next test
99 * 2. if one test fails,  then we go to the next line
100 * 3. The entire set of tests is accepted if all pass, i.e. none fail
101 ***************************************************************************/
102
103int Perms_check( struct line_list *perms, struct perm_check *check,
104	struct job *job, int job_check )
105{
106	int j, c, linecount, valuecount, key;
107	int invert = 0;
108	int result = 0, m = 0;
109	struct line_list values, args;
110	char *s, *t;					/* string */
111	int last_default_perm;
112	char buffer[4];
113
114#ifdef ORIGINAL_DEBUG//JY@1020
115	DEBUGFC(DDB1)Dump_perm_check( "Perms_check - checking", check );
116	DEBUGFC(DDB1)Dump_line_list( "Perms_check - permissions", perms );
117#endif
118	Init_line_list(&values);
119	Init_line_list(&args);
120	last_default_perm = perm_val( Default_permission_DYN );
121	DEBUGF(DDB1)("Perms_check: last_default_perm '%s', Default_perm '%s'",
122		perm_str( last_default_perm ), Default_permission_DYN );
123	if( check == 0 || perms == 0 ){
124		return( last_default_perm );
125	}
126	for( linecount = 0; result == 0 && linecount < perms->count; ++linecount ){
127		DEBUGF(DDB2)("Perms_check: line [%d]='%s'", linecount,
128			perms->list[linecount]);
129		Free_line_list(&values);
130		Split(&values,perms->list[linecount],Whitespace,0,0,0,0,0,0);
131		if( values.count == 0 ) continue;
132		result = 0; m = 0; invert = 0;
133		for( valuecount = 0; m == 0 && valuecount < values.count;
134				++valuecount ){
135			DEBUGF(DDB2)("Perms_check: [%d]='%s'",valuecount,
136				values.list[valuecount] );
137			Free_line_list(&args);
138			Split(&args,values.list[valuecount],Perm_sep,0,0,0,0,0,0);
139			if( args.count == 0 ) continue;
140			if( invert > 0 ){
141				invert = -1;
142			} else {
143				invert = 0;
144			}
145			key = perm_val( args.list[0] );
146			if( key == 0 ){
147				m = 1;
148				break;
149			}
150			/* we remove the key entry */
151			Remove_line_list( &args, 0 );
152			DEBUGF(DDB2)("Perms_check: before doing %s, result %d, %s",
153				perm_str(key), result, perm_str(result) );
154			switch( key ){
155			case P_NOT:
156				invert = 1;
157				continue;
158			case P_REJECT: result = P_REJECT; m = 0; break;
159			case P_ACCEPT: result = P_ACCEPT; m = 0; break;
160			case P_USER:
161				m = 1;
162				if( !job_check ){ m = 0; }
163				else switch (check->service){
164				case 'X': break;
165				default:
166					m = match( &args, check->user, invert );
167					break;
168				}
169				break;
170			case P_LPC:
171				m = 1;
172				switch (check->service){
173				case 'X': break;
174				case 'C':
175					m = match( &args, check->lpc, invert );
176					break;
177				}
178				break;
179
180			case P_IP:
181			case P_HOST:
182				m = 1;
183				if( !job_check ){ m = 0; }
184				else switch (check->service){
185				case 'X': break;
186				default:
187					m = match_host( &args, check->host, invert );
188					break;
189				}
190				break;
191
192			case P_GROUP:
193				m = 1;
194				if( !job_check ){ m = 0; }
195				else switch (check->service){
196				case 'X': break;
197				default:
198					m = match_group( &args, check->user, invert );
199					break;
200				}
201				break;
202
203			case P_REMOTEPORT:
204			case P_PORT:
205				m = 1;
206				switch (check->service){
207				case 'X': case 'M': case 'C':
208					m = match_range( &args, check->port, invert );
209					break;
210				}
211				break;
212			case P_REMOTEUSER:
213				m = 1;
214				switch (check->service){
215				case 'X': break;
216				default:
217					m = match( &args, check->remoteuser, invert );
218					break;
219				}
220				break;
221			case P_REMOTEGROUP:
222				m = 1;
223				switch (check->service){
224				case 'X': break;
225				default:
226					m = match_group( &args, check->remoteuser, invert );
227					break;
228				}
229				break;
230
231			case P_IFIP:
232			case P_REMOTEHOST:
233			case P_REMOTEIP:
234				m = match_host( &args, check->remotehost, invert );
235				break;
236
237			case P_AUTH:
238				m = 1;
239				switch (check->service){
240				case 'X': break;
241				default:
242					DEBUGF(DDB3)(
243						"Perms_check: P_AUTH authuser '%s'", check->authuser );
244					m = !check->authuser;
245					if( invert ) m = !m;
246				}
247				break;
248
249			case P_AUTHTYPE:
250				m = 1;
251				switch (check->service){
252				case 'X': break;
253				default:
254					DEBUGF(DDB3)(
255						"Perms_check: P_AUTHTYPE authtype '%s'", check->authtype );
256					m = match( &args, check->authtype, invert );
257				}
258				break;
259
260			case P_AUTHFROM:
261				m = 1;
262				switch (check->service){
263				case 'X': break;
264				default:
265					m = match( &args, check->authfrom, invert );
266				}
267				break;
268
269			case P_AUTHCA:
270				m = 1;
271				switch (check->service){
272				case 'X': break;
273				default:
274					m = match( &args, check->authca, invert );
275				}
276				break;
277
278			case P_AUTHUSER:
279				m = 1;
280				switch (check->service){
281				case 'X': break;
282				default:
283					m = match( &args, check->authuser, invert );
284				}
285				break;
286
287			case P_CONTROLLINE:
288				/* check to see if we have control line */
289				m = 1;
290				if( !job_check ){ m = 0; }
291				for( j = 0; m && j < args.count; ++j ){
292					if( !(t = args.list[j]) ) continue;
293					c = cval(t);
294					buffer[1] = 0; buffer[0] = c;
295					if( isupper(c) && (s = Find_str_value(&job->info,buffer,0))){
296						/* we do a glob match against line */
297						m = Globmatch( t+1, s );
298					}
299				}
300				if( invert ) m = !m;
301				break;
302			case P_PRINTER:
303				m = 1;
304				switch (check->service){
305				case 'X': break;
306				default:
307					m = match( &args, check->printer, invert );
308					break;
309				}
310				break;
311			case P_SERVICE:
312				m = match_char( &args, check->service, invert );
313				break;
314			case P_FORWARD:
315			case P_SAMEHOST:
316				m = 1;
317				if( !job_check ){ m = 0; }
318				else switch (check->service){
319				default:
320					/* P_SAMEHOST check succeeds if P_REMOTEIP == P_IP */
321					m = Same_host(check->host, check->remotehost);
322					if( m ){
323					/* check to see if both remote and local are server */
324					int r, h;
325					r = Same_host(check->remotehost,&Host_IP);
326					if( r ) r = Same_host(check->remotehost,&Localhost_IP);
327					h = Same_host(check->host,&Host_IP);
328					if( h ) h = Same_host(check->host,&Localhost_IP);
329					DEBUGF(DDB3)(
330						"Perms_check: P_SAMEHOST server name check r=%d,h=%d",
331						r, h );
332					if( h == 0 && r == 0 ){
333						m = 0;
334					}
335					}
336					if( invert ) m = !m;
337					break;
338				}
339				if( key == P_FORWARD ) m = !m;
340				break;
341			case P_SAMEUSER:
342				m = 1;
343				if( !job_check ){ m = 0; }
344				else switch (check->service){
345				default: break;
346				case 'Q': case 'M': case 'C':
347					/* check succeeds if remoteuser == user */
348					m = (safestrcmp( check->user, check->remoteuser ) != 0);
349					if( invert ) m = !m;
350					DEBUGF(DDB3)(
351					"Perms_check: P_SAMEUSER '%s' == remote '%s', rslt %d",
352					check->user, check->remoteuser, m );
353					break;
354				}
355				break;
356
357			case P_AUTHSAMEUSER:
358				m = 1;
359				if( !job_check ){ m = 0; }
360				else switch (check->service){
361				default: break;
362				case 'Q': case 'M': case 'C':
363					/* check succeeds if remoteuser == user */
364					t = Find_str_value(&job->info,AUTHUSER,Value_sep);
365					m = (safestrcmp( check->authuser, t ) != 0);
366					if( invert ) m = !m;
367					DEBUGF(DDB3)(
368					"Perms_check: P_AUTHSAMEUSER job authinfo '%s' == auth_id '%s', rslt %d",
369					t, check->authuser, m );
370					break;
371				}
372				break;
373
374			case P_AUTHJOB:
375				m = 1;
376				switch (check->service){
377				default: break;
378				case 'Q': case 'M': case 'C':
379					/* check succeeds if authinfo present */
380					t = Find_str_value(&job->info,AUTHUSER,Value_sep);
381					m = !t;
382					if( invert ) m = !m;
383					DEBUGF(DDB3)(
384					"Perms_check: P_AUTHJOB job authinfo '%s', rslt %d", t, m );
385					break;
386				}
387				break;
388
389			case P_SERVER:
390				m = 1;
391				/* check succeeds if remote P_IP and server P_IP == P_IP */
392				m = Same_host(check->remotehost,&Host_IP);
393				if( m ) m = Same_host(check->remotehost,&Localhost_IP);
394				if( invert ) m = !m;
395				break;
396
397			case P_UNIXSOCKET:
398				m = 1;
399				/* check succeeds if connection via unix socket */
400				m = !check->unix_socket;
401				if( invert ) m = !m;
402				break;
403
404			case P_DEFAULT:
405
406				DEBUGF(DDB3)("Perms_check: DEFAULT - %d, values.count %d",
407					valuecount, values.count );
408				m = 1;
409				if( values.count == 2 ){
410					switch( perm_val( values.list[1]) ){
411					case P_REJECT: last_default_perm =  P_REJECT; break;
412					case P_ACCEPT: last_default_perm =  P_ACCEPT; break;
413					}
414				}
415			}
416			DEBUGF(DDB2)("Perms_check: match %d, result '%s' default now '%s'",
417				m, perm_str(result), perm_str(last_default_perm) );
418		}
419		if( m ){
420			result = 0;
421		} else if( result == 0 ){
422			result = last_default_perm;
423		}
424		DEBUGF(DDB1)("Perms_check: '%s' - match %d, result '%s' default now '%s'",
425			perms->list[linecount],
426			m, perm_str(result), perm_str(last_default_perm) );
427	}
428	if( result == 0 ){
429		result = last_default_perm;
430	}
431	DEBUGF(DDB1)("Perms_check: final result %d '%s'",
432				result, perm_str( result ) );
433	Free_line_list(&values);
434	Free_line_list(&args);
435
436	return( result );
437}
438
439
440/***************************************************************************
441 * static int match( char **val, char *str );
442 *  returns 1 on failure, 0 on success
443 *  - match the string against the list of options
444 *    options are glob type regular expressions;  we implement this
445 *    currently using the most crude of pattern matching
446 *  - if string is null or pattern list is null, then match fails
447 *    if both are null, then match succeeds
448 ***************************************************************************/
449
450int match( struct line_list *list, const char *str, int invert )
451{
452 	int result = 1, i, c;
453	char *s;
454 	DEBUGF(DDB3)("match: str '%s', invert %d", str, invert );
455 	if(str)for( i = 0; result && i < list->count; ++i ){
456		if( !(s = list->list[i])) continue;
457		DEBUGF(DDB3)("match: str '%s' to '%s'", str, s );
458 		/* now do the match */
459		c = cval(s);
460		if( c == '@' ) {	/* look up host in netgroup */
461#ifdef HAVE_INNETGR
462			result = !innetgr( s+1, (char *)str, 0, 0 );
463#else /* HAVE_INNETGR */
464			DEBUGF(DDB3)("match: no innetgr() call, netgroups not permitted");
465#endif /* HAVE_INNETGR */
466		} else if( c == '<' && cval(s+1) == '/' ){
467			struct line_list users;
468			Init_line_list(&users);
469			Get_file_image_and_split(s+1,0,0,&users,Whitespace,
470				0,0,0,0,0,0);
471#ifdef ORIGINAL_DEBUG//JY@1020
472			DEBUGFC(DDB3)Dump_line_list("match- file contents'", &users );
473#endif
474			result = match( &users,str,0);
475			Free_line_list(&users);
476		} else {
477	 		result = Globmatch( s, str );
478		}
479		DEBUGF(DDB3)("match: list[%d]='%s', result %d", i, s,  result );
480	}
481	if( invert ) result = !result;
482 	DEBUGF(DDB3)("match: str '%s' final result %d", str, result );
483	return( result );
484}
485
486/***************************************************************************
487 * static int match_host( char **list, char *host );
488 *  returns 1 on failure, 0 on success
489 *  - match the hostname/printer strings against the list of options
490 *    options are glob type regular expressions;  we implement this
491 *    currently using the most crude of pattern matching
492 *  - if string is null or pattern list is null, then match fails
493 *    if both are null, then match succeeds
494 ***************************************************************************/
495
496int match_host( struct line_list *list, struct host_information *host,
497	int invert )
498{
499 	int result = Match_ipaddr_value(list,host);
500	if( invert ) result = !result;
501 	DEBUGF(DDB3)("match_host: host '%s' final result %d", host?host->fqdn:0,
502		result );
503	return( result );
504}
505/***************************************************************************
506 * static int match_range( char **list, int port );
507 * check the port number and/or range
508 * entry has the format:  number     number-number
509 ***************************************************************************/
510
511int portmatch( char *val, int port )
512{
513	int low, high, err;
514	char *end;
515	int result = 1;
516	char *s, *t, *tend;
517
518	err = 0;
519	s = safestrchr( val, '-' );
520	if( s ){
521		*s = 0;
522	}
523	end = val;
524	low = strtol( val, &end, 10 );
525	if( end == val || *end ) err = 1;
526
527	high = low;
528	if( s ){
529		tend = t = s+1;
530		high = strtol( t, &tend, 10 );
531		if( t == tend || *tend ) err = 1;
532		*s = '-';
533	}
534	if( err ){
535		LOGMSG( LOG_ERR) "portmatch: bad port range '%s'", val );
536	}
537	if( high < low ){
538		err = high;
539		high = low;
540		low = err;
541	}
542	result = !( port >= low && port <= high );
543	DEBUGF(DDB3)("portmatch: low %d, high %d, port %d, result %d",
544		low, high, port, result );
545	return( result );
546}
547
548int match_range( struct line_list *list, int port, int invert )
549{
550	int result = 1;
551	int i;
552	char *s;
553
554	DEBUGF(DDB3)("match_range: port '0x%x'", port );
555	for( i = 0; result && i < list->count; ++i ){
556		/* now do the match */
557		if( !(s = list->list[i]) ) continue;
558		result = portmatch( s, port );
559	}
560	if( invert ) result = !result;
561	DEBUGF(DDB3)("match_range: port '%d' result %d", port, result );
562	return( result );
563}
564
565/***************************************************************************
566 * static int match_char( char **list, int value );
567 * check for the character value in one of the option strings
568 * entry has the format:  string
569 ***************************************************************************/
570
571int match_char( struct line_list *list, int value, int invert )
572{
573	int result = 1;
574	int i;
575	char *s;
576
577#ifdef ORIGINAL_DEBUG//JY@1020
578	DEBUGF(DDB3)("match_char: value '0x%x' '%c'", value, value );
579	DEBUGFC(DDB3)Dump_line_list("match_char - lines", list );
580#endif
581	for( i = 0; result && i < list->count; ++i ){
582		if( !(s = list->list[i]) ) continue;
583		result = (safestrchr( s, value ) == 0) && (safestrchr(s,'*') == 0) ;
584		DEBUGF(DDB3)("match_char: val %c, str '%s', match %d",
585			value, s, result);
586	}
587	if( invert ) result = !result;
588	DEBUGF(DDB3)("match_char: value '%c' result %d", value, result );
589	return( result );
590}
591
592
593/***************************************************************************
594 * static int match_group( char **list, char *str );
595 *  returns 1 on failure, 0 on success
596 *  - get the UID for the named user
597 *  - scan the listed groups to see if there is a group
598 *    check to see if user is in group
599 ***************************************************************************/
600
601int match_group( struct line_list *list, const char *str, int invert )
602{
603 	int result = 1;
604 	int i;
605	char *s;
606
607 	DEBUGF(DDB3)("match_group: str '%s'", str );
608 	for( i = 0; str && result && i < list->count; ++i ){
609 		/* now do the match */
610		if( !(s = list->list[i]) ) continue;
611 		result = ingroup( s, str );
612	}
613	if( invert ) result = !result;
614 	DEBUGF(DDB3)("match: str '%s' value %d", str, result );
615	return( result );
616}
617
618/***************************************************************************
619 * static int ingroup( char* *group, char *user );
620 *  returns 1 on failure, 0 on success
621 *  scan group for user name
622 * Note: we first check for the group.  If there is none, we check for
623 *  wildcard (*) in group name, and then scan only if we need to
624 ***************************************************************************/
625
626int ingroup( char *group, const char *user )
627{
628	struct group *grent;
629	struct passwd *pwent;
630	char **members;
631	int result = 1;
632
633	DEBUGF(DDB3)("ingroup: checking '%s' for membership in group '%s'", user, group);
634	if( group == 0 || user == 0 ){
635		return( result );
636	}
637	/* first try getgrnam, see if it is a group */
638	pwent = getpwnam(user);
639	if( group[0] == '@' ) {	/* look up user in netgroup */
640#ifdef HAVE_INNETGR
641		if( !innetgr( group+1, 0, (char *)user, 0 ) ) {
642			DEBUGF(DDB3)( "ingroup: user %s P_NOT in netgroup %s", user, group+1 );
643		} else {
644			DEBUGF(DDB3)( "ingroup: user %s in netgroup %s", user, group+1 );
645			result = 0;
646		}
647#else /* HAVE_INNETGR */
648		DEBUGF(DDB3)( "ingroup: no innetgr() call, netgroups not permitted" );
649#endif /* HAVE_INNETGR */
650	} else if( group[0] == '<' && group[1] == '/' ){
651		struct line_list users;
652		Init_line_list(&users);
653		Get_file_image_and_split(group+1,0,0,&users,Whitespace,
654			0,0,0,0,0,0);
655#ifdef ORIGINAL_DEBUG//JY@1020
656		DEBUGFC(DDB3)Dump_line_list("match- file contents'", &users );
657#endif
658		result = match_group( &users,user,0);
659		Free_line_list(&users);
660	} else if( (grent = getgrnam( group )) ){
661		DEBUGF(DDB3)("ingroup: group id: %d\n", grent->gr_gid);
662		if( pwent && ((int)pwent->pw_gid == (int)grent->gr_gid) ){
663			DEBUGF(DDB3)("ingroup: user default group id: %d\n", pwent->pw_gid);
664			result = 0;
665		} else for( members = grent->gr_mem; result && *members; ++members ){
666			DEBUGF(DDB3)("ingroup: member '%s'", *members);
667			result = (safestrcmp( user, *members ) != 0);
668		}
669	} else if( safestrpbrk( group, "*[]") ){
670		/* wildcard in group name, scan through all groups */
671		setgrent();
672		while( result && (grent = getgrent()) ){
673			DEBUGF(DDB3)("ingroup: group name '%s'", grent->gr_name);
674			/* now do match against group */
675			if( Globmatch( group, grent->gr_name ) == 0 ){
676				if( pwent && ((int)pwent->pw_gid == (int)grent->gr_gid) ){
677					DEBUGF(DDB3)("ingroup: user default group id: %d\n",
678					pwent->pw_gid);
679					result = 0;
680				} else {
681					DEBUGF(DDB3)("ingroup: found '%s'", grent->gr_name);
682					for( members = grent->gr_mem; result && *members; ++members ){
683						DEBUGF(DDB3)("ingroup: member '%s'", *members);
684						result = (safestrcmp( user, *members ) != 0);
685					}
686				}
687			}
688		}
689		endgrent();
690	}
691	DEBUGF(DDB3)("ingroup: result: %d", result );
692	return( result );
693}
694
695#ifdef ORIGINAL_DEBUG//JY@1020
696/***************************************************************************
697 * Dump_perm_check( char *title, struct perm_check *check )
698 * Dump perm_check information
699 ***************************************************************************/
700
701void Dump_perm_check( char *title,  struct perm_check *check )
702{
703	char buffer[SMALLBUFFER];
704	if( title ) LOGDEBUG( "*** perm_check %s ***", title );
705	buffer[0] = 0;
706	if( check ){
707		LOGDEBUG(
708		"  user '%s', rmtuser '%s', printer '%s', service '%c', lpc '%s'",
709		check->user, check->remoteuser, check->printer, check->service, check->lpc );
710#ifdef ORIGINAL_DEBUG//JY@1020
711		Dump_host_information( "  host", check->host );
712		Dump_host_information( "  remotehost", check->remotehost );
713#endif
714/*
715		LOGDEBUG( "  ip '%s' port %d, unix_socket %d",
716			inet_ntop_sockaddr( &check->addr, buffer, sizeof(buffer)),
717			check->port, check->unix_socket );
718*/
719		LOGDEBUG( "  port %d, unix_socket %d",
720			check->port, check->unix_socket );
721		LOGDEBUG( " authtype '%s', authfrom '%s', authuser '%s', authca '%s'",
722			check->authtype, check->authfrom, check->authuser, check->authca );
723	}
724}
725#endif
726
727/***************************************************************************
728 * Perm_check_to_list( struct line_list *list, struct perm_check *check )
729 *  Put perm_check information in list
730 ***************************************************************************/
731
732void Perm_check_to_list( struct line_list *list, struct perm_check *check )
733{
734	char buffer[SMALLBUFFER];
735	Set_str_value( list, USER, check->user );
736	Set_str_value( list, REMOTEUSER, check->remoteuser );
737	Set_str_value( list, PRINTER, check->printer );
738	SNPRINTF(buffer,sizeof(buffer))"%c",check->service);
739	Set_str_value( list, SERVICE, buffer );
740	Set_str_value( list, LPC, check->lpc );
741	if( check->host ){
742		Set_str_value( list, HOST, check->host->fqdn );
743	}
744	if( check->remotehost ){
745		Set_str_value( list, HOST, check->remotehost->fqdn );
746	}
747	Set_decimal_value( list, PORT, check->port );
748	Set_str_value( list, AUTHTYPE, check->authtype );
749	Set_str_value( list, AUTHFROM, check->authfrom );
750	Set_str_value( list, AUTHUSER, check->authuser );
751	Set_str_value( list, AUTHCA, check->authca );
752}
753