1 /*
2 This software is available to you under a choice of one of two
3 licenses. You may choose to be licensed under the terms of the GNU
4 General Public License (GPL) Version 2, available at
5 <http://www.fsf.org/copyleft/gpl.html>, or the OpenIB.org BSD
6 license, available in the LICENSE.TXT file accompanying this
7 software. These details are also available at
8 <http://openib.org/license.html>.
9
10 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
11 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
13 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
14 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
15 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17 SOFTWARE.
18
19 Copyright (c) 2004 Topspin Communications. All rights reserved.
20 Copyright (c) 2006 Mellanox Technologies Ltd. All rights reserved.
21
22 $Id$
23 */
24
25 /*
26 * system includes
27 */
28 #if HAVE_CONFIG_H
29 # include <config.h>
30 #endif /* HAVE_CONFIG_H */
31 #include <unistd.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <errno.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <stdarg.h>
38 #include <string.h>
39 #include <syslog.h>
40 #include <time.h>
41 #include <limits.h>
42
43 /*
44 * SDP specific includes
45 */
46 #include "libsdp.h"
47
48 extern char *program_invocation_short_name;
49
50 typedef enum
51 {
52 SDP_LOG_FILE,
53 SDP_LOG_SYSLOG,
54 } __sdp_log_type_t;
55
56 /* --------------------------------------------------------------------- */
57 /* library static and global variables */
58 /* --------------------------------------------------------------------- */
59 int __sdp_min_level = 9;
60 static __sdp_log_type_t __sdp_log_type = SDP_LOG_FILE;
61 static FILE *__sdp_log_file = NULL;
62
63 void
__sdp_log(int level,char * format,...)64 __sdp_log(
65 int level,
66 char *format,
67 ... )
68 {
69 va_list ap;
70 char extra_format[512];
71 time_t timeval;
72 char timestr[32];
73
74 if ( level < __sdp_min_level ) {
75 return;
76 }
77
78 va_start( ap, format );
79 switch ( __sdp_log_type ) {
80 case SDP_LOG_SYSLOG:
81 sprintf( extra_format, "%s[%d] libsdp %s ",
82 program_invocation_short_name, getpid( ), format );
83 vsyslog( LOG_USER | LOG_NOTICE, extra_format, ap );
84 break;
85 case SDP_LOG_FILE:
86 timeval = time(NULL);
87 #ifdef SOLARIS_BUILD
88 ctime_r(&timeval, timestr, sizeof timestr);
89 #else
90 ctime_r(&timeval, timestr);
91 #endif
92 timestr[strlen(timestr)-1] = '\0';
93 sprintf( extra_format, "%s %s[%d] libsdp %s ",
94 timestr, program_invocation_short_name,
95 getpid( ), format );
96 if ( __sdp_log_file == NULL ) {
97 vfprintf( stderr, extra_format, ap );
98 #if 0 /* might slow everything too much? */
99 ( void )fflush( stderr );
100 #endif
101 } else {
102 vfprintf( __sdp_log_file, extra_format, ap );
103 #if 0 /* might slow everything too much? */
104 ( void )fflush( __sdp_log_file );
105 #endif
106 }
107 break;
108 }
109 va_end( ap );
110 }
111
112 int
__sdp_log_get_level(void)113 __sdp_log_get_level(
114 void )
115 {
116 return ( __sdp_min_level );
117 }
118
119 void
__sdp_log_set_min_level(int level)120 __sdp_log_set_min_level(
121 int level )
122 {
123 __sdp_min_level = level;
124 }
125
126 static void
__sdp_log_set_log_type(__sdp_log_type_t type)127 __sdp_log_set_log_type(
128 __sdp_log_type_t type )
129 {
130 if ( __sdp_log_file != NULL ) {
131 fclose( __sdp_log_file );
132 __sdp_log_file = NULL;
133 }
134
135 __sdp_log_type = type;
136 }
137
138 int
__sdp_log_set_log_stderr(void)139 __sdp_log_set_log_stderr(
140 void )
141 {
142 __sdp_log_set_log_type( SDP_LOG_FILE );
143 /* NULL means stderr */
144
145 return 1;
146 }
147
148 int
__sdp_log_set_log_syslog(void)149 __sdp_log_set_log_syslog(
150 void )
151 {
152 __sdp_log_set_log_type( SDP_LOG_SYSLOG );
153
154 return 1;
155 }
156
157 int
__sdp_log_set_log_file(char * filename)158 __sdp_log_set_log_file(
159 char *filename )
160 {
161 FILE *f;
162 uid_t uid;
163 struct stat lstat_res;
164 int status;
165
166 char *p, tfilename[PATH_MAX + 1];
167
168 /* Strip off any paths from the filename */
169 p = strrchr( filename, '/' );
170
171 /*
172 base on the active user ID we either use /var/log for root or
173 append the uid to the name
174 */
175 uid = geteuid();
176 if (uid == 0) {
177 if ( p )
178 filename = p + 1;
179 snprintf( tfilename, sizeof(tfilename), "/var/log/%s", filename );
180 } else {
181 char tdir[PATH_MAX + 1];
182 /*
183 for regular user, allow log file to be placed in a user
184 requested path. If no path is requested the log file is
185 placed in /tmp/
186 */
187 if ( p )
188 snprintf(tdir, sizeof(tdir), "%s.%d", filename, uid );
189 else
190 snprintf(tdir, sizeof(tdir ), "/tmp/%s.%d", filename, uid );
191
192 if (mkdir(tdir, 0700)) {
193 struct stat stat;
194
195 if (errno != EEXIST) {
196 __sdp_log( 9, "Couldn't create directory '%s' for logging (%m)\n", tdir );
197 return 0;
198 }
199
200 if (lstat(tdir, &stat)) {
201 __sdp_log(9, "Couldn't lstat directory %s\n", tdir);
202 return 0;
203 }
204
205 if (!S_ISDIR(stat.st_mode) || stat.st_uid != uid ||
206 (stat.st_mode & ~(S_IFMT | S_IRWXU))) {
207 __sdp_log( 9, "Cowardly refusing to log into directory:'%s'. "
208 "Make sure it is not: (1) link, (2) other uid, (3) bad permissions."
209 "thus is a security issue.\n", tdir );
210 return 0;
211 }
212 }
213
214 snprintf(tfilename, sizeof(tfilename), "%s/log", tdir);
215 printf("dir: %s file: %s\n", tdir, tfilename);
216 }
217
218 /* double check the file is not a link */
219 status = lstat(tfilename, &lstat_res);
220 if ( (status == 0) && S_ISLNK(lstat_res.st_mode) ) {
221 __sdp_log( 9, "Cowardly refusing to log into:'%s'. "
222 "It is a link - thus is a security issue.\n", tfilename );
223 return 0;
224 }
225
226 f = fopen( tfilename, "a" );
227 if ( !f ) {
228 __sdp_log( 9, "Couldn't open '%s' for logging (%m)\n", tfilename );
229 return 0;
230 }
231
232 __sdp_log_set_log_type( SDP_LOG_FILE );
233 __sdp_log_file = f;
234
235 return 1;
236 }
237