Upgrade to libtasn1 4.19.0
[platform/upstream/libtasn1.git] / src / asn1Coding.c
1 /* asn1Coding.c --- program to generate a DER coding of an ASN1 definition.
2  * Copyright (C) 2002-2022 Free Software Foundation, Inc.
3  *
4  * This file is part of LIBTASN1.
5  *
6  * This program 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  * This program 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
21 #include <config.h>
22
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <getopt.h>
28 #include <assert.h>
29
30 #include <libtasn1.h>
31
32 #include "progname.h"
33 #include "version-etc.h"
34
35 /* This feature is available in gcc versions 2.5 and later.  */
36 #if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
37 # define ATTR_NO_RETRUN
38 #else
39 # define ATTR_NO_RETRUN __attribute__ ((__noreturn__))
40 #endif
41
42 ATTR_NO_RETRUN static void
43 usage (int status)
44 {
45   if (status != EXIT_SUCCESS)
46     fprintf (stderr, "Try `%s --help' for more information.\n", program_name);
47   else
48     {
49       printf ("\
50 Usage: %s [OPTION] DEFINITIONS ASSIGNMENTS\n", program_name);
51       printf ("\
52 Generates a DER encoding of ASN.1 DEFINITIONS file\n\
53 and ASSIGNMENTS file with value assignments.\n\
54 \n");
55       printf ("\
56 Mandatory arguments to long options are mandatory for short options too.\n\
57   -c, --check           checks the syntax only\n\
58   -o, --output=FILE     output file\n\
59   -h, --help            display this help and exit\n\
60   -v, --version         output version information and exit\n");
61       emit_bug_reporting_address ();
62     }
63   exit (status);
64 }
65
66 #define ASSIGNMENT_SUCCESS 1
67 #define ASSIGNMENT_ERROR   2
68 #define ASSIGNMENT_EOF     3
69
70 static int
71 readAssignment (FILE * file, char *varName, char *value)
72 {
73
74   int ret;
75
76   ret = fscanf (file, "%1023s", varName);
77   if (ret == EOF)
78     return ASSIGNMENT_EOF;
79   if (!strcmp (varName, "''"))
80     varName[0] = 0;
81
82   ret = fscanf (file, "%1023s", value);
83   if (ret == EOF)
84     return ASSIGNMENT_ERROR;
85
86   return ASSIGNMENT_SUCCESS;
87 }
88
89 static void
90 createFileName (char *inputFileName, char **outputFileName)
91 {
92   char *char_p, *slash_p, *dot_p;
93
94   /* searching the last '/' and '.' in inputFileAssignmentName */
95   char_p = inputFileName;
96   slash_p = inputFileName;
97   while ((char_p = strchr (char_p, '/')))
98     {
99       char_p++;
100       slash_p = char_p;
101     }
102
103   char_p = slash_p;
104   dot_p = inputFileName + strlen (inputFileName);
105
106   while ((char_p = strchr (char_p, '.')))
107     {
108       dot_p = char_p;
109       char_p++;
110     }
111
112   /* outputFileName= inputFileName + .out */
113   *outputFileName = (char *) malloc (dot_p - inputFileName + 1 +
114                                      strlen (".out"));
115   if (*outputFileName == NULL)
116     {
117       fprintf (stderr, "Memory error\n");
118       exit (1);
119     }
120
121   memcpy (*outputFileName, inputFileName, dot_p - inputFileName);
122   (*outputFileName)[dot_p - inputFileName] = 0;
123   strcat (*outputFileName, ".out");
124   return;
125 }
126
127 int
128 main (int argc, char *argv[])
129 {
130   static const struct option long_options[] = {
131     {"help", no_argument, 0, 'h'},
132     {"version", no_argument, 0, 'v'},
133     {"check", no_argument, 0, 'c'},
134     {"output", required_argument, 0, 'o'},
135     {0, 0, 0, 0}
136   };
137   int option_index = 0;
138   int option_result;
139   char *outputFileName = NULL;
140   char *inputFileAsnName = NULL;
141   char *inputFileAssignmentName = NULL;
142   int checkSyntaxOnly = 0;
143   asn1_node definitions = NULL;
144   asn1_node structure = NULL;
145   char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
146   int asn1_result = ASN1_SUCCESS;
147   FILE *outputFile;
148   FILE *inputFile;
149   char varName[1024];
150   char value[1024];
151   unsigned char *der = NULL;
152   int der_len;
153   int k;
154   int last_ra;
155
156   set_program_name (argv[0]);
157
158   opterr = 0;                   /* disable error messages from getopt */
159
160   while (1)
161     {
162
163       option_result =
164         getopt_long (argc, argv, "hvco:", long_options, &option_index);
165
166       if (option_result == -1)
167         break;
168
169       switch (option_result)
170         {
171         case 'h':               /* HELP */
172           free (outputFileName);
173           usage (EXIT_SUCCESS);
174           break;
175         case 'v':               /* VERSION */
176           version_etc (stdout, program_name, PACKAGE, VERSION,
177                        "Fabio Fiorina", NULL);
178           free (outputFileName);
179           exit (0);
180           break;
181         case 'c':               /* CHECK SYNTAX */
182           checkSyntaxOnly = 1;
183           break;
184         case 'o':               /* OUTPUT */
185           assert (optarg != NULL);
186           outputFileName = strdup (optarg);
187           if (outputFileName == NULL)
188             {
189               fprintf (stderr, "Memory error\n");
190               exit (1);
191             }
192           break;
193         case '?':               /* UNKNOW OPTION */
194           free (outputFileName);
195           fprintf (stderr,
196                    "asn1Coding: option '%s' not recognized or without argument.\n\n",
197                    argv[optind - 1]);
198           usage (EXIT_FAILURE);
199           break;
200         default:
201           fprintf (stderr,
202                    "asn1Coding: ?? getopt returned character code Ox%x ??\n",
203                    (unsigned) option_result);
204         }
205     }
206
207   if (optind == argc || optind == argc - 1)
208     {
209       free (outputFileName);
210       fputs ("asn1Coding: input files missing\n", stderr);
211       usage (EXIT_FAILURE);
212     }
213
214   inputFileAsnName = strdup (argv[optind]);
215   if (inputFileAsnName == NULL)
216     {
217       fprintf (stderr, "Memory error\n");
218       exit (1);
219     }
220
221   inputFileAssignmentName = strdup (argv[optind + 1]);
222   if (inputFileAssignmentName == NULL)
223     {
224       fprintf (stderr, "Memory error\n");
225       exit (1);
226     }
227
228   asn1_result =
229     asn1_parser2tree (inputFileAsnName, &definitions, errorDescription);
230
231   switch (asn1_result)
232     {
233     case ASN1_SUCCESS:
234       fputs ("Parse: done.\n", stderr);
235       break;
236     case ASN1_FILE_NOT_FOUND:
237       fprintf (stderr, "asn1Coding: FILE %s NOT FOUND\n", inputFileAsnName);
238       break;
239     case ASN1_SYNTAX_ERROR:
240     case ASN1_IDENTIFIER_NOT_FOUND:
241     case ASN1_NAME_TOO_LONG:
242       fprintf (stderr, "asn1Coding: %s\n", errorDescription);
243       break;
244     default:
245       fprintf (stderr, "libtasn1 ERROR: %s\n", asn1_strerror (asn1_result));
246     }
247
248   if (asn1_result != ASN1_SUCCESS)
249     {
250       free (inputFileAsnName);
251       free (inputFileAssignmentName);
252       exit (1);
253     }
254
255
256   inputFile = fopen (inputFileAssignmentName, "r");
257
258   if (inputFile == NULL)
259     {
260       fprintf (stderr, "asn1Coding: file '%s' not found\n",
261                inputFileAssignmentName);
262       free (inputFileAsnName);
263       free (inputFileAssignmentName);
264       exit (1);
265     }
266
267
268   putc ('\n', stderr);
269
270   while ((last_ra = readAssignment (inputFile, varName, value))
271          == ASSIGNMENT_SUCCESS)
272     {
273       fprintf (stderr, "var=%s, value=%s\n", varName, value);
274       if (structure == NULL)
275         {
276           asn1_result = asn1_create_element (definitions, value, &structure);
277         }
278       else
279         {
280           if (strcmp (value, "(NULL)") == 0)
281             asn1_result = asn1_write_value (structure, varName, NULL, 0);
282           else
283             asn1_result = asn1_write_value (structure, varName, value, 0);
284         }
285
286       if (asn1_result != ASN1_SUCCESS)
287         {
288           fprintf (stderr, "libtasn1 ERROR: %s\n",
289                    asn1_strerror (asn1_result));
290
291           asn1_delete_structure (&definitions);
292           asn1_delete_structure (&structure);
293
294           free (inputFileAsnName);
295           free (inputFileAssignmentName);
296
297           fclose (inputFile);
298           exit (1);
299         }
300     }
301   if (last_ra != ASSIGNMENT_EOF)
302     {
303       fprintf (stderr, "asn1Coding: error reading assignment file\n");
304       exit (1);
305     }
306   fclose (inputFile);
307
308   putc ('\n', stderr);
309   asn1_print_structure (stderr, structure, "", ASN1_PRINT_NAME_TYPE_VALUE);
310
311   der_len = 0;
312   asn1_result = asn1_der_coding (structure, "", NULL, &der_len,
313                                  errorDescription);
314   if (asn1_result == ASN1_MEM_ERROR)
315     {
316       der = malloc (der_len);
317       if (der == NULL)
318         {
319           fprintf (stderr, "Memory error\n");
320           exit (1);
321         }
322       asn1_result = asn1_der_coding (structure, "", der, &der_len,
323                                      errorDescription);
324     }
325   fprintf (stderr, "\nCoding: %s\n\n", asn1_strerror (asn1_result));
326   if (asn1_result != ASN1_SUCCESS)
327     {
328       fprintf (stderr, "asn1Coding: %s\n", errorDescription);
329
330       free (der);
331
332       asn1_delete_structure (&definitions);
333       asn1_delete_structure (&structure);
334
335       free (inputFileAsnName);
336       free (inputFileAssignmentName);
337
338       exit (1);
339     }
340
341   /* Print the 'Certificate1' DER encoding */
342   fprintf (stderr, "-----------------\nNumber of bytes=%i\n", der_len);
343   for (k = 0; k < der_len; k++)
344     fprintf (stderr, "%02x ", der[k]);
345   fputs ("\n-----------------\n", stderr);
346
347   asn1_delete_structure (&definitions);
348   asn1_delete_structure (&structure);
349
350   if (!checkSyntaxOnly)
351     {
352       if (outputFileName == NULL)
353         createFileName (inputFileAssignmentName, &outputFileName);
354
355       fprintf (stderr, "\nOutputFile=%s\n", outputFileName);
356
357       outputFile = fopen (outputFileName, "w");
358
359       if (outputFile == NULL)
360         {
361           fprintf (stderr,
362                    "asn1Coding: output file '%s' not available\n",
363                    outputFileName);
364           free (der);
365           free (inputFileAsnName);
366           free (inputFileAssignmentName);
367           free (outputFileName);
368           exit (1);
369         }
370
371       for (k = 0; k < der_len; k++)
372         fprintf (outputFile, "%c", der[k]);
373       fclose (outputFile);
374       fputs ("\nWriting: done.\n", stderr);
375     }
376
377   free (der);
378
379   free (inputFileAsnName);
380   free (inputFileAssignmentName);
381   free (outputFileName);
382
383   exit (0);
384 }