Subversion Repositories oidconverter

Rev

Rev 2 | Rev 7 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2 Rev 6
1
/*###################################################################
1
/*#################################################################################
2
###                                                               ###
2
###                                                                             ###
3
### Object ID converter. Matthias Gaertner, 06/1999               ###
3
### Object ID converter. Matthias Gaertner, 06/1999                             ###
4
### Converted to plain 'C' 07/2001                                ###
4
### Converted to plain 'C' 07/2001                                              ###
5
###                                                               ###
5
###                                                                             ###
6
### Enhanced version by Daniel Marschall, ViaThinkSoft 06-07/2011 ###
6
### Enhanced version by Daniel Marschall, ViaThinkSoft 06-07/2011               ###
-
 
7
### based on (or rather synchronized to) upstream version 1.3                   ###
7
### -- NEW 1.2: 2.48 can also be encoded!                         ###
8
### -- NEW in +viathinksoft2: 2.48 can also be encoded!                         ###
8
### -- NEW 1.2: UUIDs (128-bit) are now supported!                ###
9
### -- NEW in +viathinksoft2: UUIDs (128-bit) are now supported!                ###
9
###             (requires GMPLib)                                 ###
10
###                           (requires GMPLib)                                 ###
10
### -- NEW 1.3: Length can now have more than 1 byte              ###
11
### -- NEW in +viathinksoft3: Length can now have more than 1 byte              ###
11
### -- NEW 1.4: No command line limitation anymore.               ###
12
### -- NEW in +viathinksoft4: No command line limitation anymore.               ###
12
### -- NEW 1.5: Now also relative OIDs supported                  ###
13
### -- NEW in +viathinksoft5: Now also relative OIDs supported                  ###
13
### -- NEW 1.6: 0x80 paddings are now disallowed                  ###
14
### -- NEW in +viathinksoft6: 0x80 paddings are now disallowed                  ###
14
### -- NEW 1.8: Removed Application/Context/Private "OID"s        ###
15
### -- NEW in +viathinksoft8: Removed Application/Context/Private "OID"s        ###
15
### -- NEW 1.9: Also allow decoding C-notation with "-x"          ###
16
### -- NEW in +viathinksoft9: Also allow decoding C-notation with "-x"          ###
16
### -- AS WELL AS SEVERAL BUG FIXES                               ###
17
### -- AS WELL AS SEVERAL BUG FIXES                                             ###
17
###                                                               ###
18
###                                                                             ###
18
### To compile with gcc simply use:                               ###
19
### To compile with gcc simply use:                                             ###
19
###   gcc -O2 -o oid oid.c -lgmp -lm                              ###
20
###   gcc -O2 -o oid oid.c -lgmp -lm                                            ###
20
###                                                               ###
21
###                                                                             ###
-
 
22
### To compile using lcc-win32, use:                                            ###
-
 
23
###   lcc oid.c & lcclnk oid.obj                                                ###
-
 
24
###                                                                             ###
21
### To compile using cl, use:                                     ###
25
### To compile using cl, use:                                                   ###
22
###   cl -DWIN32 -O1 oid.c (+ include gmp library)                ###
26
###   cl -DWIN32 -O1 oid.c (+ include gmp library)                              ###
23
###                                                               ###
27
###                                                                             ###
24
### Freeware - do with it whatever you want.                      ###
28
### Freeware - do with it whatever you want.                                    ###
25
### Use at your own risk. No warranty of any kind.                ###
29
### Use at your own risk. No warranty of any kind.                              ###
26
###                                                               ###
30
###                                                                             ###
27
###################################################################*/
31
#################################################################################*/
28
/* $Version: 1.11$ */
32
/* $Version: 1.3+viathinksoft11$ */
29
 
33
 
30
// FUTURE
34
// FUTURE
31
// - Alles in Funktionen kapseln. Als Parameter: Array of integer (= dot notation) oder Array of byte (= hex notation)
35
// - Alles in Funktionen kapseln. Als Parameter: Array of integer (= dot notation) oder Array of byte (= hex notation)
32
 
36
 
33
// MINOR THINGS
37
// MINOR THINGS
34
// - All stderr: Output new line at stdOut and close stdOut
38
// - All stderr: Output new line at stdOut and close stdOut
35
// - Make as much GMP as possible (e.g. nBinary counter, nBinaryWork etc)
39
// - Make as much GMP as possible (e.g. nBinary counter, nBinaryWork etc)
36
// - überlegen, wie man die return-codes (errorcodes) besser verteilt/definiert
40
// - überlegen, wie man die return-codes (errorcodes) besser verteilt/definiert
37
// - irgendwie in funktionen kapseln (z.b. class-tag-parser usw)
41
// - irgendwie in funktionen kapseln (z.b. class-tag-parser usw)
38
// - "TODO"s beachten (unklare dinge)
42
// - "TODO"s beachten (unklare dinge)
39
 
43
 
40
// MINOR PROBLEMS IN CLI-INTERPRETATION:
44
// MINOR PROBLEMS IN CLI-INTERPRETATION:
41
// - A wrong error message is shown when trying to encode "-0.0" or "x"
45
// - A wrong error message is shown when trying to encode "-0.0" or "x"
42
// - 2.9a9 is not recognized as error
46
// - 2.9a9 is not recognized as error
43
// - "./oid R 2.999" is not interpretet correctly
47
// - "./oid R 2.999" is not interpretet correctly
44
// - "./oid .2.999" will be interpreted as "0.2.999"
48
// - "./oid .2.999" will be interpreted as "0.2.999"
45
 
49
 
46
// NICE TO HAVE:
50
// NICE TO HAVE:
47
// - also allow -x to interpret "\x06\x02\x88\x37"
51
// - also allow -x to interpret "\x06\x02\x88\x37" and { 0x06, 0x02, 0x88, 0x37 }
48
// - makefile, manpage, linuxpackage
52
// - makefile, manpage, linuxpackage
49
// - better make functions instead of putting everything in main() with fprintf...
53
// - better make functions instead of putting everything in main() with fprintf...
50
 
54
 
51
// NICE TO HAVE (INFINITY-IDEA - NOT IMPORTANT):
55
// NICE TO HAVE (INFINITY-IDEA - NOT IMPORTANT):
52
// - Is it possible to detect integer overflows and therefore output errors?
56
// - Is it possible to detect integer overflows and therefore output errors?
53
 
57
 
54
 
58
 
55
// -------------------------------------------------------
59
// -------------------------------------------------------
56
 
60
 
57
// Allows OIDs which are bigger than "long"
61
// Allows OIDs which are bigger than "long"
58
// Compile with "gcc oid.c -lgmp -lm"
62
// Compile with "gcc oid.c -lgmp -lm"
59
#define is_gmp
63
#define is_gmp
60
 
64
 
61
#include <stdio.h>
65
#include <stdio.h>
62
#include <string.h>
66
#include <string.h>
63
#include <stdlib.h>
67
#include <stdlib.h>
64
 
68
 
65
#ifdef is_gmp
69
#ifdef is_gmp
66
#include <gmp.h>
70
#include <gmp.h>
67
#endif
71
#endif
68
 
72
 
69
#include <stdbool.h>
73
#include <stdbool.h>
70
 
74
 
71
#ifndef __STRNICMP_LOCAL
75
#ifndef __STRNICMP_LOCAL
72
#ifdef WIN32
76
#ifdef WIN32
73
#define __STRNICMP_LOCAL strnicmp
77
#define __STRNICMP_LOCAL strnicmp
74
#else
78
#else
75
#define __STRNICMP_LOCAL strncasecmp
79
#define __STRNICMP_LOCAL strncasecmp
76
#endif
80
#endif
77
#endif
81
#endif
78
 
82
 
79
// char abCommandLine[4096];
83
// char abCommandLine[4096];
80
const unsigned int CLI_INITIAL_SIZE = 1024;
84
const unsigned int CLI_INITIAL_SIZE = 1024;
81
const unsigned int CLI_EXPANSION_SIZE = 1024;
85
const unsigned int CLI_EXPANSION_SIZE = 1024;
82
unsigned int cli_size;
86
unsigned int cli_size;
83
char * abCommandLine;
87
char * abCommandLine;
84
 
88
 
85
// unsigned char abBinary[128];
89
// unsigned char abBinary[128];
86
const unsigned int ABB_INITIAL_SIZE = 1024;
90
const unsigned int ABB_INITIAL_SIZE = 1024;
87
const unsigned int ABB_EXPANSION_SIZE = 1024;
91
const unsigned int ABB_EXPANSION_SIZE = 1024;
88
unsigned int abb_size;
92
unsigned int abb_size;
89
unsigned char * abBinary;
93
unsigned char * abBinary;
90
 
94
 
91
unsigned int nBinary = 0;
95
unsigned int nBinary = 0;
92
 
96
 
93
const int MODE_DOT_TO_HEX = 0;
97
const int MODE_DOT_TO_HEX = 0;
94
const int MODE_HEX_TO_DOT = 1;
98
const int MODE_HEX_TO_DOT = 1;
95
 
99
 
