2 Unix SMB/Netbios implementation.
5 Copyright (C) Andrew Tridgell 2001
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.
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.
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.
22 #include <sys/types.h>
31 #define Realloc realloc
43 struct nesting *nesting;
46 static BOOL asn1_write(ASN1_DATA data, void *p, int len)
48 if (data.length < data.ofs+len) {
49 data.data = Realloc(data.data, data.ofs+len);
50 if (!data.data) return False;
51 data.length = data.ofs+len;
53 memcpy(data.data + data.ofs, p, len);
57 static BOOL asn1_push_tag(ASN1_DATA data, const char *tagstr, uint8 tag)
59 struct nesting *nesting;
62 asn1_write(data, tag);
63 nesting = (struct nesting *)malloc(sizeof(struct nesting));
64 if (!nesting) return False;
66 nesting->start = data.ofs;
67 nesting->name = strdup(tagstr);
68 nesting->next = data.nesting;
69 data.nesting = nesting;
71 asn1_write(data, &fill, 1);
75 static BOOL asn1_pop_tag(ASN1_DATA data, const char *tagstr)
77 struct nesting *nesting;
79 nesting = data.nesting;
81 if (!nesting || strcmp(tagstr, nesting->name) != 0) {
84 data.data[nesting->start] = data.ofs - nesting->start;
85 data.nesting = nesting->next;
92 static BOOL asn1_write_uint8(ASN1_DATA data, uint8 v)
94 return asn1_write(data, &v, 1);
98 static BOOL asn1_write_OID(ASN1_DATA data, const char *OID)
101 char *p = (char *)OID;
103 asn1_push_tag(data, "OID", 0x6);
104 v = strtol(p, &p, 10);
105 v2 = strtol(p, &p, 10);
106 asn1_write_uint8(data, 40*v + v2);
108 v = strtol(p, &p, 10);
109 if (v >= (1<<29)) asn1_write_uint8(data, 0x80 | ((v>>29)&0xff));
110 if (v >= (1<<22)) asn1_write_uint8(data, 0x80 | ((v>>22)&0xff));
111 if (v >= (1<<15)) asn1_write_uint8(data, 0x80 | ((v>>15)&0xff));
112 if (v >= (1<<8)) asn1_write_uint8(data, 0x80 | ((v>>8)&0xff));
113 asn1_write_uint8(data, 0x80 | ((v>>15)&0xff));
115 asn1_pop_tag(data, "OID");
119 static BOOL asn1_write_GeneralString(ASN1_DATA data, const char *s)
121 asn1_push_tag(data, "GS", 0x1b);
122 asn1_write(data, s, strlen(s));
123 asn1_pop_tag(data, "GS");
127 generate a negTokenInit packet given a GUID, a list of supported
128 OIDs (the mechanisms) and a principle name string
130 PACKET_DATA spnego_gen_negTokenInit(uint8 guid[16],
132 const char *principle)
140 asn1_write(data, guid, 16);
141 asn1_push_tag(data,"SPNEGO", 0x60);
142 asn1_write_OID(data,"1 3 6 1 5 5 2");
143 asn1_push_tag(data,"MECHS", 0xa0);
144 asn1_push_tag(data,"SEQ1", 0x30);
146 asn1_push_tag(data,"[0]", 0xa0);
147 asn1_push_tag(data,"SEQ1.1", 0x30);
148 for (i=0; OIDs[i]; i++) {
149 asn1_write_OID(data,OIDs[i]);
151 asn1_pop_tag(data,"SEQ1.1");
152 asn1_pop_tag(data,"[0]");
154 asn1_push_tag(data,"[3]", 0xa3);
155 asn1_push_tag(data,"SEQ1.2", 0x30);
156 asn1_push_tag(data,"[0]", 0xa0);
157 asn1_write_GeneralString(data,principle);
158 asn1_pop_tag(data,"[0]");
159 asn1_pop_tag(data,"SEQ1.2");
160 asn1_pop_tag(data,"[3]");
162 asn1_pop_tag(data,"SEQ1");
163 asn1_pop_tag(data,"MECHS");
165 asn1_check_empty(data);
173 uint8 guid[16] = "012345678901234";
175 data = spnego_gen_negTokenInit(guid,
176 {"1 2 840 48018 1 2 2", "1 2 840 113554 1 2 2"},
177 "blu$@VNET2.HOME.SAMBA.ORG");