1 /*
2 ** Copyright 2002 Double Precision, Inc.  See COPYING for
3 ** distribution information.
4 */
5 
6 #include "auth.h"
7 #include "courierauthdebug.h"
8 #include <ctype.h>
9 #include <stdarg.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 
14 
15 /* for internal use */
16 
17 static int courier_authdebug( const char *ofmt, const char *fmt, va_list ap );
18 
19 /*
20 ** 0 - dont debug
21 ** 1 - debug auth
22 ** 2 - debug auth + write out passwords
23 */
24 
25 int courier_authdebug_login_level = 0;
26 
27 /*
28 ** purpose: initialize debugging
29 ** function: read environment variable DEBUG_LOGIN
30 **           and set up debugging according to it
31 ** args: none
32 */
33 
courier_authdebug_login_init(void)34 void courier_authdebug_login_init( void )
35 {
36 	const char *p=getenv(DEBUG_LOGIN_ENV);
37 
38 	courier_authdebug_login_level = atoi( p ? p:"0" );
39 }
40 
41 /*
42 ** purpose: print debug message to logger
43 ** does nothing if debug level is zero
44 ** adds prefix "DEBUG: " and suffix "\n"
45 ** Since we have a return value, we can use the convenient production
46 **	courier_authdebug_login_level && courier_authdebug_printf(...)
47 ** (as a macro, saves function calls when debugging is disabled)
48 */
49 
courier_authdebug_printf(const char * fmt,...)50 int courier_authdebug_printf( const char *fmt, ... ) {
51 
52 	va_list ap;
53 	int rc;
54 
55 	if (courier_authdebug_login_level == 0) return 0;
56 	va_start( ap, fmt );
57 	rc = courier_authdebug( "DEBUG: %s\n", fmt, ap );
58 	va_end( ap );
59 	return rc;
60 }
61 
62 /*
63  * Print a string to stderr, replacing any control characters with dot and
64  * limiting the total message size, followed by a newline
65  */
66 
courier_safe_printf(const char * fmt,...)67 int courier_safe_printf(const char *fmt, ...)
68 {
69 	va_list ap;
70 	int rc;
71 
72 	va_start( ap, fmt );
73 	rc = courier_authdebug( "%s\n", fmt, ap );
74 	va_end( ap );
75 	return rc;
76 }
77 
78 /** Print error log message **/
79 
courier_auth_err(const char * fmt,...)80 int courier_auth_err( const char *fmt, ... ) {
81 
82 	va_list ap;
83 	int rc;
84 
85 	va_start( ap, fmt );
86 	rc = courier_authdebug( "ERR: %s\n", fmt, ap );
87 	va_end( ap );
88 	return rc;
89 }
90 
91 /*
92 ** purpose: print debug messages to logger - handy use
93 ** function: take message with logging level and drop
94 **           messages with too high level.
95 **           also include into the message the IP address
96 ** args:
97 ** * level - level to be compared with DEBUG_LOGIN env var.
98 ** * fmt - message format as like in printf().
99 ** * ... - and "arguments" for fmt
100 */
101 
courier_authdebug_login(int level,const char * fmt,...)102 void courier_authdebug_login( int level, const char *fmt, ... ) {
103 
104 	va_list ap;
105 	char ofmt[128];
106 
107 	/* logging severity */
108 
109 	if( level > courier_authdebug_login_level )
110 		return;
111 
112 	snprintf( ofmt, sizeof ofmt, "DEBUG: LOGIN: ip=[%s], %%s\n", getenv("TCPREMOTEIP") );
113 	va_start( ap, fmt );
114 	courier_authdebug( ofmt, fmt, ap );
115 	va_end( ap );
116 }
117 
118 /*
119 ** purpose: print debug messages to logger - general use
120 ** function: read format string and arguments
121 **           and convert them to suitable form for output.
122 ** args:
123 ** ofmt- printf() format string for output, where %s = the assembled text
124 ** fmt - printf() format string for arguments
125 ** ... - variable arguments
126 */
127 
courier_authdebug(const char * ofmt,const char * fmt,va_list ap)128 static int courier_authdebug( const char *ofmt, const char *fmt, va_list ap )
129 {
130 
131 	char	buf[DEBUG_MESSAGE_SIZE];
132 	int	i;
133 	int	len;
134 
135 	/* print into buffer to be able to replace control and other unwanted chars. */
136 	vsnprintf( buf, DEBUG_MESSAGE_SIZE, fmt, ap );
137 	len = strlen( buf );
138 
139 	/* replace nonprintable chars by dot */
140 	for( i=0 ; i<len ; i++ )
141 		if( !isprint(buf[i]) )
142 			buf[i] = '.';
143 
144 	/* emit it */
145 
146 	return fprintf( stderr, ofmt , buf );
147 }
148 
149 /*
150  * Print the information retrieved from the database into struct authinfo.
151  *
152  * The structure members 'clearpasswd' and 'passwd' are not always set at
153  * the point where this function is called, so we take separate values
154  * for these
155  */
156 
courier_authdebug_authinfo(const char * pfx,const struct authinfo * auth,const char * clearpasswd,const char * passwd)157 int courier_authdebug_authinfo(const char *pfx, const struct authinfo *auth,
158 	const char *clearpasswd, const char *passwd)
159 {
160 	char uidstr[32] = "<null>";
161 
162 	if (!courier_authdebug_login_level) return 0;
163 
164 	if (auth->sysuserid)
165 		snprintf(uidstr, sizeof uidstr, "%ld", (long)*auth->sysuserid);
166 	fprintf(stderr, "%ssysusername=%s, sysuserid=%s, "
167 		"sysgroupid=%ld, homedir=%s, address=%s, fullname=%s, "
168 		"maildir=%s, quota=%s, options=%s\n", pfx,
169 		auth->sysusername ? auth->sysusername : "<null>",
170 		uidstr, (long)auth->sysgroupid,
171 		auth->homedir ? auth->homedir : "<null>",
172 		auth->address ? auth->address : "<null>",
173 		auth->fullname ? auth->fullname : "<null>",
174 		auth->maildir ? auth->maildir : "<null>",
175 		auth->quota ? auth->quota : "<null>",
176 		auth->options ? auth->options : "<null>");
177 	if (courier_authdebug_login_level >= 2)
178 		fprintf(stderr, "%sclearpasswd=%s, passwd=%s\n", pfx,
179 			clearpasswd ? clearpasswd : "<null>",
180 			passwd ? passwd : "<null>");
181 	return 0;
182 }
183 
184