96
#ifdef is_gmp
100
#ifdef is_gmp
97
static void MakeBase128(mpz_t l, int first) {
101
static void MakeBase128(mpz_t l, int first) {
98
        if (mpz_cmp_si(l, 127) > 0) {
102
        if (mpz_cmp_si(l, 127) > 0) {
99
                mpz_t l2;
103
                mpz_t l2;
100
                mpz_init(l2);
104
                mpz_init(l2);
101
                mpz_div_ui(l2, l, 128);
105
                mpz_div_ui(l2, l, 128);
102
                MakeBase128(l2, 0);
106
                MakeBase128(l2, 0);
103
        }
107
        }
104
        mpz_mod_ui(l, l, 128);
108
        mpz_mod_ui(l, l, 128);
105
 
109
 
106
        if (nBinary+1 >= abb_size) {
110
        if (nBinary+1 >= abb_size) {
107
                abb_size += ABB_EXPANSION_SIZE;
111
                abb_size += ABB_EXPANSION_SIZE;
108
                abBinary = (unsigned char*) realloc(abBinary, abb_size);
112
                abBinary = (unsigned char*) realloc(abBinary, abb_size);
109
                if (abBinary == NULL) {
113
                if (abBinary == NULL) {
110
                        fprintf(stderr, "Memory reallocation failure!\n");
114
                        fprintf(stderr, "Memory reallocation failure!\n");
111
                        exit(EXIT_FAILURE);
115
                        exit(EXIT_FAILURE);
112
                }
116
                }
113
        }
117
        }
114
 
118
 
115
        if (first) {
119
        if (first) {
116
                abBinary[nBinary++] = mpz_get_ui(l);
120
                abBinary[nBinary++] = mpz_get_ui(l);
117
        } else {
121
        } else {
118
                abBinary[nBinary++] = 0x80 | mpz_get_ui(l);
122
                abBinary[nBinary++] = 0x80 | mpz_get_ui(l);
119
        }
123
        }
120
}
124
}
121
#else
125
#else
122
static void MakeBase128(unsigned long l, int first) {
126
static void MakeBase128(unsigned long l, int first) {
123
        if (l > 127) {
127
        if (l > 127) {
124
                MakeBase128(l / 128, 0);
128
                MakeBase128(l / 128, 0);
125
        }
129
        }
126
        l %= 128;
130
        l %= 128;
127
 
131
 
128
        if (nBinary+1 >= abb_size) {
132
        if (nBinary+1 >= abb_size) {
129
                abb_size += ABB_EXPANSION_SIZE;
133
                abb_size += ABB_EXPANSION_SIZE;
130
                abBinary = (unsigned char*) realloc(abBinary, abb_size);
134
                abBinary = (unsigned char*) realloc(abBinary, abb_size);
131
                if (abBinary == NULL) {
135
                if (abBinary == NULL) {
132
                        fprintf(stderr, "Memory reallocation failure!\n");
136
                        fprintf(stderr, "Memory reallocation failure!\n");
133
                        exit(EXIT_FAILURE);
137
                        exit(EXIT_FAILURE);
134
                }
138
                }
135
        }
139
        }
136
 
140
 
137
        if (first) {
141
        if (first) {
138
                abBinary[nBinary++] = (unsigned char)l;
142
                abBinary[nBinary++] = (unsigned char)l;
139
        } else {
143
        } else {
140
                abBinary[nBinary++] = 0x80 | (unsigned char)l;
144
                abBinary[nBinary++] = 0x80 | (unsigned char)l;
141
        }
145
        }
142
}
146
}
143
#endif
147
#endif
144
 
148
 
