1/*
2 * The ASB.1/BER parsing code is derived from ip_nat_snmp_basic.c which was in
3 * turn derived from the gxsnmp package by Gregory McLean & Jochen Friedrich
4 *
5 * Copyright (c) 2000 RP Internet (www.rpi.net.au).
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 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18 */
19
20#include <linux/module.h>
21#include <linux/types.h>
22#include <linux/kernel.h>
23#include <linux/mm.h>
24#include <linux/slab.h>
25#include "cifspdu.h"
26#include "cifsglob.h"
27#include "cifs_debug.h"
28#include "cifsproto.h"
29
30/*****************************************************************************
31 *
32 * Basic ASN.1 decoding routines (gxsnmp author Dirk Wisse)
33 *
34 *****************************************************************************/
35
36/* Class */
37#define ASN1_UNI	0	/* Universal */
38#define ASN1_APL	1	/* Application */
39#define ASN1_CTX	2	/* Context */
40#define ASN1_PRV	3	/* Private */
41
42/* Tag */
43#define ASN1_EOC	0	/* End Of Contents or N/A */
44#define ASN1_BOL	1	/* Boolean */
45#define ASN1_INT	2	/* Integer */
46#define ASN1_BTS	3	/* Bit String */
47#define ASN1_OTS	4	/* Octet String */
48#define ASN1_NUL	5	/* Null */
49#define ASN1_OJI	6	/* Object Identifier  */
50#define ASN1_OJD	7	/* Object Description */
51#define ASN1_EXT	8	/* External */
52#define ASN1_SEQ	16	/* Sequence */
53#define ASN1_SET	17	/* Set */
54#define ASN1_NUMSTR	18	/* Numerical String */
55#define ASN1_PRNSTR	19	/* Printable String */
56#define ASN1_TEXSTR	20	/* Teletext String */
57#define ASN1_VIDSTR	21	/* Video String */
58#define ASN1_IA5STR	22	/* IA5 String */
59#define ASN1_UNITIM	23	/* Universal Time */
60#define ASN1_GENTIM	24	/* General Time */
61#define ASN1_GRASTR	25	/* Graphical String */
62#define ASN1_VISSTR	26	/* Visible String */
63#define ASN1_GENSTR	27	/* General String */
64
65/* Primitive / Constructed methods*/
66#define ASN1_PRI	0	/* Primitive */
67#define ASN1_CON	1	/* Constructed */
68
69/*
70 * Error codes.
71 */
72#define ASN1_ERR_NOERROR		0
73#define ASN1_ERR_DEC_EMPTY		2
74#define ASN1_ERR_DEC_EOC_MISMATCH	3
75#define ASN1_ERR_DEC_LENGTH_MISMATCH	4
76#define ASN1_ERR_DEC_BADVALUE		5
77
78#define SPNEGO_OID_LEN 7
79#define NTLMSSP_OID_LEN  10
80static unsigned long SPNEGO_OID[7] = { 1, 3, 6, 1, 5, 5, 2 };
81static unsigned long NTLMSSP_OID[10] = { 1, 3, 6, 1, 4, 1, 311, 2, 2, 10 };
82
83/*
84 * ASN.1 context.
85 */
86struct asn1_ctx {
87	int error;		/* Error condition */
88	unsigned char *pointer;	/* Octet just to be decoded */
89	unsigned char *begin;	/* First octet */
90	unsigned char *end;	/* Octet after last octet */
91};
92
93/*
94 * Octet string (not null terminated)
95 */
96struct asn1_octstr {
97	unsigned char *data;
98	unsigned int len;
99};
100
101static void
102asn1_open(struct asn1_ctx *ctx, unsigned char *buf, unsigned int len)
103{
104	ctx->begin = buf;
105	ctx->end = buf + len;
106	ctx->pointer = buf;
107	ctx->error = ASN1_ERR_NOERROR;
108}
109
110static unsigned char
111asn1_octet_decode(struct asn1_ctx *ctx, unsigned char *ch)
112{
113	if (ctx->pointer >= ctx->end) {
114		ctx->error = ASN1_ERR_DEC_EMPTY;
115		return 0;
116	}
117	*ch = *(ctx->pointer)++;
118	return 1;
119}
120
121static unsigned char
122asn1_tag_decode(struct asn1_ctx *ctx, unsigned int *tag)
123{
124	unsigned char ch;
125
126	*tag = 0;
127
128	do {
129		if (!asn1_octet_decode(ctx, &ch))
130			return 0;
131		*tag <<= 7;
132		*tag |= ch & 0x7F;
133	} while ((ch & 0x80) == 0x80);
134	return 1;
135}
136
137static unsigned char
138asn1_id_decode(struct asn1_ctx *ctx,
139	       unsigned int *cls, unsigned int *con, unsigned int *tag)
140{
141	unsigned char ch;
142
143	if (!asn1_octet_decode(ctx, &ch))
144		return 0;
145
146	*cls = (ch & 0xC0) >> 6;
147	*con = (ch & 0x20) >> 5;
148	*tag = (ch & 0x1F);
149
150	if (*tag == 0x1F) {
151		if (!asn1_tag_decode(ctx, tag))
152			return 0;
153	}
154	return 1;
155}
156
157static unsigned char
158asn1_length_decode(struct asn1_ctx *ctx, unsigned int *def, unsigned int *len)
159{
160	unsigned char ch, cnt;
161
162	if (!asn1_octet_decode(ctx, &ch))
163		return 0;
164
165	if (ch == 0x80)
166		*def = 0;
167	else {
168		*def = 1;
169
170		if (ch < 0x80)
171			*len = ch;
172		else {
173			cnt = (unsigned char) (ch & 0x7F);
174			*len = 0;
175
176			while (cnt > 0) {
177				if (!asn1_octet_decode(ctx, &ch))
178					return 0;
179				*len <<= 8;
180				*len |= ch;
181				cnt--;
182			}
183		}
184	}
185	return 1;
186}
187
188static unsigned char
189asn1_header_decode(struct asn1_ctx *ctx,
190		   unsigned char **eoc,
191		   unsigned int *cls, unsigned int *con, unsigned int *tag)
192{
193	unsigned int def = 0;
194	unsigned int len = 0;
195
196	if (!asn1_id_decode(ctx, cls, con, tag))
197		return 0;
198
199	if (!asn1_length_decode(ctx, &def, &len))
200		return 0;
201
202	if (def)
203		*eoc = ctx->pointer + len;
204	else
205		*eoc = NULL;
206	return 1;
207}
208
209static unsigned char
210asn1_eoc_decode(struct asn1_ctx *ctx, unsigned char *eoc)
211{
212	unsigned char ch;
213
214	if (eoc == NULL) {
215		if (!asn1_octet_decode(ctx, &ch))
216			return 0;
217
218		if (ch != 0x00) {
219			ctx->error = ASN1_ERR_DEC_EOC_MISMATCH;
220			return 0;
221		}
222
223		if (!asn1_octet_decode(ctx, &ch))
224			return 0;
225
226		if (ch != 0x00) {
227			ctx->error = ASN1_ERR_DEC_EOC_MISMATCH;
228			return 0;
229		}
230		return 1;
231	} else {
232		if (ctx->pointer != eoc) {
233			ctx->error = ASN1_ERR_DEC_LENGTH_MISMATCH;
234			return 0;
235		}
236		return 1;
237	}
238}
239
240/* static unsigned char asn1_null_decode(struct asn1_ctx *ctx,
241				      unsigned char *eoc)
242{
243	ctx->pointer = eoc;
244	return 1;
245}
246
247static unsigned char asn1_long_decode(struct asn1_ctx *ctx,
248				      unsigned char *eoc, long *integer)
249{
250	unsigned char ch;
251	unsigned int len;
252
253	if (!asn1_octet_decode(ctx, &ch))
254		return 0;
255
256	*integer = (signed char) ch;
257	len = 1;
258
259	while (ctx->pointer < eoc) {
260		if (++len > sizeof(long)) {
261			ctx->error = ASN1_ERR_DEC_BADVALUE;
262			return 0;
263		}
264
265		if (!asn1_octet_decode(ctx, &ch))
266			return 0;
267
268		*integer <<= 8;
269		*integer |= ch;
270	}
271	return 1;
272}
273
274static unsigned char asn1_uint_decode(struct asn1_ctx *ctx,
275				      unsigned char *eoc,
276				      unsigned int *integer)
277{
278	unsigned char ch;
279	unsigned int len;
280
281	if (!asn1_octet_decode(ctx, &ch))
282		return 0;
283
284	*integer = ch;
285	if (ch == 0)
286		len = 0;
287	else
288		len = 1;
289
290	while (ctx->pointer < eoc) {
291		if (++len > sizeof(unsigned int)) {
292			ctx->error = ASN1_ERR_DEC_BADVALUE;
293			return 0;
294		}
295
296		if (!asn1_octet_decode(ctx, &ch))
297			return 0;
298
299		*integer <<= 8;
300		*integer |= ch;
301	}
302	return 1;
303}
304
305static unsigned char asn1_ulong_decode(struct asn1_ctx *ctx,
306				       unsigned char *eoc,
307				       unsigned long *integer)
308{
309	unsigned char ch;
310	unsigned int len;
311
312	if (!asn1_octet_decode(ctx, &ch))
313		return 0;
314
315	*integer = ch;
316	if (ch == 0)
317		len = 0;
318	else
319		len = 1;
320
321	while (ctx->pointer < eoc) {
322		if (++len > sizeof(unsigned long)) {
323			ctx->error = ASN1_ERR_DEC_BADVALUE;
324			return 0;
325		}
326
327		if (!asn1_octet_decode(ctx, &ch))
328			return 0;
329
330		*integer <<= 8;
331		*integer |= ch;
332	}
333	return 1;
334}
335
336static unsigned char
337asn1_octets_decode(struct asn1_ctx *ctx,
338		   unsigned char *eoc,
339		   unsigned char **octets, unsigned int *len)
340{
341	unsigned char *ptr;
342
343	*len = 0;
344
345	*octets = kmalloc(eoc - ctx->pointer, GFP_ATOMIC);
346	if (*octets == NULL) {
347		return 0;
348	}
349
350	ptr = *octets;
351	while (ctx->pointer < eoc) {
352		if (!asn1_octet_decode(ctx, (unsigned char *) ptr++)) {
353			kfree(*octets);
354			*octets = NULL;
355			return 0;
356		}
357		(*len)++;
358	}
359	return 1;
360} */
361
362static unsigned char
363asn1_subid_decode(struct asn1_ctx *ctx, unsigned long *subid)
364{
365	unsigned char ch;
366
367	*subid = 0;
368
369	do {
370		if (!asn1_octet_decode(ctx, &ch))
371			return 0;
372
373		*subid <<= 7;
374		*subid |= ch & 0x7F;
375	} while ((ch & 0x80) == 0x80);
376	return 1;
377}
378
379static int
380asn1_oid_decode(struct asn1_ctx *ctx,
381		unsigned char *eoc, unsigned long **oid, unsigned int *len)
382{
383	unsigned long subid;
384	unsigned int size;
385	unsigned long *optr;
386
387	size = eoc - ctx->pointer + 1;
388	*oid = kmalloc(size * sizeof (unsigned long), GFP_ATOMIC);
389	if (*oid == NULL) {
390		return 0;
391	}
392
393	optr = *oid;
394
395	if (!asn1_subid_decode(ctx, &subid)) {
396		kfree(*oid);
397		*oid = NULL;
398		return 0;
399	}
400
401	if (subid < 40) {
402		optr[0] = 0;
403		optr[1] = subid;
404	} else if (subid < 80) {
405		optr[0] = 1;
406		optr[1] = subid - 40;
407	} else {
408		optr[0] = 2;
409		optr[1] = subid - 80;
410	}
411
412	*len = 2;
413	optr += 2;
414
415	while (ctx->pointer < eoc) {
416		if (++(*len) > size) {
417			ctx->error = ASN1_ERR_DEC_BADVALUE;
418			kfree(*oid);
419			*oid = NULL;
420			return 0;
421		}
422
423		if (!asn1_subid_decode(ctx, optr++)) {
424			kfree(*oid);
425			*oid = NULL;
426			return 0;
427		}
428	}
429	return 1;
430}
431
432static int
433compare_oid(unsigned long *oid1, unsigned int oid1len,
434	    unsigned long *oid2, unsigned int oid2len)
435{
436	unsigned int i;
437
438	if (oid1len != oid2len)
439		return 0;
440	else {
441		for (i = 0; i < oid1len; i++) {
442			if (oid1[i] != oid2[i])
443				return 0;
444		}
445		return 1;
446	}
447}
448
449	/* BB check for endian conversion issues here */
450
451int
452decode_negTokenInit(unsigned char *security_blob, int length,
453		    enum securityEnum *secType)
454{
455	struct asn1_ctx ctx;
456	unsigned char *end;
457	unsigned char *sequence_end;
458	unsigned long *oid = NULL;
459	unsigned int cls, con, tag, oidlen, rc;
460	int use_ntlmssp = FALSE;
461
462	*secType = NTLM; /* BB eventually make Kerberos or NLTMSSP the default */
463
464	/* cifs_dump_mem(" Received SecBlob ", security_blob, length); */
465
466	asn1_open(&ctx, security_blob, length);
467
468	if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
469		cFYI(1, ("Error decoding negTokenInit header"));
470		return 0;
471	} else if ((cls != ASN1_APL) || (con != ASN1_CON)
472		   || (tag != ASN1_EOC)) {
473		cFYI(1, ("cls = %d con = %d tag = %d", cls, con, tag));
474		return 0;
475	} else {
476		/*      remember to free obj->oid */
477		rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
478		if (rc) {
479			if ((tag == ASN1_OJI) && (cls == ASN1_PRI)) {
480				rc = asn1_oid_decode(&ctx, end, &oid, &oidlen);
481				if (rc) {
482					rc = compare_oid(oid, oidlen,
483							 SPNEGO_OID,
484							 SPNEGO_OID_LEN);
485					kfree(oid);
486				}
487			} else
488				rc = 0;
489		}
490
491		if (!rc) {
492			cFYI(1, ("Error decoding negTokenInit header"));
493			return 0;
494		}
495
496		if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
497			cFYI(1, ("Error decoding negTokenInit"));
498			return 0;
499		} else if ((cls != ASN1_CTX) || (con != ASN1_CON)
500			   || (tag != ASN1_EOC)) {
501			cFYI(1,("cls = %d con = %d tag = %d end = %p (%d) exit 0",
502			      cls, con, tag, end, *end));
503			return 0;
504		}
505
506		if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
507			cFYI(1, ("Error decoding negTokenInit"));
508			return 0;
509		} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
510			   || (tag != ASN1_SEQ)) {
511			cFYI(1,("cls = %d con = %d tag = %d end = %p (%d) exit 1",
512			      cls, con, tag, end, *end));
513			return 0;
514		}
515
516		if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
517			cFYI(1, ("Error decoding 2nd part of negTokenInit"));
518			return 0;
519		} else if ((cls != ASN1_CTX) || (con != ASN1_CON)
520			   || (tag != ASN1_EOC)) {
521			cFYI(1,
522			     ("cls = %d con = %d tag = %d end = %p (%d) exit 0",
523			      cls, con, tag, end, *end));
524			return 0;
525		}
526
527		if (asn1_header_decode
528		    (&ctx, &sequence_end, &cls, &con, &tag) == 0) {
529			cFYI(1, ("Error decoding 2nd part of negTokenInit"));
530			return 0;
531		} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
532			   || (tag != ASN1_SEQ)) {
533			cFYI(1,
534			     ("cls = %d con = %d tag = %d end = %p (%d) exit 1",
535			      cls, con, tag, end, *end));
536			return 0;
537		}
538
539		while (!asn1_eoc_decode(&ctx, sequence_end)) {
540			rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
541			if (!rc) {
542				cFYI(1,
543				     ("Error 1 decoding negTokenInit header exit 2"));
544				return 0;
545			}
546			if ((tag == ASN1_OJI) && (con == ASN1_PRI)) {
547				rc = asn1_oid_decode(&ctx, end, &oid, &oidlen);
548				if(rc) {
549					cFYI(1,
550					  ("OID len = %d oid = 0x%lx 0x%lx 0x%lx 0x%lx",
551					   oidlen, *oid, *(oid + 1), *(oid + 2),
552					   *(oid + 3)));
553					rc = compare_oid(oid, oidlen, NTLMSSP_OID,
554						 NTLMSSP_OID_LEN);
555					kfree(oid);
556					if (rc)
557						use_ntlmssp = TRUE;
558				}
559			} else {
560				cFYI(1,("This should be an oid what is going on? "));
561			}
562		}
563
564		if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
565			cFYI(1,
566			     ("Error decoding last part of negTokenInit exit 3"));
567			return 0;
568		} else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {	/* tag = 3 indicating mechListMIC */
569			cFYI(1,
570			     ("Exit 4 cls = %d con = %d tag = %d end = %p (%d)",
571			      cls, con, tag, end, *end));
572			return 0;
573		}
574		if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
575			cFYI(1,
576			     ("Error decoding last part of negTokenInit exit 5"));
577			return 0;
578		} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
579			   || (tag != ASN1_SEQ)) {
580			cFYI(1,
581			     ("Exit 6 cls = %d con = %d tag = %d end = %p (%d)",
582			      cls, con, tag, end, *end));
583		}
584
585		if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
586			cFYI(1,
587			     ("Error decoding last part of negTokenInit exit 7"));
588			return 0;
589		} else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
590			cFYI(1,
591			     ("Exit 8 cls = %d con = %d tag = %d end = %p (%d)",
592			      cls, con, tag, end, *end));
593			return 0;
594		}
595		if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
596			cFYI(1,
597			     ("Error decoding last part of negTokenInit exit 9"));
598			return 0;
599		} else if ((cls != ASN1_UNI) || (con != ASN1_PRI)
600			   || (tag != ASN1_GENSTR)) {
601			cFYI(1,
602			     ("Exit 10 cls = %d con = %d tag = %d end = %p (%d)",
603			      cls, con, tag, end, *end));
604			return 0;
605		}
606		cFYI(1, ("Need to call asn1_octets_decode() function for this %s", ctx.pointer));	/* is this UTF-8 or ASCII? */
607	}
608
609	/* if (use_kerberos)
610	   *secType = Kerberos
611	   else */
612	if (use_ntlmssp) {
613		*secType = NTLMSSP;
614	}
615
616	return 1;
617}
618