1 /**
2  * \file util.c
3  * \brief Util functions for string management
4  *
5  * \author Fernando J. Pereda <ferdy@ferdyx.org>
6  * \author Ricardo Cervera Navarro <ricardo@zonasiete.org>
7  *
8  * This is part of nbsmtp. nbsmtp is free software;
9  * you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * nbsmtp is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with nbsmtp; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * See COPYING for details.
24  */
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <syslog.h>
28 #include <time.h>
29 #include <string.h>
30 #include <stdarg.h>
31 #include "util.h"
32 
33 /**
34  * \brief Wheter we should accept LOG_DEBUG messages or not. If debug = 2 we will print all
35  * messages to stdout
36  */
37 int debug = 0;
38 
39 /**
40  * \brief Increases memory for a string_t
41  *
42  * \param[in,out]	buffer	Pointer to string_t
43  * \param[in]		incr	Number of bytes (chars) to increment buffer size
44  */
str_incr_space(string_t * buffer,int incr)45 void str_incr_space(string_t *buffer, int incr)
46 {
47 	int i = buffer->len;
48 	buffer->str = realloc(buffer->str, buffer->len+(incr*sizeof(char)));
49 	buffer->len += incr;
50 
51 	for (; i < buffer->len; i++ )
52 	{
53 		buffer->str[i] = 0;
54 	}
55 }
56 
57 /**
58  * \brief Frees a string_t element
59  *
60  * \param[out] buffer Pointer to string_t
61  */
str_free(string_t * buffer)62 void str_free(string_t *buffer)
63 {
64 	if (buffer->len > 0)
65 	{
66 		free(buffer->str);
67 		buffer->len = 0;
68 	}
69 }
70 
71 /**
72  * \brief Initialize a string_t element
73  *
74  * \param[out]	buffer	Pointer to string_t
75  * \param[in]	size	Num of chars that will be reserved
76  */
str_init(string_t * buffer,int size)77 void str_init(string_t *buffer, int size)
78 {
79 	buffer->str = malloc((size+1)*sizeof(char));
80 	buffer->len = size;
81 }
82 
83 /**
84  * \brief Generates a date with the RFC822 (ARPA Internet Text) format
85  *
86  * \param[out] buf Where to store the string
87  */
arpadate(char * buf)88 void arpadate(char *buf)
89 {
90 	struct tm *date;
91 	time_t now;
92 	const char *const format = "%a, %e %b %Y %H:%M:%S %z (%Z)";
93 
94 	now = time(NULL);
95 
96 	date = localtime((const time_t *)&now);
97 	strftime(buf,40,format,date);
98 }
99 
100 /**
101  * \brief Logs a message to syslog, checks for debug if the priority is LOG_DEBUG
102  *
103  * \param[in] priority	An int with the message priority (LOG_INFO,LOG_DEBUG,LOG_ERR...)
104  * \param[in] format	A pointer to the message format
105  * \param[in] ...	Variable list.
106  */
log_msg(int priority,char * format,...)107 void log_msg(int priority, char *format, ...)
108 {
109 	static int mask_next = 0;
110 	char buffer[BUFSIZ];
111 	char *p;
112 	va_list list;
113 
114 	/*
115 	 * If we are receiving a LOG_DEBUG message, we check for debug
116 	 * to write it.
117 	 */
118 	if ((priority==LOG_DEBUG) && (debug==0))
119 	{
120 		return;
121 	}
122 
123 	/*
124 	 * Copy in buffer the result of parsing format with list
125 	 * up to BUFSIZ bytes
126 	 */
127 	va_start(list,format);
128 	vsnprintf(buffer,BUFSIZ,format,list);
129 	va_end(list);
130 
131 	/*
132 	 * Strip \r and \n so we don't mess syslog
133 	 */
134 	if ((p = strchr(buffer,'\r')) != NULL)
135 	{
136 		*p = '\0';
137 	}
138 
139 	if ((p = strchr(buffer,'\n')) != NULL)
140 	{
141 		*p = '\0';
142 	}
143 
144 	/*
145 	 * Remove passwords (they are only sent with debug>0)
146 	 */
147 	if (debug>0 && debug<3)
148 	{
149 		if (mask_next==1)
150 		{
151 			p = NULL;
152 
153 			if (buffer[2]=='>')
154 			{
155 				/* Skip the ' ' */
156 				p = strchr(buffer,' ')+1;
157 				mask_next = 0;
158 			}
159 		}
160 		else if ((p = strstr(buffer,"AUTH PLAIN ")) != NULL)
161 		{
162 			p += strlen("AUTH PLAIN ");
163 		}
164 		else if ((p = strstr(buffer,"AUTH LOGIN ")) != NULL)
165 		{
166 			p += strlen("AUTH LOGIN ");
167 			mask_next = 1;
168 		}
169 		else
170 		{
171 			p = NULL;
172 		}
173 
174 		if (p!=NULL)
175 		{
176 			int k;
177 
178 			for ( k = 0 ; k < 10 && *p ; k++ , p++ )
179 			{
180 				*p='X';
181 			}
182 
183 			*p = (char)NULL;
184 		}
185 	}
186 
187 	if (debug==0 || debug==1)
188 	{
189 		openlog("nbSMTP", LOG_PID, LOG_MAIL);
190 		syslog(priority,"%s",buffer);
191 		closelog();
192 	}
193 	else /* if (debug==2) */
194 	{
195 		fprintf(stderr,"%s\n",buffer);
196 	}
197 }
198 
199 /**
200  * \brief Prints an usage string
201  *
202  * \param[in] prog A pointer to argv[0]
203  */
print_usage(char * prog)204 void print_usage(char *prog)
205 {
206 	printf("Usage: %s -f from@address.com -h relayhost [OPTIONS] (use -H for help)\n",prog);
207 }
208 
209 /**
210  * \brief Prints information on how to use nbsmtp and some Copyright info.
211  *
212  * \param[in] prog A pointer to argv[0]
213  */
print_help(char * prog)214 void print_help(char *prog)
215 {
216 	int i = 0;
217 
218 	printf("nbSMTP %s\n\n",PACKAGE_VERSION);
219 
220 	printf("Features compiled-in: ");
221 
222 	puts(""
223 #ifdef HAVE_SSL
224 			"SSL "
225 #endif
226 #ifdef HAVE_INET6
227 			"IPv6 "
228 #endif
229 #ifdef HAVE_DEBUG
230 			"DEBUG "
231 #endif
232 #ifdef HAVE_OSX
233 			"OSX "
234 #endif
235 	      );
236 
237 	putchar('\n');
238 
239 	printf("nbSMTP comes with ABSOLUTELY NO WARRANTY\n\n");
240 
241 	do
242 	{
243 		printf("%s\n",authors[i]);
244 	} while (authors[++i]);
245 
246 	print_usage(prog);
247 	printf("  -d\tdomain to send in HELO request\n");
248 	printf("  -f\temail address to send in MAIL FROM request\n");
249 	printf("  -h\thost to relay mail to\n");
250 	printf("  -p\tport to connect to\n");
251 #ifdef HAVE_SSL
252 	printf("  -s\tuse SSL to transfer mail\n");
253 	printf("  -S\tuse STARTTLS to connect to server\n");
254 #endif
255 	printf("  -U\tSASL user\n");
256 	printf("  -P\tSASL password\n");
257 	printf("  -M\t{l,p} SASL mechanism to use: l - login (default) , p - plain\n");
258 	printf("  -D\tenable debug to syslog (LOG_DEBUG)\n");
259 	printf("  -N\tdo not read system-wide config file\n");
260 	printf("  -n\tdo not read local config file\n");
261 	printf("  -V\tlog to stderr instead of using syslog (implies -D)\n");
262 	printf("  -v\tprint version and exit\n");
263 	printf("  -c\tuse an additional config file\n");
264 	printf("  -H\tthis help message\n");
265 
266 	printf("\nSend bug reports and comments to <%s>.\n\n",PACKAGE_BUGREPORT);
267 }
268