c12e3a5cd3b313c5d757a1c6db35820f8856e2b9
[krb5.git] / src / lib / krb5 / asn.1 / asn1_decode.c
1 /*
2  * src/lib/krb5/asn.1/asn1_decode.c
3  * 
4  * Copyright 1994 by the Massachusetts Institute of Technology.
5  * All Rights Reserved.
6  *
7  * Export of this software from the United States of America may
8  *   require a specific license from the United States Government.
9  *   It is the responsibility of any person or organization contemplating
10  *   export to obtain such a license before exporting.
11  * 
12  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13  * distribute this software and its documentation for any purpose and
14  * without fee is hereby granted, provided that the above copyright
15  * notice appear in all copies and that both that copyright notice and
16  * this permission notice appear in supporting documentation, and that
17  * the name of M.I.T. not be used in advertising or publicity pertaining
18  * to distribution of the software without specific, written prior
19  * permission.  M.I.T. makes no representations about the suitability of
20  * this software for any purpose.  It is provided "as is" without express
21  * or implied warranty.
22  */
23
24 #include <stdio.h>
25 /* ASN.1 primitive decoders */
26 #include "asn1_decode.h"
27 #include "asn1_get.h"
28 #ifdef HAVE_SYS_TIME_H
29 #include <sys/time.h>
30 #ifdef TIME_WITH_SYS_TIME
31 #include <time.h>
32 #endif
33 #else
34 #include <time.h>
35 #endif
36
37 #define setup()\
38 asn1_error_code retval;\
39 asn1_class class;\
40 asn1_construction construction;\
41 asn1_tagnum tagnum;\
42 int length
43
44 #define tag(type)\
45 retval = asn1_get_tag(buf,&class,&construction,&tagnum,&length);\
46 if(retval) return retval;\
47 if(class != UNIVERSAL || construction != PRIMITIVE || tagnum != type)\
48   return ASN1_BAD_ID
49   
50 #define cleanup()\
51 return 0
52
53 time_t gmt_mktime PROTOTYPE((struct tm *));
54
55 asn1_error_code INTERFACE asn1_decode_integer(buf, val)
56      asn1buf * buf;
57      long * val;
58 {
59   setup();
60   asn1_octet o;
61   unsigned long n;
62
63   tag(ASN1_INTEGER);
64
65   for(n=0; length > 0; length--){
66     retval = asn1buf_remove_octet(buf,&o);
67     if(retval) return retval;
68     n = (n<<8) + (unsigned int)o;
69   }
70   *val = n;
71   cleanup();
72 }
73
74 asn1_error_code INTERFACE asn1_decode_unsigned_integer(buf, val)
75      asn1buf * buf;
76      unsigned long * val;
77 {
78   setup();
79   asn1_octet o;
80   unsigned long n;
81
82   tag(ASN1_INTEGER);
83
84   for(n=0; length > 0; length--){
85     retval = asn1buf_remove_octet(buf,&o);
86     if(retval) return retval;
87     n = (n<<8) + (unsigned int)o;
88   }
89   *val = n;
90   cleanup();
91 }
92
93 asn1_error_code INTERFACE asn1_decode_octetstring(buf, retlen, val)
94      asn1buf * buf;
95      int * retlen;
96      asn1_octet ** val;
97 {
98   setup();
99   tag(ASN1_OCTETSTRING);
100   retval = asn1buf_remove_octetstring(buf,length,val);
101   if(retval) return retval;
102   *retlen = length;
103   cleanup();
104 }
105
106 asn1_error_code INTERFACE asn1_decode_charstring(buf, retlen, val)
107      asn1buf * buf;
108      int * retlen;
109      char ** val;
110 {
111   setup();
112   tag(ASN1_OCTETSTRING);
113   retval = asn1buf_remove_charstring(buf,length,val);
114   if(retval) return retval;
115   *retlen = length;
116   cleanup();
117 }
118
119
120 asn1_error_code INTERFACE asn1_decode_generalstring(buf, retlen, val)
121      asn1buf * buf;
122      int * retlen;
123      char ** val;
124 {
125   setup();
126   tag(ASN1_GENERALSTRING);
127   retval = asn1buf_remove_charstring(buf,length,val);
128   if(retval) return retval;
129   *retlen = length;
130   cleanup();
131 }
132
133
134 asn1_error_code INTERFACE asn1_decode_null(buf)
135      asn1buf * buf;
136 {
137   setup();
138   tag(ASN1_NULL);
139   if(length != 0) return ASN1_BAD_LENGTH;
140   cleanup();
141 }
142
143 asn1_error_code INTERFACE asn1_decode_printablestring(buf, retlen, val)
144      asn1buf * buf;
145      int * retlen;
146      char ** val;
147 {
148   setup();
149   tag(ASN1_PRINTABLESTRING);
150   retval = asn1buf_remove_charstring(buf,length,val);
151   if(retval) return retval;
152   *retlen = length;
153   cleanup();
154 }
155
156 asn1_error_code INTERFACE asn1_decode_ia5string(buf, retlen, val)
157      asn1buf * buf;
158      int * retlen;
159      char ** val;
160 {
161   setup();
162   tag(ASN1_IA5STRING);
163   retval = asn1buf_remove_charstring(buf,length,val);
164   if(retval) return retval;
165   *retlen = length;
166   cleanup();
167 }
168
169 asn1_error_code INTERFACE asn1_decode_generaltime(buf, val)
170      asn1buf * buf;
171      time_t * val;
172 {
173   setup();
174   char *s;
175   struct tm ts;
176   time_t t;
177
178   tag(ASN1_GENERALTIME);
179
180   if(length != 15) return ASN1_BAD_LENGTH;
181   retval = asn1buf_remove_charstring(buf,15,&s);
182   /* Time encoding: YYYYMMDDhhmmssZ */
183   if(s[14] != 'Z') {
184       free(s);
185       return ASN1_BAD_FORMAT;
186   }
187 #define c2i(c) ((c)-'0')
188   ts.tm_year = 1000*c2i(s[0]) + 100*c2i(s[1]) + 10*c2i(s[2]) + c2i(s[3])
189     - 1900;
190   ts.tm_mon = 10*c2i(s[4]) + c2i(s[5]) - 1;
191   ts.tm_mday = 10*c2i(s[6]) + c2i(s[7]);
192   ts.tm_hour = 10*c2i(s[8]) + c2i(s[9]);
193   ts.tm_min = 10*c2i(s[10]) + c2i(s[11]);
194   ts.tm_sec = 10*c2i(s[12]) + c2i(s[13]);
195   ts.tm_isdst = -1;
196   t = gmt_mktime(&ts);
197   free(s);
198
199   if(t == -1) return ASN1_BAD_TIMEFORMAT;
200
201   *val = t;
202   cleanup();
203 }