1219820Sjeff/* 2219820Sjeff This software is available to you under a choice of one of two 3219820Sjeff licenses. You may choose to be licensed under the terms of the GNU 4219820Sjeff General Public License (GPL) Version 2, available at 5219820Sjeff <http://www.fsf.org/copyleft/gpl.html>, or the OpenIB.org BSD 6219820Sjeff license, available in the LICENSE.TXT file accompanying this 7219820Sjeff software. These details are also available at 8219820Sjeff <http://openib.org/license.html>. 9219820Sjeff 10219820Sjeff THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 11219820Sjeff EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 12219820Sjeff MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 13219820Sjeff NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 14219820Sjeff BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 15219820Sjeff ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 16219820Sjeff CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17219820Sjeff SOFTWARE. 18219820Sjeff 19219820Sjeff Copyright (c) 2004 Topspin Communications. All rights reserved. 20219820Sjeff Copyright (c) 2006 Mellanox Technologies Ltd. All rights reserved. 21219820Sjeff 22219820Sjeff $Id$ 23219820Sjeff*/ 24219820Sjeff 25219820Sjeff/* 26219820Sjeff * system includes 27219820Sjeff */ 28219820Sjeff#if HAVE_CONFIG_H 29219820Sjeff# include <config.h> 30219820Sjeff#endif /* HAVE_CONFIG_H */ 31219820Sjeff#include <unistd.h> 32219820Sjeff#include <sys/types.h> 33219820Sjeff#include <sys/stat.h> 34219820Sjeff#include <errno.h> 35219820Sjeff#include <stdio.h> 36219820Sjeff#include <stdlib.h> 37219820Sjeff#include <stdarg.h> 38219820Sjeff#include <string.h> 39219820Sjeff#include <syslog.h> 40219820Sjeff#include <time.h> 41219820Sjeff#include <limits.h> 42219820Sjeff 43219820Sjeff/* 44219820Sjeff * SDP specific includes 45219820Sjeff */ 46219820Sjeff#include "libsdp.h" 47219820Sjeff 48219820Sjeffextern char *program_invocation_short_name; 49219820Sjeff 50219820Sjefftypedef enum 51219820Sjeff{ 52219820Sjeff SDP_LOG_FILE, 53219820Sjeff SDP_LOG_SYSLOG, 54219820Sjeff} __sdp_log_type_t; 55219820Sjeff 56219820Sjeff/* --------------------------------------------------------------------- */ 57219820Sjeff/* library static and global variables */ 58219820Sjeff/* --------------------------------------------------------------------- */ 59219820Sjeffint __sdp_min_level = 9; 60219820Sjeffstatic __sdp_log_type_t __sdp_log_type = SDP_LOG_FILE; 61219820Sjeffstatic FILE *__sdp_log_file = NULL; 62219820Sjeff 63219820Sjeffvoid 64219820Sjeff__sdp_log( 65219820Sjeff int level, 66219820Sjeff char *format, 67219820Sjeff ... ) 68219820Sjeff{ 69219820Sjeff va_list ap; 70219820Sjeff char extra_format[512]; 71219820Sjeff time_t timeval; 72219820Sjeff char timestr[32]; 73219820Sjeff 74219820Sjeff if ( level < __sdp_min_level ) { 75219820Sjeff return; 76219820Sjeff } 77219820Sjeff 78219820Sjeff va_start( ap, format ); 79219820Sjeff switch ( __sdp_log_type ) { 80219820Sjeff case SDP_LOG_SYSLOG: 81219820Sjeff sprintf( extra_format, "%s[%d] libsdp %s ", 82219820Sjeff program_invocation_short_name, getpid( ), format ); 83219820Sjeff vsyslog( LOG_USER | LOG_NOTICE, extra_format, ap ); 84219820Sjeff break; 85219820Sjeff case SDP_LOG_FILE: 86219820Sjeff timeval = time(NULL); 87219820Sjeff#ifdef SOLARIS_BUILD 88219820Sjeff ctime_r(&timeval, timestr, sizeof timestr); 89219820Sjeff#else 90219820Sjeff ctime_r(&timeval, timestr); 91219820Sjeff#endif 92219820Sjeff timestr[strlen(timestr)-1] = '\0'; 93219820Sjeff sprintf( extra_format, "%s %s[%d] libsdp %s ", 94219820Sjeff timestr, program_invocation_short_name, 95219820Sjeff getpid( ), format ); 96219820Sjeff if ( __sdp_log_file == NULL ) { 97219820Sjeff vfprintf( stderr, extra_format, ap ); 98219820Sjeff#if 0 /* might slow everything too much? */ 99219820Sjeff ( void )fflush( stderr ); 100219820Sjeff#endif 101219820Sjeff } else { 102219820Sjeff vfprintf( __sdp_log_file, extra_format, ap ); 103219820Sjeff#if 0 /* might slow everything too much? */ 104219820Sjeff ( void )fflush( __sdp_log_file ); 105219820Sjeff#endif 106219820Sjeff } 107219820Sjeff break; 108219820Sjeff } 109219820Sjeff va_end( ap ); 110219820Sjeff} 111219820Sjeff 112219820Sjeffint 113219820Sjeff__sdp_log_get_level( 114219820Sjeff void ) 115219820Sjeff{ 116219820Sjeff return ( __sdp_min_level ); 117219820Sjeff} 118219820Sjeff 119219820Sjeffvoid 120219820Sjeff__sdp_log_set_min_level( 121219820Sjeff int level ) 122219820Sjeff{ 123219820Sjeff __sdp_min_level = level; 124219820Sjeff} 125219820Sjeff 126219820Sjeffstatic void 127219820Sjeff__sdp_log_set_log_type( 128219820Sjeff __sdp_log_type_t type ) 129219820Sjeff{ 130219820Sjeff if ( __sdp_log_file != NULL ) { 131219820Sjeff fclose( __sdp_log_file ); 132219820Sjeff __sdp_log_file = NULL; 133219820Sjeff } 134219820Sjeff 135219820Sjeff __sdp_log_type = type; 136219820Sjeff} 137219820Sjeff 138219820Sjeffint 139219820Sjeff__sdp_log_set_log_stderr( 140219820Sjeff void ) 141219820Sjeff{ 142219820Sjeff __sdp_log_set_log_type( SDP_LOG_FILE ); 143219820Sjeff /* NULL means stderr */ 144219820Sjeff 145219820Sjeff return 1; 146219820Sjeff} 147219820Sjeff 148219820Sjeffint 149219820Sjeff__sdp_log_set_log_syslog( 150219820Sjeff void ) 151219820Sjeff{ 152219820Sjeff __sdp_log_set_log_type( SDP_LOG_SYSLOG ); 153219820Sjeff 154219820Sjeff return 1; 155219820Sjeff} 156219820Sjeff 157219820Sjeffint 158219820Sjeff__sdp_log_set_log_file( 159219820Sjeff char *filename ) 160219820Sjeff{ 161219820Sjeff FILE *f; 162219820Sjeff uid_t uid; 163219820Sjeff struct stat lstat_res; 164219820Sjeff int status; 165219820Sjeff 166219820Sjeff char *p, tfilename[PATH_MAX + 1]; 167219820Sjeff 168219820Sjeff /* Strip off any paths from the filename */ 169219820Sjeff p = strrchr( filename, '/' ); 170219820Sjeff 171219820Sjeff /* 172219820Sjeff base on the active user ID we either use /var/log for root or 173219820Sjeff append the uid to the name 174219820Sjeff */ 175219820Sjeff uid = geteuid(); 176219820Sjeff if (uid == 0) { 177219820Sjeff if ( p ) 178219820Sjeff filename = p + 1; 179219820Sjeff snprintf( tfilename, sizeof(tfilename), "/var/log/%s", filename ); 180219820Sjeff } else { 181219820Sjeff char tdir[PATH_MAX + 1]; 182219820Sjeff /* 183219820Sjeff for regular user, allow log file to be placed in a user 184219820Sjeff requested path. If no path is requested the log file is 185219820Sjeff placed in /tmp/ 186219820Sjeff */ 187219820Sjeff if ( p ) 188219820Sjeff snprintf(tdir, sizeof(tdir), "%s.%d", filename, uid ); 189219820Sjeff else 190219820Sjeff snprintf(tdir, sizeof(tdir ), "/tmp/%s.%d", filename, uid ); 191219820Sjeff 192219820Sjeff if (mkdir(tdir, 0700)) { 193219820Sjeff struct stat stat; 194219820Sjeff 195219820Sjeff if (errno != EEXIST) { 196219820Sjeff __sdp_log( 9, "Couldn't create directory '%s' for logging (%m)\n", tdir ); 197219820Sjeff return 0; 198219820Sjeff } 199219820Sjeff 200219820Sjeff if (lstat(tdir, &stat)) { 201219820Sjeff __sdp_log(9, "Couldn't lstat directory %s\n", tdir); 202219820Sjeff return 0; 203219820Sjeff } 204219820Sjeff 205219820Sjeff if (!S_ISDIR(stat.st_mode) || stat.st_uid != uid || 206219820Sjeff (stat.st_mode & ~(S_IFMT | S_IRWXU))) { 207219820Sjeff __sdp_log( 9, "Cowardly refusing to log into directory:'%s'. " 208219820Sjeff "Make sure it is not: (1) link, (2) other uid, (3) bad permissions." 209219820Sjeff "thus is a security issue.\n", tdir ); 210219820Sjeff return 0; 211219820Sjeff } 212219820Sjeff } 213219820Sjeff 214219820Sjeff snprintf(tfilename, sizeof(tfilename), "%s/log", tdir); 215219820Sjeff printf("dir: %s file: %s\n", tdir, tfilename); 216219820Sjeff } 217219820Sjeff 218219820Sjeff /* double check the file is not a link */ 219219820Sjeff status = lstat(tfilename, &lstat_res); 220219820Sjeff if ( (status == 0) && S_ISLNK(lstat_res.st_mode) ) { 221219820Sjeff __sdp_log( 9, "Cowardly refusing to log into:'%s'. " 222219820Sjeff "It is a link - thus is a security issue.\n", tfilename ); 223219820Sjeff return 0; 224219820Sjeff } 225219820Sjeff 226219820Sjeff f = fopen( tfilename, "a" ); 227219820Sjeff if ( !f ) { 228219820Sjeff __sdp_log( 9, "Couldn't open '%s' for logging (%m)\n", tfilename ); 229219820Sjeff return 0; 230219820Sjeff } 231219820Sjeff 232219820Sjeff __sdp_log_set_log_type( SDP_LOG_FILE ); 233219820Sjeff __sdp_log_file = f; 234219820Sjeff 235219820Sjeff return 1; 236219820Sjeff} 237