* scdaemon.c, scdaemon.h: New option --pcsc-driver.
[gnupg.git] / scd / sc-investigate.c
1 /* sc-investigate.c - A tool to look around on smartcards.
2  *      Copyright (C) 2003 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 2 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, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27
28 #define JNLIB_NEED_LOG_LOGV
29 #include "scdaemon.h"
30 #include <gcrypt.h>
31
32 #include "apdu.h" /* for open_reader */
33 #include "atr.h"
34 #include "app-common.h"
35
36 #define _(a) (a)
37
38
39 enum cmd_and_opt_values 
40 { oVerbose        = 'v',
41   oReaderPort     = 500,
42   octapiDriver,
43   oDebug,
44   oDebugAll,
45
46   oGenRandom,
47
48 aTest };
49
50
51 static ARGPARSE_OPTS opts[] = {
52   
53   { 301, NULL, 0, "@Options:\n " },
54
55   { oVerbose, "verbose",   0, "verbose" },
56   { oReaderPort, "reader-port", 2, "|N|connect to reader at port N"},
57   { octapiDriver, "ctapi-driver", 2, "NAME|use NAME as ctAPI driver"},
58   { oDebug,     "debug"     ,4|16, "set debugging flags"},
59   { oDebugAll, "debug-all" ,0, "enable full debugging"},
60   { oGenRandom, "gen-random", 4, "|N|generate N bytes of random"},
61   {0}
62 };
63
64 static const char *
65 my_strusage (int level)
66 {
67   const char *p;
68   switch (level)
69     {
70     case 11: p = "sc-investigate (GnuPG)";
71       break;
72     case 13: p = VERSION; break;
73     case 17: p = PRINTABLE_OS_NAME; break;
74     case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n");
75       break;
76     case 1:
77     case 40: p =  _("Usage: sc-investigate [options] (-h for help)\n");
78       break;
79     case 41: p =  _("Syntax: sc-investigate [options] [args]]\n"
80                     "Have a look at smartcards\n");
81     break;
82     
83     default: p = NULL;
84     }
85   return p;
86 }
87
88 /* Used by gcry for logging */
89 static void
90 my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr)
91 {
92   /* translate the log levels */
93   switch (level)
94     {
95     case GCRY_LOG_CONT: level = JNLIB_LOG_CONT; break;
96     case GCRY_LOG_INFO: level = JNLIB_LOG_INFO; break;
97     case GCRY_LOG_WARN: level = JNLIB_LOG_WARN; break;
98     case GCRY_LOG_ERROR:level = JNLIB_LOG_ERROR; break;
99     case GCRY_LOG_FATAL:level = JNLIB_LOG_FATAL; break;
100     case GCRY_LOG_BUG:  level = JNLIB_LOG_BUG; break;
101     case GCRY_LOG_DEBUG:level = JNLIB_LOG_DEBUG; break;
102     default:            level = JNLIB_LOG_ERROR; break;  
103     }
104   log_logv (level, fmt, arg_ptr);
105 }
106
107
108 int
109 main (int argc, char **argv )
110 {
111   ARGPARSE_ARGS pargs;
112   int slot, rc;
113   const char *reader_port = NULL;
114   struct app_ctx_s appbuf;
115   unsigned long gen_random = 0;
116
117   memset (&appbuf, 0, sizeof appbuf);
118
119   set_strusage (my_strusage);
120   gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
121   log_set_prefix ("sc-investigate", 1); 
122
123   /* check that the libraries are suitable.  Do it here because
124      the option parsing may need services of the library */
125   if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) )
126     {
127       log_fatal( _("libgcrypt is too old (need %s, have %s)\n"),
128                  NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
129     }
130
131   gcry_set_log_handler (my_gcry_logger, NULL);
132   /* FIXME? gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);*/
133
134   pargs.argc = &argc;
135   pargs.argv = &argv;
136   pargs.flags=  1;  /* do not remove the args */
137   while (arg_parse (&pargs, opts) )
138     {
139       switch (pargs.r_opt)
140         {
141         case oVerbose: opt.verbose++; break;
142         case oDebug: opt.debug |= pargs.r.ret_ulong; break;
143         case oDebugAll: opt.debug = ~0; break;
144         case oReaderPort: reader_port = pargs.r.ret_str; break;
145         case octapiDriver: opt.ctapi_driver = pargs.r.ret_str; break;
146         case oGenRandom: gen_random = pargs.r.ret_ulong; break;
147         default : pargs.err = 2; break;
148         }
149     }
150   if (log_get_errorcount(0))
151     exit(2);
152
153   if (opt.verbose < 2)
154     opt.verbose = 2; /* hack to let select_openpgp print some info. */
155
156   if (argc)
157     usage (1);
158
159   slot = apdu_open_reader (reader_port);
160   if (slot == -1)
161     exit (1);
162   
163   if (!gen_random)
164     {
165       rc = atr_dump (slot, stdout); 
166       if (rc)
167         log_error ("can't dump ATR: %s\n", gpg_strerror (rc));
168     }
169
170   appbuf.slot = slot;
171   rc = app_select_openpgp (&appbuf, NULL, NULL);
172   if (rc)
173     log_error ("selecting openpgp failed: %s\n", gpg_strerror (rc));
174   else
175     {
176       appbuf.initialized = 1;
177       log_info ("openpgp application selected\n");
178
179       if (gen_random)
180         {
181           size_t nbytes;
182           unsigned char *buffer;
183           
184           buffer = xmalloc (4096);
185           do 
186             {
187               nbytes = gen_random > 4096? 4096 : gen_random;
188               rc = app_get_challenge (&appbuf, nbytes, buffer);
189               if (rc)
190                 log_error ("app_get_challenge failed: %s\n",gpg_strerror (rc));
191               else
192                 {
193                   if (fwrite (buffer, nbytes, 1, stdout) != 1)
194                     log_error ("writing to stdout failed: %s\n",
195                                strerror (errno));
196                   gen_random -= nbytes;
197                 }
198             }
199           while (gen_random && !log_get_errorcount (0));
200           xfree (buffer);
201         }
202     }
203
204   return log_get_errorcount (0)? 2:0;
205 }
206
207
208
209 void
210 send_status_info (CTRL ctrl, const char *keyword, ...)
211 {
212   /* DUMMY */
213 }