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 |