scd: Fix possible NULL deref in apdu.c
[gnupg.git] / common / miscellaneous.c
1 /* miscellaneous.c - Stuff not fitting elsewhere
2  *      Copyright (C) 2003, 2006 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include <stdlib.h>
22 #include <errno.h>
23
24 #define JNLIB_NEED_LOG_LOGV
25 #include "util.h"
26 #include "iobuf.h"
27 #include "i18n.h"
28
29
30 /* Used by libgcrypt for logging.  */
31 static void
32 my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr)
33 {
34   (void)dummy;
35   
36   /* Map the log levels.  */
37   switch (level)
38     {
39     case GCRY_LOG_CONT: level = JNLIB_LOG_CONT; break;
40     case GCRY_LOG_INFO: level = JNLIB_LOG_INFO; break;
41     case GCRY_LOG_WARN: level = JNLIB_LOG_WARN; break;
42     case GCRY_LOG_ERROR:level = JNLIB_LOG_ERROR; break;
43     case GCRY_LOG_FATAL:level = JNLIB_LOG_FATAL; break;
44     case GCRY_LOG_BUG:  level = JNLIB_LOG_BUG; break;
45     case GCRY_LOG_DEBUG:level = JNLIB_LOG_DEBUG; break;
46     default:            level = JNLIB_LOG_ERROR; break;  
47     }
48   log_logv (level, fmt, arg_ptr);
49 }
50
51
52 /* This function is called by libgcrypt on a fatal error.  */
53 static void
54 my_gcry_fatalerror_handler (void *opaque, int rc, const char *text)
55 {
56   (void)opaque;
57
58   log_fatal ("libgcrypt problem: %s\n", text ? text : gpg_strerror (rc));
59   abort ();
60 }
61
62
63 /* This function is called by libgcrypt if it ran out of core and
64    there is no way to return that error to the caller.  We do our own
65    function here to make use of our logging functions. */
66 static int
67 my_gcry_outofcore_handler (void *opaque, size_t req_n, unsigned int flags)
68 {
69   static int been_here;  /* Used to protect against recursive calls. */
70
71   (void)opaque;
72
73   if (!been_here)
74     {
75       been_here = 1;
76       if ( (flags & 1) )
77         log_fatal (_("out of core in secure memory "
78                      "while allocating %lu bytes"), (unsigned long)req_n);
79       else
80         log_fatal (_("out of core while allocating %lu bytes"),
81                    (unsigned long)req_n);
82     }
83   return 0; /* Let libgcrypt call its own fatal error handler.
84                Actually this will turn out to be
85                my_gcry_fatalerror_handler. */
86 }
87
88
89 /* Setup libgcrypt to use our own logging functions.  Should be used
90    early at startup. */
91 void
92 setup_libgcrypt_logging (void)
93 {
94   gcry_set_log_handler (my_gcry_logger, NULL);
95   gcry_set_fatalerror_handler (my_gcry_fatalerror_handler, NULL);
96   gcry_set_outofcore_handler (my_gcry_outofcore_handler, NULL);
97 }
98
99
100
101 /* Decide whether the filename is stdout or a real filename and return
102  * an appropriate string.  */
103 const char *
104 print_fname_stdout (const char *s)
105 {
106     if( !s || (*s == '-' && !s[1]) )
107         return "[stdout]";
108     return s;
109 }
110
111
112 /* Decide whether the filename is stdin or a real filename and return
113  * an appropriate string.  */
114 const char *
115 print_fname_stdin (const char *s)
116 {
117     if( !s || (*s == '-' && !s[1]) )
118         return "[stdin]";
119     return s;
120 }
121
122 /* fixme: Globally replace it by print_sanitized_buffer. */
123 void
124 print_string( FILE *fp, const byte *p, size_t n, int delim )
125 {
126   print_sanitized_buffer (fp, p, n, delim);
127 }
128
129 void
130 print_utf8_string2 ( FILE *fp, const byte *p, size_t n, int delim )
131 {
132   print_sanitized_utf8_buffer (fp, p, n, delim);
133 }
134
135 void
136 print_utf8_string( FILE *fp, const byte *p, size_t n )
137 {
138     print_utf8_string2 (fp, p, n, 0);
139 }
140
141 /* Write LENGTH bytes of BUFFER to FP as a hex encoded string.
142    RESERVED must be 0. */
143 void
144 print_hexstring (FILE *fp, const void *buffer, size_t length, int reserved)
145 {
146 #define tohex(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'A'))
147   const unsigned char *s;
148
149   (void)reserved;
150
151   for (s = buffer; length; s++, length--)
152     {
153       putc ( tohex ((*s>>4)&15), fp);
154       putc ( tohex (*s&15), fp);
155     }
156 #undef tohex
157 }
158
159 char *
160 make_printable_string (const void *p, size_t n, int delim )
161 {
162   return sanitize_buffer (p, n, delim);
163 }
164
165
166
167 /*
168  * Check if the file is compressed.
169  */
170 int
171 is_file_compressed (const char *s, int *ret_rc)
172 {
173     iobuf_t a;
174     byte buf[4];
175     int i, rc = 0;
176     int overflow;
177
178     struct magic_compress_s {
179         size_t len;
180         byte magic[4];
181     } magic[] = {
182         { 3, { 0x42, 0x5a, 0x68, 0x00 } }, /* bzip2 */
183         { 3, { 0x1f, 0x8b, 0x08, 0x00 } }, /* gzip */
184         { 4, { 0x50, 0x4b, 0x03, 0x04 } }, /* (pk)zip */
185     };
186     
187     if ( iobuf_is_pipe_filename (s) || !ret_rc )
188         return 0; /* We can't check stdin or no file was given */
189
190     a = iobuf_open( s );
191     if ( a == NULL ) {
192         *ret_rc = gpg_error_from_syserror ();
193         return 0;
194     }
195
196     if ( iobuf_get_filelength( a, &overflow ) < 4 && !overflow) {
197         *ret_rc = 0;
198         goto leave;
199     }
200
201     if ( iobuf_read( a, buf, 4 ) == -1 ) {
202         *ret_rc = a->error;
203         goto leave;
204     }
205
206     for ( i = 0; i < DIM( magic ); i++ ) {
207         if ( !memcmp( buf, magic[i].magic, magic[i].len ) ) {
208             *ret_rc = 0;
209             rc = 1;
210             break;
211         }
212     }
213
214 leave:    
215     iobuf_close( a );
216     return rc;
217 }
218
219
220 /* Try match against each substring of multistr, delimited by | */
221 int
222 match_multistr (const char *multistr,const char *match)
223 {
224   do
225     {
226       size_t seglen = strcspn (multistr,"|");
227       if (!seglen)
228         break;
229       /* Using the localized strncasecmp! */
230       if (strncasecmp(multistr,match,seglen)==0)
231         return 1;
232       multistr += seglen;
233       if (*multistr == '|')
234         multistr++;
235     }
236   while (*multistr);
237
238   return 0;
239 }
240
241