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 48extern char *program_invocation_short_name; 49 50typedef enum 51{ 52 SDP_LOG_FILE, 53 SDP_LOG_SYSLOG, 54} __sdp_log_type_t; 55 56/* --------------------------------------------------------------------- */ 57/* library static and global variables */ 58/* --------------------------------------------------------------------- */ 59int __sdp_min_level = 9; 60static __sdp_log_type_t __sdp_log_type = SDP_LOG_FILE; 61static FILE *__sdp_log_file = NULL; 62 63void 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 112int 113__sdp_log_get_level( 114 void ) 115{ 116 return ( __sdp_min_level ); 117} 118 119void 120__sdp_log_set_min_level( 121 int level ) 122{ 123 __sdp_min_level = level; 124} 125 126static void 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 138int 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 148int 149__sdp_log_set_log_syslog( 150 void ) 151{ 152 __sdp_log_set_log_type( SDP_LOG_SYSLOG ); 153 154 return 1; 155} 156 157int 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