145
int main(int argc, char **argv) {
149
int main(int argc, char **argv) {
146
        cli_size = CLI_INITIAL_SIZE;
150
        cli_size = CLI_INITIAL_SIZE;
147
        abCommandLine  = (char*) malloc(cli_size * sizeof(char*));
151
        abCommandLine  = (char*) malloc(cli_size * sizeof(char*));
148
        if (abCommandLine == NULL) {
152
        if (abCommandLine == NULL) {
149
                fprintf(stderr, "Memory allocation failure!\n");
153
                fprintf(stderr, "Memory allocation failure!\n");
150
                return EXIT_FAILURE;
154
                return EXIT_FAILURE;
151
        }
155
        }
152
 
156
 
153
        abb_size = ABB_INITIAL_SIZE;
157
        abb_size = ABB_INITIAL_SIZE;
154
        abBinary  = (unsigned char*) malloc(abb_size * sizeof(unsigned char*));
158
        abBinary  = (unsigned char*) malloc(abb_size * sizeof(unsigned char*));
155
        if (abBinary == NULL) {
159
        if (abBinary == NULL) {
156
                fprintf(stderr, "Memory allocation failure!\n");
160
                fprintf(stderr, "Memory allocation failure!\n");
157
                return EXIT_FAILURE;
161
                return EXIT_FAILURE;
158
        }
162
        }
159
 
163
 
160
 
164
 
161
        char *fOutName = NULL;
165
        char *fOutName = NULL;
162
        char *fInName = NULL;
166
        char *fInName = NULL;
163
        FILE *fOut = NULL;
167
        FILE *fOut = NULL;
164
 
168
 
165
        int n = 1;
169
        int n = 1;
166
        int nMode = MODE_DOT_TO_HEX;
170
        int nMode = MODE_DOT_TO_HEX;
167
        bool nCHex = false;
171
        int nCHex = 0;
168
        int nAfterOption = 0;
172
        int nAfterOption = 0;
169
        bool isRelative = false;
173
        bool isRelative = false;
170
 
174
 
171
        if (argc == 1) {
175
        if (argc == 1) {
172
                fprintf(stderr,
176
                fprintf(stderr,
173
                "OID encoder/decoder 1.11 - Matthias Gaertner 1999/2001, Daniel Marschall 2011/2012 - Freeware\n"
177
                "OID encoder/decoder 1.3+viathinksoft11 - Matthias Gaertner 1999/2001, Daniel Marschall 2011/2012 - Freeware\n"
174
                #ifdef is_gmp
178
                #ifdef is_gmp
175
                "GMP Edition (unlimited arc sizes)\n"
179
                "GMP Edition (unlimited arc sizes)\n"
176
                #else
180
                #else
177
                "%d-bit Edition (arc sizes are limited!)\n"
181
                "%d-bit Edition (arc sizes are limited!)\n"
178
                #endif
182
                #endif
179
                "\nUsage:\n"
183
                "\nUsage:\n"
180
                " OID [-C] [-r] [-o<outfile>] {-i<infile>|2.999.1}\n"
184
                " OID [-c|-C] [-r] [-o<outfile>] {-i<infile>|2.999.1}\n"
181
                "   converts dotted form to ASCII HEX DER output.\n"
185
                "   converts dotted form to ASCII HEX DER output.\n"
-
 
186
                "   -c: Output as C-syntax (array).\n"
182
                "   -C: Output as C-syntax.\n"
187
                "   -C: Output as C-syntax (string).\n"
183
                "   -r: Handle the OID as relative and not absolute.\n"
188
                "   -r: Handle the OID as relative and not absolute.\n"
184
                " OID -x [-o<outfile>] {-i<infile>|hex-digits}\n"
189
                " OID -x [-o<outfile>] {-i<infile>|hex-digits}\n"
185
                "   decodes ASCII HEX DER and gives dotted form.\n" , sizeof(unsigned long) * 8);
190
                "   decodes ASCII HEX DER and gives dotted form.\n" , sizeof(unsigned long) * 8);
186
                return 1;
191
                return 1;
187
        }
192
        }
188
 
193
 
189
        while (n < argc) {
194
        while (n < argc) {
190
                if (!nAfterOption && argv[n][0] == '-') {
195
                if (!nAfterOption && argv[n][0] == '-') {
191
                        if (argv[n][1] == 'x') {
196
                        if (argv[n][1] == 'x') {
192
                                nMode = MODE_HEX_TO_DOT;
197
                                nMode = MODE_HEX_TO_DOT;
193
                                if (argv[n][2] != '\0') {
198
                                if (argv[n][2] != '\0') {
194
                                        argv[n--] += 2;
199
                                        argv[n--] += 2;
195
                                        nAfterOption = 1;
200
                                        nAfterOption = 1;
196
                                }
201
                                }
-
 
202
                        } else if (argv[n][1] == 'c') {
-
 
203
                                nMode = MODE_DOT_TO_HEX;
-
 
204
                                nCHex = 1;
-
 
205
 
-
 
206
                                if (argv[n][2] != '\0') {
-
 
207
                                        argv[n--] += 2;
-
 
208
                                        nAfterOption = 1;
-
 
209
                                }
197
                        } else if (argv[n][1] == 'C') {
210
                        } else if (argv[n][1] == 'C') {
198
                                nMode = MODE_DOT_TO_HEX;
211
                                nMode = MODE_DOT_TO_HEX;
199
                                nCHex = true;
212
                                nCHex = 2;
200
 
213
 
201
                                if (argv[n][2] != '\0') {
214
                                if (argv[n][2] != '\0') {
202
                                        argv[n--] += 2;
215
                                        argv[n--] += 2;
203
                                        nAfterOption = 1;
216
                                        nAfterOption = 1;
204
                                }
217
                                }
205
                        } else if (argv[n][1] == 'r') {
218
                        } else if (argv[n][1] == 'r') {
206
                                nMode = MODE_DOT_TO_HEX;
219
                                nMode = MODE_DOT_TO_HEX;
207
                                isRelative = true;
220
                                isRelative = true;
208
 
221
 
209
                                if (argv[n][2] != '\0') {
222
                                if (argv[n][2] != '\0') {
210
                                        argv[n--] += 2;
223
                                        argv[n--] += 2;
211
                                        nAfterOption = 1;
224
                                        nAfterOption = 1;
212
                                }
225
                                }
213
                        } else if (argv[n][1] == 'o') {
226
                        } else if (argv[n][1] == 'o') {
214
                                if (argv[n][2] != '\0') {
227
                                if (argv[n][2] != '\0') {
215
                                        fOutName = &argv[n][2];
228
                                        fOutName = &argv[n][2];
216
                                } else if (n < argc-1) {
229
                                } else if (n < argc-1) {
217
                                        fOutName = argv[++n];
230
                                        fOutName = argv[++n];
218
                                } else {
231
                                } else {
219
                                        fprintf(stderr, "Incomplete command line.\n");
232
                                        fprintf(stderr, "Incomplete command line.\n");
220
                                        return EXIT_FAILURE;
233
                                        return EXIT_FAILURE;
221
                                }
234
                                }
222
                        } else if (argv[n][1] == 'i') {
235
                        } else if (argv[n][1] == 'i') {
223
                                if (argv[n][2] != '\0') {
236
                                if (argv[n][2] != '\0') {
224
                                        fInName = &argv[n][2];
237
                                        fInName = &argv[n][2];
225
                                } else if (n < argc-1) {
238
                                } else if (n < argc-1) {
226
                                        fInName = argv[++n];
239
                                        fInName = argv[++n];
227
                                } else {
240
                                } else {
228
                                        fprintf(stderr, "Incomplete command line.\n");
241
                                        fprintf(stderr, "Incomplete command line.\n");
229
                                        return EXIT_FAILURE;
242
                                        return EXIT_FAILURE;
230
                                }
243
                                }
231
                        }
244
                        }
232
                } else {
245
                } else {
233
                        if (fInName != NULL) { // TODO: (Unklar) Was bewirkt das? Auch für fOutName notwendig?
246
                        if (fInName != NULL) { // TODO: (Unklar) Was bewirkt das? Auch für fOutName notwendig?
234
                                break;
247
                                break;
235
                        }
248
                        }
236
 
249
 
237
                        nAfterOption = 1;
250
                        nAfterOption = 1;
238
                        if (strlen(argv[n]) + strlen(abCommandLine) >= sizeof(abCommandLine)-2) { // TODO: warum -2 ?
251
                        if (strlen(argv[n]) + strlen(abCommandLine) >= sizeof(abCommandLine)-2) { // TODO: warum -2 ?
239
                                // fprintf(stderr, "Command line too long.\n");
252
                                // fprintf(stderr, "Command line too long.\n");
240
                                // return 2;
253
                                // return 2;
241
 
254
 
242
                                cli_size += CLI_EXPANSION_SIZE + strlen(argv[n]) + 1; // 1 = "."
255
                                cli_size += CLI_EXPANSION_SIZE + strlen(argv[n]) + 1; // 1 = "."
243
                                abCommandLine = (char*) realloc(abCommandLine, cli_size);
256
                                abCommandLine = (char*) realloc(abCommandLine, cli_size);
244
                                if (abCommandLine == NULL) {
257
                                if (abCommandLine == NULL) {
245
                                        fprintf(stderr, "Memory reallocation failure!\n");
258
                                        fprintf(stderr, "Memory reallocation failure!\n");
246
                                        return EXIT_FAILURE;
259
                                        return EXIT_FAILURE;
247
                                }
260
                                }
248
                        }
261
                        }
249
                        strcat(abCommandLine, argv[n]); // (fügt ein \0 automatisch an)
262
                        strcat(abCommandLine, argv[n]); // (fügt ein \0 automatisch an)
250
                        if (n != argc - 1 && nMode != MODE_HEX_TO_DOT) {
263
                        if (n != argc - 1 && nMode != MODE_HEX_TO_DOT) {
251
                                strcat(abCommandLine, ".");
264
                                strcat(abCommandLine, ".");
252
                        }
265
                        }
253
                }
266
                }
254
                n++;
267
                n++;
255
        }
268
        }
256
 
269
 
257
        if (fInName != NULL && nMode == MODE_HEX_TO_DOT) {
270
        if (fInName != NULL && nMode == MODE_HEX_TO_DOT) {
258
                FILE *fIn = fopen(fInName, "rb");
271
                FILE *fIn = fopen(fInName, "rb");
259
                size_t nRead = 0;
272
                size_t nRead = 0;
260
                if (fIn == NULL) {
273
                if (fIn == NULL) {
261
                        fprintf(stderr, "Unable to open input file %s.\n", fInName);
274
                        fprintf(stderr, "Unable to open input file %s.\n", fInName);
262
                        return 11;
275
                        return 11;
263
                }
276
                }
264
                nRead = fread(abCommandLine, 1, sizeof(abCommandLine), fIn);
277
                nRead = fread(abCommandLine, 1, sizeof(abCommandLine), fIn);
265
                abCommandLine[nRead] = '\0';
278
                abCommandLine[nRead] = '\0';
266
                fclose(fIn);
279
                fclose(fIn);
267
        } else if (fInName != NULL && nMode == MODE_DOT_TO_HEX) {
280
        } else if (fInName != NULL && nMode == MODE_DOT_TO_HEX) {
268
                FILE *fIn = fopen(fInName, "rt");
281
                FILE *fIn = fopen(fInName, "rt");
269
                if (fIn == NULL) {
282
                if (fIn == NULL) {
270
                        fprintf(stderr, "Unable to open input file %s.\n", fInName);
283
                        fprintf(stderr, "Unable to open input file %s.\n", fInName);
271
                        return 11;
284
                        return 11;
272
                }
285
                }
273
                fgets(abCommandLine, sizeof(abCommandLine), fIn);
286
                fgets(abCommandLine, sizeof(abCommandLine), fIn);
274
                fclose(fIn);
287
                fclose(fIn);
275
        }
288
        }
276
 
289
 
277
        while (nMode == MODE_HEX_TO_DOT) { /* better if */
290
        while (nMode == MODE_HEX_TO_DOT) { /* better if */
278
                /* hex->dotted */
291
                /* hex->dotted */
279
                /*printf("Hex-In: %s\n", abCommandLine);*/
292
                /*printf("Hex-In: %s\n", abCommandLine);*/
280
 
293
 
281
                char *p = abCommandLine;
294
                char *p = abCommandLine;
282
                char *q = p;
295
                char *q = p;
283
 
296
 
284
                unsigned char *pb = NULL;
297
                unsigned char *pb = NULL;
285
                unsigned int nn = 0;
298
                unsigned int nn = 0;
286
                #ifdef is_gmp
299
                #ifdef is_gmp
287
                mpz_t ll;
300
                mpz_t ll;
288
                mpz_init(ll);
301
                mpz_init(ll);
289
                #else
302
                #else
290
                unsigned long ll = 0;
303
                unsigned long ll = 0;
291
                #endif
304
                #endif
292
                bool fOK = false;
305
                bool fOK = false;
293
                int fSub = 0; // Subtract value from next number output. Used when encoding {2 48} and up
306
                int fSub = 0; // Subtract value from next number output. Used when encoding {2 48} and up
294
 
307
 
295
                while (*p) {
308
                while (*p) {
296
                        if (*p != '.' && *p != '\r' && *p != '\n' && *p != '\x20' && *p != '\t') {
309
                        if (*p != '.' && *p != '\r' && *p != '\n' && *p != '\x20' && *p != '\t') {
297
                                *q++ = *p;
310
                                *q++ = *p;
298
                        }
311
                        }
299
                        p++;
312
                        p++;
300
                }
313
                }
301
                *q = '\0';
314
                *q = '\0';
302
 
315
 
303
                if (strlen(abCommandLine) % 2 != 0) {
316
                if (strlen(abCommandLine) % 2 != 0) {
304
                        fprintf(stderr, "Encoded OID must have even number of hex digits!\n");
317
                        fprintf(stderr, "Encoded OID must have even number of hex digits!\n");
305
                        return 2;
318
                        return 2;
306
                }
319
                }
307
 
320
 
308
                if (strlen(abCommandLine) < 3) {
321
                if (strlen(abCommandLine) < 3) {
309
                        fprintf(stderr, "Encoded OID must have at least three bytes!\n");
322
                        fprintf(stderr, "Encoded OID must have at least three bytes!\n");
310
                        return 2;
323
                        return 2;
311
                }
324
                }
312
 
325
 
313
                nBinary = 0;
326
                nBinary = 0;
314
                p = abCommandLine;
327
                p = abCommandLine;
315
 
328
 
316
                while (*p) {
329
                while (*p) {
317
                        unsigned char b;
330
                        unsigned char b;
318
 
331
 
319
                        // This allows also C-notation
332
                        // This allows also C-notation
320
                        if ((p[0] == '\\') && (p[1] == 'x')) {
333
                        if ((p[0] == '\\') && (p[1] == 'x')) {
321
                                p += 2;
334
                                p += 2;
322
                                continue;
335
                                continue;
323
                        }
336
                        }
324
 
337
 
325
                        // Interpret upper nibble
338
                        // Interpret upper nibble
326
                        if (p[0] >= 'A' && p[0] <= 'F') {
339
                        if (p[0] >= 'A' && p[0] <= 'F') {
327
                                b = (p[0] - 'A' + 10) * 16;
340
                                b = (p[0] - 'A' + 10) * 16;
328
                        } else if (p[0] >= 'a' && p[0] <= 'f') {
341
                        } else if (p[0] >= 'a' && p[0] <= 'f') {
329
                                b = (p[0] - 'a' + 10) * 16;
342
                                b = (p[0] - 'a' + 10) * 16;
330
                        } else if (p[0] >= '0' && p[0] <= '9') {
343
                        } else if (p[0] >= '0' && p[0] <= '9') {
331
                                b = (p[0] - '0') * 16;
344
                                b = (p[0] - '0') * 16;
332
                        } else {
345
                        } else {
333
                                fprintf(stderr, "Must have hex digits only!\n");
346
                                fprintf(stderr, "Must have hex digits only!\n");
334
                                return 2;
347
                                return 2;
335
                        }
348
                        }
336
 
349
 
337
                        // Interpret lower nibble
350
                        // Interpret lower nibble
338
                        if (p[1] >= 'A' && p[1] <= 'F') {
351
                        if (p[1] >= 'A' && p[1] <= 'F') {
339
                                b += (p[1] - 'A' + 10);
352
                                b += (p[1] - 'A' + 10);
340
                        } else if (p[1] >= 'a' && p[1] <= 'f') {
353
                        } else if (p[1] >= 'a' && p[1] <= 'f') {
341
                                b += (p[1] - 'a' + 10);
354
                                b += (p[1] - 'a' + 10);
342
                        } else if (p[1] >= '0' && p[1] <= '9') {
355
                        } else if (p[1] >= '0' && p[1] <= '9') {
343
                                b += (p[1] - '0');
356
                                b += (p[1] - '0');
344
                        } else {
357
                        } else {
345
                                fprintf(stderr, "Must have hex digits only!\n");
358
                                fprintf(stderr, "Must have hex digits only!\n");
346
                                return 2;
359
                                return 2;
347
                        }
360
                        }
348
 
361
 
349
                        if (nBinary+1 >= abb_size) {
362
                        if (nBinary+1 >= abb_size) {
350
                                abb_size += ABB_EXPANSION_SIZE;
363
                                abb_size += ABB_EXPANSION_SIZE;
351
                                abBinary = (unsigned char*) realloc(abBinary, abb_size);
364
                                abBinary = (unsigned char*) realloc(abBinary, abb_size);
352
                                if (abBinary == NULL) {
365
                                if (abBinary == NULL) {
353
                                        fprintf(stderr, "Memory reallocation failure!\n");
366
                                        fprintf(stderr, "Memory reallocation failure!\n");
354
                                        return EXIT_FAILURE;
367
                                        return EXIT_FAILURE;
355
                                }
368
                                }
356
                        }
369
                        }
357
 
370
 
358
                        abBinary[nBinary++] = b;
371
                        abBinary[nBinary++] = b;
359
                        p += 2;
372
                        p += 2;
360
                }
373
                }
361
 
374
 
362
                /*printf("Hex-In: %s\n", abCommandLine);*/
375
                /*printf("Hex-In: %s\n", abCommandLine);*/
363
 
376
 
364
                if (fOutName != NULL) {
377
                if (fOutName != NULL) {
365
                        fOut = fopen(fOutName, "wt");
378
                        fOut = fopen(fOutName, "wt");
366
                        if (fOut == NULL) {
379
                        if (fOut == NULL) {
367
                                fprintf(stderr, "Unable to open output file %s\n", fOutName);
380
                                fprintf(stderr, "Unable to open output file %s\n", fOutName);
368
                                return 33;
381
                                return 33;
369
                        }
382
                        }
370
                } else {
383
                } else {
371
                        fOut = stdout;
384
                        fOut = stdout;
372
                }
385
                }
373
 
386
 
374
                pb = abBinary;
387
                pb = abBinary;
375
                nn = 0;
388
                nn = 0;
376
                #ifdef is_gmp
389
                #ifdef is_gmp
377
                mpz_init(ll);
390
                mpz_init(ll);
378
                #else
391
                #else
379
                ll = 0;
392
                ll = 0;
380
                #endif
393
                #endif
381
                fOK = false;
394
                fOK = false;
382
                fSub = 0;
395
                fSub = 0;
383
 
396
 
384
                // 0 = Universal Class Identifier Tag (can be more than 1 byte, but not in our case)
397
                // 0 = Universal Class Identifier Tag (can be more than 1 byte, but not in our case)
385
                // 1 = Length part (may have more than 1 byte!)
398
                // 1 = Length part (may have more than 1 byte!)
386
                // 2 = First two arc encoding
399
                // 2 = First two arc encoding
387
                // 3 = Encoding of arc three and higher
400
                // 3 = Encoding of arc three and higher
388
                unsigned char part = 0;
401
                unsigned char part = 0;
389
 
402
 
390
                unsigned char lengthbyte_count = 0;
403
                unsigned char lengthbyte_count = 0;
391
                unsigned char lengthbyte_pos = 0;
404
                unsigned char lengthbyte_pos = 0;
392
                bool lengthfinished = false;
405
                bool lengthfinished = false;
393
 
406
 
394
                bool arcBeginning = true;
407
                bool arcBeginning = true;
395
                bool firstWrittenArc = true;
408
                bool firstWrittenArc = true;
396
 
409
 
397
                while (nn < nBinary) {
410
                while (nn < nBinary) {
398
                        if (part == 0) { // Class Tag
411
                        if (part == 0) { // Class Tag
399
 
412
 
400
                                // Leading octet
413
                                // Leading octet
401
                                // Bit 7 / Bit 6 = Universal (00), Application (01), Context (10), Private(11)
414
                                // Bit 7 / Bit 6 = Universal (00), Application (01), Context (10), Private(11)
402
                                // Bit 5 = Primitive (0), Constructed (1)
415
                                // Bit 5 = Primitive (0), Constructed (1)
403
                                // Bit 4..0 = 00000 .. 11110 => Tag 0..30, 11111 for Tag > 30 (following bytes with the highest bit as "more" bit)
416
                                // Bit 4..0 = 00000 .. 11110 => Tag 0..30, 11111 for Tag > 30 (following bytes with the highest bit as "more" bit)
404
                                // --> We don't need to respect 11111 (class-tag encodes in more than 1 octet)
417
                                // --> We don't need to respect 11111 (class-tag encodes in more than 1 octet)
405
                                //     as we terminate when the tag is not of type OID or RELATEIVE-OID
418
                                //     as we terminate when the tag is not of type OID or RELATEIVE-OID
406
                                // See page 396 of "ASN.1 - Communication between Heterogeneous Systems" by Olivier Dubuisson.
419
                                // See page 396 of "ASN.1 - Communication between Heterogeneous Systems" by Olivier Dubuisson.
407
 
420
 
408
                                // Class: 8. - 7. bit
421
                                // Class: 8. - 7. bit
409
                                // 0 (00) = Universal
422
                                // 0 (00) = Universal
410
                                // 1 (01) = Application
423
                                // 1 (01) = Application
411
                                // 2 (10) = Context
424
                                // 2 (10) = Context
412
                                // 3 (11) = Private
425
                                // 3 (11) = Private
413
                                unsigned char cl = ((*pb & 0xC0) >> 6) & 0x03;
426
                                unsigned char cl = ((*pb & 0xC0) >> 6) & 0x03;
414
                                if (cl != 0) {
427
                                if (cl != 0) {
415
                                        fprintf(stderr, "\nError at type: The OID tags are only defined as UNIVERSAL class tags.\n");
428
                                        fprintf(stderr, "\nError at type: The OID tags are only defined as UNIVERSAL class tags.\n");
416
                                        fprintf(fOut, "\n");
429
                                        fprintf(fOut, "\n");
417
                                        return 6;
430
                                        return 6;
418
                                }
431
                                }
419
 
432
 
420
                                // Primitive/Constructed: 6. bit
433
                                // Primitive/Constructed: 6. bit
421
                                // 0 = Primitive
434
                                // 0 = Primitive
422
                                // 1 = Constructed
435
                                // 1 = Constructed
423
                                unsigned char pc = *pb & 0x20;
436
                                unsigned char pc = *pb & 0x20;
424
                                if (pc != 0) {
437
                                if (pc != 0) {
425
                                        fprintf(stderr, "\nError at type: OIDs must be primitive, not constructed.\n");
438
                                        fprintf(stderr, "\nError at type: OIDs must be primitive, not constructed.\n");
426
                                        fprintf(fOut, "\n");
439
                                        fprintf(fOut, "\n");
427
                                        return 6;
440
                                        return 6;
428
                                }
441
                                }
429
 
442
 
430
                                // Tag number: 5. - 1. bit
443
                                // Tag number: 5. - 1. bit
431
                                unsigned char tag = *pb & 0x1F;
444
                                unsigned char tag = *pb & 0x1F;
432
                                if (tag == 0x0D) {
445
                                if (tag == 0x0D) {
433
                                        isRelative = true;
446
                                        isRelative = true;
434
                                } else if (tag == 0x06) {
447
                                } else if (tag == 0x06) {
435
                                        isRelative = false;
448
                                        isRelative = false;
436
                                } else {
449
                                } else {
437
                                        fprintf(stderr, "\nError at type: The tag number is neither an absolute OID (0x06) nor a relative OID (0x0D).\n");
450
                                        fprintf(stderr, "\nError at type: The tag number is neither an absolute OID (0x06) nor a relative OID (0x0D).\n");
438
                                        fprintf(fOut, "\n");
451
                                        fprintf(fOut, "\n");
439
                                        return 6;
452
                                        return 6;
440
                                }
453
                                }
441
 
454
 
442
                                // Output
455
                                // Output
443
                                if (isRelative) {
456
                                if (isRelative) {
444
                                        fprintf(fOut, "RELATIVE");
457
                                        fprintf(fOut, "RELATIVE");
445
                                } else {
458
                                } else {
446
                                        fprintf(fOut, "ABSOLUTE");
459
                                        fprintf(fOut, "ABSOLUTE");
447
                                }
460
                                }
448
 
461
 
449
                                fprintf(fOut, " OID");
462
                                fprintf(fOut, " OID");
450
                                part++;
463
                                part++;
451
                        } else if (part == 1) { // Length
464
                        } else if (part == 1) { // Length
452
 
465
 
453
                                // Find out the length and save it into ll
466
                                // Find out the length and save it into ll
454
 
467
 
455
                                // [length] is encoded as follows:
468
                                // [length] is encoded as follows:
456
                                //  0x00 .. 0x7F = The actual length is in this byte, followed by [data].
469
                                //  0x00 .. 0x7F = The actual length is in this byte, followed by [data].
457
                                //  0x80 + n     = The length of [data] is spread over the following 'n' bytes. (0 < n < 0x7F)
470
                                //  0x80 + n     = The length of [data] is spread over the following 'n' bytes. (0 < n < 0x7F)
458
                                //  0x80         = "indefinite length" (only constructed form) -- Invalid
471
                                //  0x80         = "indefinite length" (only constructed form) -- Invalid
459
                                //  0xFF         = Reserved for further implementations -- Invalid
472
                                //  0xFF         = Reserved for further implementations -- Invalid
460
                                //  See page 396 of "ASN.1 - Communication between Heterogeneous Systems" by Olivier Dubuisson.
473
                                //  See page 396 of "ASN.1 - Communication between Heterogeneous Systems" by Olivier Dubuisson.
461
 
474
 
462
                                if (nn == 1) { // The first length byte
475
                                if (nn == 1) { // The first length byte
463
                                        lengthbyte_pos = 0;
476
                                        lengthbyte_pos = 0;
464
                                        if ((*pb & 0x80) != 0) {
477
                                        if ((*pb & 0x80) != 0) {
465
                                                // 0x80 + n => The length is spread over the following 'n' bytes
478
                                                // 0x80 + n => The length is spread over the following 'n' bytes
466
                                                lengthfinished = false;
479
                                                lengthfinished = false;
467
                                                lengthbyte_count = *pb & 0x7F;
480
                                                lengthbyte_count = *pb & 0x7F;
468
                                                if (lengthbyte_count == 0x00) {
481
                                                if (lengthbyte_count == 0x00) {
469
                                                        fprintf(stderr, "\nLength value 0x80 is invalid (\"indefinite length\") for primitive types.\n");
482
                                                        fprintf(stderr, "\nLength value 0x80 is invalid (\"indefinite length\") for primitive types.\n");
470
                                                        fprintf(fOut, "\n");
483
                                                        fprintf(fOut, "\n");
471
                                                        return 7;
484
                                                        return 7;
472
                                                } else if (lengthbyte_count == 0x7F) {
485
                                                } else if (lengthbyte_count == 0x7F) {
473
                                                        fprintf(stderr, "\nLength value 0xFF is reserved for further extensions.\n");
486
                                                        fprintf(stderr, "\nLength value 0xFF is reserved for further extensions.\n");
474
                                                        fprintf(fOut, "\n");
487
                                                        fprintf(fOut, "\n");
475
                                                        return 7;
488
                                                        return 7;
476
                                                }
489
                                                }
477
                                                fOK = false;
490
                                                fOK = false;
478
                                        } else {
491
                                        } else {
479
                                                // 0x01 .. 0x7F => The actual length
492
                                                // 0x01 .. 0x7F => The actual length
480
 
493
 
481
                                                if (*pb == 0x00) {
494
                                                if (*pb == 0x00) {
482
                                                        fprintf(stderr, "\nLength value 0x00 is invalid for an OID.\n");
495
                                                        fprintf(stderr, "\nLength value 0x00 is invalid for an OID.\n");
483
                                                        fprintf(fOut, "\n");
496
                                                        fprintf(fOut, "\n");
484
                                                        return 7;
497
                                                        return 7;
485
                                                }
498
                                                }
486
 
499
 
487
                                                #ifdef is_gmp
500
                                                #ifdef is_gmp
488
                                                mpz_set_ui(ll, *pb);
501
                                                mpz_set_ui(ll, *pb);
489
                                                #else
502
                                                #else
490
                                                ll = *pb;
503
                                                ll = *pb;
491
                                                #endif
504
                                                #endif
492
                                                lengthfinished = true;
505
                                                lengthfinished = true;
493
                                                lengthbyte_count = 0;
506
                                                lengthbyte_count = 0;
494
                                                fOK = true;
507
                                                fOK = true;
495
                                        }
508
                                        }
496
                                } else {
509
                                } else {
497
                                        if (lengthbyte_count > lengthbyte_pos) {
510
                                        if (lengthbyte_count > lengthbyte_pos) {
498
                                                #ifdef is_gmp
511
                                                #ifdef is_gmp
499
                                                mpz_mul_ui(ll, ll, 0x100);
512
                                                mpz_mul_ui(ll, ll, 0x100);
500
                                                mpz_add_ui(ll, ll, *pb);
513
                                                mpz_add_ui(ll, ll, *pb);
501
                                                #else
514
                                                #else
502
                                                ll *= 0x100;
515
                                                ll *= 0x100;
503
                                                ll += *pb;
516
                                                ll += *pb;
504
                                                #endif
517
                                                #endif
505
                                                lengthbyte_pos++;
518
                                                lengthbyte_pos++;
506
                                        }
519
                                        }
507
 
520
 
508
                                        if (lengthbyte_count == lengthbyte_pos) {
521
                                        if (lengthbyte_count == lengthbyte_pos) {
509
                                                lengthfinished = true;
522
                                                lengthfinished = true;
510
                                                fOK = true;
523
                                                fOK = true;
511
                                        }
524
                                        }
512
                                }
525
                                }
513
 
526
 
514
                                if (lengthfinished) { // The length is now in ll
527
                                if (lengthfinished) { // The length is now in ll
515
                                        #ifdef is_gmp
528
                                        #ifdef is_gmp
516
                                        if (mpz_cmp_ui(ll,  nBinary - 2 - lengthbyte_count) != 0) {
529
                                        if (mpz_cmp_ui(ll,  nBinary - 2 - lengthbyte_count) != 0) {
517
                                                fprintf(fOut, "\n");
530
                                                fprintf(fOut, "\n");
518
                                                if (fOut != stdout) {
531
                                                if (fOut != stdout) {
519
                                                        fclose(fOut);
532
                                                        fclose(fOut);
520
                                                }
533
                                                }
521
                                                fprintf(stderr, "\nInvalid length (%d entered, but %s expected)\n", nBinary - 2, mpz_get_str(NULL, 10, ll));
534
                                                fprintf(stderr, "\nInvalid length (%d entered, but %s expected)\n", nBinary - 2, mpz_get_str(NULL, 10, ll));
522
                                                return 3;
535
                                                return 3;
523
                                        }
536
                                        }
524
                                        mpz_set_ui(ll, 0); // reset for later usage
537
                                        mpz_set_ui(ll, 0); // reset for later usage
525
                                        #else
538
                                        #else
526
                                        if (ll != nBinary - 2 - lengthbyte_count) {
539
                                        if (ll != nBinary - 2 - lengthbyte_count) {
527
                                                fprintf(fOut, "\n");
540
                                                fprintf(fOut, "\n");
528
                                                if (fOut != stdout) {
541
                                                if (fOut != stdout) {
529
                                                        fclose(fOut);
542
                                                        fclose(fOut);
530
                                                }
543
                                                }
531
                                                fprintf(stderr, "\nInvalid length (%d entered, but %d expected)\n", nBinary - 2, ll);
544
                                                fprintf(stderr, "\nInvalid length (%d entered, but %d expected)\n", nBinary - 2, ll);
532
                                                return 3;
545
                                                return 3;
533
                                        }
546
                                        }
534
                                        ll = 0; // reset for later usage
547
                                        ll = 0; // reset for later usage
535
                                        #endif
548
                                        #endif
536
                                        fOK = true;
549
                                        fOK = true;
537
                                        part++;
550
                                        part++;
538
                                        if (isRelative) part++; // Goto step 3!
551
                                        if (isRelative) part++; // Goto step 3!
539
                                }
552
                                }
540
                        } else if (part == 2) { // First two arcs
553
                        } else if (part == 2) { // First two arcs
541
                                int first = *pb / 40;
554
                                int first = *pb / 40;
542
                                int second = *pb % 40;
555
                                int second = *pb % 40;
543
                                if (first > 2) {
556
                                if (first > 2) {
544
                                        first = 2;
557
                                        first = 2;
545
                                        fprintf(fOut, " %d", first);
558
                                        fprintf(fOut, " %d", first);
546
                                        firstWrittenArc = false;
559
                                        firstWrittenArc = false;
547
                                        arcBeginning = true;
560
                                        arcBeginning = true;
548
 
561
 
549
                                        if ((*pb & 0x80) != 0) {
562
                                        if ((*pb & 0x80) != 0) {
550
                                                // 2.48 and up => 2+ octets
563
                                                // 2.48 and up => 2+ octets
551
                                                // Output in "part 3"
564
                                                // Output in "part 3"
552
 
565
 
553
                                                if (arcBeginning && (*pb == 0x80)) {
566
                                                if (arcBeginning && (*pb == 0x80)) {
554
                                                        fprintf(fOut, "\n");
567
                                                        fprintf(fOut, "\n");
555
                                                        if (fOut != stdout) {
568
                                                        if (fOut != stdout) {
556
                                                                fclose(fOut);
569
                                                                fclose(fOut);
557
                                                        }
570
                                                        }
558
                                                        fprintf(stderr, "\nEncoding error. Illegal 0x80 paddings. (See Rec. ITU-T X.690, clause 8.19.2)\n");
571
                                                        fprintf(stderr, "\nEncoding error. Illegal 0x80 paddings. (See Rec. ITU-T X.690, clause 8.19.2)\n");
559
                                                        return 4;
572
                                                        return 4;
560
                                                } else {
573
                                                } else {
561
                                                        arcBeginning = false;
574
                                                        arcBeginning = false;
562
                                                }
575
                                                }
563
 
576
 
564
                                                #ifdef is_gmp
577
                                                #ifdef is_gmp
565
                                                mpz_add_ui(ll, ll, (*pb & 0x7F));
578
                                                mpz_add_ui(ll, ll, (*pb & 0x7F));
566
                                                #else
579
                                                #else
567
                                                ll += (*pb & 0x7F);
580
                                                ll += (*pb & 0x7F);
568
                                                #endif
581
                                                #endif
569
                                                fSub = 80;
582
                                                fSub = 80;
570
                                                fOK = false;
583
                                                fOK = false;
571
                                        } else {
584
                                        } else {
572
                                                // 2.0 till 2.47 => 1 octet
585
                                                // 2.0 till 2.47 => 1 octet
573
                                                second = *pb - 80;
586
                                                second = *pb - 80;
574
                                                fprintf(fOut, ".%d", second);
587
                                                fprintf(fOut, ".%d", second);
575
                                                arcBeginning = true;
588
                                                arcBeginning = true;
576
                                                fOK = true;
589
                                                fOK = true;
577
                                                #ifdef is_gmp
590
                                                #ifdef is_gmp
578
                                                mpz_set_ui(ll, 0);
591
                                                mpz_set_ui(ll, 0);
579
                                                #else
592
                                                #else
580
                                                ll = 0;
593
                                                ll = 0;
581
                                                #endif
594
                                                #endif
582
                                        }
595
                                        }
583
                                } else {
596
                                } else {
584
                                        // 0.0 till 0.37 => 1 octet
597
                                        // 0.0 till 0.37 => 1 octet
585
                                        // 1.0 till 1.37 => 1 octet
598
                                        // 1.0 till 1.37 => 1 octet
586
                                        fprintf(fOut, " %d.%d", first, second);
599
                                        fprintf(fOut, " %d.%d", first, second);
587
                                        firstWrittenArc = false;
600
                                        firstWrittenArc = false;
588
                                        arcBeginning = true;
601
                                        arcBeginning = true;
589
                                        fOK = true;
602
                                        fOK = true;
590
                                        #ifdef is_gmp
603
                                        #ifdef is_gmp
591
                                        mpz_set_ui(ll, 0);
604
                                        mpz_set_ui(ll, 0);
592
                                        #else
605
                                        #else
593
                                        ll = 0;
606
                                        ll = 0;
594
                                        #endif
607
                                        #endif
595
                                }
608
                                }
596
                                part++;
609
                                part++;
597
                        } else if (part == 3) { // Arc three and higher
610
                        } else if (part == 3) { // Arc three and higher
598
                                if ((*pb & 0x80) != 0) {
611
                                if ((*pb & 0x80) != 0) {
599
                                        if (arcBeginning && (*pb == 0x80)) {
612
                                        if (arcBeginning && (*pb == 0x80)) {
600
                                                fprintf(fOut, "\n");
613
                                                fprintf(fOut, "\n");
601
                                                if (fOut != stdout) {
614
                                                if (fOut != stdout) {
602
                                                        fclose(fOut);
615
                                                        fclose(fOut);
603
                                                }
616
                                                }
604
                                                fprintf(stderr, "\nEncoding error. Illegal 0x80 paddings. (See Rec. ITU-T X.690, clause 8.19.2)\n");
617
                                                fprintf(stderr, "\nEncoding error. Illegal 0x80 paddings. (See Rec. ITU-T X.690, clause 8.19.2)\n");
605
                                                return 4;
618
                                                return 4;
606
                                        } else {
619
                                        } else {
607
                                                arcBeginning = false;
620
                                                arcBeginning = false;
608
                                        }
621
                                        }
609
 
622
 
610
                                        #ifdef is_gmp
623
                                        #ifdef is_gmp
611
                                        mpz_mul_ui(ll, ll, 0x80);
624
                                        mpz_mul_ui(ll, ll, 0x80);
612
                                        mpz_add_ui(ll, ll, (*pb & 0x7F));
625
                                        mpz_add_ui(ll, ll, (*pb & 0x7F));
613
                                        #else
626
                                        #else
614
                                        ll *= 0x80;
627
                                        ll *= 0x80;
615
                                        ll += (*pb & 0x7F);
628
                                        ll += (*pb & 0x7F);
616
                                        #endif
629
                                        #endif
617
                                        fOK = false;
630
                                        fOK = false;
618
                                } else {
631
                                } else {
619
                                        fOK = true;
632
                                        fOK = true;
620
                                        #ifdef is_gmp
633
                                        #ifdef is_gmp
621
                                        mpz_mul_ui(ll, ll, 0x80);
634
                                        mpz_mul_ui(ll, ll, 0x80);
622
                                        mpz_add_ui(ll, ll, *pb);
635
                                        mpz_add_ui(ll, ll, *pb);
623
                                        mpz_sub_ui(ll, ll, fSub);
636
                                        mpz_sub_ui(ll, ll, fSub);
624
                                        if (firstWrittenArc) {
637
                                        if (firstWrittenArc) {
625
                                                fprintf(fOut, " %s", mpz_get_str(NULL, 10, ll));
638
                                                fprintf(fOut, " %s", mpz_get_str(NULL, 10, ll));
626
                                                firstWrittenArc = false;
639
                                                firstWrittenArc = false;
627
                                        } else {
640
                                        } else {
628
                                                fprintf(fOut, ".%s", mpz_get_str(NULL, 10, ll));
641
                                                fprintf(fOut, ".%s", mpz_get_str(NULL, 10, ll));
629
                                        }
642
                                        }
630
                                        // Happens only if 0x80 paddings are allowed
643
                                        // Happens only if 0x80 paddings are allowed
631
                                        // fOK = mpz_cmp_ui(ll, 0) >= 0;
644
                                        // fOK = mpz_cmp_ui(ll, 0) >= 0;
632
                                        mpz_set_ui(ll, 0);
645
                                        mpz_set_ui(ll, 0);
633
                                        #else
646
                                        #else
634
                                        ll *= 0x80;
647
                                        ll *= 0x80;
635
                                        ll += *pb;
648
                                        ll += *pb;
636
                                        ll -= fSub;
649
                                        ll -= fSub;
637
                                        if (firstWrittenArc) {
650
                                        if (firstWrittenArc) {
638
                                                fprintf(fOut, " %lu", ll);
651
                                                fprintf(fOut, " %lu", ll);
639
                                                firstWrittenArc = false;
652
                                                firstWrittenArc = false;
640
                                        } else {
653
                                        } else {
641
                                                fprintf(fOut, ".%lu", ll);
654
                                                fprintf(fOut, ".%lu", ll);
642
                                        }
655
                                        }
643
                                        // Happens only if 0x80 paddings are allowed
656
                                        // Happens only if 0x80 paddings are allowed
644
                                        // fOK = ll >= 0;
657
                                        // fOK = ll >= 0;
645
                                        ll = 0;
658
                                        ll = 0;
646
                                        #endif
659
                                        #endif
647
                                        fSub = 0;
660
                                        fSub = 0;
648
                                        arcBeginning = true;
661
                                        arcBeginning = true;
649
                                }
662
                                }
650
                        }
663
                        }
651
 
664
 
652
                        pb++;
665
                        pb++;
653
                        nn++;
666
                        nn++;
654
                }
667
                }
655
 
668
 
656
                if (!fOK) {
669
                if (!fOK) {
657
                        fprintf(fOut, "\n");
670
                        fprintf(fOut, "\n");
658
                        if (fOut != stdout) {
671
                        if (fOut != stdout) {
659
                                fclose(fOut);
672
                                fclose(fOut);
660
                        }
673
                        }
661
                        fprintf(stderr, "\nEncoding error. The OID is not constructed properly.\n");
674
                        fprintf(stderr, "\nEncoding error. The OID is not constructed properly.\n");
662
                        return 4;
675
                        return 4;
663
                } else {
676
                } else {
664
                        fprintf(fOut, "\n");
677
                        fprintf(fOut, "\n");
665
                }
678
                }
666
 
679
 
667
                if (fOut != stdout) {
680
                if (fOut != stdout) {
668
                        fclose(fOut);
681
                        fclose(fOut);
669
                }
682
                }
670
                break;
683
                break;
671
        };
684
        };
672
 
685
 
673
        while (nMode == MODE_DOT_TO_HEX) { /* better if */
686
        while (nMode == MODE_DOT_TO_HEX) { /* better if */
674
                /* dotted->hex */
687
                /* dotted->hex */
675
                /* printf("OID %s\n", abCommandLine); */
688
                /* printf("OID %s\n", abCommandLine); */
676
 
689
 
677
                char *p = abCommandLine;
690
                char *p = abCommandLine;
678
                unsigned char cl = 0x00;
691
                unsigned char cl = 0x00;
679
                char *q = NULL;
692
                char *q = NULL;
680
                int nPieces = 1;
693
                int nPieces = 1;
681
                int n = 0;
694
                int n = 0;
682
                unsigned char b = 0;
695
                unsigned char b = 0;
683
                unsigned int nn = 0;
696
                unsigned int nn = 0;
684
                #ifdef is_gmp
697
                #ifdef is_gmp
685
                mpz_t l;
698
                mpz_t l;
686
                #else
699
                #else
687
                unsigned long l = 0;
700
                unsigned long l = 0;
688
                #endif
701
                #endif
689
                bool isjoint = false;
702
                bool isjoint = false;
690
 
703
 
691
                // Alternative call: ./oid RELATIVE.2.999
704
                // Alternative call: ./oid RELATIVE.2.999
692
                if (__STRNICMP_LOCAL(p, "ABSOLUTE.", 9) == 0) {
705
                if (__STRNICMP_LOCAL(p, "ABSOLUTE.", 9) == 0) {
693
                        isRelative = false;
706
                        isRelative = false;
694
                        p+=9;
707
                        p+=9;
695
                } else if (__STRNICMP_LOCAL(p, "RELATIVE.", 9) == 0) {
708
                } else if (__STRNICMP_LOCAL(p, "RELATIVE.", 9) == 0) {
696
                        isRelative = true;
709
                        isRelative = true;
697
                        p+=9;
710
                        p+=9;
698
                } else {
711
                } else {
699
                        // use the CLI option
712
                        // use the CLI option
700
                        // isRelative = false;
713
                        // isRelative = false;
701
                }
714
                }
702
 
715
 
703
                cl = 0x00; // Class. Always UNIVERSAL (00)
716
                cl = 0x00; // Class. Always UNIVERSAL (00)
704
 
717
 
705
                // Tag for Universal Class
718
                // Tag for Universal Class
706
                if (isRelative) {
719
                if (isRelative) {
707
                        cl |= 0x0D;
720
                        cl |= 0x0D;
708
                } else {
721
                } else {
709
                        cl |= 0x06;
722
                        cl |= 0x06;
710
                }
723
                }
711
 
724
 
712
                /* if (__STRNICMP_LOCAL(p, "OID.", 4) == 0) {
725
                /* if (__STRNICMP_LOCAL(p, "OID.", 4) == 0) {
713
                        p+=4;
726
                        p+=4;
714
                } */
727
                } */
715
 
728
 
716
                q = p;
729
                q = p;
717
                nPieces = 1;
730
                nPieces = 1;
718
                while (*p) {
731
                while (*p) {
719
                        if (*p == '.') {
732
                        if (*p == '.') {
720
                                nPieces++;
733
                                nPieces++;
721
                        }
734
                        }
722
                        p++;
735
                        p++;
723
                }
736
                }
724
 
737
 
725
                n = 0;
738
                n = 0;
726
                b = 0;
739
                b = 0;
727
                p = q;
740
                p = q;
728
                while (n < nPieces) {
741
                while (n < nPieces) {
729
                        q = p;
742
                        q = p;
730
                        while (*p) {
743
                        while (*p) {
731
                                if (*p == '.') {
744
                                if (*p == '.') {
732
                                        break;
745
                                        break;
733
                                }
746
                                }
734
                                p++;
747
                                p++;
735
                        }
748
                        }
736
 
749
 
737
                        #ifdef is_gmp
750
                        #ifdef is_gmp
738
                        mpz_init(l);
751
                        mpz_init(l);
739
                        #else
752
                        #else
740
                        l = 0;
753
                        l = 0;
741
                        #endif
754
                        #endif
742
                        if (*p == '.') {
755
                        if (*p == '.') {
743
                                *p = 0;
756
                                *p = 0;
744
                                #ifdef is_gmp
757
                                #ifdef is_gmp
745
                                mpz_set_str(l, q, 10);
758
                                mpz_set_str(l, q, 10);
746
                                #else
759
                                #else
747
                                l = (unsigned long) atoi(q);
760
                                l = (unsigned long) atoi(q);
748
                                #endif
761
                                #endif
749
                                q = p+1;
762
                                q = p+1;
750
                                p = q;
763
                                p = q;
751
                        } else {
764
                        } else {
752
                                #ifdef is_gmp
765
                                #ifdef is_gmp
753
                                mpz_set_str(l, q, 10);
766
                                mpz_set_str(l, q, 10);
754
                                #else
767
                                #else
755
                                l = (unsigned long) atoi(q);
768
                                l = (unsigned long) atoi(q);
756
                                #endif
769
                                #endif
757
                                q = p;
770
                                q = p;
758
                        }
771
                        }
759
 
772
 
760
                        /* Digit is in l. */
773
                        /* Digit is in l. */
761
                        if ((!isRelative) && (n == 0)) {
774
                        if ((!isRelative) && (n == 0)) {
762
                                #ifdef is_gmp
775
                                #ifdef is_gmp
763
                                if (mpz_cmp_ui(l, 2) > 0) {
776
                                if (mpz_cmp_ui(l, 2) > 0) {
764
                                #else
777
                                #else
765
                                if (l > 2) {
778
                                if (l > 2) {
766
                                #endif
779
                                #endif
767
                                        fprintf(stderr, "\nEncoding error. The top arc is limited to 0, 1 and 2.\n");
780
                                        fprintf(stderr, "\nEncoding error. The top arc is limited to 0, 1 and 2.\n");
768
                                        return 5;
781
                                        return 5;
769
                                }
782
                                }
770
                                #ifdef is_gmp
783
                                #ifdef is_gmp
771
                                b += 40 * mpz_get_ui(l);
784
                                b += 40 * mpz_get_ui(l);
772
                                isjoint = mpz_cmp_ui(l, 2) == 0;
785
                                isjoint = mpz_cmp_ui(l, 2) == 0;
773
                                #else
786
                                #else
774
                                b = 40 * ((unsigned char)l);
787
                                b = 40 * ((unsigned char)l);
775
                                isjoint = l == 2;
788
                                isjoint = l == 2;
776
                                #endif
789
                                #endif
777
                        } else if ((!isRelative) && (n == 1)) {
790
                        } else if ((!isRelative) && (n == 1)) {
778
                                #ifdef is_gmp
791
                                #ifdef is_gmp
779
                                if ((!isjoint) && (mpz_cmp_ui(l, 39) > 0)) {
792
                                if ((!isjoint) && (mpz_cmp_ui(l, 39) > 0)) {
780
                                #else
793
                                #else
781
                                if ((l > 39) && (!isjoint)) {
794
                                if ((l > 39) && (!isjoint)) {
782
                                #endif
795
                                #endif
783
                                        fprintf(stderr, "\nEncoding error. The second arc is limited to 0..39 for root arcs 0 and 1.\n");
796
                                        fprintf(stderr, "\nEncoding error. The second arc is limited to 0..39 for root arcs 0 and 1.\n");
784
                                        return 5;
797
                                        return 5;
785
                                }
798
                                }
786
 
799
 
787
                                #ifdef is_gmp
800
                                #ifdef is_gmp
788
                                if (mpz_cmp_ui(l, 47) > 0) {
801
                                if (mpz_cmp_ui(l, 47) > 0) {
789
                                        mpz_add_ui(l, l, 80);
802
                                        mpz_add_ui(l, l, 80);
790
                                        MakeBase128(l, 1);
803
                                        MakeBase128(l, 1);
791
                                } else {
804
                                } else {
792
                                        b += mpz_get_ui(l);
805
                                        b += mpz_get_ui(l);
793
                                        if (nBinary+1 >= abb_size) {
806
                                        if (nBinary+1 >= abb_size) {
794
                                                abb_size += ABB_EXPANSION_SIZE;
807
                                                abb_size += ABB_EXPANSION_SIZE;
795
                                                abBinary = (unsigned char*) realloc(abBinary, abb_size);
808
                                                abBinary = (unsigned char*) realloc(abBinary, abb_size);
796
                                                if (abBinary == NULL) {
809
                                                if (abBinary == NULL) {
797
                                                        fprintf(stderr, "Memory reallocation failure!\n");
810
                                                        fprintf(stderr, "Memory reallocation failure!\n");
798
                                                        return EXIT_FAILURE;
811
                                                        return EXIT_FAILURE;
799
                                                }
812
                                                }
800
                                        }
813
                                        }
801
                                        abBinary[nBinary++] = b;
814
                                        abBinary[nBinary++] = b;
802
                                }
815
                                }
803
                                #else
816
                                #else
804
                                if (l > 47) {
817
                                if (l > 47) {
805
                                        l += 80;
818
                                        l += 80;
806
                                        MakeBase128(l, 1);
819
                                        MakeBase128(l, 1);
807
                                } else {
820
                                } else {
808
                                        b += ((unsigned char) l);
821
                                        b += ((unsigned char) l);
809
                                        if (nBinary+1 >= abb_size) {
822
                                        if (nBinary+1 >= abb_size) {
810
                                                abb_size += ABB_EXPANSION_SIZE;
823
                                                abb_size += ABB_EXPANSION_SIZE;
811
                                                abBinary = (unsigned char*) realloc(abBinary, abb_size);
824
                                                abBinary = (unsigned char*) realloc(abBinary, abb_size);
812
                                                if (abBinary == NULL) {
825
                                                if (abBinary == NULL) {
813
                                                        fprintf(stderr, "Memory reallocation failure!\n");
826
                                                        fprintf(stderr, "Memory reallocation failure!\n");
814
                                                        return EXIT_FAILURE;
827
                                                        return EXIT_FAILURE;
815
                                                }
828
                                                }
816
                                        }
829
                                        }
817
                                        abBinary[nBinary++] = b;
830
                                        abBinary[nBinary++] = b;
818
                                }
831
                                }
819
                                #endif
832
                                #endif
820
                        } else {
833
                        } else {
821
                                MakeBase128(l, 1);
834
                                MakeBase128(l, 1);
822
                        }
835
                        }
823
                        n++;
836
                        n++;
824
                }
837
                }
825
 
838
 
826
                if ((!isRelative) && (n < 2)) {
839
                if ((!isRelative) && (n < 2)) {
827
                        fprintf(stderr, "\nEncoding error. The minimum depth of an encodeable absolute OID is 2. (e.g. 2.999)\n");
840
                        fprintf(stderr, "\nEncoding error. The minimum depth of an encodeable absolute OID is 2. (e.g. 2.999)\n");
828
                        return 5;
841
                        return 5;
829
                }
842
                }
830
 
843
 
831
                if (fOutName != NULL) {
844
                if (fOutName != NULL) {
832
                        fOut = fopen(fOutName, "wt");
845
                        fOut = fopen(fOutName, "wt");
833
                        if (fOut == NULL) {
846
                        if (fOut == NULL) {
834
                                fprintf(stderr, "Unable to open output file %s\n", fOutName);
847
                                fprintf(stderr, "Unable to open output file %s\n", fOutName);
835
                                return 33;
848
                                return 33;
836
                        }
849
                        }
837
                } else {
850
                } else {
838
                        fOut = stdout;
851
                        fOut = stdout;
839
                }
852
                }
840
 
853
 
841
                // Write class-tag
854
                // Write class-tag
842
                if (nCHex) {
855
                if (nCHex == 1) {
-
 
856
                        fprintf(fOut, "{ 0x%02X, ", cl);
-
 
857
                } else if (nCHex == 2) {
843
                        fprintf(fOut, "\"\\x%02X", cl);
858
                        fprintf(fOut, "\"\\x%02X", cl);
844
                } else {
859
                } else {
845
                        fprintf(fOut, "%02X ", cl);
860
                        fprintf(fOut, "%02X ", cl);
846
                }
861
                }
847
 
862
 
848
                // Write length
863
                // Write length
849
                if (nBinary <= 0x7F) {
864
                if (nBinary <= 0x7F) {
850
                        if (nCHex) {
865
                        if (nCHex == 1) {
-
 
866
                                fprintf(fOut, "0x%02X, ", nBinary);
-
 
867
                        } else if (nCHex == 2) {
851
                                fprintf(fOut, "\\x%02X", nBinary);
868
                                fprintf(fOut, "\\x%02X", nBinary);
852
                        } else {
869
                        } else {
853
                                fprintf(fOut, "%02X ", nBinary);
870
                                fprintf(fOut, "%02X ", nBinary);
854
                        }
871
                        }
855
                } else {
872
                } else {
856
                        unsigned int nBinaryWork;
873
                        unsigned int nBinaryWork;
857
                        unsigned int lengthCount = 0;
874
                        unsigned int lengthCount = 0;
858
 
875
 
859
                        nBinaryWork = nBinary;
876
                        nBinaryWork = nBinary;
860
                        do {
877
                        do {
861
                                lengthCount++;
878
                                lengthCount++;
862
                                nBinaryWork /= 0x100;
879
                                nBinaryWork /= 0x100;
863
                        } while (nBinaryWork > 0);
880
                        } while (nBinaryWork > 0);
864
 
881
 
865
                        if (lengthCount >= 0x7F) {
882
                        if (lengthCount >= 0x7F) {
866
                                fprintf(stderr, "\nThe length cannot be encoded.\n");
883
                                fprintf(stderr, "\nThe length cannot be encoded.\n");
867
                                return 8;
884
                                return 8;
868
                        }
885
                        }
869
 
886
 
870
                        if (nCHex) {
887
                        if (nCHex == 1) {
-
 
888
                                fprintf(fOut, "0x%02X, ", 0x80 + lengthCount);
-
 
889
                        } else if (nCHex == 2) {
871
                                fprintf(fOut, "\\x%02X", 0x80 + lengthCount);
890
                                fprintf(fOut, "\\x%02X", 0x80 + lengthCount);
872
                        } else {
891
                        } else {
873
                                fprintf(fOut, "%02X ", 0x80 + lengthCount);
892
                                fprintf(fOut, "%02X ", 0x80 + lengthCount);
874
                        }
893
                        }
875
 
894
 
876
                        nBinaryWork = nBinary;
895
                        nBinaryWork = nBinary;
877
                        do {
896
                        do {
878
                                if (nCHex) {
897
                                if (nCHex == 1) {
-
 
898
                                        fprintf(fOut, "0x%02X, ", nBinaryWork & 0xFF);
-
 
899
                                } else if (nCHex == 2) {
879
                                        fprintf(fOut, "\\x%02X", nBinaryWork & 0xFF);
900
                                        fprintf(fOut, "\\x%02X", nBinaryWork & 0xFF);
880
                                } else {
901
                                } else {
881
                                        fprintf(fOut, "%02X ", nBinaryWork & 0xFF);
902
                                        fprintf(fOut, "%02X ", nBinaryWork & 0xFF);
882
                                }
903
                                }
883
                                nBinaryWork /= 0x100;
904
                                nBinaryWork /= 0x100;
884
                        } while (nBinaryWork > 0);
905
                        } while (nBinaryWork > 0);
885
                }
906
                }
886
 
907
 
887
                nn = 0;
908
                nn = 0;
888
                while (nn < nBinary) {
909
                while (nn < nBinary) {
889
                        unsigned char b = abBinary[nn++];
910
                        unsigned char b = abBinary[nn++];
890
                        if (nn == nBinary) {
911
                        if (nn == nBinary) {
891
                                if (nCHex) {
912
                                if (nCHex == 1) {
-
 
913
                                        fprintf(fOut, "0x%02X }\n", b);
-
 
914
                                } else if (nCHex == 2) {
892
                                        fprintf(fOut, "\\x%02X\"\n", b);
915
                                        fprintf(fOut, "\\x%02X\"\n", b);
893
                                } else {
916
                                } else {
894
                                        fprintf(fOut, "%02X\n", b);
917
                                        fprintf(fOut, "%02X\n", b);
895
                                }
918
                                }
896
                        } else {
919
                        } else {
897
                                if (nCHex) {
920
                                if (nCHex == 1) {
-
 
921
                                        fprintf(fOut, "0x%02X, ", b);
-
 
922
                                } else if (nCHex == 2) {
898
                                        fprintf(fOut, "\\x%02X", b);
923
                                        fprintf(fOut, "\\x%02X", b);
899
                                } else {
924
                                } else {
900
                                        fprintf(fOut, "%02X ", b);
925
                                        fprintf(fOut, "%02X ", b);
901
                                }
926
                                }
902
                        }
927
                        }
903
                }
928
                }
904
                if (fOut != stdout) {
929
                if (fOut != stdout) {
905
                        fclose(fOut);
930
                        fclose(fOut);
906
                }
931
                }
907
                break;
932
                break;
908
        }
933
        }
909
 
934
 
910
        free(abCommandLine);
935
        free(abCommandLine);
911
        free(abBinary);
936
        free(abBinary);
912
 
937
 
913
        return 0;
938
        return 0;
914
}
939
}
915
 
940