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