initial kerberos/ADS/SPNEGO support in libsmb and smbclient. To
[kai/samba.git] / source3 / libsmb / asn1.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 3.0
4    simple SPNEGO routines
5    Copyright (C) Andrew Tridgell 2001
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24 void asn1_free(ASN1_DATA *data)
25 {
26         free(data->data);
27 }
28
29 BOOL asn1_check_empty(ASN1_DATA *data)
30 {
31         if (data->nesting) return False;
32         return True;
33 }
34
35 BOOL asn1_write(ASN1_DATA *data, const void *p, int len)
36 {
37         if (data->length < data->ofs+len) {
38                 data->data = Realloc(data->data, data->ofs+len);
39                 if (!data->data) return False;
40                 data->length = data->ofs+len;
41         }
42         memcpy(data->data + data->ofs, p, len);
43         data->ofs += len;
44         return True;
45 }
46
47 BOOL asn1_write_uint8(ASN1_DATA *data, uint8 v)
48 {
49         return asn1_write(data, &v, 1);
50 }
51
52 BOOL asn1_push_tag(ASN1_DATA *data, uint8 tag)
53 {
54         struct nesting *nesting;
55
56         asn1_write_uint8(data, tag);
57         nesting = (struct nesting *)malloc(sizeof(struct nesting));
58         if (!nesting) return False;
59
60         nesting->start = data->ofs;
61         nesting->next = data->nesting;
62         data->nesting = nesting;
63         asn1_write_uint8(data, 0xff);
64         return True;
65 }
66
67 BOOL asn1_pop_tag(ASN1_DATA *data)
68 {
69         struct nesting *nesting;
70         size_t len;
71
72         nesting = data->nesting;
73
74         if (!nesting) {
75                 return False;
76         }
77         len = data->ofs - (nesting->start+1);
78         if (len > 127) {
79                 data->data[nesting->start] = 0x82;
80                 asn1_write_uint8(data, 0);
81                 asn1_write_uint8(data, 0);
82                 memmove(data->data+nesting->start+3, data->data+nesting->start+1, len);
83                 data->data[nesting->start+1] = len>>8;
84                 data->data[nesting->start+2] = len&0xff;
85         } else {
86                 data->data[nesting->start] = len;
87         }
88
89         data->nesting = nesting->next;
90         free(nesting);
91         return True;
92 }
93
94
95 BOOL asn1_write_OID(ASN1_DATA *data, const char *OID)
96 {
97         unsigned v, v2;
98         char *p = (char *)OID;
99
100         asn1_push_tag(data, ASN1_OID);
101         v = strtol(p, &p, 10);
102         v2 = strtol(p, &p, 10);
103         asn1_write_uint8(data, 40*v + v2);
104
105         while (*p) {
106                 v = strtol(p, &p, 10);
107                 if (v >= (1<<28)) asn1_write_uint8(data, 0x80 | ((v>>28)&0xff));
108                 if (v >= (1<<21)) asn1_write_uint8(data, 0x80 | ((v>>21)&0xff));
109                 if (v >= (1<<14)) asn1_write_uint8(data, 0x80 | ((v>>14)&0xff));
110                 if (v >= (1<<7)) asn1_write_uint8(data, 0x80 | ((v>>7)&0xff));
111                 asn1_write_uint8(data, v&0x7f);
112         }
113         asn1_pop_tag(data);
114         return True;
115 }
116
117 BOOL asn1_write_OctetString(ASN1_DATA *data, const void *p, size_t length)
118 {
119         asn1_push_tag(data, ASN1_OCTET_STRING);
120         asn1_write(data, p, length);
121         asn1_pop_tag(data);
122         return True;
123 }
124
125 BOOL asn1_write_GeneralString(ASN1_DATA *data, const char *s)
126 {
127         asn1_push_tag(data, ASN1_GENERAL_STRING);
128         asn1_write(data, s, strlen(s));
129         asn1_pop_tag(data);
130         return True;
131 }
132
133 BOOL asn1_write_BOOLEAN(ASN1_DATA *data, BOOL v)
134 {
135         asn1_write_uint8(data, ASN1_BOOLEAN);
136         asn1_write_uint8(data, v);
137         return True;
138 }
139