Subversion Repositories oidconverter

Rev

Rev 7 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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