mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	cifsd: add server-side procedures for SMB3
This adds smb3 engine, NTLM/NTLMv2/Kerberos authentication, oplock/lease cache mechanism for cifsd. Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com> Signed-off-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com> Signed-off-by: Hyunchul Lee <hyc.lee@gmail.com> Acked-by: Ronnie Sahlberg <lsahlber@redhat.com> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
		
							parent
							
								
									0626e6641f
								
							
						
					
					
						commit
						e2f34481b2
					
				
					 41 changed files with 24537 additions and 0 deletions
				
			
		
							
								
								
									
										702
									
								
								fs/cifsd/asn1.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										702
									
								
								fs/cifsd/asn1.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,702 @@
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: GPL-2.0-or-later
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * The ASB.1/BER parsing code is derived from ip_nat_snmp_basic.c which was in
 | 
				
			||||||
 | 
					 * turn derived from the gxsnmp package by Gregory McLean & Jochen Friedrich
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (c) 2000 RP Internet (www.rpi.net.au).
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <linux/module.h>
 | 
				
			||||||
 | 
					#include <linux/types.h>
 | 
				
			||||||
 | 
					#include <linux/kernel.h>
 | 
				
			||||||
 | 
					#include <linux/mm.h>
 | 
				
			||||||
 | 
					#include <linux/slab.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "glob.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "asn1.h"
 | 
				
			||||||
 | 
					#include "connection.h"
 | 
				
			||||||
 | 
					#include "auth.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*****************************************************************************
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Basic ASN.1 decoding routines (gxsnmp author Dirk Wisse)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *****************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Class */
 | 
				
			||||||
 | 
					#define ASN1_UNI	0	/* Universal */
 | 
				
			||||||
 | 
					#define ASN1_APL	1	/* Application */
 | 
				
			||||||
 | 
					#define ASN1_CTX	2	/* Context */
 | 
				
			||||||
 | 
					#define ASN1_PRV	3	/* Private */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Tag */
 | 
				
			||||||
 | 
					#define ASN1_EOC	0	/* End Of Contents or N/A */
 | 
				
			||||||
 | 
					#define ASN1_BOL	1	/* Boolean */
 | 
				
			||||||
 | 
					#define ASN1_INT	2	/* Integer */
 | 
				
			||||||
 | 
					#define ASN1_BTS	3	/* Bit String */
 | 
				
			||||||
 | 
					#define ASN1_OTS	4	/* Octet String */
 | 
				
			||||||
 | 
					#define ASN1_NUL	5	/* Null */
 | 
				
			||||||
 | 
					#define ASN1_OJI	6	/* Object Identifier  */
 | 
				
			||||||
 | 
					#define ASN1_OJD	7	/* Object Description */
 | 
				
			||||||
 | 
					#define ASN1_EXT	8	/* External */
 | 
				
			||||||
 | 
					#define ASN1_ENUM	10	/* Enumerated */
 | 
				
			||||||
 | 
					#define ASN1_SEQ	16	/* Sequence */
 | 
				
			||||||
 | 
					#define ASN1_SET	17	/* Set */
 | 
				
			||||||
 | 
					#define ASN1_NUMSTR	18	/* Numerical String */
 | 
				
			||||||
 | 
					#define ASN1_PRNSTR	19	/* Printable String */
 | 
				
			||||||
 | 
					#define ASN1_TEXSTR	20	/* Teletext String */
 | 
				
			||||||
 | 
					#define ASN1_VIDSTR	21	/* Video String */
 | 
				
			||||||
 | 
					#define ASN1_IA5STR	22	/* IA5 String */
 | 
				
			||||||
 | 
					#define ASN1_UNITIM	23	/* Universal Time */
 | 
				
			||||||
 | 
					#define ASN1_GENTIM	24	/* General Time */
 | 
				
			||||||
 | 
					#define ASN1_GRASTR	25	/* Graphical String */
 | 
				
			||||||
 | 
					#define ASN1_VISSTR	26	/* Visible String */
 | 
				
			||||||
 | 
					#define ASN1_GENSTR	27	/* General String */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Primitive / Constructed methods*/
 | 
				
			||||||
 | 
					#define ASN1_PRI	0	/* Primitive */
 | 
				
			||||||
 | 
					#define ASN1_CON	1	/* Constructed */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Error codes.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define ASN1_ERR_NOERROR		0
 | 
				
			||||||
 | 
					#define ASN1_ERR_DEC_EMPTY		2
 | 
				
			||||||
 | 
					#define ASN1_ERR_DEC_EOC_MISMATCH	3
 | 
				
			||||||
 | 
					#define ASN1_ERR_DEC_LENGTH_MISMATCH	4
 | 
				
			||||||
 | 
					#define ASN1_ERR_DEC_BADVALUE		5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SPNEGO_OID_LEN 7
 | 
				
			||||||
 | 
					#define NTLMSSP_OID_LEN  10
 | 
				
			||||||
 | 
					#define KRB5_OID_LEN  7
 | 
				
			||||||
 | 
					#define KRB5U2U_OID_LEN  8
 | 
				
			||||||
 | 
					#define MSKRB5_OID_LEN  7
 | 
				
			||||||
 | 
					static unsigned long SPNEGO_OID[7] = { 1, 3, 6, 1, 5, 5, 2 };
 | 
				
			||||||
 | 
					static unsigned long NTLMSSP_OID[10] = { 1, 3, 6, 1, 4, 1, 311, 2, 2, 10 };
 | 
				
			||||||
 | 
					static unsigned long KRB5_OID[7] = { 1, 2, 840, 113554, 1, 2, 2 };
 | 
				
			||||||
 | 
					static unsigned long KRB5U2U_OID[8] = { 1, 2, 840, 113554, 1, 2, 2, 3 };
 | 
				
			||||||
 | 
					static unsigned long MSKRB5_OID[7] = { 1, 2, 840, 48018, 1, 2, 2 };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static char NTLMSSP_OID_STR[NTLMSSP_OID_LEN] = { 0x2b, 0x06, 0x01, 0x04, 0x01,
 | 
				
			||||||
 | 
						0x82, 0x37, 0x02, 0x02, 0x0a };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * ASN.1 context.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct asn1_ctx {
 | 
				
			||||||
 | 
						int error;		/* Error condition */
 | 
				
			||||||
 | 
						unsigned char *pointer;	/* Octet just to be decoded */
 | 
				
			||||||
 | 
						unsigned char *begin;	/* First octet */
 | 
				
			||||||
 | 
						unsigned char *end;	/* Octet after last octet */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Octet string (not null terminated)
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct asn1_octstr {
 | 
				
			||||||
 | 
						unsigned char *data;
 | 
				
			||||||
 | 
						unsigned int len;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					asn1_open(struct asn1_ctx *ctx, unsigned char *buf, unsigned int len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						ctx->begin = buf;
 | 
				
			||||||
 | 
						ctx->end = buf + len;
 | 
				
			||||||
 | 
						ctx->pointer = buf;
 | 
				
			||||||
 | 
						ctx->error = ASN1_ERR_NOERROR;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static unsigned char
 | 
				
			||||||
 | 
					asn1_octet_decode(struct asn1_ctx *ctx, unsigned char *ch)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (ctx->pointer >= ctx->end) {
 | 
				
			||||||
 | 
							ctx->error = ASN1_ERR_DEC_EMPTY;
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						*ch = *(ctx->pointer)++;
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static unsigned char
 | 
				
			||||||
 | 
					asn1_tag_decode(struct asn1_ctx *ctx, unsigned int *tag)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char ch;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*tag = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						do {
 | 
				
			||||||
 | 
							if (!asn1_octet_decode(ctx, &ch))
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							*tag <<= 7;
 | 
				
			||||||
 | 
							*tag |= ch & 0x7F;
 | 
				
			||||||
 | 
						} while ((ch & 0x80) == 0x80);
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static unsigned char
 | 
				
			||||||
 | 
					asn1_id_decode(struct asn1_ctx *ctx,
 | 
				
			||||||
 | 
						       unsigned int *cls, unsigned int *con, unsigned int *tag)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char ch;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!asn1_octet_decode(ctx, &ch))
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*cls = (ch & 0xC0) >> 6;
 | 
				
			||||||
 | 
						*con = (ch & 0x20) >> 5;
 | 
				
			||||||
 | 
						*tag = (ch & 0x1F);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (*tag == 0x1F) {
 | 
				
			||||||
 | 
							if (!asn1_tag_decode(ctx, tag))
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static unsigned char
 | 
				
			||||||
 | 
					asn1_length_decode(struct asn1_ctx *ctx, unsigned int *def, unsigned int *len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char ch, cnt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!asn1_octet_decode(ctx, &ch))
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ch == 0x80)
 | 
				
			||||||
 | 
							*def = 0;
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							*def = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (ch < 0x80)
 | 
				
			||||||
 | 
								*len = ch;
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								cnt = (unsigned char) (ch & 0x7F);
 | 
				
			||||||
 | 
								*len = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								while (cnt > 0) {
 | 
				
			||||||
 | 
									if (!asn1_octet_decode(ctx, &ch))
 | 
				
			||||||
 | 
										return 0;
 | 
				
			||||||
 | 
									*len <<= 8;
 | 
				
			||||||
 | 
									*len |= ch;
 | 
				
			||||||
 | 
									cnt--;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* don't trust len bigger than ctx buffer */
 | 
				
			||||||
 | 
						if (*len > ctx->end - ctx->pointer)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static unsigned char
 | 
				
			||||||
 | 
					asn1_header_decode(struct asn1_ctx *ctx,
 | 
				
			||||||
 | 
							   unsigned char **eoc,
 | 
				
			||||||
 | 
							   unsigned int *cls, unsigned int *con, unsigned int *tag)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned int def = 0;
 | 
				
			||||||
 | 
						unsigned int len = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!asn1_id_decode(ctx, cls, con, tag))
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!asn1_length_decode(ctx, &def, &len))
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* primitive shall be definite, indefinite shall be constructed */
 | 
				
			||||||
 | 
						if (*con == ASN1_PRI && !def)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (def)
 | 
				
			||||||
 | 
							*eoc = ctx->pointer + len;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							*eoc = NULL;
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static unsigned char
 | 
				
			||||||
 | 
					asn1_eoc_decode(struct asn1_ctx *ctx, unsigned char *eoc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char ch;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!eoc) {
 | 
				
			||||||
 | 
							if (!asn1_octet_decode(ctx, &ch))
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (ch != 0x00) {
 | 
				
			||||||
 | 
								ctx->error = ASN1_ERR_DEC_EOC_MISMATCH;
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!asn1_octet_decode(ctx, &ch))
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (ch != 0x00) {
 | 
				
			||||||
 | 
								ctx->error = ASN1_ERR_DEC_EOC_MISMATCH;
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							if (ctx->pointer != eoc) {
 | 
				
			||||||
 | 
								ctx->error = ASN1_ERR_DEC_LENGTH_MISMATCH;
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static unsigned char
 | 
				
			||||||
 | 
					asn1_subid_decode(struct asn1_ctx *ctx, unsigned long *subid)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char ch;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*subid = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						do {
 | 
				
			||||||
 | 
							if (!asn1_octet_decode(ctx, &ch))
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							*subid <<= 7;
 | 
				
			||||||
 | 
							*subid |= ch & 0x7F;
 | 
				
			||||||
 | 
						} while ((ch & 0x80) == 0x80);
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					asn1_oid_decode(struct asn1_ctx *ctx,
 | 
				
			||||||
 | 
							unsigned char *eoc, unsigned long **oid, unsigned int *len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned long subid;
 | 
				
			||||||
 | 
						unsigned int size;
 | 
				
			||||||
 | 
						unsigned long *optr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						size = eoc - ctx->pointer + 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* first subid actually encodes first two subids */
 | 
				
			||||||
 | 
						if (size < 2 || size > UINT_MAX/sizeof(unsigned long))
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*oid = kmalloc(size * sizeof(unsigned long), GFP_KERNEL);
 | 
				
			||||||
 | 
						if (!*oid)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						optr = *oid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!asn1_subid_decode(ctx, &subid)) {
 | 
				
			||||||
 | 
							kfree(*oid);
 | 
				
			||||||
 | 
							*oid = NULL;
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (subid < 40) {
 | 
				
			||||||
 | 
							optr[0] = 0;
 | 
				
			||||||
 | 
							optr[1] = subid;
 | 
				
			||||||
 | 
						} else if (subid < 80) {
 | 
				
			||||||
 | 
							optr[0] = 1;
 | 
				
			||||||
 | 
							optr[1] = subid - 40;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							optr[0] = 2;
 | 
				
			||||||
 | 
							optr[1] = subid - 80;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*len = 2;
 | 
				
			||||||
 | 
						optr += 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (ctx->pointer < eoc) {
 | 
				
			||||||
 | 
							if (++(*len) > size) {
 | 
				
			||||||
 | 
								ctx->error = ASN1_ERR_DEC_BADVALUE;
 | 
				
			||||||
 | 
								kfree(*oid);
 | 
				
			||||||
 | 
								*oid = NULL;
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!asn1_subid_decode(ctx, optr++)) {
 | 
				
			||||||
 | 
								kfree(*oid);
 | 
				
			||||||
 | 
								*oid = NULL;
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					compare_oid(unsigned long *oid1, unsigned int oid1len,
 | 
				
			||||||
 | 
						    unsigned long *oid2, unsigned int oid2len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (oid1len != oid2len)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < oid1len; i++) {
 | 
				
			||||||
 | 
							if (oid1[i] != oid2[i])
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* BB check for endian conversion issues here */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					ksmbd_decode_negTokenInit(unsigned char *security_blob, int length,
 | 
				
			||||||
 | 
							    struct ksmbd_conn *conn)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct asn1_ctx ctx;
 | 
				
			||||||
 | 
						unsigned char *end;
 | 
				
			||||||
 | 
						unsigned char *sequence_end;
 | 
				
			||||||
 | 
						unsigned long *oid = NULL;
 | 
				
			||||||
 | 
						unsigned int cls, con, tag, oidlen, rc, mechTokenlen;
 | 
				
			||||||
 | 
						unsigned int mech_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ksmbd_debug(AUTH, "Received SecBlob: length %d\n", length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						asn1_open(&ctx, security_blob, length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* GSSAPI header */
 | 
				
			||||||
 | 
						if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
 | 
				
			||||||
 | 
							ksmbd_debug(AUTH, "Error decoding negTokenInit header\n");
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						} else if ((cls != ASN1_APL) || (con != ASN1_CON)
 | 
				
			||||||
 | 
							   || (tag != ASN1_EOC)) {
 | 
				
			||||||
 | 
							ksmbd_debug(AUTH, "cls = %d con = %d tag = %d\n", cls, con,
 | 
				
			||||||
 | 
								tag);
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Check for SPNEGO OID -- remember to free obj->oid */
 | 
				
			||||||
 | 
						rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
 | 
				
			||||||
 | 
						if (rc) {
 | 
				
			||||||
 | 
							if ((tag == ASN1_OJI) && (con == ASN1_PRI) &&
 | 
				
			||||||
 | 
							    (cls == ASN1_UNI)) {
 | 
				
			||||||
 | 
								rc = asn1_oid_decode(&ctx, end, &oid, &oidlen);
 | 
				
			||||||
 | 
								if (rc) {
 | 
				
			||||||
 | 
									rc = compare_oid(oid, oidlen, SPNEGO_OID,
 | 
				
			||||||
 | 
											 SPNEGO_OID_LEN);
 | 
				
			||||||
 | 
									kfree(oid);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else
 | 
				
			||||||
 | 
								rc = 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* SPNEGO OID not present or garbled -- bail out */
 | 
				
			||||||
 | 
						if (!rc) {
 | 
				
			||||||
 | 
							ksmbd_debug(AUTH, "Error decoding negTokenInit header\n");
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* SPNEGO */
 | 
				
			||||||
 | 
						if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
 | 
				
			||||||
 | 
							ksmbd_debug(AUTH, "Error decoding negTokenInit\n");
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						} else if ((cls != ASN1_CTX) || (con != ASN1_CON)
 | 
				
			||||||
 | 
							   || (tag != ASN1_EOC)) {
 | 
				
			||||||
 | 
							ksmbd_debug(AUTH,
 | 
				
			||||||
 | 
								"cls = %d con = %d tag = %d end = %p (%d) exit 0\n",
 | 
				
			||||||
 | 
								cls, con, tag, end, *end);
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* negTokenInit */
 | 
				
			||||||
 | 
						if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
 | 
				
			||||||
 | 
							ksmbd_debug(AUTH, "Error decoding negTokenInit\n");
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
 | 
				
			||||||
 | 
							   || (tag != ASN1_SEQ)) {
 | 
				
			||||||
 | 
							ksmbd_debug(AUTH,
 | 
				
			||||||
 | 
								"cls = %d con = %d tag = %d end = %p (%d) exit 1\n",
 | 
				
			||||||
 | 
								cls, con, tag, end, *end);
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* sequence */
 | 
				
			||||||
 | 
						if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
 | 
				
			||||||
 | 
							ksmbd_debug(AUTH, "Error decoding 2nd part of negTokenInit\n");
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						} else if ((cls != ASN1_CTX) || (con != ASN1_CON)
 | 
				
			||||||
 | 
							   || (tag != ASN1_EOC)) {
 | 
				
			||||||
 | 
							ksmbd_debug(AUTH,
 | 
				
			||||||
 | 
								"cls = %d con = %d tag = %d end = %p (%d) exit 0\n",
 | 
				
			||||||
 | 
								cls, con, tag, end, *end);
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* sequence of */
 | 
				
			||||||
 | 
						if (asn1_header_decode
 | 
				
			||||||
 | 
						    (&ctx, &sequence_end, &cls, &con, &tag) == 0) {
 | 
				
			||||||
 | 
							ksmbd_debug(AUTH, "Error decoding 2nd part of negTokenInit\n");
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
 | 
				
			||||||
 | 
							   || (tag != ASN1_SEQ)) {
 | 
				
			||||||
 | 
							ksmbd_debug(AUTH,
 | 
				
			||||||
 | 
								"cls = %d con = %d tag = %d end = %p (%d) exit 1\n",
 | 
				
			||||||
 | 
								cls, con, tag, end, *end);
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* list of security mechanisms */
 | 
				
			||||||
 | 
						while (!asn1_eoc_decode(&ctx, sequence_end)) {
 | 
				
			||||||
 | 
							rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
 | 
				
			||||||
 | 
							if (!rc) {
 | 
				
			||||||
 | 
								ksmbd_debug(AUTH,
 | 
				
			||||||
 | 
									"Error decoding negTokenInit hdr exit2\n");
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if ((tag == ASN1_OJI) && (con == ASN1_PRI)) {
 | 
				
			||||||
 | 
								if (asn1_oid_decode(&ctx, end, &oid, &oidlen)) {
 | 
				
			||||||
 | 
									if (compare_oid(oid, oidlen, MSKRB5_OID,
 | 
				
			||||||
 | 
											MSKRB5_OID_LEN))
 | 
				
			||||||
 | 
										mech_type = KSMBD_AUTH_MSKRB5;
 | 
				
			||||||
 | 
									else if (compare_oid(oid, oidlen, KRB5U2U_OID,
 | 
				
			||||||
 | 
											     KRB5U2U_OID_LEN))
 | 
				
			||||||
 | 
										mech_type = KSMBD_AUTH_KRB5U2U;
 | 
				
			||||||
 | 
									else if (compare_oid(oid, oidlen, KRB5_OID,
 | 
				
			||||||
 | 
											     KRB5_OID_LEN))
 | 
				
			||||||
 | 
										mech_type = KSMBD_AUTH_KRB5;
 | 
				
			||||||
 | 
									else if (compare_oid(oid, oidlen, NTLMSSP_OID,
 | 
				
			||||||
 | 
											     NTLMSSP_OID_LEN))
 | 
				
			||||||
 | 
										mech_type = KSMBD_AUTH_NTLMSSP;
 | 
				
			||||||
 | 
									else {
 | 
				
			||||||
 | 
										kfree(oid);
 | 
				
			||||||
 | 
										continue;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									conn->auth_mechs |= mech_type;
 | 
				
			||||||
 | 
									if (conn->preferred_auth_mech == 0)
 | 
				
			||||||
 | 
										conn->preferred_auth_mech = mech_type;
 | 
				
			||||||
 | 
									kfree(oid);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								ksmbd_debug(AUTH,
 | 
				
			||||||
 | 
									"Should be an oid what is going on?\n");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* sequence */
 | 
				
			||||||
 | 
						if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
 | 
				
			||||||
 | 
							ksmbd_debug(AUTH, "Error decoding 2nd part of negTokenInit\n");
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						} else if ((cls != ASN1_CTX) || (con != ASN1_CON)
 | 
				
			||||||
 | 
							   || (tag != ASN1_INT)) {
 | 
				
			||||||
 | 
							ksmbd_debug(AUTH,
 | 
				
			||||||
 | 
								"cls = %d con = %d tag = %d end = %p (%d) exit 0\n",
 | 
				
			||||||
 | 
								cls, con, tag, end, *end);
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* sequence of */
 | 
				
			||||||
 | 
						if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
 | 
				
			||||||
 | 
							ksmbd_debug(AUTH, "Error decoding 2nd part of negTokenInit\n");
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						} else if ((cls != ASN1_UNI) || (con != ASN1_PRI)
 | 
				
			||||||
 | 
							   || (tag != ASN1_OTS)) {
 | 
				
			||||||
 | 
							ksmbd_debug(AUTH,
 | 
				
			||||||
 | 
								"cls = %d con = %d tag = %d end = %p (%d) exit 0\n",
 | 
				
			||||||
 | 
								cls, con, tag, end, *end);
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mechTokenlen = ctx.end - ctx.pointer;
 | 
				
			||||||
 | 
						conn->mechToken = kmalloc(mechTokenlen + 1, GFP_KERNEL);
 | 
				
			||||||
 | 
						if (!conn->mechToken) {
 | 
				
			||||||
 | 
							ksmbd_err("memory allocation error\n");
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memcpy(conn->mechToken, ctx.pointer, mechTokenlen);
 | 
				
			||||||
 | 
						conn->mechToken[mechTokenlen] = '\0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					ksmbd_decode_negTokenTarg(unsigned char *security_blob, int length,
 | 
				
			||||||
 | 
							    struct ksmbd_conn *conn)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct asn1_ctx ctx;
 | 
				
			||||||
 | 
						unsigned char *end;
 | 
				
			||||||
 | 
						unsigned int cls, con, tag, mechTokenlen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ksmbd_debug(AUTH, "Received Auth SecBlob: length %d\n", length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						asn1_open(&ctx, security_blob, length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* GSSAPI header */
 | 
				
			||||||
 | 
						if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
 | 
				
			||||||
 | 
							ksmbd_debug(AUTH, "Error decoding negTokenInit header\n");
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						} else if ((cls != ASN1_CTX) || (con != ASN1_CON)
 | 
				
			||||||
 | 
							   || (tag != ASN1_BOL)) {
 | 
				
			||||||
 | 
							ksmbd_debug(AUTH, "cls = %d con = %d tag = %d\n", cls, con,
 | 
				
			||||||
 | 
								tag);
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* SPNEGO */
 | 
				
			||||||
 | 
						if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
 | 
				
			||||||
 | 
							ksmbd_debug(AUTH, "Error decoding negTokenInit\n");
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
 | 
				
			||||||
 | 
							   || (tag != ASN1_SEQ)) {
 | 
				
			||||||
 | 
							ksmbd_debug(AUTH,
 | 
				
			||||||
 | 
								"cls = %d con = %d tag = %d end = %p (%d) exit 0\n",
 | 
				
			||||||
 | 
								cls, con, tag, end, *end);
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* negTokenTarg */
 | 
				
			||||||
 | 
						if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
 | 
				
			||||||
 | 
							ksmbd_debug(AUTH, "Error decoding negTokenInit\n");
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						} else if ((cls != ASN1_CTX) || (con != ASN1_CON)
 | 
				
			||||||
 | 
							   || (tag != ASN1_INT)) {
 | 
				
			||||||
 | 
							ksmbd_debug(AUTH,
 | 
				
			||||||
 | 
								"cls = %d con = %d tag = %d end = %p (%d) exit 1\n",
 | 
				
			||||||
 | 
								cls, con, tag, end, *end);
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* negTokenTarg */
 | 
				
			||||||
 | 
						if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
 | 
				
			||||||
 | 
							ksmbd_debug(AUTH, "Error decoding negTokenInit\n");
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						} else if ((cls != ASN1_UNI) || (con != ASN1_PRI)
 | 
				
			||||||
 | 
							   || (tag != ASN1_OTS)) {
 | 
				
			||||||
 | 
							ksmbd_debug(AUTH,
 | 
				
			||||||
 | 
								"cls = %d con = %d tag = %d end = %p (%d) exit 1\n",
 | 
				
			||||||
 | 
								cls, con, tag, end, *end);
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mechTokenlen = ctx.end - ctx.pointer;
 | 
				
			||||||
 | 
						conn->mechToken = kmalloc(mechTokenlen + 1, GFP_KERNEL);
 | 
				
			||||||
 | 
						if (!conn->mechToken) {
 | 
				
			||||||
 | 
							ksmbd_err("memory allocation error\n");
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memcpy(conn->mechToken, ctx.pointer, mechTokenlen);
 | 
				
			||||||
 | 
						conn->mechToken[mechTokenlen] = '\0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int compute_asn_hdr_len_bytes(int len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (len > 0xFFFFFF)
 | 
				
			||||||
 | 
							return 4;
 | 
				
			||||||
 | 
						else if (len > 0xFFFF)
 | 
				
			||||||
 | 
							return 3;
 | 
				
			||||||
 | 
						else if (len > 0xFF)
 | 
				
			||||||
 | 
							return 2;
 | 
				
			||||||
 | 
						else if (len > 0x7F)
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void encode_asn_tag(char *buf,
 | 
				
			||||||
 | 
								   unsigned int *ofs,
 | 
				
			||||||
 | 
								   char tag,
 | 
				
			||||||
 | 
								   char seq,
 | 
				
			||||||
 | 
								   int length)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						int index = *ofs;
 | 
				
			||||||
 | 
						char hdr_len = compute_asn_hdr_len_bytes(length);
 | 
				
			||||||
 | 
						int len = length + 2 + hdr_len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* insert tag */
 | 
				
			||||||
 | 
						buf[index++] = tag;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!hdr_len)
 | 
				
			||||||
 | 
							buf[index++] = len;
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							buf[index++] = 0x80 | hdr_len;
 | 
				
			||||||
 | 
							for (i = hdr_len - 1; i >= 0; i--)
 | 
				
			||||||
 | 
								buf[index++] = (len >> (i * 8)) & 0xFF;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* insert seq */
 | 
				
			||||||
 | 
						len = len - (index - *ofs);
 | 
				
			||||||
 | 
						buf[index++] = seq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!hdr_len)
 | 
				
			||||||
 | 
							buf[index++] = len;
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							buf[index++] = 0x80 | hdr_len;
 | 
				
			||||||
 | 
							for (i = hdr_len - 1; i >= 0; i--)
 | 
				
			||||||
 | 
								buf[index++] = (len >> (i * 8)) & 0xFF;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*ofs += (index - *ofs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int build_spnego_ntlmssp_neg_blob(unsigned char **pbuffer, u16 *buflen,
 | 
				
			||||||
 | 
							char *ntlm_blob, int ntlm_blob_len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						char *buf;
 | 
				
			||||||
 | 
						unsigned int ofs = 0;
 | 
				
			||||||
 | 
						int neg_result_len = 4 + compute_asn_hdr_len_bytes(1) * 2 + 1;
 | 
				
			||||||
 | 
						int oid_len = 4 + compute_asn_hdr_len_bytes(NTLMSSP_OID_LEN) * 2 +
 | 
				
			||||||
 | 
							NTLMSSP_OID_LEN;
 | 
				
			||||||
 | 
						int ntlmssp_len = 4 + compute_asn_hdr_len_bytes(ntlm_blob_len) * 2 +
 | 
				
			||||||
 | 
							ntlm_blob_len;
 | 
				
			||||||
 | 
						int total_len = 4 + compute_asn_hdr_len_bytes(neg_result_len +
 | 
				
			||||||
 | 
								oid_len + ntlmssp_len) * 2 +
 | 
				
			||||||
 | 
								neg_result_len + oid_len + ntlmssp_len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						buf = kmalloc(total_len, GFP_KERNEL);
 | 
				
			||||||
 | 
						if (!buf)
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* insert main gss header */
 | 
				
			||||||
 | 
						encode_asn_tag(buf, &ofs, 0xa1, 0x30, neg_result_len + oid_len +
 | 
				
			||||||
 | 
								ntlmssp_len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* insert neg result */
 | 
				
			||||||
 | 
						encode_asn_tag(buf, &ofs, 0xa0, 0x0a, 1);
 | 
				
			||||||
 | 
						buf[ofs++] = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* insert oid */
 | 
				
			||||||
 | 
						encode_asn_tag(buf, &ofs, 0xa1, 0x06, NTLMSSP_OID_LEN);
 | 
				
			||||||
 | 
						memcpy(buf + ofs, NTLMSSP_OID_STR, NTLMSSP_OID_LEN);
 | 
				
			||||||
 | 
						ofs += NTLMSSP_OID_LEN;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* insert response token - ntlmssp blob */
 | 
				
			||||||
 | 
						encode_asn_tag(buf, &ofs, 0xa2, 0x04, ntlm_blob_len);
 | 
				
			||||||
 | 
						memcpy(buf + ofs, ntlm_blob, ntlm_blob_len);
 | 
				
			||||||
 | 
						ofs += ntlm_blob_len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*pbuffer = buf;
 | 
				
			||||||
 | 
						*buflen = total_len;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int build_spnego_ntlmssp_auth_blob(unsigned char **pbuffer, u16 *buflen,
 | 
				
			||||||
 | 
							int neg_result)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						char *buf;
 | 
				
			||||||
 | 
						unsigned int ofs = 0;
 | 
				
			||||||
 | 
						int neg_result_len = 4 + compute_asn_hdr_len_bytes(1) * 2 + 1;
 | 
				
			||||||
 | 
						int total_len = 4 + compute_asn_hdr_len_bytes(neg_result_len) * 2 +
 | 
				
			||||||
 | 
							neg_result_len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						buf = kmalloc(total_len, GFP_KERNEL);
 | 
				
			||||||
 | 
						if (!buf)
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* insert main gss header */
 | 
				
			||||||
 | 
						encode_asn_tag(buf, &ofs, 0xa1, 0x30, neg_result_len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* insert neg result */
 | 
				
			||||||
 | 
						encode_asn_tag(buf, &ofs, 0xa0, 0x0a, 1);
 | 
				
			||||||
 | 
						if (neg_result)
 | 
				
			||||||
 | 
							buf[ofs++] = 2;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							buf[ofs++] = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*pbuffer = buf;
 | 
				
			||||||
 | 
						*buflen = total_len;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										29
									
								
								fs/cifsd/asn1.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								fs/cifsd/asn1.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,29 @@
 | 
				
			||||||
 | 
					/* SPDX-License-Identifier: GPL-2.0-or-later */
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * The ASB.1/BER parsing code is derived from ip_nat_snmp_basic.c which was in
 | 
				
			||||||
 | 
					 * turn derived from the gxsnmp package by Gregory McLean & Jochen Friedrich
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (c) 2000 RP Internet (www.rpi.net.au).
 | 
				
			||||||
 | 
					 * Copyright (C) 2018 Samsung Electronics Co., Ltd.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef __ASN1_H__
 | 
				
			||||||
 | 
					#define __ASN1_H__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_decode_negTokenInit(unsigned char *security_blob,
 | 
				
			||||||
 | 
								      int length,
 | 
				
			||||||
 | 
								      struct ksmbd_conn *conn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_decode_negTokenTarg(unsigned char *security_blob,
 | 
				
			||||||
 | 
								      int length,
 | 
				
			||||||
 | 
								      struct ksmbd_conn *conn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int build_spnego_ntlmssp_neg_blob(unsigned char **pbuffer,
 | 
				
			||||||
 | 
									  u16 *buflen,
 | 
				
			||||||
 | 
									  char *ntlm_blob,
 | 
				
			||||||
 | 
									  int ntlm_blob_len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int build_spnego_ntlmssp_auth_blob(unsigned char **pbuffer,
 | 
				
			||||||
 | 
									   u16 *buflen,
 | 
				
			||||||
 | 
									   int neg_result);
 | 
				
			||||||
 | 
					#endif /* __ASN1_H__ */
 | 
				
			||||||
							
								
								
									
										1348
									
								
								fs/cifsd/auth.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1348
									
								
								fs/cifsd/auth.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										90
									
								
								fs/cifsd/auth.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								fs/cifsd/auth.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,90 @@
 | 
				
			||||||
 | 
					/* SPDX-License-Identifier: GPL-2.0-or-later */
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *   Copyright (C) 2018 Samsung Electronics Co., Ltd.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef __AUTH_H__
 | 
				
			||||||
 | 
					#define __AUTH_H__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "ntlmssp.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef CONFIG_SMB_SERVER_KERBEROS5
 | 
				
			||||||
 | 
					#define AUTH_GSS_LENGTH		96
 | 
				
			||||||
 | 
					#define AUTH_GSS_PADDING	0
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#define AUTH_GSS_LENGTH		74
 | 
				
			||||||
 | 
					#define AUTH_GSS_PADDING	6
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CIFS_HMAC_MD5_HASH_SIZE	(16)
 | 
				
			||||||
 | 
					#define CIFS_NTHASH_SIZE	(16)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Size of the ntlm client response
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define CIFS_AUTH_RESP_SIZE		24
 | 
				
			||||||
 | 
					#define CIFS_SMB1_SIGNATURE_SIZE	8
 | 
				
			||||||
 | 
					#define CIFS_SMB1_SESSKEY_SIZE		16
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define KSMBD_AUTH_NTLMSSP	0x0001
 | 
				
			||||||
 | 
					#define KSMBD_AUTH_KRB5		0x0002
 | 
				
			||||||
 | 
					#define KSMBD_AUTH_MSKRB5	0x0004
 | 
				
			||||||
 | 
					#define KSMBD_AUTH_KRB5U2U	0x0008
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_session;
 | 
				
			||||||
 | 
					struct ksmbd_conn;
 | 
				
			||||||
 | 
					struct kvec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_crypt_message(struct ksmbd_conn *conn,
 | 
				
			||||||
 | 
								struct kvec *iov,
 | 
				
			||||||
 | 
								unsigned int nvec,
 | 
				
			||||||
 | 
								int enc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ksmbd_copy_gss_neg_header(void *buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_auth_ntlm(struct ksmbd_session *sess,
 | 
				
			||||||
 | 
							    char *pw_buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_auth_ntlmv2(struct ksmbd_session *sess,
 | 
				
			||||||
 | 
							      struct ntlmv2_resp *ntlmv2,
 | 
				
			||||||
 | 
							      int blen,
 | 
				
			||||||
 | 
							      char *domain_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_decode_ntlmssp_auth_blob(struct authenticate_message *authblob,
 | 
				
			||||||
 | 
									   int blob_len,
 | 
				
			||||||
 | 
									   struct ksmbd_session *sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_decode_ntlmssp_neg_blob(struct negotiate_message *negblob,
 | 
				
			||||||
 | 
									  int blob_len,
 | 
				
			||||||
 | 
									  struct ksmbd_session *sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unsigned int
 | 
				
			||||||
 | 
					ksmbd_build_ntlmssp_challenge_blob(struct challenge_message *chgblob,
 | 
				
			||||||
 | 
							struct ksmbd_session *sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_krb5_authenticate(struct ksmbd_session *sess,
 | 
				
			||||||
 | 
								char *in_blob, int in_len,
 | 
				
			||||||
 | 
								char *out_blob, int *out_len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_sign_smb2_pdu(struct ksmbd_conn *conn,
 | 
				
			||||||
 | 
								char *key,
 | 
				
			||||||
 | 
								struct kvec *iov,
 | 
				
			||||||
 | 
								int n_vec,
 | 
				
			||||||
 | 
								char *sig);
 | 
				
			||||||
 | 
					int ksmbd_sign_smb3_pdu(struct ksmbd_conn *conn,
 | 
				
			||||||
 | 
								char *key,
 | 
				
			||||||
 | 
								struct kvec *iov,
 | 
				
			||||||
 | 
								int n_vec,
 | 
				
			||||||
 | 
								char *sig);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_gen_smb30_signingkey(struct ksmbd_session *sess);
 | 
				
			||||||
 | 
					int ksmbd_gen_smb311_signingkey(struct ksmbd_session *sess);
 | 
				
			||||||
 | 
					int ksmbd_gen_smb30_encryptionkey(struct ksmbd_session *sess);
 | 
				
			||||||
 | 
					int ksmbd_gen_smb311_encryptionkey(struct ksmbd_session *sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_gen_preauth_integrity_hash(struct ksmbd_conn *conn,
 | 
				
			||||||
 | 
									     char *buf,
 | 
				
			||||||
 | 
									     __u8 *pi_hash);
 | 
				
			||||||
 | 
					int ksmbd_gen_sd_hash(struct ksmbd_conn *conn, char *sd_buf, int len,
 | 
				
			||||||
 | 
							__u8 *pi_hash);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										287
									
								
								fs/cifsd/crypto_ctx.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										287
									
								
								fs/cifsd/crypto_ctx.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,287 @@
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: GPL-2.0-or-later
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *   Copyright (C) 2019 Samsung Electronics Co., Ltd.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <linux/kernel.h>
 | 
				
			||||||
 | 
					#include <linux/string.h>
 | 
				
			||||||
 | 
					#include <linux/err.h>
 | 
				
			||||||
 | 
					#include <linux/slab.h>
 | 
				
			||||||
 | 
					#include <linux/wait.h>
 | 
				
			||||||
 | 
					#include <linux/sched.h>
 | 
				
			||||||
 | 
					#include <linux/version.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "glob.h"
 | 
				
			||||||
 | 
					#include "crypto_ctx.h"
 | 
				
			||||||
 | 
					#include "buffer_pool.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct crypto_ctx_list {
 | 
				
			||||||
 | 
						spinlock_t		ctx_lock;
 | 
				
			||||||
 | 
						int			avail_ctx;
 | 
				
			||||||
 | 
						struct list_head	idle_ctx;
 | 
				
			||||||
 | 
						wait_queue_head_t	ctx_wait;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct crypto_ctx_list ctx_list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void free_aead(struct crypto_aead *aead)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (aead)
 | 
				
			||||||
 | 
							crypto_free_aead(aead);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void free_shash(struct shash_desc *shash)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (shash) {
 | 
				
			||||||
 | 
							crypto_free_shash(shash->tfm);
 | 
				
			||||||
 | 
							kfree(shash);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct crypto_aead *alloc_aead(int id)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct crypto_aead *tfm = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (id) {
 | 
				
			||||||
 | 
						case CRYPTO_AEAD_AES128_GCM:
 | 
				
			||||||
 | 
							tfm = crypto_alloc_aead("gcm(aes)", 0, 0);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case CRYPTO_AEAD_AES128_CCM:
 | 
				
			||||||
 | 
							tfm = crypto_alloc_aead("ccm(aes)", 0, 0);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							ksmbd_err("Does not support encrypt ahead(id : %d)\n", id);
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (IS_ERR(tfm)) {
 | 
				
			||||||
 | 
							ksmbd_err("Failed to alloc encrypt aead : %ld\n", PTR_ERR(tfm));
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return tfm;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct shash_desc *alloc_shash_desc(int id)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct crypto_shash *tfm = NULL;
 | 
				
			||||||
 | 
						struct shash_desc *shash;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (id) {
 | 
				
			||||||
 | 
						case CRYPTO_SHASH_HMACMD5:
 | 
				
			||||||
 | 
							tfm = crypto_alloc_shash("hmac(md5)", 0, 0);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case CRYPTO_SHASH_HMACSHA256:
 | 
				
			||||||
 | 
							tfm = crypto_alloc_shash("hmac(sha256)", 0, 0);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case CRYPTO_SHASH_CMACAES:
 | 
				
			||||||
 | 
							tfm = crypto_alloc_shash("cmac(aes)", 0, 0);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case CRYPTO_SHASH_SHA256:
 | 
				
			||||||
 | 
							tfm = crypto_alloc_shash("sha256", 0, 0);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case CRYPTO_SHASH_SHA512:
 | 
				
			||||||
 | 
							tfm = crypto_alloc_shash("sha512", 0, 0);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case CRYPTO_SHASH_MD4:
 | 
				
			||||||
 | 
							tfm = crypto_alloc_shash("md4", 0, 0);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case CRYPTO_SHASH_MD5:
 | 
				
			||||||
 | 
							tfm = crypto_alloc_shash("md5", 0, 0);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (IS_ERR(tfm))
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						shash = kzalloc(sizeof(*shash) + crypto_shash_descsize(tfm),
 | 
				
			||||||
 | 
								GFP_KERNEL);
 | 
				
			||||||
 | 
						if (!shash)
 | 
				
			||||||
 | 
							crypto_free_shash(tfm);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							shash->tfm = tfm;
 | 
				
			||||||
 | 
						return shash;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct ksmbd_crypto_ctx *ctx_alloc(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ksmbd_alloc(sizeof(struct ksmbd_crypto_ctx));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void ctx_free(struct ksmbd_crypto_ctx *ctx)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < CRYPTO_SHASH_MAX; i++)
 | 
				
			||||||
 | 
							free_shash(ctx->desc[i]);
 | 
				
			||||||
 | 
						for (i = 0; i < CRYPTO_AEAD_MAX; i++)
 | 
				
			||||||
 | 
							free_aead(ctx->ccmaes[i]);
 | 
				
			||||||
 | 
						ksmbd_free(ctx);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct ksmbd_crypto_ctx *ksmbd_find_crypto_ctx(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ksmbd_crypto_ctx *ctx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (1) {
 | 
				
			||||||
 | 
							spin_lock(&ctx_list.ctx_lock);
 | 
				
			||||||
 | 
							if (!list_empty(&ctx_list.idle_ctx)) {
 | 
				
			||||||
 | 
								ctx = list_entry(ctx_list.idle_ctx.next,
 | 
				
			||||||
 | 
										  struct ksmbd_crypto_ctx,
 | 
				
			||||||
 | 
										  list);
 | 
				
			||||||
 | 
								list_del(&ctx->list);
 | 
				
			||||||
 | 
								spin_unlock(&ctx_list.ctx_lock);
 | 
				
			||||||
 | 
								return ctx;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (ctx_list.avail_ctx > num_online_cpus()) {
 | 
				
			||||||
 | 
								spin_unlock(&ctx_list.ctx_lock);
 | 
				
			||||||
 | 
								wait_event(ctx_list.ctx_wait,
 | 
				
			||||||
 | 
									   !list_empty(&ctx_list.idle_ctx));
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ctx_list.avail_ctx++;
 | 
				
			||||||
 | 
							spin_unlock(&ctx_list.ctx_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ctx = ctx_alloc();
 | 
				
			||||||
 | 
							if (!ctx) {
 | 
				
			||||||
 | 
								spin_lock(&ctx_list.ctx_lock);
 | 
				
			||||||
 | 
								ctx_list.avail_ctx--;
 | 
				
			||||||
 | 
								spin_unlock(&ctx_list.ctx_lock);
 | 
				
			||||||
 | 
								wait_event(ctx_list.ctx_wait,
 | 
				
			||||||
 | 
									   !list_empty(&ctx_list.idle_ctx));
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ctx;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ksmbd_release_crypto_ctx(struct ksmbd_crypto_ctx *ctx)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!ctx)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock(&ctx_list.ctx_lock);
 | 
				
			||||||
 | 
						if (ctx_list.avail_ctx <= num_online_cpus()) {
 | 
				
			||||||
 | 
							list_add(&ctx->list, &ctx_list.idle_ctx);
 | 
				
			||||||
 | 
							spin_unlock(&ctx_list.ctx_lock);
 | 
				
			||||||
 | 
							wake_up(&ctx_list.ctx_wait);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx_list.avail_ctx--;
 | 
				
			||||||
 | 
						spin_unlock(&ctx_list.ctx_lock);
 | 
				
			||||||
 | 
						ctx_free(ctx);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct ksmbd_crypto_ctx *____crypto_shash_ctx_find(int id)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ksmbd_crypto_ctx *ctx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (id >= CRYPTO_SHASH_MAX)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx = ksmbd_find_crypto_ctx();
 | 
				
			||||||
 | 
						if (ctx->desc[id])
 | 
				
			||||||
 | 
							return ctx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx->desc[id] = alloc_shash_desc(id);
 | 
				
			||||||
 | 
						if (ctx->desc[id])
 | 
				
			||||||
 | 
							return ctx;
 | 
				
			||||||
 | 
						ksmbd_release_crypto_ctx(ctx);
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_hmacmd5(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ____crypto_shash_ctx_find(CRYPTO_SHASH_HMACMD5);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_hmacsha256(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ____crypto_shash_ctx_find(CRYPTO_SHASH_HMACSHA256);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_cmacaes(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ____crypto_shash_ctx_find(CRYPTO_SHASH_CMACAES);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_sha256(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ____crypto_shash_ctx_find(CRYPTO_SHASH_SHA256);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_sha512(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ____crypto_shash_ctx_find(CRYPTO_SHASH_SHA512);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_md4(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ____crypto_shash_ctx_find(CRYPTO_SHASH_MD4);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_md5(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ____crypto_shash_ctx_find(CRYPTO_SHASH_MD5);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct ksmbd_crypto_ctx *____crypto_aead_ctx_find(int id)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ksmbd_crypto_ctx *ctx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (id >= CRYPTO_AEAD_MAX)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx = ksmbd_find_crypto_ctx();
 | 
				
			||||||
 | 
						if (ctx->ccmaes[id])
 | 
				
			||||||
 | 
							return ctx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx->ccmaes[id] = alloc_aead(id);
 | 
				
			||||||
 | 
						if (ctx->ccmaes[id])
 | 
				
			||||||
 | 
							return ctx;
 | 
				
			||||||
 | 
						ksmbd_release_crypto_ctx(ctx);
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_gcm(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ____crypto_aead_ctx_find(CRYPTO_AEAD_AES128_GCM);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_ccm(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ____crypto_aead_ctx_find(CRYPTO_AEAD_AES128_CCM);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ksmbd_crypto_destroy(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ksmbd_crypto_ctx *ctx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (!list_empty(&ctx_list.idle_ctx)) {
 | 
				
			||||||
 | 
							ctx = list_entry(ctx_list.idle_ctx.next,
 | 
				
			||||||
 | 
									 struct ksmbd_crypto_ctx,
 | 
				
			||||||
 | 
									 list);
 | 
				
			||||||
 | 
							list_del(&ctx->list);
 | 
				
			||||||
 | 
							ctx_free(ctx);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_crypto_create(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ksmbd_crypto_ctx *ctx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock_init(&ctx_list.ctx_lock);
 | 
				
			||||||
 | 
						INIT_LIST_HEAD(&ctx_list.idle_ctx);
 | 
				
			||||||
 | 
						init_waitqueue_head(&ctx_list.ctx_wait);
 | 
				
			||||||
 | 
						ctx_list.avail_ctx = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx = ctx_alloc();
 | 
				
			||||||
 | 
						if (!ctx)
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
						list_add(&ctx->list, &ctx_list.idle_ctx);
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										77
									
								
								fs/cifsd/crypto_ctx.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								fs/cifsd/crypto_ctx.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,77 @@
 | 
				
			||||||
 | 
					/* SPDX-License-Identifier: GPL-2.0-or-later */
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *   Copyright (C) 2019 Samsung Electronics Co., Ltd.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef __CRYPTO_CTX_H__
 | 
				
			||||||
 | 
					#define __CRYPTO_CTX_H__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <crypto/hash.h>
 | 
				
			||||||
 | 
					#include <crypto/aead.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum {
 | 
				
			||||||
 | 
						CRYPTO_SHASH_HMACMD5	= 0,
 | 
				
			||||||
 | 
						CRYPTO_SHASH_HMACSHA256,
 | 
				
			||||||
 | 
						CRYPTO_SHASH_CMACAES,
 | 
				
			||||||
 | 
						CRYPTO_SHASH_SHA256,
 | 
				
			||||||
 | 
						CRYPTO_SHASH_SHA512,
 | 
				
			||||||
 | 
						CRYPTO_SHASH_MD4,
 | 
				
			||||||
 | 
						CRYPTO_SHASH_MD5,
 | 
				
			||||||
 | 
						CRYPTO_SHASH_MAX,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum {
 | 
				
			||||||
 | 
						CRYPTO_AEAD_AES128_GCM = 16,
 | 
				
			||||||
 | 
						CRYPTO_AEAD_AES128_CCM,
 | 
				
			||||||
 | 
						CRYPTO_AEAD_MAX,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum {
 | 
				
			||||||
 | 
						CRYPTO_BLK_ECBDES	= 32,
 | 
				
			||||||
 | 
						CRYPTO_BLK_MAX,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_crypto_ctx {
 | 
				
			||||||
 | 
						struct list_head		list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct shash_desc		*desc[CRYPTO_SHASH_MAX];
 | 
				
			||||||
 | 
						struct crypto_aead		*ccmaes[CRYPTO_AEAD_MAX];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CRYPTO_HMACMD5(c)	((c)->desc[CRYPTO_SHASH_HMACMD5])
 | 
				
			||||||
 | 
					#define CRYPTO_HMACSHA256(c)	((c)->desc[CRYPTO_SHASH_HMACSHA256])
 | 
				
			||||||
 | 
					#define CRYPTO_CMACAES(c)	((c)->desc[CRYPTO_SHASH_CMACAES])
 | 
				
			||||||
 | 
					#define CRYPTO_SHA256(c)	((c)->desc[CRYPTO_SHASH_SHA256])
 | 
				
			||||||
 | 
					#define CRYPTO_SHA512(c)	((c)->desc[CRYPTO_SHASH_SHA512])
 | 
				
			||||||
 | 
					#define CRYPTO_MD4(c)		((c)->desc[CRYPTO_SHASH_MD4])
 | 
				
			||||||
 | 
					#define CRYPTO_MD5(c)		((c)->desc[CRYPTO_SHASH_MD5])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CRYPTO_HMACMD5_TFM(c)	((c)->desc[CRYPTO_SHASH_HMACMD5]->tfm)
 | 
				
			||||||
 | 
					#define CRYPTO_HMACSHA256_TFM(c)\
 | 
				
			||||||
 | 
									((c)->desc[CRYPTO_SHASH_HMACSHA256]->tfm)
 | 
				
			||||||
 | 
					#define CRYPTO_CMACAES_TFM(c)	((c)->desc[CRYPTO_SHASH_CMACAES]->tfm)
 | 
				
			||||||
 | 
					#define CRYPTO_SHA256_TFM(c)	((c)->desc[CRYPTO_SHASH_SHA256]->tfm)
 | 
				
			||||||
 | 
					#define CRYPTO_SHA512_TFM(c)	((c)->desc[CRYPTO_SHASH_SHA512]->tfm)
 | 
				
			||||||
 | 
					#define CRYPTO_MD4_TFM(c)	((c)->desc[CRYPTO_SHASH_MD4]->tfm)
 | 
				
			||||||
 | 
					#define CRYPTO_MD5_TFM(c)	((c)->desc[CRYPTO_SHASH_MD5]->tfm)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CRYPTO_GCM(c)		((c)->ccmaes[CRYPTO_AEAD_AES128_GCM])
 | 
				
			||||||
 | 
					#define CRYPTO_CCM(c)		((c)->ccmaes[CRYPTO_AEAD_AES128_CCM])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ksmbd_release_crypto_ctx(struct ksmbd_crypto_ctx *ctx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_hmacmd5(void);
 | 
				
			||||||
 | 
					struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_hmacsha256(void);
 | 
				
			||||||
 | 
					struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_cmacaes(void);
 | 
				
			||||||
 | 
					struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_sha512(void);
 | 
				
			||||||
 | 
					struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_sha256(void);
 | 
				
			||||||
 | 
					struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_md4(void);
 | 
				
			||||||
 | 
					struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_md5(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_gcm(void);
 | 
				
			||||||
 | 
					struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_ccm(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ksmbd_crypto_destroy(void);
 | 
				
			||||||
 | 
					int ksmbd_crypto_create(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* __CRYPTO_CTX_H__ */
 | 
				
			||||||
							
								
								
									
										69
									
								
								fs/cifsd/mgmt/ksmbd_ida.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								fs/cifsd/mgmt/ksmbd_ida.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,69 @@
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: GPL-2.0-or-later
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *   Copyright (C) 2018 Samsung Electronics Co., Ltd.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "ksmbd_ida.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_ida *ksmbd_ida_alloc(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ksmbd_ida *ida;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ida = kmalloc(sizeof(struct ksmbd_ida), GFP_KERNEL);
 | 
				
			||||||
 | 
						if (!ida)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ida_init(&ida->map);
 | 
				
			||||||
 | 
						return ida;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ksmbd_ida_free(struct ksmbd_ida *ida)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!ida)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ida_destroy(&ida->map);
 | 
				
			||||||
 | 
						kfree(ida);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline int __acquire_id(struct ksmbd_ida *ida, int from, int to)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ida_simple_get(&ida->map, from, to, GFP_KERNEL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_acquire_smb2_tid(struct ksmbd_ida *ida)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						do {
 | 
				
			||||||
 | 
							id = __acquire_id(ida, 0, 0);
 | 
				
			||||||
 | 
						} while (id == 0xFFFF);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return id;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_acquire_smb2_uid(struct ksmbd_ida *ida)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						do {
 | 
				
			||||||
 | 
							id = __acquire_id(ida, 1, 0);
 | 
				
			||||||
 | 
						} while (id == 0xFFFE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return id;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_acquire_async_msg_id(struct ksmbd_ida *ida)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return __acquire_id(ida, 1, 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_acquire_id(struct ksmbd_ida *ida)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return __acquire_id(ida, 0, 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ksmbd_release_id(struct ksmbd_ida *ida, int id)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						ida_simple_remove(&ida->map, id);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										41
									
								
								fs/cifsd/mgmt/ksmbd_ida.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								fs/cifsd/mgmt/ksmbd_ida.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,41 @@
 | 
				
			||||||
 | 
					/* SPDX-License-Identifier: GPL-2.0-or-later */
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *   Copyright (C) 2018 Samsung Electronics Co., Ltd.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef __KSMBD_IDA_MANAGEMENT_H__
 | 
				
			||||||
 | 
					#define __KSMBD_IDA_MANAGEMENT_H__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <linux/slab.h>
 | 
				
			||||||
 | 
					#include <linux/idr.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_ida {
 | 
				
			||||||
 | 
						struct ida	map;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_ida *ksmbd_ida_alloc(void);
 | 
				
			||||||
 | 
					void ksmbd_ida_free(struct ksmbd_ida *ida);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * 2.2.1.6.7 TID Generation
 | 
				
			||||||
 | 
					 *    The value 0xFFFF MUST NOT be used as a valid TID. All other
 | 
				
			||||||
 | 
					 *    possible values for TID, including zero (0x0000), are valid.
 | 
				
			||||||
 | 
					 *    The value 0xFFFF is used to specify all TIDs or no TID,
 | 
				
			||||||
 | 
					 *    depending upon the context in which it is used.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int ksmbd_acquire_smb2_tid(struct ksmbd_ida *ida);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * 2.2.1.6.8 UID Generation
 | 
				
			||||||
 | 
					 *    The value 0xFFFE was declared reserved in the LAN Manager 1.0
 | 
				
			||||||
 | 
					 *    documentation, so a value of 0xFFFE SHOULD NOT be used as a
 | 
				
			||||||
 | 
					 *    valid UID.<21> All other possible values for a UID, excluding
 | 
				
			||||||
 | 
					 *    zero (0x0000), are valid.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int ksmbd_acquire_smb2_uid(struct ksmbd_ida *ida);
 | 
				
			||||||
 | 
					int ksmbd_acquire_async_msg_id(struct ksmbd_ida *ida);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_acquire_id(struct ksmbd_ida *ida);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ksmbd_release_id(struct ksmbd_ida *ida, int id);
 | 
				
			||||||
 | 
					#endif /* __KSMBD_IDA_MANAGEMENT_H__ */
 | 
				
			||||||
							
								
								
									
										239
									
								
								fs/cifsd/mgmt/share_config.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										239
									
								
								fs/cifsd/mgmt/share_config.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,239 @@
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: GPL-2.0-or-later
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *   Copyright (C) 2018 Samsung Electronics Co., Ltd.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <linux/list.h>
 | 
				
			||||||
 | 
					#include <linux/jhash.h>
 | 
				
			||||||
 | 
					#include <linux/slab.h>
 | 
				
			||||||
 | 
					#include <linux/rwsem.h>
 | 
				
			||||||
 | 
					#include <linux/parser.h>
 | 
				
			||||||
 | 
					#include <linux/namei.h>
 | 
				
			||||||
 | 
					#include <linux/sched.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "share_config.h"
 | 
				
			||||||
 | 
					#include "user_config.h"
 | 
				
			||||||
 | 
					#include "user_session.h"
 | 
				
			||||||
 | 
					#include "../buffer_pool.h"
 | 
				
			||||||
 | 
					#include "../transport_ipc.h"
 | 
				
			||||||
 | 
					#include "../ksmbd_server.h" /* FIXME */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SHARE_HASH_BITS		3
 | 
				
			||||||
 | 
					static DEFINE_HASHTABLE(shares_table, SHARE_HASH_BITS);
 | 
				
			||||||
 | 
					static DECLARE_RWSEM(shares_table_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_veto_pattern {
 | 
				
			||||||
 | 
						char			*pattern;
 | 
				
			||||||
 | 
						struct list_head	list;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static unsigned int share_name_hash(char *name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return jhash(name, strlen(name), 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void kill_share(struct ksmbd_share_config *share)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						while (!list_empty(&share->veto_list)) {
 | 
				
			||||||
 | 
							struct ksmbd_veto_pattern *p;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							p = list_entry(share->veto_list.next,
 | 
				
			||||||
 | 
								       struct ksmbd_veto_pattern,
 | 
				
			||||||
 | 
								       list);
 | 
				
			||||||
 | 
							list_del(&p->list);
 | 
				
			||||||
 | 
							kfree(p->pattern);
 | 
				
			||||||
 | 
							kfree(p);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (share->path)
 | 
				
			||||||
 | 
							path_put(&share->vfs_path);
 | 
				
			||||||
 | 
						kfree(share->name);
 | 
				
			||||||
 | 
						kfree(share->path);
 | 
				
			||||||
 | 
						kfree(share);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void __ksmbd_share_config_put(struct ksmbd_share_config *share)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						down_write(&shares_table_lock);
 | 
				
			||||||
 | 
						hash_del(&share->hlist);
 | 
				
			||||||
 | 
						up_write(&shares_table_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						kill_share(share);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct ksmbd_share_config *
 | 
				
			||||||
 | 
					__get_share_config(struct ksmbd_share_config *share)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!atomic_inc_not_zero(&share->refcount))
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						return share;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct ksmbd_share_config *__share_lookup(char *name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ksmbd_share_config *share;
 | 
				
			||||||
 | 
						unsigned int key = share_name_hash(name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hash_for_each_possible(shares_table, share, hlist, key) {
 | 
				
			||||||
 | 
							if (!strcmp(name, share->name))
 | 
				
			||||||
 | 
								return share;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int parse_veto_list(struct ksmbd_share_config *share,
 | 
				
			||||||
 | 
								   char *veto_list,
 | 
				
			||||||
 | 
								   int veto_list_sz)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int sz = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!veto_list_sz)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (veto_list_sz > 0) {
 | 
				
			||||||
 | 
							struct ksmbd_veto_pattern *p;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							p = ksmbd_alloc(sizeof(struct ksmbd_veto_pattern));
 | 
				
			||||||
 | 
							if (!p)
 | 
				
			||||||
 | 
								return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							sz = strlen(veto_list);
 | 
				
			||||||
 | 
							if (!sz)
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							p->pattern = kstrdup(veto_list, GFP_KERNEL);
 | 
				
			||||||
 | 
							if (!p->pattern) {
 | 
				
			||||||
 | 
								ksmbd_free(p);
 | 
				
			||||||
 | 
								return -ENOMEM;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							list_add(&p->list, &share->veto_list);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							veto_list += sz + 1;
 | 
				
			||||||
 | 
							veto_list_sz -= (sz + 1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct ksmbd_share_config *share_config_request(char *name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ksmbd_share_config_response *resp;
 | 
				
			||||||
 | 
						struct ksmbd_share_config *share = NULL;
 | 
				
			||||||
 | 
						struct ksmbd_share_config *lookup;
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						resp = ksmbd_ipc_share_config_request(name);
 | 
				
			||||||
 | 
						if (!resp)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (resp->flags == KSMBD_SHARE_FLAG_INVALID)
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						share = ksmbd_alloc(sizeof(struct ksmbd_share_config));
 | 
				
			||||||
 | 
						if (!share)
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						share->flags = resp->flags;
 | 
				
			||||||
 | 
						atomic_set(&share->refcount, 1);
 | 
				
			||||||
 | 
						INIT_LIST_HEAD(&share->veto_list);
 | 
				
			||||||
 | 
						share->name = kstrdup(name, GFP_KERNEL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!test_share_config_flag(share, KSMBD_SHARE_FLAG_PIPE)) {
 | 
				
			||||||
 | 
							share->path = kstrdup(KSMBD_SHARE_CONFIG_PATH(resp),
 | 
				
			||||||
 | 
									      GFP_KERNEL);
 | 
				
			||||||
 | 
							if (share->path)
 | 
				
			||||||
 | 
								share->path_sz = strlen(share->path);
 | 
				
			||||||
 | 
							share->create_mask = resp->create_mask;
 | 
				
			||||||
 | 
							share->directory_mask = resp->directory_mask;
 | 
				
			||||||
 | 
							share->force_create_mode = resp->force_create_mode;
 | 
				
			||||||
 | 
							share->force_directory_mode = resp->force_directory_mode;
 | 
				
			||||||
 | 
							share->force_uid = resp->force_uid;
 | 
				
			||||||
 | 
							share->force_gid = resp->force_gid;
 | 
				
			||||||
 | 
							ret = parse_veto_list(share,
 | 
				
			||||||
 | 
									      KSMBD_SHARE_CONFIG_VETO_LIST(resp),
 | 
				
			||||||
 | 
									      resp->veto_list_sz);
 | 
				
			||||||
 | 
							if (!ret && share->path) {
 | 
				
			||||||
 | 
								ret = kern_path(share->path, 0, &share->vfs_path);
 | 
				
			||||||
 | 
								if (ret) {
 | 
				
			||||||
 | 
									ksmbd_debug(SMB, "failed to access '%s'\n",
 | 
				
			||||||
 | 
										share->path);
 | 
				
			||||||
 | 
									/* Avoid put_path() */
 | 
				
			||||||
 | 
									kfree(share->path);
 | 
				
			||||||
 | 
									share->path = NULL;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (ret || !share->name) {
 | 
				
			||||||
 | 
								kill_share(share);
 | 
				
			||||||
 | 
								share = NULL;
 | 
				
			||||||
 | 
								goto out;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						down_write(&shares_table_lock);
 | 
				
			||||||
 | 
						lookup = __share_lookup(name);
 | 
				
			||||||
 | 
						if (lookup)
 | 
				
			||||||
 | 
							lookup = __get_share_config(lookup);
 | 
				
			||||||
 | 
						if (!lookup) {
 | 
				
			||||||
 | 
							hash_add(shares_table, &share->hlist, share_name_hash(name));
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							kill_share(share);
 | 
				
			||||||
 | 
							share = lookup;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						up_write(&shares_table_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					out:
 | 
				
			||||||
 | 
						ksmbd_free(resp);
 | 
				
			||||||
 | 
						return share;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void strtolower(char *share_name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						while (*share_name) {
 | 
				
			||||||
 | 
							*share_name = tolower(*share_name);
 | 
				
			||||||
 | 
							share_name++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_share_config *ksmbd_share_config_get(char *name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ksmbd_share_config *share;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						strtolower(name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						down_read(&shares_table_lock);
 | 
				
			||||||
 | 
						share = __share_lookup(name);
 | 
				
			||||||
 | 
						if (share)
 | 
				
			||||||
 | 
							share = __get_share_config(share);
 | 
				
			||||||
 | 
						up_read(&shares_table_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (share)
 | 
				
			||||||
 | 
							return share;
 | 
				
			||||||
 | 
						return share_config_request(name);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool ksmbd_share_veto_filename(struct ksmbd_share_config *share,
 | 
				
			||||||
 | 
								       const char *filename)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ksmbd_veto_pattern *p;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list_for_each_entry(p, &share->veto_list, list) {
 | 
				
			||||||
 | 
							if (match_wildcard(p->pattern, filename))
 | 
				
			||||||
 | 
								return true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ksmbd_share_configs_cleanup(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ksmbd_share_config *share;
 | 
				
			||||||
 | 
						struct hlist_node *tmp;
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						down_write(&shares_table_lock);
 | 
				
			||||||
 | 
						hash_for_each_safe(shares_table, i, tmp, share, hlist) {
 | 
				
			||||||
 | 
							hash_del(&share->hlist);
 | 
				
			||||||
 | 
							kill_share(share);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						up_write(&shares_table_lock);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										83
									
								
								fs/cifsd/mgmt/share_config.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								fs/cifsd/mgmt/share_config.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,83 @@
 | 
				
			||||||
 | 
					/* SPDX-License-Identifier: GPL-2.0-or-later */
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *   Copyright (C) 2018 Samsung Electronics Co., Ltd.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef __SHARE_CONFIG_MANAGEMENT_H__
 | 
				
			||||||
 | 
					#define __SHARE_CONFIG_MANAGEMENT_H__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <linux/workqueue.h>
 | 
				
			||||||
 | 
					#include <linux/hashtable.h>
 | 
				
			||||||
 | 
					#include <linux/path.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "../glob.h"  /* FIXME */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_share_config {
 | 
				
			||||||
 | 
						char			*name;
 | 
				
			||||||
 | 
						char			*path;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						unsigned int		path_sz;
 | 
				
			||||||
 | 
						unsigned int		flags;
 | 
				
			||||||
 | 
						struct list_head	veto_list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct path		vfs_path;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						atomic_t		refcount;
 | 
				
			||||||
 | 
						struct hlist_node	hlist;
 | 
				
			||||||
 | 
						unsigned short		create_mask;
 | 
				
			||||||
 | 
						unsigned short		directory_mask;
 | 
				
			||||||
 | 
						unsigned short		force_create_mode;
 | 
				
			||||||
 | 
						unsigned short		force_directory_mode;
 | 
				
			||||||
 | 
						unsigned short		force_uid;
 | 
				
			||||||
 | 
						unsigned short		force_gid;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define KSMBD_SHARE_INVALID_UID	((__u16)-1)
 | 
				
			||||||
 | 
					#define KSMBD_SHARE_INVALID_GID	((__u16)-1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline int share_config_create_mode(struct ksmbd_share_config *share,
 | 
				
			||||||
 | 
						umode_t posix_mode)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!share->force_create_mode) {
 | 
				
			||||||
 | 
							if (!posix_mode)
 | 
				
			||||||
 | 
								return share->create_mask;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								return posix_mode & share->create_mask;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return share->force_create_mode & share->create_mask;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline int share_config_directory_mode(struct ksmbd_share_config *share,
 | 
				
			||||||
 | 
						umode_t posix_mode)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!share->force_directory_mode) {
 | 
				
			||||||
 | 
							if (!posix_mode)
 | 
				
			||||||
 | 
								return share->directory_mask;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								return posix_mode & share->directory_mask;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return share->force_directory_mode & share->directory_mask;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline int test_share_config_flag(struct ksmbd_share_config *share,
 | 
				
			||||||
 | 
										 int flag)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return share->flags & flag;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern void __ksmbd_share_config_put(struct ksmbd_share_config *share);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void ksmbd_share_config_put(struct ksmbd_share_config *share)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!atomic_dec_and_test(&share->refcount))
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						__ksmbd_share_config_put(share);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_share_config *ksmbd_share_config_get(char *name);
 | 
				
			||||||
 | 
					bool ksmbd_share_veto_filename(struct ksmbd_share_config *share,
 | 
				
			||||||
 | 
								       const char *filename);
 | 
				
			||||||
 | 
					void ksmbd_share_configs_cleanup(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* __SHARE_CONFIG_MANAGEMENT_H__ */
 | 
				
			||||||
							
								
								
									
										129
									
								
								fs/cifsd/mgmt/tree_connect.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								fs/cifsd/mgmt/tree_connect.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,129 @@
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: GPL-2.0-or-later
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *   Copyright (C) 2018 Samsung Electronics Co., Ltd.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <linux/list.h>
 | 
				
			||||||
 | 
					#include <linux/slab.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "../ksmbd_server.h" /* FIXME */
 | 
				
			||||||
 | 
					#include "../buffer_pool.h"
 | 
				
			||||||
 | 
					#include "../transport_ipc.h"
 | 
				
			||||||
 | 
					#include "../connection.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "tree_connect.h"
 | 
				
			||||||
 | 
					#include "user_config.h"
 | 
				
			||||||
 | 
					#include "share_config.h"
 | 
				
			||||||
 | 
					#include "user_session.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_tree_conn_status
 | 
				
			||||||
 | 
					ksmbd_tree_conn_connect(struct ksmbd_session *sess, char *share_name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ksmbd_tree_conn_status status = {-EINVAL, NULL};
 | 
				
			||||||
 | 
						struct ksmbd_tree_connect_response *resp = NULL;
 | 
				
			||||||
 | 
						struct ksmbd_share_config *sc;
 | 
				
			||||||
 | 
						struct ksmbd_tree_connect *tree_conn = NULL;
 | 
				
			||||||
 | 
						struct sockaddr *peer_addr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sc = ksmbd_share_config_get(share_name);
 | 
				
			||||||
 | 
						if (!sc)
 | 
				
			||||||
 | 
							return status;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tree_conn = ksmbd_alloc(sizeof(struct ksmbd_tree_connect));
 | 
				
			||||||
 | 
						if (!tree_conn) {
 | 
				
			||||||
 | 
							status.ret = -ENOMEM;
 | 
				
			||||||
 | 
							goto out_error;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tree_conn->id = ksmbd_acquire_tree_conn_id(sess);
 | 
				
			||||||
 | 
						if (tree_conn->id < 0) {
 | 
				
			||||||
 | 
							status.ret = -EINVAL;
 | 
				
			||||||
 | 
							goto out_error;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						peer_addr = KSMBD_TCP_PEER_SOCKADDR(sess->conn);
 | 
				
			||||||
 | 
						resp = ksmbd_ipc_tree_connect_request(sess,
 | 
				
			||||||
 | 
										      sc,
 | 
				
			||||||
 | 
										      tree_conn,
 | 
				
			||||||
 | 
										      peer_addr);
 | 
				
			||||||
 | 
						if (!resp) {
 | 
				
			||||||
 | 
							status.ret = -EINVAL;
 | 
				
			||||||
 | 
							goto out_error;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						status.ret = resp->status;
 | 
				
			||||||
 | 
						if (status.ret != KSMBD_TREE_CONN_STATUS_OK)
 | 
				
			||||||
 | 
							goto out_error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tree_conn->flags = resp->connection_flags;
 | 
				
			||||||
 | 
						tree_conn->user = sess->user;
 | 
				
			||||||
 | 
						tree_conn->share_conf = sc;
 | 
				
			||||||
 | 
						status.tree_conn = tree_conn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list_add(&tree_conn->list, &sess->tree_conn_list);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ksmbd_free(resp);
 | 
				
			||||||
 | 
						return status;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					out_error:
 | 
				
			||||||
 | 
						if (tree_conn)
 | 
				
			||||||
 | 
							ksmbd_release_tree_conn_id(sess, tree_conn->id);
 | 
				
			||||||
 | 
						ksmbd_share_config_put(sc);
 | 
				
			||||||
 | 
						ksmbd_free(tree_conn);
 | 
				
			||||||
 | 
						ksmbd_free(resp);
 | 
				
			||||||
 | 
						return status;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_tree_conn_disconnect(struct ksmbd_session *sess,
 | 
				
			||||||
 | 
								       struct ksmbd_tree_connect *tree_conn)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = ksmbd_ipc_tree_disconnect_request(sess->id, tree_conn->id);
 | 
				
			||||||
 | 
						ksmbd_release_tree_conn_id(sess, tree_conn->id);
 | 
				
			||||||
 | 
						list_del(&tree_conn->list);
 | 
				
			||||||
 | 
						ksmbd_share_config_put(tree_conn->share_conf);
 | 
				
			||||||
 | 
						ksmbd_free(tree_conn);
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_tree_connect *ksmbd_tree_conn_lookup(struct ksmbd_session *sess,
 | 
				
			||||||
 | 
											  unsigned int id)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ksmbd_tree_connect *tree_conn;
 | 
				
			||||||
 | 
						struct list_head *tmp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list_for_each(tmp, &sess->tree_conn_list) {
 | 
				
			||||||
 | 
							tree_conn = list_entry(tmp, struct ksmbd_tree_connect, list);
 | 
				
			||||||
 | 
							if (tree_conn->id == id)
 | 
				
			||||||
 | 
								return tree_conn;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_share_config *ksmbd_tree_conn_share(struct ksmbd_session *sess,
 | 
				
			||||||
 | 
											 unsigned int id)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ksmbd_tree_connect *tc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tc = ksmbd_tree_conn_lookup(sess, id);
 | 
				
			||||||
 | 
						if (tc)
 | 
				
			||||||
 | 
							return tc->share_conf;
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_tree_conn_session_logoff(struct ksmbd_session *sess)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ret = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (!list_empty(&sess->tree_conn_list)) {
 | 
				
			||||||
 | 
							struct ksmbd_tree_connect *tc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							tc = list_entry(sess->tree_conn_list.next,
 | 
				
			||||||
 | 
									struct ksmbd_tree_connect,
 | 
				
			||||||
 | 
									list);
 | 
				
			||||||
 | 
							ret |= ksmbd_tree_conn_disconnect(sess, tc);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										56
									
								
								fs/cifsd/mgmt/tree_connect.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								fs/cifsd/mgmt/tree_connect.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,56 @@
 | 
				
			||||||
 | 
					/* SPDX-License-Identifier: GPL-2.0-or-later */
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *   Copyright (C) 2018 Samsung Electronics Co., Ltd.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef __TREE_CONNECT_MANAGEMENT_H__
 | 
				
			||||||
 | 
					#define __TREE_CONNECT_MANAGEMENT_H__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <linux/hashtable.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "../ksmbd_server.h" /* FIXME */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_share_config;
 | 
				
			||||||
 | 
					struct ksmbd_user;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_tree_connect {
 | 
				
			||||||
 | 
						int				id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						unsigned int			flags;
 | 
				
			||||||
 | 
						struct ksmbd_share_config	*share_conf;
 | 
				
			||||||
 | 
						struct ksmbd_user		*user;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct list_head		list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int				maximal_access;
 | 
				
			||||||
 | 
						bool				posix_extensions;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_tree_conn_status {
 | 
				
			||||||
 | 
						unsigned int			ret;
 | 
				
			||||||
 | 
						struct ksmbd_tree_connect	*tree_conn;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline int test_tree_conn_flag(struct ksmbd_tree_connect *tree_conn,
 | 
				
			||||||
 | 
									      int flag)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return tree_conn->flags & flag;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_session;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_tree_conn_status
 | 
				
			||||||
 | 
					ksmbd_tree_conn_connect(struct ksmbd_session *sess, char *share_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_tree_conn_disconnect(struct ksmbd_session *sess,
 | 
				
			||||||
 | 
								       struct ksmbd_tree_connect *tree_conn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_tree_connect *ksmbd_tree_conn_lookup(struct ksmbd_session *sess,
 | 
				
			||||||
 | 
											  unsigned int id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_share_config *ksmbd_tree_conn_share(struct ksmbd_session *sess,
 | 
				
			||||||
 | 
											 unsigned int id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_tree_conn_session_logoff(struct ksmbd_session *sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* __TREE_CONNECT_MANAGEMENT_H__ */
 | 
				
			||||||
							
								
								
									
										70
									
								
								fs/cifsd/mgmt/user_config.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								fs/cifsd/mgmt/user_config.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,70 @@
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: GPL-2.0-or-later
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *   Copyright (C) 2018 Samsung Electronics Co., Ltd.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <linux/slab.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "user_config.h"
 | 
				
			||||||
 | 
					#include "../buffer_pool.h"
 | 
				
			||||||
 | 
					#include "../transport_ipc.h"
 | 
				
			||||||
 | 
					#include "../ksmbd_server.h" /* FIXME */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_user *ksmbd_login_user(const char *account)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ksmbd_login_response *resp;
 | 
				
			||||||
 | 
						struct ksmbd_user *user = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						resp = ksmbd_ipc_login_request(account);
 | 
				
			||||||
 | 
						if (!resp)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!(resp->status & KSMBD_USER_FLAG_OK))
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						user = ksmbd_alloc_user(resp);
 | 
				
			||||||
 | 
					out:
 | 
				
			||||||
 | 
						ksmbd_free(resp);
 | 
				
			||||||
 | 
						return user;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_user *ksmbd_alloc_user(struct ksmbd_login_response *resp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ksmbd_user *user = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						user = ksmbd_alloc(sizeof(struct ksmbd_user));
 | 
				
			||||||
 | 
						if (!user)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						user->name = kstrdup(resp->account, GFP_KERNEL);
 | 
				
			||||||
 | 
						user->flags = resp->status;
 | 
				
			||||||
 | 
						user->gid = resp->gid;
 | 
				
			||||||
 | 
						user->uid = resp->uid;
 | 
				
			||||||
 | 
						user->passkey_sz = resp->hash_sz;
 | 
				
			||||||
 | 
						user->passkey = ksmbd_alloc(resp->hash_sz);
 | 
				
			||||||
 | 
						if (user->passkey)
 | 
				
			||||||
 | 
							memcpy(user->passkey, resp->hash, resp->hash_sz);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!user->name || !user->passkey) {
 | 
				
			||||||
 | 
							kfree(user->name);
 | 
				
			||||||
 | 
							ksmbd_free(user->passkey);
 | 
				
			||||||
 | 
							ksmbd_free(user);
 | 
				
			||||||
 | 
							user = NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return user;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ksmbd_free_user(struct ksmbd_user *user)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						ksmbd_ipc_logout_request(user->name);
 | 
				
			||||||
 | 
						kfree(user->name);
 | 
				
			||||||
 | 
						ksmbd_free(user->passkey);
 | 
				
			||||||
 | 
						ksmbd_free(user);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_anonymous_user(struct ksmbd_user *user)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (user->name[0] == '\0')
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										67
									
								
								fs/cifsd/mgmt/user_config.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								fs/cifsd/mgmt/user_config.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,67 @@
 | 
				
			||||||
 | 
					/* SPDX-License-Identifier: GPL-2.0-or-later */
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *   Copyright (C) 2018 Samsung Electronics Co., Ltd.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef __USER_CONFIG_MANAGEMENT_H__
 | 
				
			||||||
 | 
					#define __USER_CONFIG_MANAGEMENT_H__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "../glob.h"  /* FIXME */
 | 
				
			||||||
 | 
					#include "../ksmbd_server.h" /* FIXME */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_user {
 | 
				
			||||||
 | 
						unsigned short		flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						unsigned int		uid;
 | 
				
			||||||
 | 
						unsigned int		gid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						char			*name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						size_t			passkey_sz;
 | 
				
			||||||
 | 
						char			*passkey;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline bool user_guest(struct ksmbd_user *user)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return user->flags & KSMBD_USER_FLAG_GUEST_ACCOUNT;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void set_user_flag(struct ksmbd_user *user, int flag)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						user->flags |= flag;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline int test_user_flag(struct ksmbd_user *user, int flag)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return user->flags & flag;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void set_user_guest(struct ksmbd_user *user)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline char *user_passkey(struct ksmbd_user *user)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return user->passkey;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline char *user_name(struct ksmbd_user *user)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return user->name;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline unsigned int user_uid(struct ksmbd_user *user)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return user->uid;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline unsigned int user_gid(struct ksmbd_user *user)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return user->gid;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_user *ksmbd_login_user(const char *account);
 | 
				
			||||||
 | 
					struct ksmbd_user *ksmbd_alloc_user(struct ksmbd_login_response *resp);
 | 
				
			||||||
 | 
					void ksmbd_free_user(struct ksmbd_user *user);
 | 
				
			||||||
 | 
					int ksmbd_anonymous_user(struct ksmbd_user *user);
 | 
				
			||||||
 | 
					#endif /* __USER_CONFIG_MANAGEMENT_H__ */
 | 
				
			||||||
							
								
								
									
										345
									
								
								fs/cifsd/mgmt/user_session.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										345
									
								
								fs/cifsd/mgmt/user_session.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,345 @@
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: GPL-2.0-or-later
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *   Copyright (C) 2018 Samsung Electronics Co., Ltd.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <linux/list.h>
 | 
				
			||||||
 | 
					#include <linux/slab.h>
 | 
				
			||||||
 | 
					#include <linux/rwsem.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "ksmbd_ida.h"
 | 
				
			||||||
 | 
					#include "user_session.h"
 | 
				
			||||||
 | 
					#include "user_config.h"
 | 
				
			||||||
 | 
					#include "tree_connect.h"
 | 
				
			||||||
 | 
					#include "../transport_ipc.h"
 | 
				
			||||||
 | 
					#include "../connection.h"
 | 
				
			||||||
 | 
					#include "../buffer_pool.h"
 | 
				
			||||||
 | 
					#include "../ksmbd_server.h" /* FIXME */
 | 
				
			||||||
 | 
					#include "../vfs_cache.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct ksmbd_ida *session_ida;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SESSION_HASH_BITS		3
 | 
				
			||||||
 | 
					static DEFINE_HASHTABLE(sessions_table, SESSION_HASH_BITS);
 | 
				
			||||||
 | 
					static DECLARE_RWSEM(sessions_table_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_session_rpc {
 | 
				
			||||||
 | 
						int			id;
 | 
				
			||||||
 | 
						unsigned int		method;
 | 
				
			||||||
 | 
						struct list_head	list;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void free_channel_list(struct ksmbd_session *sess)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct channel *chann;
 | 
				
			||||||
 | 
						struct list_head *tmp, *t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list_for_each_safe(tmp, t, &sess->ksmbd_chann_list) {
 | 
				
			||||||
 | 
							chann = list_entry(tmp, struct channel, chann_list);
 | 
				
			||||||
 | 
							if (chann) {
 | 
				
			||||||
 | 
								list_del(&chann->chann_list);
 | 
				
			||||||
 | 
								kfree(chann);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void __session_rpc_close(struct ksmbd_session *sess,
 | 
				
			||||||
 | 
									struct ksmbd_session_rpc *entry)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ksmbd_rpc_command *resp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						resp = ksmbd_rpc_close(sess, entry->id);
 | 
				
			||||||
 | 
						if (!resp)
 | 
				
			||||||
 | 
							pr_err("Unable to close RPC pipe %d\n", entry->id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ksmbd_free(resp);
 | 
				
			||||||
 | 
						ksmbd_rpc_id_free(entry->id);
 | 
				
			||||||
 | 
						ksmbd_free(entry);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void ksmbd_session_rpc_clear_list(struct ksmbd_session *sess)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ksmbd_session_rpc *entry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (!list_empty(&sess->rpc_handle_list)) {
 | 
				
			||||||
 | 
							entry = list_entry(sess->rpc_handle_list.next,
 | 
				
			||||||
 | 
									   struct ksmbd_session_rpc,
 | 
				
			||||||
 | 
									   list);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							list_del(&entry->list);
 | 
				
			||||||
 | 
							__session_rpc_close(sess, entry);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int __rpc_method(char *rpc_name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!strcmp(rpc_name, "\\srvsvc") || !strcmp(rpc_name, "srvsvc"))
 | 
				
			||||||
 | 
							return KSMBD_RPC_SRVSVC_METHOD_INVOKE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!strcmp(rpc_name, "\\wkssvc") || !strcmp(rpc_name, "wkssvc"))
 | 
				
			||||||
 | 
							return KSMBD_RPC_WKSSVC_METHOD_INVOKE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!strcmp(rpc_name, "LANMAN") || !strcmp(rpc_name, "lanman"))
 | 
				
			||||||
 | 
							return KSMBD_RPC_RAP_METHOD;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!strcmp(rpc_name, "\\samr") || !strcmp(rpc_name, "samr"))
 | 
				
			||||||
 | 
							return KSMBD_RPC_SAMR_METHOD_INVOKE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!strcmp(rpc_name, "\\lsarpc") || !strcmp(rpc_name, "lsarpc"))
 | 
				
			||||||
 | 
							return KSMBD_RPC_LSARPC_METHOD_INVOKE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ksmbd_err("Unsupported RPC: %s\n", rpc_name);
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_session_rpc_open(struct ksmbd_session *sess, char *rpc_name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ksmbd_session_rpc *entry;
 | 
				
			||||||
 | 
						struct ksmbd_rpc_command *resp;
 | 
				
			||||||
 | 
						int method;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						method = __rpc_method(rpc_name);
 | 
				
			||||||
 | 
						if (!method)
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						entry = ksmbd_alloc(sizeof(struct ksmbd_session_rpc));
 | 
				
			||||||
 | 
						if (!entry)
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list_add(&entry->list, &sess->rpc_handle_list);
 | 
				
			||||||
 | 
						entry->method = method;
 | 
				
			||||||
 | 
						entry->id = ksmbd_ipc_id_alloc();
 | 
				
			||||||
 | 
						if (entry->id < 0)
 | 
				
			||||||
 | 
							goto error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						resp = ksmbd_rpc_open(sess, entry->id);
 | 
				
			||||||
 | 
						if (!resp)
 | 
				
			||||||
 | 
							goto error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ksmbd_free(resp);
 | 
				
			||||||
 | 
						return entry->id;
 | 
				
			||||||
 | 
					error:
 | 
				
			||||||
 | 
						list_del(&entry->list);
 | 
				
			||||||
 | 
						ksmbd_free(entry);
 | 
				
			||||||
 | 
						return -EINVAL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ksmbd_session_rpc_close(struct ksmbd_session *sess, int id)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ksmbd_session_rpc *entry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list_for_each_entry(entry, &sess->rpc_handle_list, list) {
 | 
				
			||||||
 | 
							if (entry->id == id) {
 | 
				
			||||||
 | 
								list_del(&entry->list);
 | 
				
			||||||
 | 
								__session_rpc_close(sess, entry);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_session_rpc_method(struct ksmbd_session *sess, int id)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ksmbd_session_rpc *entry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list_for_each_entry(entry, &sess->rpc_handle_list, list) {
 | 
				
			||||||
 | 
							if (entry->id == id)
 | 
				
			||||||
 | 
								return entry->method;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ksmbd_session_destroy(struct ksmbd_session *sess)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!sess)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!atomic_dec_and_test(&sess->refcnt))
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list_del(&sess->sessions_entry);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (IS_SMB2(sess->conn)) {
 | 
				
			||||||
 | 
							down_write(&sessions_table_lock);
 | 
				
			||||||
 | 
							hash_del(&sess->hlist);
 | 
				
			||||||
 | 
							up_write(&sessions_table_lock);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (sess->user)
 | 
				
			||||||
 | 
							ksmbd_free_user(sess->user);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ksmbd_tree_conn_session_logoff(sess);
 | 
				
			||||||
 | 
						ksmbd_destroy_file_table(&sess->file_table);
 | 
				
			||||||
 | 
						ksmbd_session_rpc_clear_list(sess);
 | 
				
			||||||
 | 
						free_channel_list(sess);
 | 
				
			||||||
 | 
						kfree(sess->Preauth_HashValue);
 | 
				
			||||||
 | 
						ksmbd_release_id(session_ida, sess->id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ksmbd_ida_free(sess->tree_conn_ida);
 | 
				
			||||||
 | 
						ksmbd_free(sess);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct ksmbd_session *__session_lookup(unsigned long long id)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ksmbd_session *sess;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hash_for_each_possible(sessions_table, sess, hlist, id) {
 | 
				
			||||||
 | 
							if (id == sess->id)
 | 
				
			||||||
 | 
								return sess;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ksmbd_session_register(struct ksmbd_conn *conn,
 | 
				
			||||||
 | 
								    struct ksmbd_session *sess)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						sess->conn = conn;
 | 
				
			||||||
 | 
						list_add(&sess->sessions_entry, &conn->sessions);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ksmbd_sessions_deregister(struct ksmbd_conn *conn)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ksmbd_session *sess;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (!list_empty(&conn->sessions)) {
 | 
				
			||||||
 | 
							sess = list_entry(conn->sessions.next,
 | 
				
			||||||
 | 
									  struct ksmbd_session,
 | 
				
			||||||
 | 
									  sessions_entry);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ksmbd_session_destroy(sess);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool ksmbd_session_id_match(struct ksmbd_session *sess, unsigned long long id)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return sess->id == id;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn,
 | 
				
			||||||
 | 
										   unsigned long long id)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ksmbd_session *sess = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list_for_each_entry(sess, &conn->sessions, sessions_entry) {
 | 
				
			||||||
 | 
							if (ksmbd_session_id_match(sess, id))
 | 
				
			||||||
 | 
								return sess;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int get_session(struct ksmbd_session *sess)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return atomic_inc_not_zero(&sess->refcnt);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void put_session(struct ksmbd_session *sess)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (atomic_dec_and_test(&sess->refcnt))
 | 
				
			||||||
 | 
							ksmbd_err("get/%s seems to be mismatched.", __func__);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_session *ksmbd_session_lookup_slowpath(unsigned long long id)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ksmbd_session *sess;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						down_read(&sessions_table_lock);
 | 
				
			||||||
 | 
						sess = __session_lookup(id);
 | 
				
			||||||
 | 
						if (sess) {
 | 
				
			||||||
 | 
							if (!get_session(sess))
 | 
				
			||||||
 | 
								sess = NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						up_read(&sessions_table_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return sess;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int __init_smb2_session(struct ksmbd_session *sess)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int id = ksmbd_acquire_smb2_uid(session_ida);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (id < 0)
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						sess->id = id;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct ksmbd_session *__session_create(int protocol)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ksmbd_session *sess;
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sess = ksmbd_alloc(sizeof(struct ksmbd_session));
 | 
				
			||||||
 | 
						if (!sess)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ksmbd_init_file_table(&sess->file_table))
 | 
				
			||||||
 | 
							goto error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						set_session_flag(sess, protocol);
 | 
				
			||||||
 | 
						INIT_LIST_HEAD(&sess->sessions_entry);
 | 
				
			||||||
 | 
						INIT_LIST_HEAD(&sess->tree_conn_list);
 | 
				
			||||||
 | 
						INIT_LIST_HEAD(&sess->ksmbd_chann_list);
 | 
				
			||||||
 | 
						INIT_LIST_HEAD(&sess->rpc_handle_list);
 | 
				
			||||||
 | 
						sess->sequence_number = 1;
 | 
				
			||||||
 | 
						atomic_set(&sess->refcnt, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (protocol) {
 | 
				
			||||||
 | 
						case CIFDS_SESSION_FLAG_SMB2:
 | 
				
			||||||
 | 
							ret = __init_smb2_session(sess);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							ret = -EINVAL;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ret)
 | 
				
			||||||
 | 
							goto error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sess->tree_conn_ida = ksmbd_ida_alloc();
 | 
				
			||||||
 | 
						if (!sess->tree_conn_ida)
 | 
				
			||||||
 | 
							goto error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (protocol == CIFDS_SESSION_FLAG_SMB2) {
 | 
				
			||||||
 | 
							down_read(&sessions_table_lock);
 | 
				
			||||||
 | 
							hash_add(sessions_table, &sess->hlist, sess->id);
 | 
				
			||||||
 | 
							up_read(&sessions_table_lock);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return sess;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					error:
 | 
				
			||||||
 | 
						ksmbd_session_destroy(sess);
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_session *ksmbd_smb2_session_create(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return __session_create(CIFDS_SESSION_FLAG_SMB2);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_acquire_tree_conn_id(struct ksmbd_session *sess)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int id = -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (test_session_flag(sess, CIFDS_SESSION_FLAG_SMB2))
 | 
				
			||||||
 | 
							id = ksmbd_acquire_smb2_tid(sess->tree_conn_ida);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return id;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ksmbd_release_tree_conn_id(struct ksmbd_session *sess, int id)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (id >= 0)
 | 
				
			||||||
 | 
							ksmbd_release_id(sess->tree_conn_ida, id);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_init_session_table(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						session_ida = ksmbd_ida_alloc();
 | 
				
			||||||
 | 
						if (!session_ida)
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ksmbd_free_session_table(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						ksmbd_ida_free(session_ida);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										105
									
								
								fs/cifsd/mgmt/user_session.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								fs/cifsd/mgmt/user_session.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,105 @@
 | 
				
			||||||
 | 
					/* SPDX-License-Identifier: GPL-2.0-or-later */
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *   Copyright (C) 2018 Samsung Electronics Co., Ltd.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef __USER_SESSION_MANAGEMENT_H__
 | 
				
			||||||
 | 
					#define __USER_SESSION_MANAGEMENT_H__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <linux/hashtable.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "../smb_common.h"
 | 
				
			||||||
 | 
					#include "../ntlmssp.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CIFDS_SESSION_FLAG_SMB2		(1 << 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PREAUTH_HASHVALUE_SIZE		64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_ida;
 | 
				
			||||||
 | 
					struct ksmbd_file_table;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct channel {
 | 
				
			||||||
 | 
						__u8			smb3signingkey[SMB3_SIGN_KEY_SIZE];
 | 
				
			||||||
 | 
						struct ksmbd_conn	*conn;
 | 
				
			||||||
 | 
						struct list_head	chann_list;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct preauth_session {
 | 
				
			||||||
 | 
						__u8			Preauth_HashValue[PREAUTH_HASHVALUE_SIZE];
 | 
				
			||||||
 | 
						uint64_t		sess_id;
 | 
				
			||||||
 | 
						struct list_head	list_entry;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_session {
 | 
				
			||||||
 | 
						uint64_t			id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct ksmbd_user		*user;
 | 
				
			||||||
 | 
						struct ksmbd_conn		*conn;
 | 
				
			||||||
 | 
						unsigned int			sequence_number;
 | 
				
			||||||
 | 
						unsigned int			flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool				sign;
 | 
				
			||||||
 | 
						bool				enc;
 | 
				
			||||||
 | 
						bool				is_anonymous;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int				state;
 | 
				
			||||||
 | 
						__u8				*Preauth_HashValue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct ntlmssp_auth		ntlmssp;
 | 
				
			||||||
 | 
						char				sess_key[CIFS_KEY_SIZE];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct hlist_node		hlist;
 | 
				
			||||||
 | 
						struct list_head		ksmbd_chann_list;
 | 
				
			||||||
 | 
						struct list_head		tree_conn_list;
 | 
				
			||||||
 | 
						struct ksmbd_ida		*tree_conn_ida;
 | 
				
			||||||
 | 
						struct list_head		rpc_handle_list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						__u8				smb3encryptionkey[SMB3_SIGN_KEY_SIZE];
 | 
				
			||||||
 | 
						__u8				smb3decryptionkey[SMB3_SIGN_KEY_SIZE];
 | 
				
			||||||
 | 
						__u8				smb3signingkey[SMB3_SIGN_KEY_SIZE];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct list_head		sessions_entry;
 | 
				
			||||||
 | 
						struct ksmbd_file_table		file_table;
 | 
				
			||||||
 | 
						atomic_t			refcnt;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline int test_session_flag(struct ksmbd_session *sess, int bit)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return sess->flags & bit;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void set_session_flag(struct ksmbd_session *sess, int bit)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						sess->flags |= bit;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void clear_session_flag(struct ksmbd_session *sess, int bit)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						sess->flags &= ~bit;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_session *ksmbd_smb2_session_create(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ksmbd_session_destroy(struct ksmbd_session *sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool ksmbd_session_id_match(struct ksmbd_session *sess, unsigned long long id);
 | 
				
			||||||
 | 
					struct ksmbd_session *ksmbd_session_lookup_slowpath(unsigned long long id);
 | 
				
			||||||
 | 
					struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn,
 | 
				
			||||||
 | 
										   unsigned long long id);
 | 
				
			||||||
 | 
					void ksmbd_session_register(struct ksmbd_conn *conn,
 | 
				
			||||||
 | 
								    struct ksmbd_session *sess);
 | 
				
			||||||
 | 
					void ksmbd_sessions_deregister(struct ksmbd_conn *conn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_acquire_tree_conn_id(struct ksmbd_session *sess);
 | 
				
			||||||
 | 
					void ksmbd_release_tree_conn_id(struct ksmbd_session *sess, int id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_session_rpc_open(struct ksmbd_session *sess, char *rpc_name);
 | 
				
			||||||
 | 
					void ksmbd_session_rpc_close(struct ksmbd_session *sess, int id);
 | 
				
			||||||
 | 
					int ksmbd_session_rpc_method(struct ksmbd_session *sess, int id);
 | 
				
			||||||
 | 
					int get_session(struct ksmbd_session *sess);
 | 
				
			||||||
 | 
					void put_session(struct ksmbd_session *sess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_init_session_table(void);
 | 
				
			||||||
 | 
					void ksmbd_free_session_table(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* __USER_SESSION_MANAGEMENT_H__ */
 | 
				
			||||||
							
								
								
									
										293
									
								
								fs/cifsd/misc.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										293
									
								
								fs/cifsd/misc.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,293 @@
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: GPL-2.0-or-later
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *   Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
 | 
				
			||||||
 | 
					 *   Copyright (C) 2018 Samsung Electronics Co., Ltd.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <linux/kernel.h>
 | 
				
			||||||
 | 
					#include <linux/version.h>
 | 
				
			||||||
 | 
					#include <linux/xattr.h>
 | 
				
			||||||
 | 
					#include <linux/fs.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "misc.h"
 | 
				
			||||||
 | 
					#include "smb_common.h"
 | 
				
			||||||
 | 
					#include "connection.h"
 | 
				
			||||||
 | 
					#include "vfs.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "mgmt/share_config.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * match_pattern() - compare a string with a pattern which might include
 | 
				
			||||||
 | 
					 * wildcard '*' and '?'
 | 
				
			||||||
 | 
					 * TODO : implement consideration about DOS_DOT, DOS_QM and DOS_STAR
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @string:	string to compare with a pattern
 | 
				
			||||||
 | 
					 * @pattern:	pattern string which might include wildcard '*' and '?'
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return:	0 if pattern matched with the string, otherwise non zero value
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int match_pattern(const char *str, const char *pattern)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const char *s = str;
 | 
				
			||||||
 | 
						const char *p = pattern;
 | 
				
			||||||
 | 
						bool star = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (*s) {
 | 
				
			||||||
 | 
							switch (*p) {
 | 
				
			||||||
 | 
							case '?':
 | 
				
			||||||
 | 
								s++;
 | 
				
			||||||
 | 
								p++;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case '*':
 | 
				
			||||||
 | 
								star = true;
 | 
				
			||||||
 | 
								str = s;
 | 
				
			||||||
 | 
								if (!*++p)
 | 
				
			||||||
 | 
									return true;
 | 
				
			||||||
 | 
								pattern = p;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								if (tolower(*s) == tolower(*p)) {
 | 
				
			||||||
 | 
									s++;
 | 
				
			||||||
 | 
									p++;
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									if (!star)
 | 
				
			||||||
 | 
										return false;
 | 
				
			||||||
 | 
									str++;
 | 
				
			||||||
 | 
									s = str;
 | 
				
			||||||
 | 
									p = pattern;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (*p == '*')
 | 
				
			||||||
 | 
							++p;
 | 
				
			||||||
 | 
						return !*p;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * is_char_allowed() - check for valid character
 | 
				
			||||||
 | 
					 * @ch:		input character to be checked
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return:	1 if char is allowed, otherwise 0
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline int is_char_allowed(char ch)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/* check for control chars, wildcards etc. */
 | 
				
			||||||
 | 
						if (!(ch & 0x80) &&
 | 
				
			||||||
 | 
							(ch <= 0x1f ||
 | 
				
			||||||
 | 
							 ch == '?' || ch == '"' || ch == '<' ||
 | 
				
			||||||
 | 
							 ch == '>' || ch == '|' || ch == '*'))
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_validate_filename(char *filename)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						while (*filename) {
 | 
				
			||||||
 | 
							char c = *filename;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							filename++;
 | 
				
			||||||
 | 
							if (!is_char_allowed(c)) {
 | 
				
			||||||
 | 
								ksmbd_debug(VFS, "File name validation failed: 0x%x\n", c);
 | 
				
			||||||
 | 
								return -ENOENT;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int ksmbd_validate_stream_name(char *stream_name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						while (*stream_name) {
 | 
				
			||||||
 | 
							char c = *stream_name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							stream_name++;
 | 
				
			||||||
 | 
							if (c == '/' || c == ':' || c == '\\') {
 | 
				
			||||||
 | 
								ksmbd_err("Stream name validation failed: %c\n", c);
 | 
				
			||||||
 | 
								return -ENOENT;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int parse_stream_name(char *filename, char **stream_name, int *s_type)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						char *stream_type;
 | 
				
			||||||
 | 
						char *s_name;
 | 
				
			||||||
 | 
						int rc = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						s_name = filename;
 | 
				
			||||||
 | 
						filename = strsep(&s_name, ":");
 | 
				
			||||||
 | 
						ksmbd_debug(SMB, "filename : %s, streams : %s\n", filename, s_name);
 | 
				
			||||||
 | 
						if (strchr(s_name, ':')) {
 | 
				
			||||||
 | 
							stream_type = s_name;
 | 
				
			||||||
 | 
							s_name = strsep(&stream_type, ":");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							rc = ksmbd_validate_stream_name(s_name);
 | 
				
			||||||
 | 
							if (rc < 0) {
 | 
				
			||||||
 | 
								rc = -ENOENT;
 | 
				
			||||||
 | 
								goto out;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ksmbd_debug(SMB, "stream name : %s, stream type : %s\n", s_name,
 | 
				
			||||||
 | 
									stream_type);
 | 
				
			||||||
 | 
							if (!strncasecmp("$data", stream_type, 5))
 | 
				
			||||||
 | 
								*s_type = DATA_STREAM;
 | 
				
			||||||
 | 
							else if (!strncasecmp("$index_allocation", stream_type, 17))
 | 
				
			||||||
 | 
								*s_type = DIR_STREAM;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								rc = -ENOENT;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*stream_name = s_name;
 | 
				
			||||||
 | 
					out:
 | 
				
			||||||
 | 
						return rc;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * convert_to_nt_pathname() - extract and return windows path string
 | 
				
			||||||
 | 
					 *      whose share directory prefix was removed from file path
 | 
				
			||||||
 | 
					 * @filename : unix filename
 | 
				
			||||||
 | 
					 * @sharepath: share path string
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return : windows path string or error
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					char *convert_to_nt_pathname(char *filename, char *sharepath)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						char *ab_pathname;
 | 
				
			||||||
 | 
						int len, name_len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						name_len = strlen(filename);
 | 
				
			||||||
 | 
						ab_pathname = kmalloc(name_len, GFP_KERNEL);
 | 
				
			||||||
 | 
						if (!ab_pathname)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ab_pathname[0] = '\\';
 | 
				
			||||||
 | 
						ab_pathname[1] = '\0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						len = strlen(sharepath);
 | 
				
			||||||
 | 
						if (!strncmp(filename, sharepath, len) && name_len != len) {
 | 
				
			||||||
 | 
							strscpy(ab_pathname, &filename[len], name_len);
 | 
				
			||||||
 | 
							ksmbd_conv_path_to_windows(ab_pathname);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ab_pathname;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int get_nlink(struct kstat *st)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int nlink;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nlink = st->nlink;
 | 
				
			||||||
 | 
						if (S_ISDIR(st->mode))
 | 
				
			||||||
 | 
							nlink--;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nlink;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ksmbd_conv_path_to_unix(char *path)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						strreplace(path, '\\', '/');
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ksmbd_strip_last_slash(char *path)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int len = strlen(path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (len && path[len - 1] == '/') {
 | 
				
			||||||
 | 
							path[len - 1] = '\0';
 | 
				
			||||||
 | 
							len--;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ksmbd_conv_path_to_windows(char *path)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						strreplace(path, '/', '\\');
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * extract_sharename() - get share name from tree connect request
 | 
				
			||||||
 | 
					 * @treename:	buffer containing tree name and share name
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return:      share name on success, otherwise error
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					char *extract_sharename(char *treename)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						char *name = treename;
 | 
				
			||||||
 | 
						char *dst;
 | 
				
			||||||
 | 
						char *pos = strrchr(name, '\\');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (pos)
 | 
				
			||||||
 | 
							name = (pos + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* caller has to free the memory */
 | 
				
			||||||
 | 
						dst = kstrdup(name, GFP_KERNEL);
 | 
				
			||||||
 | 
						if (!dst)
 | 
				
			||||||
 | 
							return ERR_PTR(-ENOMEM);
 | 
				
			||||||
 | 
						return dst;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * convert_to_unix_name() - convert windows name to unix format
 | 
				
			||||||
 | 
					 * @path:	name to be converted
 | 
				
			||||||
 | 
					 * @tid:	tree id of mathing share
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return:	converted name on success, otherwise NULL
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					char *convert_to_unix_name(struct ksmbd_share_config *share, char *name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int no_slash = 0, name_len, path_len;
 | 
				
			||||||
 | 
						char *new_name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (name[0] == '/')
 | 
				
			||||||
 | 
							name++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						path_len = share->path_sz;
 | 
				
			||||||
 | 
						name_len = strlen(name);
 | 
				
			||||||
 | 
						new_name = kmalloc(path_len + name_len + 2, GFP_KERNEL);
 | 
				
			||||||
 | 
						if (!new_name)
 | 
				
			||||||
 | 
							return new_name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memcpy(new_name, share->path, path_len);
 | 
				
			||||||
 | 
						if (new_name[path_len - 1] != '/') {
 | 
				
			||||||
 | 
							new_name[path_len] = '/';
 | 
				
			||||||
 | 
							no_slash = 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memcpy(new_name + path_len + no_slash, name, name_len);
 | 
				
			||||||
 | 
						path_len += name_len + no_slash;
 | 
				
			||||||
 | 
						new_name[path_len] = 0x00;
 | 
				
			||||||
 | 
						return new_name;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					char *ksmbd_convert_dir_info_name(struct ksmbd_dir_info *d_info,
 | 
				
			||||||
 | 
									  const struct nls_table *local_nls,
 | 
				
			||||||
 | 
									  int *conv_len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						char *conv;
 | 
				
			||||||
 | 
						int  sz = min(4 * d_info->name_len, PATH_MAX);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!sz)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						conv = kmalloc(sz, GFP_KERNEL);
 | 
				
			||||||
 | 
						if (!conv)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* XXX */
 | 
				
			||||||
 | 
						*conv_len = smbConvertToUTF16((__le16 *)conv,
 | 
				
			||||||
 | 
										d_info->name,
 | 
				
			||||||
 | 
										d_info->name_len,
 | 
				
			||||||
 | 
										local_nls,
 | 
				
			||||||
 | 
										0);
 | 
				
			||||||
 | 
						*conv_len *= 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* We allocate buffer twice bigger than needed. */
 | 
				
			||||||
 | 
						conv[*conv_len] = 0x00;
 | 
				
			||||||
 | 
						conv[*conv_len + 1] = 0x00;
 | 
				
			||||||
 | 
						return conv;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										38
									
								
								fs/cifsd/misc.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								fs/cifsd/misc.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,38 @@
 | 
				
			||||||
 | 
					/* SPDX-License-Identifier: GPL-2.0-or-later */
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *   Copyright (C) 2018 Samsung Electronics Co., Ltd.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef __KSMBD_MISC_H__
 | 
				
			||||||
 | 
					#define __KSMBD_MISC_H__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_share_config;
 | 
				
			||||||
 | 
					struct nls_table;
 | 
				
			||||||
 | 
					struct kstat;
 | 
				
			||||||
 | 
					struct ksmbd_file;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int match_pattern(const char *str, const char *pattern);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_validate_filename(char *filename);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int parse_stream_name(char *filename, char **stream_name, int *s_type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					char *convert_to_nt_pathname(char *filename, char *sharepath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int get_nlink(struct kstat *st);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ksmbd_conv_path_to_unix(char *path);
 | 
				
			||||||
 | 
					void ksmbd_strip_last_slash(char *path);
 | 
				
			||||||
 | 
					void ksmbd_conv_path_to_windows(char *path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					char *extract_sharename(char *treename);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					char *convert_to_unix_name(struct ksmbd_share_config *share, char *name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define KSMBD_DIR_INFO_ALIGNMENT	8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_dir_info;
 | 
				
			||||||
 | 
					char *ksmbd_convert_dir_info_name(struct ksmbd_dir_info *d_info,
 | 
				
			||||||
 | 
									  const struct nls_table *local_nls,
 | 
				
			||||||
 | 
									  int *conv_len);
 | 
				
			||||||
 | 
					#endif /* __KSMBD_MISC_H__ */
 | 
				
			||||||
							
								
								
									
										344
									
								
								fs/cifsd/ndr.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										344
									
								
								fs/cifsd/ndr.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,344 @@
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: GPL-2.0-or-later
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *   Copyright (C) 2021 Samsung Electronics Co., Ltd.
 | 
				
			||||||
 | 
					 *   Author(s): Namjae Jeon <linkinjeon@kernel.org>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <linux/fs.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "glob.h"
 | 
				
			||||||
 | 
					#include "ndr.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PAYLOAD_HEAD(d) ((d)->data + (d)->offset)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define KSMBD_ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define KSMBD_ALIGN(x, a)							\
 | 
				
			||||||
 | 
						({									\
 | 
				
			||||||
 | 
							typeof(x) ret = (x);						\
 | 
				
			||||||
 | 
							if (((x) & ((typeof(x))(a) - 1)) != 0)				\
 | 
				
			||||||
 | 
								ret = KSMBD_ALIGN_MASK(x, (typeof(x))(a) - 1);		\
 | 
				
			||||||
 | 
							ret;								\
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void align_offset(struct ndr *ndr, int n)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						ndr->offset = KSMBD_ALIGN(ndr->offset, n);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int try_to_realloc_ndr_blob(struct ndr *n, size_t sz)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						char *data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						data = krealloc(n->data, n->offset + sz + 1024, GFP_KERNEL);
 | 
				
			||||||
 | 
						if (!data)
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						n->data = data;
 | 
				
			||||||
 | 
						n->length += 1024;
 | 
				
			||||||
 | 
						memset(n->data + n->offset, 0, 1024);
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void ndr_write_int16(struct ndr *n, __u16 value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (n->length <= n->offset + sizeof(value))
 | 
				
			||||||
 | 
							try_to_realloc_ndr_blob(n, sizeof(value));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*(__le16 *)PAYLOAD_HEAD(n) = cpu_to_le16(value);
 | 
				
			||||||
 | 
						n->offset += sizeof(value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void ndr_write_int32(struct ndr *n, __u32 value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (n->length <= n->offset + sizeof(value))
 | 
				
			||||||
 | 
							try_to_realloc_ndr_blob(n, sizeof(value));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*(__le32 *)PAYLOAD_HEAD(n) = cpu_to_le32(value);
 | 
				
			||||||
 | 
						n->offset += sizeof(value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void ndr_write_int64(struct ndr *n, __u64 value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (n->length <= n->offset + sizeof(value))
 | 
				
			||||||
 | 
							try_to_realloc_ndr_blob(n, sizeof(value));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*(__le64 *)PAYLOAD_HEAD(n) = cpu_to_le64(value);
 | 
				
			||||||
 | 
						n->offset += sizeof(value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int ndr_write_bytes(struct ndr *n, void *value, size_t sz)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (n->length <= n->offset + sz)
 | 
				
			||||||
 | 
							try_to_realloc_ndr_blob(n, sz);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memcpy(PAYLOAD_HEAD(n), value, sz);
 | 
				
			||||||
 | 
						n->offset += sz;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int ndr_write_string(struct ndr *n, void *value, size_t sz)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (n->length <= n->offset + sz)
 | 
				
			||||||
 | 
							try_to_realloc_ndr_blob(n, sz);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						strncpy(PAYLOAD_HEAD(n), value, sz);
 | 
				
			||||||
 | 
						sz++;
 | 
				
			||||||
 | 
						n->offset += sz;
 | 
				
			||||||
 | 
						align_offset(n, 2);
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int ndr_read_string(struct ndr *n, void *value, size_t sz)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int len = strnlen(PAYLOAD_HEAD(n), sz);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memcpy(value, PAYLOAD_HEAD(n), len);
 | 
				
			||||||
 | 
						len++;
 | 
				
			||||||
 | 
						n->offset += len;
 | 
				
			||||||
 | 
						align_offset(n, 2);
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int ndr_read_bytes(struct ndr *n, void *value, size_t sz)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						memcpy(value, PAYLOAD_HEAD(n), sz);
 | 
				
			||||||
 | 
						n->offset += sz;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static __u16 ndr_read_int16(struct ndr *n)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						__u16 ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = le16_to_cpu(*(__le16 *)PAYLOAD_HEAD(n));
 | 
				
			||||||
 | 
						n->offset += sizeof(__u16);
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static __u32 ndr_read_int32(struct ndr *n)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						__u32 ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = le32_to_cpu(*(__le32 *)PAYLOAD_HEAD(n));
 | 
				
			||||||
 | 
						n->offset += sizeof(__u32);
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static __u64 ndr_read_int64(struct ndr *n)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						__u64 ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = le64_to_cpu(*(__le64 *)PAYLOAD_HEAD(n));
 | 
				
			||||||
 | 
						n->offset += sizeof(__u64);
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ndr_encode_dos_attr(struct ndr *n, struct xattr_dos_attrib *da)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						char hex_attr[12] = {0};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						n->offset = 0;
 | 
				
			||||||
 | 
						n->length = 1024;
 | 
				
			||||||
 | 
						n->data = kzalloc(n->length, GFP_KERNEL);
 | 
				
			||||||
 | 
						if (!n->data)
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (da->version == 3) {
 | 
				
			||||||
 | 
							snprintf(hex_attr, 10, "0x%x", da->attr);
 | 
				
			||||||
 | 
							ndr_write_string(n, hex_attr, strlen(hex_attr));
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							ndr_write_string(n, "", strlen(""));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ndr_write_int16(n, da->version);
 | 
				
			||||||
 | 
						ndr_write_int32(n, da->version);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ndr_write_int32(n, da->flags);
 | 
				
			||||||
 | 
						ndr_write_int32(n, da->attr);
 | 
				
			||||||
 | 
						if (da->version == 3) {
 | 
				
			||||||
 | 
							ndr_write_int32(n, da->ea_size);
 | 
				
			||||||
 | 
							ndr_write_int64(n, da->size);
 | 
				
			||||||
 | 
							ndr_write_int64(n, da->alloc_size);
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
							ndr_write_int64(n, da->itime);
 | 
				
			||||||
 | 
						ndr_write_int64(n, da->create_time);
 | 
				
			||||||
 | 
						if (da->version == 3)
 | 
				
			||||||
 | 
							ndr_write_int64(n, da->change_time);
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ndr_decode_dos_attr(struct ndr *n, struct xattr_dos_attrib *da)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						char hex_attr[12] = {0};
 | 
				
			||||||
 | 
						int version2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						n->offset = 0;
 | 
				
			||||||
 | 
						ndr_read_string(n, hex_attr, n->length - n->offset);
 | 
				
			||||||
 | 
						da->version = ndr_read_int16(n);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (da->version != 3 && da->version != 4) {
 | 
				
			||||||
 | 
							ksmbd_err("v%d version is not supported\n", da->version);
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						version2 = ndr_read_int32(n);
 | 
				
			||||||
 | 
						if (da->version != version2) {
 | 
				
			||||||
 | 
							ksmbd_err("ndr version mismatched(version: %d, version2: %d)\n",
 | 
				
			||||||
 | 
									da->version, version2);
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ndr_read_int32(n);
 | 
				
			||||||
 | 
						da->attr = ndr_read_int32(n);
 | 
				
			||||||
 | 
						if (da->version == 4) {
 | 
				
			||||||
 | 
							da->itime = ndr_read_int64(n);
 | 
				
			||||||
 | 
							da->create_time = ndr_read_int64(n);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							ndr_read_int32(n);
 | 
				
			||||||
 | 
							ndr_read_int64(n);
 | 
				
			||||||
 | 
							ndr_read_int64(n);
 | 
				
			||||||
 | 
							da->create_time = ndr_read_int64(n);
 | 
				
			||||||
 | 
							ndr_read_int64(n);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int ndr_encode_posix_acl_entry(struct ndr *n, struct xattr_smb_acl *acl)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ndr_write_int32(n, acl->count);
 | 
				
			||||||
 | 
						align_offset(n, 8);
 | 
				
			||||||
 | 
						ndr_write_int32(n, acl->count);
 | 
				
			||||||
 | 
						ndr_write_int32(n, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < acl->count; i++) {
 | 
				
			||||||
 | 
							align_offset(n, 8);
 | 
				
			||||||
 | 
							ndr_write_int16(n, acl->entries[i].type);
 | 
				
			||||||
 | 
							ndr_write_int16(n, acl->entries[i].type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (acl->entries[i].type == SMB_ACL_USER) {
 | 
				
			||||||
 | 
								align_offset(n, 8);
 | 
				
			||||||
 | 
								ndr_write_int64(n, acl->entries[i].uid);
 | 
				
			||||||
 | 
							} else if (acl->entries[i].type == SMB_ACL_GROUP) {
 | 
				
			||||||
 | 
								align_offset(n, 8);
 | 
				
			||||||
 | 
								ndr_write_int64(n, acl->entries[i].gid);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* push permission */
 | 
				
			||||||
 | 
							ndr_write_int32(n, acl->entries[i].perm);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ndr_encode_posix_acl(struct ndr *n, struct inode *inode,
 | 
				
			||||||
 | 
							struct xattr_smb_acl *acl, struct xattr_smb_acl *def_acl)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ref_id = 0x00020000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						n->offset = 0;
 | 
				
			||||||
 | 
						n->length = 1024;
 | 
				
			||||||
 | 
						n->data = kzalloc(n->length, GFP_KERNEL);
 | 
				
			||||||
 | 
						if (!n->data)
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (acl) {
 | 
				
			||||||
 | 
							/* ACL ACCESS */
 | 
				
			||||||
 | 
							ndr_write_int32(n, ref_id);
 | 
				
			||||||
 | 
							ref_id += 4;
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
							ndr_write_int32(n, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (def_acl) {
 | 
				
			||||||
 | 
							/* DEFAULT ACL ACCESS */
 | 
				
			||||||
 | 
							ndr_write_int32(n, ref_id);
 | 
				
			||||||
 | 
							ref_id += 4;
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
							ndr_write_int32(n, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ndr_write_int64(n, from_kuid(&init_user_ns, inode->i_uid));
 | 
				
			||||||
 | 
						ndr_write_int64(n, from_kgid(&init_user_ns, inode->i_gid));
 | 
				
			||||||
 | 
						ndr_write_int32(n, inode->i_mode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (acl) {
 | 
				
			||||||
 | 
							ndr_encode_posix_acl_entry(n, acl);
 | 
				
			||||||
 | 
							if (def_acl)
 | 
				
			||||||
 | 
								ndr_encode_posix_acl_entry(n, def_acl);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ndr_encode_v4_ntacl(struct ndr *n, struct xattr_ntacl *acl)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ref_id = 0x00020004;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						n->offset = 0;
 | 
				
			||||||
 | 
						n->length = 2048;
 | 
				
			||||||
 | 
						n->data = kzalloc(n->length, GFP_KERNEL);
 | 
				
			||||||
 | 
						if (!n->data)
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ndr_write_int16(n, acl->version);
 | 
				
			||||||
 | 
						ndr_write_int32(n, acl->version);
 | 
				
			||||||
 | 
						ndr_write_int16(n, 2);
 | 
				
			||||||
 | 
						ndr_write_int32(n, ref_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* push hash type and hash 64bytes */
 | 
				
			||||||
 | 
						ndr_write_int16(n, acl->hash_type);
 | 
				
			||||||
 | 
						ndr_write_bytes(n, acl->hash, XATTR_SD_HASH_SIZE);
 | 
				
			||||||
 | 
						ndr_write_bytes(n, acl->desc, acl->desc_len);
 | 
				
			||||||
 | 
						ndr_write_int64(n, acl->current_time);
 | 
				
			||||||
 | 
						ndr_write_bytes(n, acl->posix_acl_hash, XATTR_SD_HASH_SIZE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* push ndr for security descriptor */
 | 
				
			||||||
 | 
						ndr_write_bytes(n, acl->sd_buf, acl->sd_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ndr_decode_v4_ntacl(struct ndr *n, struct xattr_ntacl *acl)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int version2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						n->offset = 0;
 | 
				
			||||||
 | 
						acl->version = ndr_read_int16(n);
 | 
				
			||||||
 | 
						if (acl->version != 4) {
 | 
				
			||||||
 | 
							ksmbd_err("v%d version is not supported\n", acl->version);
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						version2 = ndr_read_int32(n);
 | 
				
			||||||
 | 
						if (acl->version != version2) {
 | 
				
			||||||
 | 
							ksmbd_err("ndr version mismatched(version: %d, version2: %d)\n",
 | 
				
			||||||
 | 
									acl->version, version2);
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Read Level */
 | 
				
			||||||
 | 
						ndr_read_int16(n);
 | 
				
			||||||
 | 
						/* Read Ref Id */
 | 
				
			||||||
 | 
						ndr_read_int32(n);
 | 
				
			||||||
 | 
						acl->hash_type = ndr_read_int16(n);
 | 
				
			||||||
 | 
						ndr_read_bytes(n, acl->hash, XATTR_SD_HASH_SIZE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ndr_read_bytes(n, acl->desc, 10);
 | 
				
			||||||
 | 
						if (strncmp(acl->desc, "posix_acl", 9)) {
 | 
				
			||||||
 | 
							ksmbd_err("Invalid acl desciption : %s\n", acl->desc);
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Read Time */
 | 
				
			||||||
 | 
						ndr_read_int64(n);
 | 
				
			||||||
 | 
						/* Read Posix ACL hash */
 | 
				
			||||||
 | 
						ndr_read_bytes(n, acl->posix_acl_hash, XATTR_SD_HASH_SIZE);
 | 
				
			||||||
 | 
						acl->sd_size = n->length - n->offset;
 | 
				
			||||||
 | 
						acl->sd_buf = kzalloc(acl->sd_size, GFP_KERNEL);
 | 
				
			||||||
 | 
						if (!acl->sd_buf)
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ndr_read_bytes(n, acl->sd_buf, acl->sd_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										21
									
								
								fs/cifsd/ndr.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								fs/cifsd/ndr.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,21 @@
 | 
				
			||||||
 | 
					/* SPDX-License-Identifier: GPL-2.0-or-later */
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *   Copyright (C) 2020 Samsung Electronics Co., Ltd.
 | 
				
			||||||
 | 
					 *   Author(s): Namjae Jeon <linkinjeon@kernel.org>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ndr {
 | 
				
			||||||
 | 
						char	*data;
 | 
				
			||||||
 | 
						int	offset;
 | 
				
			||||||
 | 
						int	length;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NDR_NTSD_OFFSETOF	0xA0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ndr_encode_dos_attr(struct ndr *n, struct xattr_dos_attrib *da);
 | 
				
			||||||
 | 
					int ndr_decode_dos_attr(struct ndr *n, struct xattr_dos_attrib *da);
 | 
				
			||||||
 | 
					int ndr_encode_posix_acl(struct ndr *n, struct inode *inode,
 | 
				
			||||||
 | 
							struct xattr_smb_acl *acl, struct xattr_smb_acl *def_acl);
 | 
				
			||||||
 | 
					int ndr_encode_v4_ntacl(struct ndr *n, struct xattr_ntacl *acl);
 | 
				
			||||||
 | 
					int ndr_encode_v3_ntacl(struct ndr *n, struct xattr_ntacl *acl);
 | 
				
			||||||
 | 
					int ndr_decode_v4_ntacl(struct ndr *n, struct xattr_ntacl *acl);
 | 
				
			||||||
							
								
								
									
										46
									
								
								fs/cifsd/netmisc.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								fs/cifsd/netmisc.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,46 @@
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: GPL-2.0-or-later
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *   fs/ksmbd/netmisc.c
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   Copyright (c) International Business Machines  Corp., 2002,2008
 | 
				
			||||||
 | 
					 *   Author(s): Steve French (sfrench@us.ibm.com)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   Error mapping routines from Samba libsmb/errormap.c
 | 
				
			||||||
 | 
					 *   Copyright (C) Andrew Tridgell 2001
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "glob.h"
 | 
				
			||||||
 | 
					#include "smberr.h"
 | 
				
			||||||
 | 
					#include "nterr.h"
 | 
				
			||||||
 | 
					#include "time_wrappers.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Convert the NT UTC (based 1601-01-01, in hundred nanosecond units)
 | 
				
			||||||
 | 
					 * into Unix UTC (based 1970-01-01, in seconds).
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct timespec64 ksmbd_NTtimeToUnix(__le64 ntutc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct timespec64 ts;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Subtract the NTFS time offset, then convert to 1s intervals. */
 | 
				
			||||||
 | 
						s64 t = le64_to_cpu(ntutc) - NTFS_TIME_OFFSET;
 | 
				
			||||||
 | 
						u64 abs_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Unfortunately can not use normal 64 bit division on 32 bit arch, but
 | 
				
			||||||
 | 
						 * the alternative, do_div, does not work with negative numbers so have
 | 
				
			||||||
 | 
						 * to special case them
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (t < 0) {
 | 
				
			||||||
 | 
							abs_t = -t;
 | 
				
			||||||
 | 
							ts.tv_nsec = do_div(abs_t, 10000000) * 100;
 | 
				
			||||||
 | 
							ts.tv_nsec = -ts.tv_nsec;
 | 
				
			||||||
 | 
							ts.tv_sec = -abs_t;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							abs_t = t;
 | 
				
			||||||
 | 
							ts.tv_nsec = do_div(abs_t, 10000000) * 100;
 | 
				
			||||||
 | 
							ts.tv_sec = abs_t;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ts;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										674
									
								
								fs/cifsd/nterr.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										674
									
								
								fs/cifsd/nterr.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,674 @@
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: GPL-2.0-or-later
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  Unix SMB/Netbios implementation.
 | 
				
			||||||
 | 
					 *  Version 1.9.
 | 
				
			||||||
 | 
					 *  RPC Pipe client / server routines
 | 
				
			||||||
 | 
					 *  Copyright (C) Luke Kenneth Casson Leighton 1997-2001.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* NT error codes - see nterr.h */
 | 
				
			||||||
 | 
					#include <linux/types.h>
 | 
				
			||||||
 | 
					#include <linux/fs.h>
 | 
				
			||||||
 | 
					#include "nterr.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const struct nt_err_code_struct nt_errs[] = {
 | 
				
			||||||
 | 
						{"NT_STATUS_OK", NT_STATUS_OK},
 | 
				
			||||||
 | 
						{"NT_STATUS_UNSUCCESSFUL", NT_STATUS_UNSUCCESSFUL},
 | 
				
			||||||
 | 
						{"NT_STATUS_NOT_IMPLEMENTED", NT_STATUS_NOT_IMPLEMENTED},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_INFO_CLASS", NT_STATUS_INVALID_INFO_CLASS},
 | 
				
			||||||
 | 
						{"NT_STATUS_INFO_LENGTH_MISMATCH", NT_STATUS_INFO_LENGTH_MISMATCH},
 | 
				
			||||||
 | 
						{"NT_STATUS_ACCESS_VIOLATION", NT_STATUS_ACCESS_VIOLATION},
 | 
				
			||||||
 | 
						{"NT_STATUS_BUFFER_OVERFLOW", NT_STATUS_BUFFER_OVERFLOW},
 | 
				
			||||||
 | 
						{"NT_STATUS_IN_PAGE_ERROR", NT_STATUS_IN_PAGE_ERROR},
 | 
				
			||||||
 | 
						{"NT_STATUS_PAGEFILE_QUOTA", NT_STATUS_PAGEFILE_QUOTA},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_HANDLE", NT_STATUS_INVALID_HANDLE},
 | 
				
			||||||
 | 
						{"NT_STATUS_BAD_INITIAL_STACK", NT_STATUS_BAD_INITIAL_STACK},
 | 
				
			||||||
 | 
						{"NT_STATUS_BAD_INITIAL_PC", NT_STATUS_BAD_INITIAL_PC},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_CID", NT_STATUS_INVALID_CID},
 | 
				
			||||||
 | 
						{"NT_STATUS_TIMER_NOT_CANCELED", NT_STATUS_TIMER_NOT_CANCELED},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_PARAMETER", NT_STATUS_INVALID_PARAMETER},
 | 
				
			||||||
 | 
						{"NT_STATUS_NO_SUCH_DEVICE", NT_STATUS_NO_SUCH_DEVICE},
 | 
				
			||||||
 | 
						{"NT_STATUS_NO_SUCH_FILE", NT_STATUS_NO_SUCH_FILE},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_DEVICE_REQUEST",
 | 
				
			||||||
 | 
						 NT_STATUS_INVALID_DEVICE_REQUEST},
 | 
				
			||||||
 | 
						{"NT_STATUS_END_OF_FILE", NT_STATUS_END_OF_FILE},
 | 
				
			||||||
 | 
						{"NT_STATUS_WRONG_VOLUME", NT_STATUS_WRONG_VOLUME},
 | 
				
			||||||
 | 
						{"NT_STATUS_NO_MEDIA_IN_DEVICE", NT_STATUS_NO_MEDIA_IN_DEVICE},
 | 
				
			||||||
 | 
						{"NT_STATUS_UNRECOGNIZED_MEDIA", NT_STATUS_UNRECOGNIZED_MEDIA},
 | 
				
			||||||
 | 
						{"NT_STATUS_NONEXISTENT_SECTOR", NT_STATUS_NONEXISTENT_SECTOR},
 | 
				
			||||||
 | 
						{"NT_STATUS_MORE_PROCESSING_REQUIRED",
 | 
				
			||||||
 | 
						 NT_STATUS_MORE_PROCESSING_REQUIRED},
 | 
				
			||||||
 | 
						{"NT_STATUS_NO_MEMORY", NT_STATUS_NO_MEMORY},
 | 
				
			||||||
 | 
						{"NT_STATUS_CONFLICTING_ADDRESSES",
 | 
				
			||||||
 | 
						 NT_STATUS_CONFLICTING_ADDRESSES},
 | 
				
			||||||
 | 
						{"NT_STATUS_NOT_MAPPED_VIEW", NT_STATUS_NOT_MAPPED_VIEW},
 | 
				
			||||||
 | 
						{"NT_STATUS_UNABLE_TO_FREE_VM", NT_STATUS_UNABLE_TO_FREE_VM},
 | 
				
			||||||
 | 
						{"NT_STATUS_UNABLE_TO_DELETE_SECTION",
 | 
				
			||||||
 | 
						 NT_STATUS_UNABLE_TO_DELETE_SECTION},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_SYSTEM_SERVICE",
 | 
				
			||||||
 | 
						 NT_STATUS_INVALID_SYSTEM_SERVICE},
 | 
				
			||||||
 | 
						{"NT_STATUS_ILLEGAL_INSTRUCTION", NT_STATUS_ILLEGAL_INSTRUCTION},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_LOCK_SEQUENCE",
 | 
				
			||||||
 | 
						 NT_STATUS_INVALID_LOCK_SEQUENCE},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_VIEW_SIZE", NT_STATUS_INVALID_VIEW_SIZE},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_FILE_FOR_SECTION",
 | 
				
			||||||
 | 
						 NT_STATUS_INVALID_FILE_FOR_SECTION},
 | 
				
			||||||
 | 
						{"NT_STATUS_ALREADY_COMMITTED", NT_STATUS_ALREADY_COMMITTED},
 | 
				
			||||||
 | 
						{"NT_STATUS_ACCESS_DENIED", NT_STATUS_ACCESS_DENIED},
 | 
				
			||||||
 | 
						{"NT_STATUS_BUFFER_TOO_SMALL", NT_STATUS_BUFFER_TOO_SMALL},
 | 
				
			||||||
 | 
						{"NT_STATUS_OBJECT_TYPE_MISMATCH", NT_STATUS_OBJECT_TYPE_MISMATCH},
 | 
				
			||||||
 | 
						{"NT_STATUS_NONCONTINUABLE_EXCEPTION",
 | 
				
			||||||
 | 
						 NT_STATUS_NONCONTINUABLE_EXCEPTION},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_DISPOSITION", NT_STATUS_INVALID_DISPOSITION},
 | 
				
			||||||
 | 
						{"NT_STATUS_UNWIND", NT_STATUS_UNWIND},
 | 
				
			||||||
 | 
						{"NT_STATUS_BAD_STACK", NT_STATUS_BAD_STACK},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_UNWIND_TARGET",
 | 
				
			||||||
 | 
						 NT_STATUS_INVALID_UNWIND_TARGET},
 | 
				
			||||||
 | 
						{"NT_STATUS_NOT_LOCKED", NT_STATUS_NOT_LOCKED},
 | 
				
			||||||
 | 
						{"NT_STATUS_PARITY_ERROR", NT_STATUS_PARITY_ERROR},
 | 
				
			||||||
 | 
						{"NT_STATUS_UNABLE_TO_DECOMMIT_VM",
 | 
				
			||||||
 | 
						 NT_STATUS_UNABLE_TO_DECOMMIT_VM},
 | 
				
			||||||
 | 
						{"NT_STATUS_NOT_COMMITTED", NT_STATUS_NOT_COMMITTED},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_PORT_ATTRIBUTES",
 | 
				
			||||||
 | 
						 NT_STATUS_INVALID_PORT_ATTRIBUTES},
 | 
				
			||||||
 | 
						{"NT_STATUS_PORT_MESSAGE_TOO_LONG",
 | 
				
			||||||
 | 
						 NT_STATUS_PORT_MESSAGE_TOO_LONG},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_PARAMETER_MIX",
 | 
				
			||||||
 | 
						 NT_STATUS_INVALID_PARAMETER_MIX},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_QUOTA_LOWER", NT_STATUS_INVALID_QUOTA_LOWER},
 | 
				
			||||||
 | 
						{"NT_STATUS_DISK_CORRUPT_ERROR", NT_STATUS_DISK_CORRUPT_ERROR},
 | 
				
			||||||
 | 
						{"NT_STATUS_OBJECT_NAME_INVALID", NT_STATUS_OBJECT_NAME_INVALID},
 | 
				
			||||||
 | 
						{"NT_STATUS_OBJECT_NAME_NOT_FOUND",
 | 
				
			||||||
 | 
						 NT_STATUS_OBJECT_NAME_NOT_FOUND},
 | 
				
			||||||
 | 
						{"NT_STATUS_OBJECT_NAME_COLLISION",
 | 
				
			||||||
 | 
						 NT_STATUS_OBJECT_NAME_COLLISION},
 | 
				
			||||||
 | 
						{"NT_STATUS_HANDLE_NOT_WAITABLE", NT_STATUS_HANDLE_NOT_WAITABLE},
 | 
				
			||||||
 | 
						{"NT_STATUS_PORT_DISCONNECTED", NT_STATUS_PORT_DISCONNECTED},
 | 
				
			||||||
 | 
						{"NT_STATUS_DEVICE_ALREADY_ATTACHED",
 | 
				
			||||||
 | 
						 NT_STATUS_DEVICE_ALREADY_ATTACHED},
 | 
				
			||||||
 | 
						{"NT_STATUS_OBJECT_PATH_INVALID", NT_STATUS_OBJECT_PATH_INVALID},
 | 
				
			||||||
 | 
						{"NT_STATUS_OBJECT_PATH_NOT_FOUND",
 | 
				
			||||||
 | 
						 NT_STATUS_OBJECT_PATH_NOT_FOUND},
 | 
				
			||||||
 | 
						{"NT_STATUS_OBJECT_PATH_SYNTAX_BAD",
 | 
				
			||||||
 | 
						 NT_STATUS_OBJECT_PATH_SYNTAX_BAD},
 | 
				
			||||||
 | 
						{"NT_STATUS_DATA_OVERRUN", NT_STATUS_DATA_OVERRUN},
 | 
				
			||||||
 | 
						{"NT_STATUS_DATA_LATE_ERROR", NT_STATUS_DATA_LATE_ERROR},
 | 
				
			||||||
 | 
						{"NT_STATUS_DATA_ERROR", NT_STATUS_DATA_ERROR},
 | 
				
			||||||
 | 
						{"NT_STATUS_CRC_ERROR", NT_STATUS_CRC_ERROR},
 | 
				
			||||||
 | 
						{"NT_STATUS_SECTION_TOO_BIG", NT_STATUS_SECTION_TOO_BIG},
 | 
				
			||||||
 | 
						{"NT_STATUS_PORT_CONNECTION_REFUSED",
 | 
				
			||||||
 | 
						 NT_STATUS_PORT_CONNECTION_REFUSED},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_PORT_HANDLE", NT_STATUS_INVALID_PORT_HANDLE},
 | 
				
			||||||
 | 
						{"NT_STATUS_SHARING_VIOLATION", NT_STATUS_SHARING_VIOLATION},
 | 
				
			||||||
 | 
						{"NT_STATUS_QUOTA_EXCEEDED", NT_STATUS_QUOTA_EXCEEDED},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_PAGE_PROTECTION",
 | 
				
			||||||
 | 
						 NT_STATUS_INVALID_PAGE_PROTECTION},
 | 
				
			||||||
 | 
						{"NT_STATUS_MUTANT_NOT_OWNED", NT_STATUS_MUTANT_NOT_OWNED},
 | 
				
			||||||
 | 
						{"NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED",
 | 
				
			||||||
 | 
						 NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED},
 | 
				
			||||||
 | 
						{"NT_STATUS_PORT_ALREADY_SET", NT_STATUS_PORT_ALREADY_SET},
 | 
				
			||||||
 | 
						{"NT_STATUS_SECTION_NOT_IMAGE", NT_STATUS_SECTION_NOT_IMAGE},
 | 
				
			||||||
 | 
						{"NT_STATUS_SUSPEND_COUNT_EXCEEDED",
 | 
				
			||||||
 | 
						 NT_STATUS_SUSPEND_COUNT_EXCEEDED},
 | 
				
			||||||
 | 
						{"NT_STATUS_THREAD_IS_TERMINATING",
 | 
				
			||||||
 | 
						 NT_STATUS_THREAD_IS_TERMINATING},
 | 
				
			||||||
 | 
						{"NT_STATUS_BAD_WORKING_SET_LIMIT",
 | 
				
			||||||
 | 
						 NT_STATUS_BAD_WORKING_SET_LIMIT},
 | 
				
			||||||
 | 
						{"NT_STATUS_INCOMPATIBLE_FILE_MAP",
 | 
				
			||||||
 | 
						 NT_STATUS_INCOMPATIBLE_FILE_MAP},
 | 
				
			||||||
 | 
						{"NT_STATUS_SECTION_PROTECTION", NT_STATUS_SECTION_PROTECTION},
 | 
				
			||||||
 | 
						{"NT_STATUS_EAS_NOT_SUPPORTED", NT_STATUS_EAS_NOT_SUPPORTED},
 | 
				
			||||||
 | 
						{"NT_STATUS_EA_TOO_LARGE", NT_STATUS_EA_TOO_LARGE},
 | 
				
			||||||
 | 
						{"NT_STATUS_NONEXISTENT_EA_ENTRY", NT_STATUS_NONEXISTENT_EA_ENTRY},
 | 
				
			||||||
 | 
						{"NT_STATUS_NO_EAS_ON_FILE", NT_STATUS_NO_EAS_ON_FILE},
 | 
				
			||||||
 | 
						{"NT_STATUS_EA_CORRUPT_ERROR", NT_STATUS_EA_CORRUPT_ERROR},
 | 
				
			||||||
 | 
						{"NT_STATUS_FILE_LOCK_CONFLICT", NT_STATUS_FILE_LOCK_CONFLICT},
 | 
				
			||||||
 | 
						{"NT_STATUS_LOCK_NOT_GRANTED", NT_STATUS_LOCK_NOT_GRANTED},
 | 
				
			||||||
 | 
						{"NT_STATUS_DELETE_PENDING", NT_STATUS_DELETE_PENDING},
 | 
				
			||||||
 | 
						{"NT_STATUS_CTL_FILE_NOT_SUPPORTED",
 | 
				
			||||||
 | 
						 NT_STATUS_CTL_FILE_NOT_SUPPORTED},
 | 
				
			||||||
 | 
						{"NT_STATUS_UNKNOWN_REVISION", NT_STATUS_UNKNOWN_REVISION},
 | 
				
			||||||
 | 
						{"NT_STATUS_REVISION_MISMATCH", NT_STATUS_REVISION_MISMATCH},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_OWNER", NT_STATUS_INVALID_OWNER},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_PRIMARY_GROUP",
 | 
				
			||||||
 | 
						 NT_STATUS_INVALID_PRIMARY_GROUP},
 | 
				
			||||||
 | 
						{"NT_STATUS_NO_IMPERSONATION_TOKEN",
 | 
				
			||||||
 | 
						 NT_STATUS_NO_IMPERSONATION_TOKEN},
 | 
				
			||||||
 | 
						{"NT_STATUS_CANT_DISABLE_MANDATORY",
 | 
				
			||||||
 | 
						 NT_STATUS_CANT_DISABLE_MANDATORY},
 | 
				
			||||||
 | 
						{"NT_STATUS_NO_LOGON_SERVERS", NT_STATUS_NO_LOGON_SERVERS},
 | 
				
			||||||
 | 
						{"NT_STATUS_NO_SUCH_LOGON_SESSION",
 | 
				
			||||||
 | 
						 NT_STATUS_NO_SUCH_LOGON_SESSION},
 | 
				
			||||||
 | 
						{"NT_STATUS_NO_SUCH_PRIVILEGE", NT_STATUS_NO_SUCH_PRIVILEGE},
 | 
				
			||||||
 | 
						{"NT_STATUS_PRIVILEGE_NOT_HELD", NT_STATUS_PRIVILEGE_NOT_HELD},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_ACCOUNT_NAME", NT_STATUS_INVALID_ACCOUNT_NAME},
 | 
				
			||||||
 | 
						{"NT_STATUS_USER_EXISTS", NT_STATUS_USER_EXISTS},
 | 
				
			||||||
 | 
						{"NT_STATUS_NO_SUCH_USER", NT_STATUS_NO_SUCH_USER},
 | 
				
			||||||
 | 
						{"NT_STATUS_GROUP_EXISTS", NT_STATUS_GROUP_EXISTS},
 | 
				
			||||||
 | 
						{"NT_STATUS_NO_SUCH_GROUP", NT_STATUS_NO_SUCH_GROUP},
 | 
				
			||||||
 | 
						{"NT_STATUS_MEMBER_IN_GROUP", NT_STATUS_MEMBER_IN_GROUP},
 | 
				
			||||||
 | 
						{"NT_STATUS_MEMBER_NOT_IN_GROUP", NT_STATUS_MEMBER_NOT_IN_GROUP},
 | 
				
			||||||
 | 
						{"NT_STATUS_LAST_ADMIN", NT_STATUS_LAST_ADMIN},
 | 
				
			||||||
 | 
						{"NT_STATUS_WRONG_PASSWORD", NT_STATUS_WRONG_PASSWORD},
 | 
				
			||||||
 | 
						{"NT_STATUS_ILL_FORMED_PASSWORD", NT_STATUS_ILL_FORMED_PASSWORD},
 | 
				
			||||||
 | 
						{"NT_STATUS_PASSWORD_RESTRICTION", NT_STATUS_PASSWORD_RESTRICTION},
 | 
				
			||||||
 | 
						{"NT_STATUS_LOGON_FAILURE", NT_STATUS_LOGON_FAILURE},
 | 
				
			||||||
 | 
						{"NT_STATUS_ACCOUNT_RESTRICTION", NT_STATUS_ACCOUNT_RESTRICTION},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_LOGON_HOURS", NT_STATUS_INVALID_LOGON_HOURS},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_WORKSTATION", NT_STATUS_INVALID_WORKSTATION},
 | 
				
			||||||
 | 
						{"NT_STATUS_PASSWORD_EXPIRED", NT_STATUS_PASSWORD_EXPIRED},
 | 
				
			||||||
 | 
						{"NT_STATUS_ACCOUNT_DISABLED", NT_STATUS_ACCOUNT_DISABLED},
 | 
				
			||||||
 | 
						{"NT_STATUS_NONE_MAPPED", NT_STATUS_NONE_MAPPED},
 | 
				
			||||||
 | 
						{"NT_STATUS_TOO_MANY_LUIDS_REQUESTED",
 | 
				
			||||||
 | 
						 NT_STATUS_TOO_MANY_LUIDS_REQUESTED},
 | 
				
			||||||
 | 
						{"NT_STATUS_LUIDS_EXHAUSTED", NT_STATUS_LUIDS_EXHAUSTED},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_SUB_AUTHORITY",
 | 
				
			||||||
 | 
						 NT_STATUS_INVALID_SUB_AUTHORITY},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_ACL", NT_STATUS_INVALID_ACL},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_SID", NT_STATUS_INVALID_SID},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_SECURITY_DESCR",
 | 
				
			||||||
 | 
						 NT_STATUS_INVALID_SECURITY_DESCR},
 | 
				
			||||||
 | 
						{"NT_STATUS_PROCEDURE_NOT_FOUND", NT_STATUS_PROCEDURE_NOT_FOUND},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_IMAGE_FORMAT", NT_STATUS_INVALID_IMAGE_FORMAT},
 | 
				
			||||||
 | 
						{"NT_STATUS_NO_TOKEN", NT_STATUS_NO_TOKEN},
 | 
				
			||||||
 | 
						{"NT_STATUS_BAD_INHERITANCE_ACL", NT_STATUS_BAD_INHERITANCE_ACL},
 | 
				
			||||||
 | 
						{"NT_STATUS_RANGE_NOT_LOCKED", NT_STATUS_RANGE_NOT_LOCKED},
 | 
				
			||||||
 | 
						{"NT_STATUS_DISK_FULL", NT_STATUS_DISK_FULL},
 | 
				
			||||||
 | 
						{"NT_STATUS_SERVER_DISABLED", NT_STATUS_SERVER_DISABLED},
 | 
				
			||||||
 | 
						{"NT_STATUS_SERVER_NOT_DISABLED", NT_STATUS_SERVER_NOT_DISABLED},
 | 
				
			||||||
 | 
						{"NT_STATUS_TOO_MANY_GUIDS_REQUESTED",
 | 
				
			||||||
 | 
						 NT_STATUS_TOO_MANY_GUIDS_REQUESTED},
 | 
				
			||||||
 | 
						{"NT_STATUS_GUIDS_EXHAUSTED", NT_STATUS_GUIDS_EXHAUSTED},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_ID_AUTHORITY", NT_STATUS_INVALID_ID_AUTHORITY},
 | 
				
			||||||
 | 
						{"NT_STATUS_AGENTS_EXHAUSTED", NT_STATUS_AGENTS_EXHAUSTED},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_VOLUME_LABEL", NT_STATUS_INVALID_VOLUME_LABEL},
 | 
				
			||||||
 | 
						{"NT_STATUS_SECTION_NOT_EXTENDED", NT_STATUS_SECTION_NOT_EXTENDED},
 | 
				
			||||||
 | 
						{"NT_STATUS_NOT_MAPPED_DATA", NT_STATUS_NOT_MAPPED_DATA},
 | 
				
			||||||
 | 
						{"NT_STATUS_RESOURCE_DATA_NOT_FOUND",
 | 
				
			||||||
 | 
						 NT_STATUS_RESOURCE_DATA_NOT_FOUND},
 | 
				
			||||||
 | 
						{"NT_STATUS_RESOURCE_TYPE_NOT_FOUND",
 | 
				
			||||||
 | 
						 NT_STATUS_RESOURCE_TYPE_NOT_FOUND},
 | 
				
			||||||
 | 
						{"NT_STATUS_RESOURCE_NAME_NOT_FOUND",
 | 
				
			||||||
 | 
						 NT_STATUS_RESOURCE_NAME_NOT_FOUND},
 | 
				
			||||||
 | 
						{"NT_STATUS_ARRAY_BOUNDS_EXCEEDED",
 | 
				
			||||||
 | 
						 NT_STATUS_ARRAY_BOUNDS_EXCEEDED},
 | 
				
			||||||
 | 
						{"NT_STATUS_FLOAT_DENORMAL_OPERAND",
 | 
				
			||||||
 | 
						 NT_STATUS_FLOAT_DENORMAL_OPERAND},
 | 
				
			||||||
 | 
						{"NT_STATUS_FLOAT_DIVIDE_BY_ZERO", NT_STATUS_FLOAT_DIVIDE_BY_ZERO},
 | 
				
			||||||
 | 
						{"NT_STATUS_FLOAT_INEXACT_RESULT", NT_STATUS_FLOAT_INEXACT_RESULT},
 | 
				
			||||||
 | 
						{"NT_STATUS_FLOAT_INVALID_OPERATION",
 | 
				
			||||||
 | 
						 NT_STATUS_FLOAT_INVALID_OPERATION},
 | 
				
			||||||
 | 
						{"NT_STATUS_FLOAT_OVERFLOW", NT_STATUS_FLOAT_OVERFLOW},
 | 
				
			||||||
 | 
						{"NT_STATUS_FLOAT_STACK_CHECK", NT_STATUS_FLOAT_STACK_CHECK},
 | 
				
			||||||
 | 
						{"NT_STATUS_FLOAT_UNDERFLOW", NT_STATUS_FLOAT_UNDERFLOW},
 | 
				
			||||||
 | 
						{"NT_STATUS_INTEGER_DIVIDE_BY_ZERO",
 | 
				
			||||||
 | 
						 NT_STATUS_INTEGER_DIVIDE_BY_ZERO},
 | 
				
			||||||
 | 
						{"NT_STATUS_INTEGER_OVERFLOW", NT_STATUS_INTEGER_OVERFLOW},
 | 
				
			||||||
 | 
						{"NT_STATUS_PRIVILEGED_INSTRUCTION",
 | 
				
			||||||
 | 
						 NT_STATUS_PRIVILEGED_INSTRUCTION},
 | 
				
			||||||
 | 
						{"NT_STATUS_TOO_MANY_PAGING_FILES",
 | 
				
			||||||
 | 
						 NT_STATUS_TOO_MANY_PAGING_FILES},
 | 
				
			||||||
 | 
						{"NT_STATUS_FILE_INVALID", NT_STATUS_FILE_INVALID},
 | 
				
			||||||
 | 
						{"NT_STATUS_ALLOTTED_SPACE_EXCEEDED",
 | 
				
			||||||
 | 
						 NT_STATUS_ALLOTTED_SPACE_EXCEEDED},
 | 
				
			||||||
 | 
						{"NT_STATUS_INSUFFICIENT_RESOURCES",
 | 
				
			||||||
 | 
						 NT_STATUS_INSUFFICIENT_RESOURCES},
 | 
				
			||||||
 | 
						{"NT_STATUS_DFS_EXIT_PATH_FOUND", NT_STATUS_DFS_EXIT_PATH_FOUND},
 | 
				
			||||||
 | 
						{"NT_STATUS_DEVICE_DATA_ERROR", NT_STATUS_DEVICE_DATA_ERROR},
 | 
				
			||||||
 | 
						{"NT_STATUS_DEVICE_NOT_CONNECTED", NT_STATUS_DEVICE_NOT_CONNECTED},
 | 
				
			||||||
 | 
						{"NT_STATUS_DEVICE_POWER_FAILURE", NT_STATUS_DEVICE_POWER_FAILURE},
 | 
				
			||||||
 | 
						{"NT_STATUS_FREE_VM_NOT_AT_BASE", NT_STATUS_FREE_VM_NOT_AT_BASE},
 | 
				
			||||||
 | 
						{"NT_STATUS_MEMORY_NOT_ALLOCATED", NT_STATUS_MEMORY_NOT_ALLOCATED},
 | 
				
			||||||
 | 
						{"NT_STATUS_WORKING_SET_QUOTA", NT_STATUS_WORKING_SET_QUOTA},
 | 
				
			||||||
 | 
						{"NT_STATUS_MEDIA_WRITE_PROTECTED",
 | 
				
			||||||
 | 
						 NT_STATUS_MEDIA_WRITE_PROTECTED},
 | 
				
			||||||
 | 
						{"NT_STATUS_DEVICE_NOT_READY", NT_STATUS_DEVICE_NOT_READY},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_GROUP_ATTRIBUTES",
 | 
				
			||||||
 | 
						 NT_STATUS_INVALID_GROUP_ATTRIBUTES},
 | 
				
			||||||
 | 
						{"NT_STATUS_BAD_IMPERSONATION_LEVEL",
 | 
				
			||||||
 | 
						 NT_STATUS_BAD_IMPERSONATION_LEVEL},
 | 
				
			||||||
 | 
						{"NT_STATUS_CANT_OPEN_ANONYMOUS", NT_STATUS_CANT_OPEN_ANONYMOUS},
 | 
				
			||||||
 | 
						{"NT_STATUS_BAD_VALIDATION_CLASS", NT_STATUS_BAD_VALIDATION_CLASS},
 | 
				
			||||||
 | 
						{"NT_STATUS_BAD_TOKEN_TYPE", NT_STATUS_BAD_TOKEN_TYPE},
 | 
				
			||||||
 | 
						{"NT_STATUS_BAD_MASTER_BOOT_RECORD",
 | 
				
			||||||
 | 
						 NT_STATUS_BAD_MASTER_BOOT_RECORD},
 | 
				
			||||||
 | 
						{"NT_STATUS_INSTRUCTION_MISALIGNMENT",
 | 
				
			||||||
 | 
						 NT_STATUS_INSTRUCTION_MISALIGNMENT},
 | 
				
			||||||
 | 
						{"NT_STATUS_INSTANCE_NOT_AVAILABLE",
 | 
				
			||||||
 | 
						 NT_STATUS_INSTANCE_NOT_AVAILABLE},
 | 
				
			||||||
 | 
						{"NT_STATUS_PIPE_NOT_AVAILABLE", NT_STATUS_PIPE_NOT_AVAILABLE},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_PIPE_STATE", NT_STATUS_INVALID_PIPE_STATE},
 | 
				
			||||||
 | 
						{"NT_STATUS_PIPE_BUSY", NT_STATUS_PIPE_BUSY},
 | 
				
			||||||
 | 
						{"NT_STATUS_ILLEGAL_FUNCTION", NT_STATUS_ILLEGAL_FUNCTION},
 | 
				
			||||||
 | 
						{"NT_STATUS_PIPE_DISCONNECTED", NT_STATUS_PIPE_DISCONNECTED},
 | 
				
			||||||
 | 
						{"NT_STATUS_PIPE_CLOSING", NT_STATUS_PIPE_CLOSING},
 | 
				
			||||||
 | 
						{"NT_STATUS_PIPE_CONNECTED", NT_STATUS_PIPE_CONNECTED},
 | 
				
			||||||
 | 
						{"NT_STATUS_PIPE_LISTENING", NT_STATUS_PIPE_LISTENING},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_READ_MODE", NT_STATUS_INVALID_READ_MODE},
 | 
				
			||||||
 | 
						{"NT_STATUS_IO_TIMEOUT", NT_STATUS_IO_TIMEOUT},
 | 
				
			||||||
 | 
						{"NT_STATUS_FILE_FORCED_CLOSED", NT_STATUS_FILE_FORCED_CLOSED},
 | 
				
			||||||
 | 
						{"NT_STATUS_PROFILING_NOT_STARTED",
 | 
				
			||||||
 | 
						 NT_STATUS_PROFILING_NOT_STARTED},
 | 
				
			||||||
 | 
						{"NT_STATUS_PROFILING_NOT_STOPPED",
 | 
				
			||||||
 | 
						 NT_STATUS_PROFILING_NOT_STOPPED},
 | 
				
			||||||
 | 
						{"NT_STATUS_COULD_NOT_INTERPRET", NT_STATUS_COULD_NOT_INTERPRET},
 | 
				
			||||||
 | 
						{"NT_STATUS_FILE_IS_A_DIRECTORY", NT_STATUS_FILE_IS_A_DIRECTORY},
 | 
				
			||||||
 | 
						{"NT_STATUS_NOT_SUPPORTED", NT_STATUS_NOT_SUPPORTED},
 | 
				
			||||||
 | 
						{"NT_STATUS_REMOTE_NOT_LISTENING", NT_STATUS_REMOTE_NOT_LISTENING},
 | 
				
			||||||
 | 
						{"NT_STATUS_DUPLICATE_NAME", NT_STATUS_DUPLICATE_NAME},
 | 
				
			||||||
 | 
						{"NT_STATUS_BAD_NETWORK_PATH", NT_STATUS_BAD_NETWORK_PATH},
 | 
				
			||||||
 | 
						{"NT_STATUS_NETWORK_BUSY", NT_STATUS_NETWORK_BUSY},
 | 
				
			||||||
 | 
						{"NT_STATUS_DEVICE_DOES_NOT_EXIST",
 | 
				
			||||||
 | 
						 NT_STATUS_DEVICE_DOES_NOT_EXIST},
 | 
				
			||||||
 | 
						{"NT_STATUS_TOO_MANY_COMMANDS", NT_STATUS_TOO_MANY_COMMANDS},
 | 
				
			||||||
 | 
						{"NT_STATUS_ADAPTER_HARDWARE_ERROR",
 | 
				
			||||||
 | 
						 NT_STATUS_ADAPTER_HARDWARE_ERROR},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_NETWORK_RESPONSE",
 | 
				
			||||||
 | 
						 NT_STATUS_INVALID_NETWORK_RESPONSE},
 | 
				
			||||||
 | 
						{"NT_STATUS_UNEXPECTED_NETWORK_ERROR",
 | 
				
			||||||
 | 
						 NT_STATUS_UNEXPECTED_NETWORK_ERROR},
 | 
				
			||||||
 | 
						{"NT_STATUS_BAD_REMOTE_ADAPTER", NT_STATUS_BAD_REMOTE_ADAPTER},
 | 
				
			||||||
 | 
						{"NT_STATUS_PRINT_QUEUE_FULL", NT_STATUS_PRINT_QUEUE_FULL},
 | 
				
			||||||
 | 
						{"NT_STATUS_NO_SPOOL_SPACE", NT_STATUS_NO_SPOOL_SPACE},
 | 
				
			||||||
 | 
						{"NT_STATUS_PRINT_CANCELLED", NT_STATUS_PRINT_CANCELLED},
 | 
				
			||||||
 | 
						{"NT_STATUS_NETWORK_NAME_DELETED", NT_STATUS_NETWORK_NAME_DELETED},
 | 
				
			||||||
 | 
						{"NT_STATUS_NETWORK_ACCESS_DENIED",
 | 
				
			||||||
 | 
						 NT_STATUS_NETWORK_ACCESS_DENIED},
 | 
				
			||||||
 | 
						{"NT_STATUS_BAD_DEVICE_TYPE", NT_STATUS_BAD_DEVICE_TYPE},
 | 
				
			||||||
 | 
						{"NT_STATUS_BAD_NETWORK_NAME", NT_STATUS_BAD_NETWORK_NAME},
 | 
				
			||||||
 | 
						{"NT_STATUS_TOO_MANY_NAMES", NT_STATUS_TOO_MANY_NAMES},
 | 
				
			||||||
 | 
						{"NT_STATUS_TOO_MANY_SESSIONS", NT_STATUS_TOO_MANY_SESSIONS},
 | 
				
			||||||
 | 
						{"NT_STATUS_SHARING_PAUSED", NT_STATUS_SHARING_PAUSED},
 | 
				
			||||||
 | 
						{"NT_STATUS_REQUEST_NOT_ACCEPTED", NT_STATUS_REQUEST_NOT_ACCEPTED},
 | 
				
			||||||
 | 
						{"NT_STATUS_REDIRECTOR_PAUSED", NT_STATUS_REDIRECTOR_PAUSED},
 | 
				
			||||||
 | 
						{"NT_STATUS_NET_WRITE_FAULT", NT_STATUS_NET_WRITE_FAULT},
 | 
				
			||||||
 | 
						{"NT_STATUS_PROFILING_AT_LIMIT", NT_STATUS_PROFILING_AT_LIMIT},
 | 
				
			||||||
 | 
						{"NT_STATUS_NOT_SAME_DEVICE", NT_STATUS_NOT_SAME_DEVICE},
 | 
				
			||||||
 | 
						{"NT_STATUS_FILE_RENAMED", NT_STATUS_FILE_RENAMED},
 | 
				
			||||||
 | 
						{"NT_STATUS_VIRTUAL_CIRCUIT_CLOSED",
 | 
				
			||||||
 | 
						 NT_STATUS_VIRTUAL_CIRCUIT_CLOSED},
 | 
				
			||||||
 | 
						{"NT_STATUS_NO_SECURITY_ON_OBJECT",
 | 
				
			||||||
 | 
						 NT_STATUS_NO_SECURITY_ON_OBJECT},
 | 
				
			||||||
 | 
						{"NT_STATUS_CANT_WAIT", NT_STATUS_CANT_WAIT},
 | 
				
			||||||
 | 
						{"NT_STATUS_PIPE_EMPTY", NT_STATUS_PIPE_EMPTY},
 | 
				
			||||||
 | 
						{"NT_STATUS_CANT_ACCESS_DOMAIN_INFO",
 | 
				
			||||||
 | 
						 NT_STATUS_CANT_ACCESS_DOMAIN_INFO},
 | 
				
			||||||
 | 
						{"NT_STATUS_CANT_TERMINATE_SELF", NT_STATUS_CANT_TERMINATE_SELF},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_SERVER_STATE", NT_STATUS_INVALID_SERVER_STATE},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_DOMAIN_STATE", NT_STATUS_INVALID_DOMAIN_STATE},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_DOMAIN_ROLE", NT_STATUS_INVALID_DOMAIN_ROLE},
 | 
				
			||||||
 | 
						{"NT_STATUS_NO_SUCH_DOMAIN", NT_STATUS_NO_SUCH_DOMAIN},
 | 
				
			||||||
 | 
						{"NT_STATUS_DOMAIN_EXISTS", NT_STATUS_DOMAIN_EXISTS},
 | 
				
			||||||
 | 
						{"NT_STATUS_DOMAIN_LIMIT_EXCEEDED",
 | 
				
			||||||
 | 
						 NT_STATUS_DOMAIN_LIMIT_EXCEEDED},
 | 
				
			||||||
 | 
						{"NT_STATUS_OPLOCK_NOT_GRANTED", NT_STATUS_OPLOCK_NOT_GRANTED},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_OPLOCK_PROTOCOL",
 | 
				
			||||||
 | 
						 NT_STATUS_INVALID_OPLOCK_PROTOCOL},
 | 
				
			||||||
 | 
						{"NT_STATUS_INTERNAL_DB_CORRUPTION",
 | 
				
			||||||
 | 
						 NT_STATUS_INTERNAL_DB_CORRUPTION},
 | 
				
			||||||
 | 
						{"NT_STATUS_INTERNAL_ERROR", NT_STATUS_INTERNAL_ERROR},
 | 
				
			||||||
 | 
						{"NT_STATUS_GENERIC_NOT_MAPPED", NT_STATUS_GENERIC_NOT_MAPPED},
 | 
				
			||||||
 | 
						{"NT_STATUS_BAD_DESCRIPTOR_FORMAT",
 | 
				
			||||||
 | 
						 NT_STATUS_BAD_DESCRIPTOR_FORMAT},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_USER_BUFFER", NT_STATUS_INVALID_USER_BUFFER},
 | 
				
			||||||
 | 
						{"NT_STATUS_UNEXPECTED_IO_ERROR", NT_STATUS_UNEXPECTED_IO_ERROR},
 | 
				
			||||||
 | 
						{"NT_STATUS_UNEXPECTED_MM_CREATE_ERR",
 | 
				
			||||||
 | 
						 NT_STATUS_UNEXPECTED_MM_CREATE_ERR},
 | 
				
			||||||
 | 
						{"NT_STATUS_UNEXPECTED_MM_MAP_ERROR",
 | 
				
			||||||
 | 
						 NT_STATUS_UNEXPECTED_MM_MAP_ERROR},
 | 
				
			||||||
 | 
						{"NT_STATUS_UNEXPECTED_MM_EXTEND_ERR",
 | 
				
			||||||
 | 
						 NT_STATUS_UNEXPECTED_MM_EXTEND_ERR},
 | 
				
			||||||
 | 
						{"NT_STATUS_NOT_LOGON_PROCESS", NT_STATUS_NOT_LOGON_PROCESS},
 | 
				
			||||||
 | 
						{"NT_STATUS_LOGON_SESSION_EXISTS", NT_STATUS_LOGON_SESSION_EXISTS},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_PARAMETER_1", NT_STATUS_INVALID_PARAMETER_1},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_PARAMETER_2", NT_STATUS_INVALID_PARAMETER_2},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_PARAMETER_3", NT_STATUS_INVALID_PARAMETER_3},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_PARAMETER_4", NT_STATUS_INVALID_PARAMETER_4},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_PARAMETER_5", NT_STATUS_INVALID_PARAMETER_5},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_PARAMETER_6", NT_STATUS_INVALID_PARAMETER_6},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_PARAMETER_7", NT_STATUS_INVALID_PARAMETER_7},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_PARAMETER_8", NT_STATUS_INVALID_PARAMETER_8},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_PARAMETER_9", NT_STATUS_INVALID_PARAMETER_9},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_PARAMETER_10", NT_STATUS_INVALID_PARAMETER_10},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_PARAMETER_11", NT_STATUS_INVALID_PARAMETER_11},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_PARAMETER_12", NT_STATUS_INVALID_PARAMETER_12},
 | 
				
			||||||
 | 
						{"NT_STATUS_REDIRECTOR_NOT_STARTED",
 | 
				
			||||||
 | 
						 NT_STATUS_REDIRECTOR_NOT_STARTED},
 | 
				
			||||||
 | 
						{"NT_STATUS_REDIRECTOR_STARTED", NT_STATUS_REDIRECTOR_STARTED},
 | 
				
			||||||
 | 
						{"NT_STATUS_STACK_OVERFLOW", NT_STATUS_STACK_OVERFLOW},
 | 
				
			||||||
 | 
						{"NT_STATUS_NO_SUCH_PACKAGE", NT_STATUS_NO_SUCH_PACKAGE},
 | 
				
			||||||
 | 
						{"NT_STATUS_BAD_FUNCTION_TABLE", NT_STATUS_BAD_FUNCTION_TABLE},
 | 
				
			||||||
 | 
						{"NT_STATUS_DIRECTORY_NOT_EMPTY", NT_STATUS_DIRECTORY_NOT_EMPTY},
 | 
				
			||||||
 | 
						{"NT_STATUS_FILE_CORRUPT_ERROR", NT_STATUS_FILE_CORRUPT_ERROR},
 | 
				
			||||||
 | 
						{"NT_STATUS_NOT_A_DIRECTORY", NT_STATUS_NOT_A_DIRECTORY},
 | 
				
			||||||
 | 
						{"NT_STATUS_BAD_LOGON_SESSION_STATE",
 | 
				
			||||||
 | 
						 NT_STATUS_BAD_LOGON_SESSION_STATE},
 | 
				
			||||||
 | 
						{"NT_STATUS_LOGON_SESSION_COLLISION",
 | 
				
			||||||
 | 
						 NT_STATUS_LOGON_SESSION_COLLISION},
 | 
				
			||||||
 | 
						{"NT_STATUS_NAME_TOO_LONG", NT_STATUS_NAME_TOO_LONG},
 | 
				
			||||||
 | 
						{"NT_STATUS_FILES_OPEN", NT_STATUS_FILES_OPEN},
 | 
				
			||||||
 | 
						{"NT_STATUS_CONNECTION_IN_USE", NT_STATUS_CONNECTION_IN_USE},
 | 
				
			||||||
 | 
						{"NT_STATUS_MESSAGE_NOT_FOUND", NT_STATUS_MESSAGE_NOT_FOUND},
 | 
				
			||||||
 | 
						{"NT_STATUS_PROCESS_IS_TERMINATING",
 | 
				
			||||||
 | 
						 NT_STATUS_PROCESS_IS_TERMINATING},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_LOGON_TYPE", NT_STATUS_INVALID_LOGON_TYPE},
 | 
				
			||||||
 | 
						{"NT_STATUS_NO_GUID_TRANSLATION", NT_STATUS_NO_GUID_TRANSLATION},
 | 
				
			||||||
 | 
						{"NT_STATUS_CANNOT_IMPERSONATE", NT_STATUS_CANNOT_IMPERSONATE},
 | 
				
			||||||
 | 
						{"NT_STATUS_IMAGE_ALREADY_LOADED", NT_STATUS_IMAGE_ALREADY_LOADED},
 | 
				
			||||||
 | 
						{"NT_STATUS_ABIOS_NOT_PRESENT", NT_STATUS_ABIOS_NOT_PRESENT},
 | 
				
			||||||
 | 
						{"NT_STATUS_ABIOS_LID_NOT_EXIST", NT_STATUS_ABIOS_LID_NOT_EXIST},
 | 
				
			||||||
 | 
						{"NT_STATUS_ABIOS_LID_ALREADY_OWNED",
 | 
				
			||||||
 | 
						 NT_STATUS_ABIOS_LID_ALREADY_OWNED},
 | 
				
			||||||
 | 
						{"NT_STATUS_ABIOS_NOT_LID_OWNER", NT_STATUS_ABIOS_NOT_LID_OWNER},
 | 
				
			||||||
 | 
						{"NT_STATUS_ABIOS_INVALID_COMMAND",
 | 
				
			||||||
 | 
						 NT_STATUS_ABIOS_INVALID_COMMAND},
 | 
				
			||||||
 | 
						{"NT_STATUS_ABIOS_INVALID_LID", NT_STATUS_ABIOS_INVALID_LID},
 | 
				
			||||||
 | 
						{"NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE",
 | 
				
			||||||
 | 
						 NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE},
 | 
				
			||||||
 | 
						{"NT_STATUS_ABIOS_INVALID_SELECTOR",
 | 
				
			||||||
 | 
						 NT_STATUS_ABIOS_INVALID_SELECTOR},
 | 
				
			||||||
 | 
						{"NT_STATUS_NO_LDT", NT_STATUS_NO_LDT},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_LDT_SIZE", NT_STATUS_INVALID_LDT_SIZE},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_LDT_OFFSET", NT_STATUS_INVALID_LDT_OFFSET},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_LDT_DESCRIPTOR",
 | 
				
			||||||
 | 
						 NT_STATUS_INVALID_LDT_DESCRIPTOR},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_IMAGE_NE_FORMAT",
 | 
				
			||||||
 | 
						 NT_STATUS_INVALID_IMAGE_NE_FORMAT},
 | 
				
			||||||
 | 
						{"NT_STATUS_RXACT_INVALID_STATE", NT_STATUS_RXACT_INVALID_STATE},
 | 
				
			||||||
 | 
						{"NT_STATUS_RXACT_COMMIT_FAILURE", NT_STATUS_RXACT_COMMIT_FAILURE},
 | 
				
			||||||
 | 
						{"NT_STATUS_MAPPED_FILE_SIZE_ZERO",
 | 
				
			||||||
 | 
						 NT_STATUS_MAPPED_FILE_SIZE_ZERO},
 | 
				
			||||||
 | 
						{"NT_STATUS_TOO_MANY_OPENED_FILES",
 | 
				
			||||||
 | 
						 NT_STATUS_TOO_MANY_OPENED_FILES},
 | 
				
			||||||
 | 
						{"NT_STATUS_CANCELLED", NT_STATUS_CANCELLED},
 | 
				
			||||||
 | 
						{"NT_STATUS_CANNOT_DELETE", NT_STATUS_CANNOT_DELETE},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_COMPUTER_NAME",
 | 
				
			||||||
 | 
						 NT_STATUS_INVALID_COMPUTER_NAME},
 | 
				
			||||||
 | 
						{"NT_STATUS_FILE_DELETED", NT_STATUS_FILE_DELETED},
 | 
				
			||||||
 | 
						{"NT_STATUS_SPECIAL_ACCOUNT", NT_STATUS_SPECIAL_ACCOUNT},
 | 
				
			||||||
 | 
						{"NT_STATUS_SPECIAL_GROUP", NT_STATUS_SPECIAL_GROUP},
 | 
				
			||||||
 | 
						{"NT_STATUS_SPECIAL_USER", NT_STATUS_SPECIAL_USER},
 | 
				
			||||||
 | 
						{"NT_STATUS_MEMBERS_PRIMARY_GROUP",
 | 
				
			||||||
 | 
						 NT_STATUS_MEMBERS_PRIMARY_GROUP},
 | 
				
			||||||
 | 
						{"NT_STATUS_FILE_CLOSED", NT_STATUS_FILE_CLOSED},
 | 
				
			||||||
 | 
						{"NT_STATUS_TOO_MANY_THREADS", NT_STATUS_TOO_MANY_THREADS},
 | 
				
			||||||
 | 
						{"NT_STATUS_THREAD_NOT_IN_PROCESS",
 | 
				
			||||||
 | 
						 NT_STATUS_THREAD_NOT_IN_PROCESS},
 | 
				
			||||||
 | 
						{"NT_STATUS_TOKEN_ALREADY_IN_USE", NT_STATUS_TOKEN_ALREADY_IN_USE},
 | 
				
			||||||
 | 
						{"NT_STATUS_PAGEFILE_QUOTA_EXCEEDED",
 | 
				
			||||||
 | 
						 NT_STATUS_PAGEFILE_QUOTA_EXCEEDED},
 | 
				
			||||||
 | 
						{"NT_STATUS_COMMITMENT_LIMIT", NT_STATUS_COMMITMENT_LIMIT},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_IMAGE_LE_FORMAT",
 | 
				
			||||||
 | 
						 NT_STATUS_INVALID_IMAGE_LE_FORMAT},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_IMAGE_NOT_MZ", NT_STATUS_INVALID_IMAGE_NOT_MZ},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_IMAGE_PROTECT",
 | 
				
			||||||
 | 
						 NT_STATUS_INVALID_IMAGE_PROTECT},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_IMAGE_WIN_16", NT_STATUS_INVALID_IMAGE_WIN_16},
 | 
				
			||||||
 | 
						{"NT_STATUS_LOGON_SERVER_CONFLICT",
 | 
				
			||||||
 | 
						 NT_STATUS_LOGON_SERVER_CONFLICT},
 | 
				
			||||||
 | 
						{"NT_STATUS_TIME_DIFFERENCE_AT_DC",
 | 
				
			||||||
 | 
						 NT_STATUS_TIME_DIFFERENCE_AT_DC},
 | 
				
			||||||
 | 
						{"NT_STATUS_SYNCHRONIZATION_REQUIRED",
 | 
				
			||||||
 | 
						 NT_STATUS_SYNCHRONIZATION_REQUIRED},
 | 
				
			||||||
 | 
						{"NT_STATUS_DLL_NOT_FOUND", NT_STATUS_DLL_NOT_FOUND},
 | 
				
			||||||
 | 
						{"NT_STATUS_OPEN_FAILED", NT_STATUS_OPEN_FAILED},
 | 
				
			||||||
 | 
						{"NT_STATUS_IO_PRIVILEGE_FAILED", NT_STATUS_IO_PRIVILEGE_FAILED},
 | 
				
			||||||
 | 
						{"NT_STATUS_ORDINAL_NOT_FOUND", NT_STATUS_ORDINAL_NOT_FOUND},
 | 
				
			||||||
 | 
						{"NT_STATUS_ENTRYPOINT_NOT_FOUND", NT_STATUS_ENTRYPOINT_NOT_FOUND},
 | 
				
			||||||
 | 
						{"NT_STATUS_CONTROL_C_EXIT", NT_STATUS_CONTROL_C_EXIT},
 | 
				
			||||||
 | 
						{"NT_STATUS_LOCAL_DISCONNECT", NT_STATUS_LOCAL_DISCONNECT},
 | 
				
			||||||
 | 
						{"NT_STATUS_REMOTE_DISCONNECT", NT_STATUS_REMOTE_DISCONNECT},
 | 
				
			||||||
 | 
						{"NT_STATUS_REMOTE_RESOURCES", NT_STATUS_REMOTE_RESOURCES},
 | 
				
			||||||
 | 
						{"NT_STATUS_LINK_FAILED", NT_STATUS_LINK_FAILED},
 | 
				
			||||||
 | 
						{"NT_STATUS_LINK_TIMEOUT", NT_STATUS_LINK_TIMEOUT},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_CONNECTION", NT_STATUS_INVALID_CONNECTION},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_ADDRESS", NT_STATUS_INVALID_ADDRESS},
 | 
				
			||||||
 | 
						{"NT_STATUS_DLL_INIT_FAILED", NT_STATUS_DLL_INIT_FAILED},
 | 
				
			||||||
 | 
						{"NT_STATUS_MISSING_SYSTEMFILE", NT_STATUS_MISSING_SYSTEMFILE},
 | 
				
			||||||
 | 
						{"NT_STATUS_UNHANDLED_EXCEPTION", NT_STATUS_UNHANDLED_EXCEPTION},
 | 
				
			||||||
 | 
						{"NT_STATUS_APP_INIT_FAILURE", NT_STATUS_APP_INIT_FAILURE},
 | 
				
			||||||
 | 
						{"NT_STATUS_PAGEFILE_CREATE_FAILED",
 | 
				
			||||||
 | 
						 NT_STATUS_PAGEFILE_CREATE_FAILED},
 | 
				
			||||||
 | 
						{"NT_STATUS_NO_PAGEFILE", NT_STATUS_NO_PAGEFILE},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_LEVEL", NT_STATUS_INVALID_LEVEL},
 | 
				
			||||||
 | 
						{"NT_STATUS_WRONG_PASSWORD_CORE", NT_STATUS_WRONG_PASSWORD_CORE},
 | 
				
			||||||
 | 
						{"NT_STATUS_ILLEGAL_FLOAT_CONTEXT",
 | 
				
			||||||
 | 
						 NT_STATUS_ILLEGAL_FLOAT_CONTEXT},
 | 
				
			||||||
 | 
						{"NT_STATUS_PIPE_BROKEN", NT_STATUS_PIPE_BROKEN},
 | 
				
			||||||
 | 
						{"NT_STATUS_REGISTRY_CORRUPT", NT_STATUS_REGISTRY_CORRUPT},
 | 
				
			||||||
 | 
						{"NT_STATUS_REGISTRY_IO_FAILED", NT_STATUS_REGISTRY_IO_FAILED},
 | 
				
			||||||
 | 
						{"NT_STATUS_NO_EVENT_PAIR", NT_STATUS_NO_EVENT_PAIR},
 | 
				
			||||||
 | 
						{"NT_STATUS_UNRECOGNIZED_VOLUME", NT_STATUS_UNRECOGNIZED_VOLUME},
 | 
				
			||||||
 | 
						{"NT_STATUS_SERIAL_NO_DEVICE_INITED",
 | 
				
			||||||
 | 
						 NT_STATUS_SERIAL_NO_DEVICE_INITED},
 | 
				
			||||||
 | 
						{"NT_STATUS_NO_SUCH_ALIAS", NT_STATUS_NO_SUCH_ALIAS},
 | 
				
			||||||
 | 
						{"NT_STATUS_MEMBER_NOT_IN_ALIAS", NT_STATUS_MEMBER_NOT_IN_ALIAS},
 | 
				
			||||||
 | 
						{"NT_STATUS_MEMBER_IN_ALIAS", NT_STATUS_MEMBER_IN_ALIAS},
 | 
				
			||||||
 | 
						{"NT_STATUS_ALIAS_EXISTS", NT_STATUS_ALIAS_EXISTS},
 | 
				
			||||||
 | 
						{"NT_STATUS_LOGON_NOT_GRANTED", NT_STATUS_LOGON_NOT_GRANTED},
 | 
				
			||||||
 | 
						{"NT_STATUS_TOO_MANY_SECRETS", NT_STATUS_TOO_MANY_SECRETS},
 | 
				
			||||||
 | 
						{"NT_STATUS_SECRET_TOO_LONG", NT_STATUS_SECRET_TOO_LONG},
 | 
				
			||||||
 | 
						{"NT_STATUS_INTERNAL_DB_ERROR", NT_STATUS_INTERNAL_DB_ERROR},
 | 
				
			||||||
 | 
						{"NT_STATUS_FULLSCREEN_MODE", NT_STATUS_FULLSCREEN_MODE},
 | 
				
			||||||
 | 
						{"NT_STATUS_TOO_MANY_CONTEXT_IDS", NT_STATUS_TOO_MANY_CONTEXT_IDS},
 | 
				
			||||||
 | 
						{"NT_STATUS_LOGON_TYPE_NOT_GRANTED",
 | 
				
			||||||
 | 
						 NT_STATUS_LOGON_TYPE_NOT_GRANTED},
 | 
				
			||||||
 | 
						{"NT_STATUS_NOT_REGISTRY_FILE", NT_STATUS_NOT_REGISTRY_FILE},
 | 
				
			||||||
 | 
						{"NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED",
 | 
				
			||||||
 | 
						 NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED},
 | 
				
			||||||
 | 
						{"NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR",
 | 
				
			||||||
 | 
						 NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR},
 | 
				
			||||||
 | 
						{"NT_STATUS_FT_MISSING_MEMBER", NT_STATUS_FT_MISSING_MEMBER},
 | 
				
			||||||
 | 
						{"NT_STATUS_ILL_FORMED_SERVICE_ENTRY",
 | 
				
			||||||
 | 
						 NT_STATUS_ILL_FORMED_SERVICE_ENTRY},
 | 
				
			||||||
 | 
						{"NT_STATUS_ILLEGAL_CHARACTER", NT_STATUS_ILLEGAL_CHARACTER},
 | 
				
			||||||
 | 
						{"NT_STATUS_UNMAPPABLE_CHARACTER", NT_STATUS_UNMAPPABLE_CHARACTER},
 | 
				
			||||||
 | 
						{"NT_STATUS_UNDEFINED_CHARACTER", NT_STATUS_UNDEFINED_CHARACTER},
 | 
				
			||||||
 | 
						{"NT_STATUS_FLOPPY_VOLUME", NT_STATUS_FLOPPY_VOLUME},
 | 
				
			||||||
 | 
						{"NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND",
 | 
				
			||||||
 | 
						 NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND},
 | 
				
			||||||
 | 
						{"NT_STATUS_FLOPPY_WRONG_CYLINDER",
 | 
				
			||||||
 | 
						 NT_STATUS_FLOPPY_WRONG_CYLINDER},
 | 
				
			||||||
 | 
						{"NT_STATUS_FLOPPY_UNKNOWN_ERROR", NT_STATUS_FLOPPY_UNKNOWN_ERROR},
 | 
				
			||||||
 | 
						{"NT_STATUS_FLOPPY_BAD_REGISTERS", NT_STATUS_FLOPPY_BAD_REGISTERS},
 | 
				
			||||||
 | 
						{"NT_STATUS_DISK_RECALIBRATE_FAILED",
 | 
				
			||||||
 | 
						 NT_STATUS_DISK_RECALIBRATE_FAILED},
 | 
				
			||||||
 | 
						{"NT_STATUS_DISK_OPERATION_FAILED",
 | 
				
			||||||
 | 
						 NT_STATUS_DISK_OPERATION_FAILED},
 | 
				
			||||||
 | 
						{"NT_STATUS_DISK_RESET_FAILED", NT_STATUS_DISK_RESET_FAILED},
 | 
				
			||||||
 | 
						{"NT_STATUS_SHARED_IRQ_BUSY", NT_STATUS_SHARED_IRQ_BUSY},
 | 
				
			||||||
 | 
						{"NT_STATUS_FT_ORPHANING", NT_STATUS_FT_ORPHANING},
 | 
				
			||||||
 | 
						{"NT_STATUS_PARTITION_FAILURE", NT_STATUS_PARTITION_FAILURE},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_BLOCK_LENGTH", NT_STATUS_INVALID_BLOCK_LENGTH},
 | 
				
			||||||
 | 
						{"NT_STATUS_DEVICE_NOT_PARTITIONED",
 | 
				
			||||||
 | 
						 NT_STATUS_DEVICE_NOT_PARTITIONED},
 | 
				
			||||||
 | 
						{"NT_STATUS_UNABLE_TO_LOCK_MEDIA", NT_STATUS_UNABLE_TO_LOCK_MEDIA},
 | 
				
			||||||
 | 
						{"NT_STATUS_UNABLE_TO_UNLOAD_MEDIA",
 | 
				
			||||||
 | 
						 NT_STATUS_UNABLE_TO_UNLOAD_MEDIA},
 | 
				
			||||||
 | 
						{"NT_STATUS_EOM_OVERFLOW", NT_STATUS_EOM_OVERFLOW},
 | 
				
			||||||
 | 
						{"NT_STATUS_NO_MEDIA", NT_STATUS_NO_MEDIA},
 | 
				
			||||||
 | 
						{"NT_STATUS_NO_SUCH_MEMBER", NT_STATUS_NO_SUCH_MEMBER},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_MEMBER", NT_STATUS_INVALID_MEMBER},
 | 
				
			||||||
 | 
						{"NT_STATUS_KEY_DELETED", NT_STATUS_KEY_DELETED},
 | 
				
			||||||
 | 
						{"NT_STATUS_NO_LOG_SPACE", NT_STATUS_NO_LOG_SPACE},
 | 
				
			||||||
 | 
						{"NT_STATUS_TOO_MANY_SIDS", NT_STATUS_TOO_MANY_SIDS},
 | 
				
			||||||
 | 
						{"NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED",
 | 
				
			||||||
 | 
						 NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED},
 | 
				
			||||||
 | 
						{"NT_STATUS_KEY_HAS_CHILDREN", NT_STATUS_KEY_HAS_CHILDREN},
 | 
				
			||||||
 | 
						{"NT_STATUS_CHILD_MUST_BE_VOLATILE",
 | 
				
			||||||
 | 
						 NT_STATUS_CHILD_MUST_BE_VOLATILE},
 | 
				
			||||||
 | 
						{"NT_STATUS_DEVICE_CONFIGURATION_ERROR",
 | 
				
			||||||
 | 
						 NT_STATUS_DEVICE_CONFIGURATION_ERROR},
 | 
				
			||||||
 | 
						{"NT_STATUS_DRIVER_INTERNAL_ERROR",
 | 
				
			||||||
 | 
						 NT_STATUS_DRIVER_INTERNAL_ERROR},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_DEVICE_STATE", NT_STATUS_INVALID_DEVICE_STATE},
 | 
				
			||||||
 | 
						{"NT_STATUS_IO_DEVICE_ERROR", NT_STATUS_IO_DEVICE_ERROR},
 | 
				
			||||||
 | 
						{"NT_STATUS_DEVICE_PROTOCOL_ERROR",
 | 
				
			||||||
 | 
						 NT_STATUS_DEVICE_PROTOCOL_ERROR},
 | 
				
			||||||
 | 
						{"NT_STATUS_BACKUP_CONTROLLER", NT_STATUS_BACKUP_CONTROLLER},
 | 
				
			||||||
 | 
						{"NT_STATUS_LOG_FILE_FULL", NT_STATUS_LOG_FILE_FULL},
 | 
				
			||||||
 | 
						{"NT_STATUS_TOO_LATE", NT_STATUS_TOO_LATE},
 | 
				
			||||||
 | 
						{"NT_STATUS_NO_TRUST_LSA_SECRET", NT_STATUS_NO_TRUST_LSA_SECRET},
 | 
				
			||||||
 | 
						{"NT_STATUS_NO_TRUST_SAM_ACCOUNT", NT_STATUS_NO_TRUST_SAM_ACCOUNT},
 | 
				
			||||||
 | 
						{"NT_STATUS_TRUSTED_DOMAIN_FAILURE",
 | 
				
			||||||
 | 
						 NT_STATUS_TRUSTED_DOMAIN_FAILURE},
 | 
				
			||||||
 | 
						{"NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE",
 | 
				
			||||||
 | 
						 NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE},
 | 
				
			||||||
 | 
						{"NT_STATUS_EVENTLOG_FILE_CORRUPT",
 | 
				
			||||||
 | 
						 NT_STATUS_EVENTLOG_FILE_CORRUPT},
 | 
				
			||||||
 | 
						{"NT_STATUS_EVENTLOG_CANT_START", NT_STATUS_EVENTLOG_CANT_START},
 | 
				
			||||||
 | 
						{"NT_STATUS_TRUST_FAILURE", NT_STATUS_TRUST_FAILURE},
 | 
				
			||||||
 | 
						{"NT_STATUS_MUTANT_LIMIT_EXCEEDED",
 | 
				
			||||||
 | 
						 NT_STATUS_MUTANT_LIMIT_EXCEEDED},
 | 
				
			||||||
 | 
						{"NT_STATUS_NETLOGON_NOT_STARTED", NT_STATUS_NETLOGON_NOT_STARTED},
 | 
				
			||||||
 | 
						{"NT_STATUS_ACCOUNT_EXPIRED", NT_STATUS_ACCOUNT_EXPIRED},
 | 
				
			||||||
 | 
						{"NT_STATUS_POSSIBLE_DEADLOCK", NT_STATUS_POSSIBLE_DEADLOCK},
 | 
				
			||||||
 | 
						{"NT_STATUS_NETWORK_CREDENTIAL_CONFLICT",
 | 
				
			||||||
 | 
						 NT_STATUS_NETWORK_CREDENTIAL_CONFLICT},
 | 
				
			||||||
 | 
						{"NT_STATUS_REMOTE_SESSION_LIMIT", NT_STATUS_REMOTE_SESSION_LIMIT},
 | 
				
			||||||
 | 
						{"NT_STATUS_EVENTLOG_FILE_CHANGED",
 | 
				
			||||||
 | 
						 NT_STATUS_EVENTLOG_FILE_CHANGED},
 | 
				
			||||||
 | 
						{"NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT",
 | 
				
			||||||
 | 
						 NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT},
 | 
				
			||||||
 | 
						{"NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT",
 | 
				
			||||||
 | 
						 NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT},
 | 
				
			||||||
 | 
						{"NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT",
 | 
				
			||||||
 | 
						 NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT},
 | 
				
			||||||
 | 
						{"NT_STATUS_DOMAIN_TRUST_INCONSISTENT",
 | 
				
			||||||
 | 
						 NT_STATUS_DOMAIN_TRUST_INCONSISTENT},
 | 
				
			||||||
 | 
						{"NT_STATUS_FS_DRIVER_REQUIRED", NT_STATUS_FS_DRIVER_REQUIRED},
 | 
				
			||||||
 | 
						{"NT_STATUS_NO_USER_SESSION_KEY", NT_STATUS_NO_USER_SESSION_KEY},
 | 
				
			||||||
 | 
						{"NT_STATUS_USER_SESSION_DELETED", NT_STATUS_USER_SESSION_DELETED},
 | 
				
			||||||
 | 
						{"NT_STATUS_RESOURCE_LANG_NOT_FOUND",
 | 
				
			||||||
 | 
						 NT_STATUS_RESOURCE_LANG_NOT_FOUND},
 | 
				
			||||||
 | 
						{"NT_STATUS_INSUFF_SERVER_RESOURCES",
 | 
				
			||||||
 | 
						 NT_STATUS_INSUFF_SERVER_RESOURCES},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_BUFFER_SIZE", NT_STATUS_INVALID_BUFFER_SIZE},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_ADDRESS_COMPONENT",
 | 
				
			||||||
 | 
						 NT_STATUS_INVALID_ADDRESS_COMPONENT},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_ADDRESS_WILDCARD",
 | 
				
			||||||
 | 
						 NT_STATUS_INVALID_ADDRESS_WILDCARD},
 | 
				
			||||||
 | 
						{"NT_STATUS_TOO_MANY_ADDRESSES", NT_STATUS_TOO_MANY_ADDRESSES},
 | 
				
			||||||
 | 
						{"NT_STATUS_ADDRESS_ALREADY_EXISTS",
 | 
				
			||||||
 | 
						 NT_STATUS_ADDRESS_ALREADY_EXISTS},
 | 
				
			||||||
 | 
						{"NT_STATUS_ADDRESS_CLOSED", NT_STATUS_ADDRESS_CLOSED},
 | 
				
			||||||
 | 
						{"NT_STATUS_CONNECTION_DISCONNECTED",
 | 
				
			||||||
 | 
						 NT_STATUS_CONNECTION_DISCONNECTED},
 | 
				
			||||||
 | 
						{"NT_STATUS_CONNECTION_RESET", NT_STATUS_CONNECTION_RESET},
 | 
				
			||||||
 | 
						{"NT_STATUS_TOO_MANY_NODES", NT_STATUS_TOO_MANY_NODES},
 | 
				
			||||||
 | 
						{"NT_STATUS_TRANSACTION_ABORTED", NT_STATUS_TRANSACTION_ABORTED},
 | 
				
			||||||
 | 
						{"NT_STATUS_TRANSACTION_TIMED_OUT",
 | 
				
			||||||
 | 
						 NT_STATUS_TRANSACTION_TIMED_OUT},
 | 
				
			||||||
 | 
						{"NT_STATUS_TRANSACTION_NO_RELEASE",
 | 
				
			||||||
 | 
						 NT_STATUS_TRANSACTION_NO_RELEASE},
 | 
				
			||||||
 | 
						{"NT_STATUS_TRANSACTION_NO_MATCH", NT_STATUS_TRANSACTION_NO_MATCH},
 | 
				
			||||||
 | 
						{"NT_STATUS_TRANSACTION_RESPONDED",
 | 
				
			||||||
 | 
						 NT_STATUS_TRANSACTION_RESPONDED},
 | 
				
			||||||
 | 
						{"NT_STATUS_TRANSACTION_INVALID_ID",
 | 
				
			||||||
 | 
						 NT_STATUS_TRANSACTION_INVALID_ID},
 | 
				
			||||||
 | 
						{"NT_STATUS_TRANSACTION_INVALID_TYPE",
 | 
				
			||||||
 | 
						 NT_STATUS_TRANSACTION_INVALID_TYPE},
 | 
				
			||||||
 | 
						{"NT_STATUS_NOT_SERVER_SESSION", NT_STATUS_NOT_SERVER_SESSION},
 | 
				
			||||||
 | 
						{"NT_STATUS_NOT_CLIENT_SESSION", NT_STATUS_NOT_CLIENT_SESSION},
 | 
				
			||||||
 | 
						{"NT_STATUS_CANNOT_LOAD_REGISTRY_FILE",
 | 
				
			||||||
 | 
						 NT_STATUS_CANNOT_LOAD_REGISTRY_FILE},
 | 
				
			||||||
 | 
						{"NT_STATUS_DEBUG_ATTACH_FAILED", NT_STATUS_DEBUG_ATTACH_FAILED},
 | 
				
			||||||
 | 
						{"NT_STATUS_SYSTEM_PROCESS_TERMINATED",
 | 
				
			||||||
 | 
						 NT_STATUS_SYSTEM_PROCESS_TERMINATED},
 | 
				
			||||||
 | 
						{"NT_STATUS_DATA_NOT_ACCEPTED", NT_STATUS_DATA_NOT_ACCEPTED},
 | 
				
			||||||
 | 
						{"NT_STATUS_NO_BROWSER_SERVERS_FOUND",
 | 
				
			||||||
 | 
						 NT_STATUS_NO_BROWSER_SERVERS_FOUND},
 | 
				
			||||||
 | 
						{"NT_STATUS_VDM_HARD_ERROR", NT_STATUS_VDM_HARD_ERROR},
 | 
				
			||||||
 | 
						{"NT_STATUS_DRIVER_CANCEL_TIMEOUT",
 | 
				
			||||||
 | 
						 NT_STATUS_DRIVER_CANCEL_TIMEOUT},
 | 
				
			||||||
 | 
						{"NT_STATUS_REPLY_MESSAGE_MISMATCH",
 | 
				
			||||||
 | 
						 NT_STATUS_REPLY_MESSAGE_MISMATCH},
 | 
				
			||||||
 | 
						{"NT_STATUS_MAPPED_ALIGNMENT", NT_STATUS_MAPPED_ALIGNMENT},
 | 
				
			||||||
 | 
						{"NT_STATUS_IMAGE_CHECKSUM_MISMATCH",
 | 
				
			||||||
 | 
						 NT_STATUS_IMAGE_CHECKSUM_MISMATCH},
 | 
				
			||||||
 | 
						{"NT_STATUS_LOST_WRITEBEHIND_DATA",
 | 
				
			||||||
 | 
						 NT_STATUS_LOST_WRITEBEHIND_DATA},
 | 
				
			||||||
 | 
						{"NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID",
 | 
				
			||||||
 | 
						 NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID},
 | 
				
			||||||
 | 
						{"NT_STATUS_PASSWORD_MUST_CHANGE", NT_STATUS_PASSWORD_MUST_CHANGE},
 | 
				
			||||||
 | 
						{"NT_STATUS_NOT_FOUND", NT_STATUS_NOT_FOUND},
 | 
				
			||||||
 | 
						{"NT_STATUS_NOT_TINY_STREAM", NT_STATUS_NOT_TINY_STREAM},
 | 
				
			||||||
 | 
						{"NT_STATUS_RECOVERY_FAILURE", NT_STATUS_RECOVERY_FAILURE},
 | 
				
			||||||
 | 
						{"NT_STATUS_STACK_OVERFLOW_READ", NT_STATUS_STACK_OVERFLOW_READ},
 | 
				
			||||||
 | 
						{"NT_STATUS_FAIL_CHECK", NT_STATUS_FAIL_CHECK},
 | 
				
			||||||
 | 
						{"NT_STATUS_DUPLICATE_OBJECTID", NT_STATUS_DUPLICATE_OBJECTID},
 | 
				
			||||||
 | 
						{"NT_STATUS_OBJECTID_EXISTS", NT_STATUS_OBJECTID_EXISTS},
 | 
				
			||||||
 | 
						{"NT_STATUS_CONVERT_TO_LARGE", NT_STATUS_CONVERT_TO_LARGE},
 | 
				
			||||||
 | 
						{"NT_STATUS_RETRY", NT_STATUS_RETRY},
 | 
				
			||||||
 | 
						{"NT_STATUS_FOUND_OUT_OF_SCOPE", NT_STATUS_FOUND_OUT_OF_SCOPE},
 | 
				
			||||||
 | 
						{"NT_STATUS_ALLOCATE_BUCKET", NT_STATUS_ALLOCATE_BUCKET},
 | 
				
			||||||
 | 
						{"NT_STATUS_PROPSET_NOT_FOUND", NT_STATUS_PROPSET_NOT_FOUND},
 | 
				
			||||||
 | 
						{"NT_STATUS_MARSHALL_OVERFLOW", NT_STATUS_MARSHALL_OVERFLOW},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_VARIANT", NT_STATUS_INVALID_VARIANT},
 | 
				
			||||||
 | 
						{"NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND",
 | 
				
			||||||
 | 
						 NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND},
 | 
				
			||||||
 | 
						{"NT_STATUS_ACCOUNT_LOCKED_OUT", NT_STATUS_ACCOUNT_LOCKED_OUT},
 | 
				
			||||||
 | 
						{"NT_STATUS_HANDLE_NOT_CLOSABLE", NT_STATUS_HANDLE_NOT_CLOSABLE},
 | 
				
			||||||
 | 
						{"NT_STATUS_CONNECTION_REFUSED", NT_STATUS_CONNECTION_REFUSED},
 | 
				
			||||||
 | 
						{"NT_STATUS_GRACEFUL_DISCONNECT", NT_STATUS_GRACEFUL_DISCONNECT},
 | 
				
			||||||
 | 
						{"NT_STATUS_ADDRESS_ALREADY_ASSOCIATED",
 | 
				
			||||||
 | 
						 NT_STATUS_ADDRESS_ALREADY_ASSOCIATED},
 | 
				
			||||||
 | 
						{"NT_STATUS_ADDRESS_NOT_ASSOCIATED",
 | 
				
			||||||
 | 
						 NT_STATUS_ADDRESS_NOT_ASSOCIATED},
 | 
				
			||||||
 | 
						{"NT_STATUS_CONNECTION_INVALID", NT_STATUS_CONNECTION_INVALID},
 | 
				
			||||||
 | 
						{"NT_STATUS_CONNECTION_ACTIVE", NT_STATUS_CONNECTION_ACTIVE},
 | 
				
			||||||
 | 
						{"NT_STATUS_NETWORK_UNREACHABLE", NT_STATUS_NETWORK_UNREACHABLE},
 | 
				
			||||||
 | 
						{"NT_STATUS_HOST_UNREACHABLE", NT_STATUS_HOST_UNREACHABLE},
 | 
				
			||||||
 | 
						{"NT_STATUS_PROTOCOL_UNREACHABLE", NT_STATUS_PROTOCOL_UNREACHABLE},
 | 
				
			||||||
 | 
						{"NT_STATUS_PORT_UNREACHABLE", NT_STATUS_PORT_UNREACHABLE},
 | 
				
			||||||
 | 
						{"NT_STATUS_REQUEST_ABORTED", NT_STATUS_REQUEST_ABORTED},
 | 
				
			||||||
 | 
						{"NT_STATUS_CONNECTION_ABORTED", NT_STATUS_CONNECTION_ABORTED},
 | 
				
			||||||
 | 
						{"NT_STATUS_BAD_COMPRESSION_BUFFER",
 | 
				
			||||||
 | 
						 NT_STATUS_BAD_COMPRESSION_BUFFER},
 | 
				
			||||||
 | 
						{"NT_STATUS_USER_MAPPED_FILE", NT_STATUS_USER_MAPPED_FILE},
 | 
				
			||||||
 | 
						{"NT_STATUS_AUDIT_FAILED", NT_STATUS_AUDIT_FAILED},
 | 
				
			||||||
 | 
						{"NT_STATUS_TIMER_RESOLUTION_NOT_SET",
 | 
				
			||||||
 | 
						 NT_STATUS_TIMER_RESOLUTION_NOT_SET},
 | 
				
			||||||
 | 
						{"NT_STATUS_CONNECTION_COUNT_LIMIT",
 | 
				
			||||||
 | 
						 NT_STATUS_CONNECTION_COUNT_LIMIT},
 | 
				
			||||||
 | 
						{"NT_STATUS_LOGIN_TIME_RESTRICTION",
 | 
				
			||||||
 | 
						 NT_STATUS_LOGIN_TIME_RESTRICTION},
 | 
				
			||||||
 | 
						{"NT_STATUS_LOGIN_WKSTA_RESTRICTION",
 | 
				
			||||||
 | 
						 NT_STATUS_LOGIN_WKSTA_RESTRICTION},
 | 
				
			||||||
 | 
						{"NT_STATUS_IMAGE_MP_UP_MISMATCH", NT_STATUS_IMAGE_MP_UP_MISMATCH},
 | 
				
			||||||
 | 
						{"NT_STATUS_INSUFFICIENT_LOGON_INFO",
 | 
				
			||||||
 | 
						 NT_STATUS_INSUFFICIENT_LOGON_INFO},
 | 
				
			||||||
 | 
						{"NT_STATUS_BAD_DLL_ENTRYPOINT", NT_STATUS_BAD_DLL_ENTRYPOINT},
 | 
				
			||||||
 | 
						{"NT_STATUS_BAD_SERVICE_ENTRYPOINT",
 | 
				
			||||||
 | 
						 NT_STATUS_BAD_SERVICE_ENTRYPOINT},
 | 
				
			||||||
 | 
						{"NT_STATUS_LPC_REPLY_LOST", NT_STATUS_LPC_REPLY_LOST},
 | 
				
			||||||
 | 
						{"NT_STATUS_IP_ADDRESS_CONFLICT1", NT_STATUS_IP_ADDRESS_CONFLICT1},
 | 
				
			||||||
 | 
						{"NT_STATUS_IP_ADDRESS_CONFLICT2", NT_STATUS_IP_ADDRESS_CONFLICT2},
 | 
				
			||||||
 | 
						{"NT_STATUS_REGISTRY_QUOTA_LIMIT", NT_STATUS_REGISTRY_QUOTA_LIMIT},
 | 
				
			||||||
 | 
						{"NT_STATUS_PATH_NOT_COVERED", NT_STATUS_PATH_NOT_COVERED},
 | 
				
			||||||
 | 
						{"NT_STATUS_NO_CALLBACK_ACTIVE", NT_STATUS_NO_CALLBACK_ACTIVE},
 | 
				
			||||||
 | 
						{"NT_STATUS_LICENSE_QUOTA_EXCEEDED",
 | 
				
			||||||
 | 
						 NT_STATUS_LICENSE_QUOTA_EXCEEDED},
 | 
				
			||||||
 | 
						{"NT_STATUS_PWD_TOO_SHORT", NT_STATUS_PWD_TOO_SHORT},
 | 
				
			||||||
 | 
						{"NT_STATUS_PWD_TOO_RECENT", NT_STATUS_PWD_TOO_RECENT},
 | 
				
			||||||
 | 
						{"NT_STATUS_PWD_HISTORY_CONFLICT", NT_STATUS_PWD_HISTORY_CONFLICT},
 | 
				
			||||||
 | 
						{"NT_STATUS_PLUGPLAY_NO_DEVICE", NT_STATUS_PLUGPLAY_NO_DEVICE},
 | 
				
			||||||
 | 
						{"NT_STATUS_UNSUPPORTED_COMPRESSION",
 | 
				
			||||||
 | 
						 NT_STATUS_UNSUPPORTED_COMPRESSION},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_HW_PROFILE", NT_STATUS_INVALID_HW_PROFILE},
 | 
				
			||||||
 | 
						{"NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH",
 | 
				
			||||||
 | 
						 NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH},
 | 
				
			||||||
 | 
						{"NT_STATUS_DRIVER_ORDINAL_NOT_FOUND",
 | 
				
			||||||
 | 
						 NT_STATUS_DRIVER_ORDINAL_NOT_FOUND},
 | 
				
			||||||
 | 
						{"NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND",
 | 
				
			||||||
 | 
						 NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND},
 | 
				
			||||||
 | 
						{"NT_STATUS_RESOURCE_NOT_OWNED", NT_STATUS_RESOURCE_NOT_OWNED},
 | 
				
			||||||
 | 
						{"NT_STATUS_TOO_MANY_LINKS", NT_STATUS_TOO_MANY_LINKS},
 | 
				
			||||||
 | 
						{"NT_STATUS_QUOTA_LIST_INCONSISTENT",
 | 
				
			||||||
 | 
						 NT_STATUS_QUOTA_LIST_INCONSISTENT},
 | 
				
			||||||
 | 
						{"NT_STATUS_FILE_IS_OFFLINE", NT_STATUS_FILE_IS_OFFLINE},
 | 
				
			||||||
 | 
						{"NT_STATUS_NO_MORE_ENTRIES", NT_STATUS_NO_MORE_ENTRIES},
 | 
				
			||||||
 | 
						{"NT_STATUS_MORE_ENTRIES", NT_STATUS_MORE_ENTRIES},
 | 
				
			||||||
 | 
						{"NT_STATUS_SOME_UNMAPPED", NT_STATUS_SOME_UNMAPPED},
 | 
				
			||||||
 | 
						{NULL, 0}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										552
									
								
								fs/cifsd/nterr.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										552
									
								
								fs/cifsd/nterr.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,552 @@
 | 
				
			||||||
 | 
					/* SPDX-License-Identifier: GPL-2.0-or-later */
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Unix SMB/Netbios implementation.
 | 
				
			||||||
 | 
					 * Version 1.9.
 | 
				
			||||||
 | 
					 * NT error code constants
 | 
				
			||||||
 | 
					 * Copyright (C) Andrew Tridgell              1992-2000
 | 
				
			||||||
 | 
					 * Copyright (C) John H Terpstra              1996-2000
 | 
				
			||||||
 | 
					 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000
 | 
				
			||||||
 | 
					 * Copyright (C) Paul Ashton                  1998-2000
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef _NTERR_H
 | 
				
			||||||
 | 
					#define _NTERR_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct nt_err_code_struct {
 | 
				
			||||||
 | 
						char *nt_errstr;
 | 
				
			||||||
 | 
						__u32 nt_errcode;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern const struct nt_err_code_struct nt_errs[];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Win32 Status codes. */
 | 
				
			||||||
 | 
					#define NT_STATUS_MORE_ENTRIES         0x0105
 | 
				
			||||||
 | 
					#define NT_ERROR_INVALID_PARAMETER     0x0057
 | 
				
			||||||
 | 
					#define NT_ERROR_INSUFFICIENT_BUFFER   0x007a
 | 
				
			||||||
 | 
					#define NT_STATUS_1804                 0x070c
 | 
				
			||||||
 | 
					#define NT_STATUS_NOTIFY_ENUM_DIR      0x010c
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_LOCK_RANGE   (0xC0000000 | 0x01a1)
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Win32 Error codes extracted using a loop in smbclient then printing a netmon
 | 
				
			||||||
 | 
					 * sniff to a file.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NT_STATUS_OK                   0x0000
 | 
				
			||||||
 | 
					#define NT_STATUS_SOME_UNMAPPED        0x0107
 | 
				
			||||||
 | 
					#define NT_STATUS_BUFFER_OVERFLOW  0x80000005
 | 
				
			||||||
 | 
					#define NT_STATUS_NO_MORE_ENTRIES  0x8000001a
 | 
				
			||||||
 | 
					#define NT_STATUS_MEDIA_CHANGED    0x8000001c
 | 
				
			||||||
 | 
					#define NT_STATUS_END_OF_MEDIA     0x8000001e
 | 
				
			||||||
 | 
					#define NT_STATUS_MEDIA_CHECK      0x80000020
 | 
				
			||||||
 | 
					#define NT_STATUS_NO_DATA_DETECTED 0x8000001c
 | 
				
			||||||
 | 
					#define NT_STATUS_STOPPED_ON_SYMLINK 0x8000002d
 | 
				
			||||||
 | 
					#define NT_STATUS_DEVICE_REQUIRES_CLEANING 0x80000288
 | 
				
			||||||
 | 
					#define NT_STATUS_DEVICE_DOOR_OPEN 0x80000288
 | 
				
			||||||
 | 
					#define NT_STATUS_UNSUCCESSFUL (0xC0000000 | 0x0001)
 | 
				
			||||||
 | 
					#define NT_STATUS_NOT_IMPLEMENTED (0xC0000000 | 0x0002)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_INFO_CLASS (0xC0000000 | 0x0003)
 | 
				
			||||||
 | 
					#define NT_STATUS_INFO_LENGTH_MISMATCH (0xC0000000 | 0x0004)
 | 
				
			||||||
 | 
					#define NT_STATUS_ACCESS_VIOLATION (0xC0000000 | 0x0005)
 | 
				
			||||||
 | 
					#define NT_STATUS_IN_PAGE_ERROR (0xC0000000 | 0x0006)
 | 
				
			||||||
 | 
					#define NT_STATUS_PAGEFILE_QUOTA (0xC0000000 | 0x0007)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_HANDLE (0xC0000000 | 0x0008)
 | 
				
			||||||
 | 
					#define NT_STATUS_BAD_INITIAL_STACK (0xC0000000 | 0x0009)
 | 
				
			||||||
 | 
					#define NT_STATUS_BAD_INITIAL_PC (0xC0000000 | 0x000a)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_CID (0xC0000000 | 0x000b)
 | 
				
			||||||
 | 
					#define NT_STATUS_TIMER_NOT_CANCELED (0xC0000000 | 0x000c)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_PARAMETER (0xC0000000 | 0x000d)
 | 
				
			||||||
 | 
					#define NT_STATUS_NO_SUCH_DEVICE (0xC0000000 | 0x000e)
 | 
				
			||||||
 | 
					#define NT_STATUS_NO_SUCH_FILE (0xC0000000 | 0x000f)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_DEVICE_REQUEST (0xC0000000 | 0x0010)
 | 
				
			||||||
 | 
					#define NT_STATUS_END_OF_FILE (0xC0000000 | 0x0011)
 | 
				
			||||||
 | 
					#define NT_STATUS_WRONG_VOLUME (0xC0000000 | 0x0012)
 | 
				
			||||||
 | 
					#define NT_STATUS_NO_MEDIA_IN_DEVICE (0xC0000000 | 0x0013)
 | 
				
			||||||
 | 
					#define NT_STATUS_UNRECOGNIZED_MEDIA (0xC0000000 | 0x0014)
 | 
				
			||||||
 | 
					#define NT_STATUS_NONEXISTENT_SECTOR (0xC0000000 | 0x0015)
 | 
				
			||||||
 | 
					#define NT_STATUS_MORE_PROCESSING_REQUIRED (0xC0000000 | 0x0016)
 | 
				
			||||||
 | 
					#define NT_STATUS_NO_MEMORY (0xC0000000 | 0x0017)
 | 
				
			||||||
 | 
					#define NT_STATUS_CONFLICTING_ADDRESSES (0xC0000000 | 0x0018)
 | 
				
			||||||
 | 
					#define NT_STATUS_NOT_MAPPED_VIEW (0xC0000000 | 0x0019)
 | 
				
			||||||
 | 
					#define NT_STATUS_UNABLE_TO_FREE_VM (0x80000000 | 0x001a)
 | 
				
			||||||
 | 
					#define NT_STATUS_UNABLE_TO_DELETE_SECTION (0xC0000000 | 0x001b)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_SYSTEM_SERVICE (0xC0000000 | 0x001c)
 | 
				
			||||||
 | 
					#define NT_STATUS_ILLEGAL_INSTRUCTION (0xC0000000 | 0x001d)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_LOCK_SEQUENCE (0xC0000000 | 0x001e)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_VIEW_SIZE (0xC0000000 | 0x001f)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_FILE_FOR_SECTION (0xC0000000 | 0x0020)
 | 
				
			||||||
 | 
					#define NT_STATUS_ALREADY_COMMITTED (0xC0000000 | 0x0021)
 | 
				
			||||||
 | 
					#define NT_STATUS_ACCESS_DENIED (0xC0000000 | 0x0022)
 | 
				
			||||||
 | 
					#define NT_STATUS_BUFFER_TOO_SMALL (0xC0000000 | 0x0023)
 | 
				
			||||||
 | 
					#define NT_STATUS_OBJECT_TYPE_MISMATCH (0xC0000000 | 0x0024)
 | 
				
			||||||
 | 
					#define NT_STATUS_NONCONTINUABLE_EXCEPTION (0xC0000000 | 0x0025)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_DISPOSITION (0xC0000000 | 0x0026)
 | 
				
			||||||
 | 
					#define NT_STATUS_UNWIND (0xC0000000 | 0x0027)
 | 
				
			||||||
 | 
					#define NT_STATUS_BAD_STACK (0xC0000000 | 0x0028)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_UNWIND_TARGET (0xC0000000 | 0x0029)
 | 
				
			||||||
 | 
					#define NT_STATUS_NOT_LOCKED (0xC0000000 | 0x002a)
 | 
				
			||||||
 | 
					#define NT_STATUS_PARITY_ERROR (0xC0000000 | 0x002b)
 | 
				
			||||||
 | 
					#define NT_STATUS_UNABLE_TO_DECOMMIT_VM (0xC0000000 | 0x002c)
 | 
				
			||||||
 | 
					#define NT_STATUS_NOT_COMMITTED (0xC0000000 | 0x002d)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_PORT_ATTRIBUTES (0xC0000000 | 0x002e)
 | 
				
			||||||
 | 
					#define NT_STATUS_PORT_MESSAGE_TOO_LONG (0xC0000000 | 0x002f)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_PARAMETER_MIX (0xC0000000 | 0x0030)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_QUOTA_LOWER (0xC0000000 | 0x0031)
 | 
				
			||||||
 | 
					#define NT_STATUS_DISK_CORRUPT_ERROR (0xC0000000 | 0x0032)
 | 
				
			||||||
 | 
					#define NT_STATUS_OBJECT_NAME_INVALID (0xC0000000 | 0x0033)
 | 
				
			||||||
 | 
					#define NT_STATUS_OBJECT_NAME_NOT_FOUND (0xC0000000 | 0x0034)
 | 
				
			||||||
 | 
					#define NT_STATUS_OBJECT_NAME_COLLISION (0xC0000000 | 0x0035)
 | 
				
			||||||
 | 
					#define NT_STATUS_HANDLE_NOT_WAITABLE (0xC0000000 | 0x0036)
 | 
				
			||||||
 | 
					#define NT_STATUS_PORT_DISCONNECTED (0xC0000000 | 0x0037)
 | 
				
			||||||
 | 
					#define NT_STATUS_DEVICE_ALREADY_ATTACHED (0xC0000000 | 0x0038)
 | 
				
			||||||
 | 
					#define NT_STATUS_OBJECT_PATH_INVALID (0xC0000000 | 0x0039)
 | 
				
			||||||
 | 
					#define NT_STATUS_OBJECT_PATH_NOT_FOUND (0xC0000000 | 0x003a)
 | 
				
			||||||
 | 
					#define NT_STATUS_OBJECT_PATH_SYNTAX_BAD (0xC0000000 | 0x003b)
 | 
				
			||||||
 | 
					#define NT_STATUS_DATA_OVERRUN (0xC0000000 | 0x003c)
 | 
				
			||||||
 | 
					#define NT_STATUS_DATA_LATE_ERROR (0xC0000000 | 0x003d)
 | 
				
			||||||
 | 
					#define NT_STATUS_DATA_ERROR (0xC0000000 | 0x003e)
 | 
				
			||||||
 | 
					#define NT_STATUS_CRC_ERROR (0xC0000000 | 0x003f)
 | 
				
			||||||
 | 
					#define NT_STATUS_SECTION_TOO_BIG (0xC0000000 | 0x0040)
 | 
				
			||||||
 | 
					#define NT_STATUS_PORT_CONNECTION_REFUSED (0xC0000000 | 0x0041)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_PORT_HANDLE (0xC0000000 | 0x0042)
 | 
				
			||||||
 | 
					#define NT_STATUS_SHARING_VIOLATION (0xC0000000 | 0x0043)
 | 
				
			||||||
 | 
					#define NT_STATUS_QUOTA_EXCEEDED (0xC0000000 | 0x0044)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_PAGE_PROTECTION (0xC0000000 | 0x0045)
 | 
				
			||||||
 | 
					#define NT_STATUS_MUTANT_NOT_OWNED (0xC0000000 | 0x0046)
 | 
				
			||||||
 | 
					#define NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED (0xC0000000 | 0x0047)
 | 
				
			||||||
 | 
					#define NT_STATUS_PORT_ALREADY_SET (0xC0000000 | 0x0048)
 | 
				
			||||||
 | 
					#define NT_STATUS_SECTION_NOT_IMAGE (0xC0000000 | 0x0049)
 | 
				
			||||||
 | 
					#define NT_STATUS_SUSPEND_COUNT_EXCEEDED (0xC0000000 | 0x004a)
 | 
				
			||||||
 | 
					#define NT_STATUS_THREAD_IS_TERMINATING (0xC0000000 | 0x004b)
 | 
				
			||||||
 | 
					#define NT_STATUS_BAD_WORKING_SET_LIMIT (0xC0000000 | 0x004c)
 | 
				
			||||||
 | 
					#define NT_STATUS_INCOMPATIBLE_FILE_MAP (0xC0000000 | 0x004d)
 | 
				
			||||||
 | 
					#define NT_STATUS_SECTION_PROTECTION (0xC0000000 | 0x004e)
 | 
				
			||||||
 | 
					#define NT_STATUS_EAS_NOT_SUPPORTED (0xC0000000 | 0x004f)
 | 
				
			||||||
 | 
					#define NT_STATUS_EA_TOO_LARGE (0xC0000000 | 0x0050)
 | 
				
			||||||
 | 
					#define NT_STATUS_NONEXISTENT_EA_ENTRY (0xC0000000 | 0x0051)
 | 
				
			||||||
 | 
					#define NT_STATUS_NO_EAS_ON_FILE (0xC0000000 | 0x0052)
 | 
				
			||||||
 | 
					#define NT_STATUS_EA_CORRUPT_ERROR (0xC0000000 | 0x0053)
 | 
				
			||||||
 | 
					#define NT_STATUS_FILE_LOCK_CONFLICT (0xC0000000 | 0x0054)
 | 
				
			||||||
 | 
					#define NT_STATUS_LOCK_NOT_GRANTED (0xC0000000 | 0x0055)
 | 
				
			||||||
 | 
					#define NT_STATUS_DELETE_PENDING (0xC0000000 | 0x0056)
 | 
				
			||||||
 | 
					#define NT_STATUS_CTL_FILE_NOT_SUPPORTED (0xC0000000 | 0x0057)
 | 
				
			||||||
 | 
					#define NT_STATUS_UNKNOWN_REVISION (0xC0000000 | 0x0058)
 | 
				
			||||||
 | 
					#define NT_STATUS_REVISION_MISMATCH (0xC0000000 | 0x0059)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_OWNER (0xC0000000 | 0x005a)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_PRIMARY_GROUP (0xC0000000 | 0x005b)
 | 
				
			||||||
 | 
					#define NT_STATUS_NO_IMPERSONATION_TOKEN (0xC0000000 | 0x005c)
 | 
				
			||||||
 | 
					#define NT_STATUS_CANT_DISABLE_MANDATORY (0xC0000000 | 0x005d)
 | 
				
			||||||
 | 
					#define NT_STATUS_NO_LOGON_SERVERS (0xC0000000 | 0x005e)
 | 
				
			||||||
 | 
					#define NT_STATUS_NO_SUCH_LOGON_SESSION (0xC0000000 | 0x005f)
 | 
				
			||||||
 | 
					#define NT_STATUS_NO_SUCH_PRIVILEGE (0xC0000000 | 0x0060)
 | 
				
			||||||
 | 
					#define NT_STATUS_PRIVILEGE_NOT_HELD (0xC0000000 | 0x0061)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_ACCOUNT_NAME (0xC0000000 | 0x0062)
 | 
				
			||||||
 | 
					#define NT_STATUS_USER_EXISTS (0xC0000000 | 0x0063)
 | 
				
			||||||
 | 
					#define NT_STATUS_NO_SUCH_USER (0xC0000000 | 0x0064)
 | 
				
			||||||
 | 
					#define NT_STATUS_GROUP_EXISTS (0xC0000000 | 0x0065)
 | 
				
			||||||
 | 
					#define NT_STATUS_NO_SUCH_GROUP (0xC0000000 | 0x0066)
 | 
				
			||||||
 | 
					#define NT_STATUS_MEMBER_IN_GROUP (0xC0000000 | 0x0067)
 | 
				
			||||||
 | 
					#define NT_STATUS_MEMBER_NOT_IN_GROUP (0xC0000000 | 0x0068)
 | 
				
			||||||
 | 
					#define NT_STATUS_LAST_ADMIN (0xC0000000 | 0x0069)
 | 
				
			||||||
 | 
					#define NT_STATUS_WRONG_PASSWORD (0xC0000000 | 0x006a)
 | 
				
			||||||
 | 
					#define NT_STATUS_ILL_FORMED_PASSWORD (0xC0000000 | 0x006b)
 | 
				
			||||||
 | 
					#define NT_STATUS_PASSWORD_RESTRICTION (0xC0000000 | 0x006c)
 | 
				
			||||||
 | 
					#define NT_STATUS_LOGON_FAILURE (0xC0000000 | 0x006d)
 | 
				
			||||||
 | 
					#define NT_STATUS_ACCOUNT_RESTRICTION (0xC0000000 | 0x006e)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_LOGON_HOURS (0xC0000000 | 0x006f)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_WORKSTATION (0xC0000000 | 0x0070)
 | 
				
			||||||
 | 
					#define NT_STATUS_PASSWORD_EXPIRED (0xC0000000 | 0x0071)
 | 
				
			||||||
 | 
					#define NT_STATUS_ACCOUNT_DISABLED (0xC0000000 | 0x0072)
 | 
				
			||||||
 | 
					#define NT_STATUS_NONE_MAPPED (0xC0000000 | 0x0073)
 | 
				
			||||||
 | 
					#define NT_STATUS_TOO_MANY_LUIDS_REQUESTED (0xC0000000 | 0x0074)
 | 
				
			||||||
 | 
					#define NT_STATUS_LUIDS_EXHAUSTED (0xC0000000 | 0x0075)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_SUB_AUTHORITY (0xC0000000 | 0x0076)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_ACL (0xC0000000 | 0x0077)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_SID (0xC0000000 | 0x0078)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_SECURITY_DESCR (0xC0000000 | 0x0079)
 | 
				
			||||||
 | 
					#define NT_STATUS_PROCEDURE_NOT_FOUND (0xC0000000 | 0x007a)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_IMAGE_FORMAT (0xC0000000 | 0x007b)
 | 
				
			||||||
 | 
					#define NT_STATUS_NO_TOKEN (0xC0000000 | 0x007c)
 | 
				
			||||||
 | 
					#define NT_STATUS_BAD_INHERITANCE_ACL (0xC0000000 | 0x007d)
 | 
				
			||||||
 | 
					#define NT_STATUS_RANGE_NOT_LOCKED (0xC0000000 | 0x007e)
 | 
				
			||||||
 | 
					#define NT_STATUS_DISK_FULL (0xC0000000 | 0x007f)
 | 
				
			||||||
 | 
					#define NT_STATUS_SERVER_DISABLED (0xC0000000 | 0x0080)
 | 
				
			||||||
 | 
					#define NT_STATUS_SERVER_NOT_DISABLED (0xC0000000 | 0x0081)
 | 
				
			||||||
 | 
					#define NT_STATUS_TOO_MANY_GUIDS_REQUESTED (0xC0000000 | 0x0082)
 | 
				
			||||||
 | 
					#define NT_STATUS_GUIDS_EXHAUSTED (0xC0000000 | 0x0083)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_ID_AUTHORITY (0xC0000000 | 0x0084)
 | 
				
			||||||
 | 
					#define NT_STATUS_AGENTS_EXHAUSTED (0xC0000000 | 0x0085)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_VOLUME_LABEL (0xC0000000 | 0x0086)
 | 
				
			||||||
 | 
					#define NT_STATUS_SECTION_NOT_EXTENDED (0xC0000000 | 0x0087)
 | 
				
			||||||
 | 
					#define NT_STATUS_NOT_MAPPED_DATA (0xC0000000 | 0x0088)
 | 
				
			||||||
 | 
					#define NT_STATUS_RESOURCE_DATA_NOT_FOUND (0xC0000000 | 0x0089)
 | 
				
			||||||
 | 
					#define NT_STATUS_RESOURCE_TYPE_NOT_FOUND (0xC0000000 | 0x008a)
 | 
				
			||||||
 | 
					#define NT_STATUS_RESOURCE_NAME_NOT_FOUND (0xC0000000 | 0x008b)
 | 
				
			||||||
 | 
					#define NT_STATUS_ARRAY_BOUNDS_EXCEEDED (0xC0000000 | 0x008c)
 | 
				
			||||||
 | 
					#define NT_STATUS_FLOAT_DENORMAL_OPERAND (0xC0000000 | 0x008d)
 | 
				
			||||||
 | 
					#define NT_STATUS_FLOAT_DIVIDE_BY_ZERO (0xC0000000 | 0x008e)
 | 
				
			||||||
 | 
					#define NT_STATUS_FLOAT_INEXACT_RESULT (0xC0000000 | 0x008f)
 | 
				
			||||||
 | 
					#define NT_STATUS_FLOAT_INVALID_OPERATION (0xC0000000 | 0x0090)
 | 
				
			||||||
 | 
					#define NT_STATUS_FLOAT_OVERFLOW (0xC0000000 | 0x0091)
 | 
				
			||||||
 | 
					#define NT_STATUS_FLOAT_STACK_CHECK (0xC0000000 | 0x0092)
 | 
				
			||||||
 | 
					#define NT_STATUS_FLOAT_UNDERFLOW (0xC0000000 | 0x0093)
 | 
				
			||||||
 | 
					#define NT_STATUS_INTEGER_DIVIDE_BY_ZERO (0xC0000000 | 0x0094)
 | 
				
			||||||
 | 
					#define NT_STATUS_INTEGER_OVERFLOW (0xC0000000 | 0x0095)
 | 
				
			||||||
 | 
					#define NT_STATUS_PRIVILEGED_INSTRUCTION (0xC0000000 | 0x0096)
 | 
				
			||||||
 | 
					#define NT_STATUS_TOO_MANY_PAGING_FILES (0xC0000000 | 0x0097)
 | 
				
			||||||
 | 
					#define NT_STATUS_FILE_INVALID (0xC0000000 | 0x0098)
 | 
				
			||||||
 | 
					#define NT_STATUS_ALLOTTED_SPACE_EXCEEDED (0xC0000000 | 0x0099)
 | 
				
			||||||
 | 
					#define NT_STATUS_INSUFFICIENT_RESOURCES (0xC0000000 | 0x009a)
 | 
				
			||||||
 | 
					#define NT_STATUS_DFS_EXIT_PATH_FOUND (0xC0000000 | 0x009b)
 | 
				
			||||||
 | 
					#define NT_STATUS_DEVICE_DATA_ERROR (0xC0000000 | 0x009c)
 | 
				
			||||||
 | 
					#define NT_STATUS_DEVICE_NOT_CONNECTED (0xC0000000 | 0x009d)
 | 
				
			||||||
 | 
					#define NT_STATUS_DEVICE_POWER_FAILURE (0xC0000000 | 0x009e)
 | 
				
			||||||
 | 
					#define NT_STATUS_FREE_VM_NOT_AT_BASE (0xC0000000 | 0x009f)
 | 
				
			||||||
 | 
					#define NT_STATUS_MEMORY_NOT_ALLOCATED (0xC0000000 | 0x00a0)
 | 
				
			||||||
 | 
					#define NT_STATUS_WORKING_SET_QUOTA (0xC0000000 | 0x00a1)
 | 
				
			||||||
 | 
					#define NT_STATUS_MEDIA_WRITE_PROTECTED (0xC0000000 | 0x00a2)
 | 
				
			||||||
 | 
					#define NT_STATUS_DEVICE_NOT_READY (0xC0000000 | 0x00a3)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_GROUP_ATTRIBUTES (0xC0000000 | 0x00a4)
 | 
				
			||||||
 | 
					#define NT_STATUS_BAD_IMPERSONATION_LEVEL (0xC0000000 | 0x00a5)
 | 
				
			||||||
 | 
					#define NT_STATUS_CANT_OPEN_ANONYMOUS (0xC0000000 | 0x00a6)
 | 
				
			||||||
 | 
					#define NT_STATUS_BAD_VALIDATION_CLASS (0xC0000000 | 0x00a7)
 | 
				
			||||||
 | 
					#define NT_STATUS_BAD_TOKEN_TYPE (0xC0000000 | 0x00a8)
 | 
				
			||||||
 | 
					#define NT_STATUS_BAD_MASTER_BOOT_RECORD (0xC0000000 | 0x00a9)
 | 
				
			||||||
 | 
					#define NT_STATUS_INSTRUCTION_MISALIGNMENT (0xC0000000 | 0x00aa)
 | 
				
			||||||
 | 
					#define NT_STATUS_INSTANCE_NOT_AVAILABLE (0xC0000000 | 0x00ab)
 | 
				
			||||||
 | 
					#define NT_STATUS_PIPE_NOT_AVAILABLE (0xC0000000 | 0x00ac)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_PIPE_STATE (0xC0000000 | 0x00ad)
 | 
				
			||||||
 | 
					#define NT_STATUS_PIPE_BUSY (0xC0000000 | 0x00ae)
 | 
				
			||||||
 | 
					#define NT_STATUS_ILLEGAL_FUNCTION (0xC0000000 | 0x00af)
 | 
				
			||||||
 | 
					#define NT_STATUS_PIPE_DISCONNECTED (0xC0000000 | 0x00b0)
 | 
				
			||||||
 | 
					#define NT_STATUS_PIPE_CLOSING (0xC0000000 | 0x00b1)
 | 
				
			||||||
 | 
					#define NT_STATUS_PIPE_CONNECTED (0xC0000000 | 0x00b2)
 | 
				
			||||||
 | 
					#define NT_STATUS_PIPE_LISTENING (0xC0000000 | 0x00b3)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_READ_MODE (0xC0000000 | 0x00b4)
 | 
				
			||||||
 | 
					#define NT_STATUS_IO_TIMEOUT (0xC0000000 | 0x00b5)
 | 
				
			||||||
 | 
					#define NT_STATUS_FILE_FORCED_CLOSED (0xC0000000 | 0x00b6)
 | 
				
			||||||
 | 
					#define NT_STATUS_PROFILING_NOT_STARTED (0xC0000000 | 0x00b7)
 | 
				
			||||||
 | 
					#define NT_STATUS_PROFILING_NOT_STOPPED (0xC0000000 | 0x00b8)
 | 
				
			||||||
 | 
					#define NT_STATUS_COULD_NOT_INTERPRET (0xC0000000 | 0x00b9)
 | 
				
			||||||
 | 
					#define NT_STATUS_FILE_IS_A_DIRECTORY (0xC0000000 | 0x00ba)
 | 
				
			||||||
 | 
					#define NT_STATUS_NOT_SUPPORTED (0xC0000000 | 0x00bb)
 | 
				
			||||||
 | 
					#define NT_STATUS_REMOTE_NOT_LISTENING (0xC0000000 | 0x00bc)
 | 
				
			||||||
 | 
					#define NT_STATUS_DUPLICATE_NAME (0xC0000000 | 0x00bd)
 | 
				
			||||||
 | 
					#define NT_STATUS_BAD_NETWORK_PATH (0xC0000000 | 0x00be)
 | 
				
			||||||
 | 
					#define NT_STATUS_NETWORK_BUSY (0xC0000000 | 0x00bf)
 | 
				
			||||||
 | 
					#define NT_STATUS_DEVICE_DOES_NOT_EXIST (0xC0000000 | 0x00c0)
 | 
				
			||||||
 | 
					#define NT_STATUS_TOO_MANY_COMMANDS (0xC0000000 | 0x00c1)
 | 
				
			||||||
 | 
					#define NT_STATUS_ADAPTER_HARDWARE_ERROR (0xC0000000 | 0x00c2)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_NETWORK_RESPONSE (0xC0000000 | 0x00c3)
 | 
				
			||||||
 | 
					#define NT_STATUS_UNEXPECTED_NETWORK_ERROR (0xC0000000 | 0x00c4)
 | 
				
			||||||
 | 
					#define NT_STATUS_BAD_REMOTE_ADAPTER (0xC0000000 | 0x00c5)
 | 
				
			||||||
 | 
					#define NT_STATUS_PRINT_QUEUE_FULL (0xC0000000 | 0x00c6)
 | 
				
			||||||
 | 
					#define NT_STATUS_NO_SPOOL_SPACE (0xC0000000 | 0x00c7)
 | 
				
			||||||
 | 
					#define NT_STATUS_PRINT_CANCELLED (0xC0000000 | 0x00c8)
 | 
				
			||||||
 | 
					#define NT_STATUS_NETWORK_NAME_DELETED (0xC0000000 | 0x00c9)
 | 
				
			||||||
 | 
					#define NT_STATUS_NETWORK_ACCESS_DENIED (0xC0000000 | 0x00ca)
 | 
				
			||||||
 | 
					#define NT_STATUS_BAD_DEVICE_TYPE (0xC0000000 | 0x00cb)
 | 
				
			||||||
 | 
					#define NT_STATUS_BAD_NETWORK_NAME (0xC0000000 | 0x00cc)
 | 
				
			||||||
 | 
					#define NT_STATUS_TOO_MANY_NAMES (0xC0000000 | 0x00cd)
 | 
				
			||||||
 | 
					#define NT_STATUS_TOO_MANY_SESSIONS (0xC0000000 | 0x00ce)
 | 
				
			||||||
 | 
					#define NT_STATUS_SHARING_PAUSED (0xC0000000 | 0x00cf)
 | 
				
			||||||
 | 
					#define NT_STATUS_REQUEST_NOT_ACCEPTED (0xC0000000 | 0x00d0)
 | 
				
			||||||
 | 
					#define NT_STATUS_REDIRECTOR_PAUSED (0xC0000000 | 0x00d1)
 | 
				
			||||||
 | 
					#define NT_STATUS_NET_WRITE_FAULT (0xC0000000 | 0x00d2)
 | 
				
			||||||
 | 
					#define NT_STATUS_PROFILING_AT_LIMIT (0xC0000000 | 0x00d3)
 | 
				
			||||||
 | 
					#define NT_STATUS_NOT_SAME_DEVICE (0xC0000000 | 0x00d4)
 | 
				
			||||||
 | 
					#define NT_STATUS_FILE_RENAMED (0xC0000000 | 0x00d5)
 | 
				
			||||||
 | 
					#define NT_STATUS_VIRTUAL_CIRCUIT_CLOSED (0xC0000000 | 0x00d6)
 | 
				
			||||||
 | 
					#define NT_STATUS_NO_SECURITY_ON_OBJECT (0xC0000000 | 0x00d7)
 | 
				
			||||||
 | 
					#define NT_STATUS_CANT_WAIT (0xC0000000 | 0x00d8)
 | 
				
			||||||
 | 
					#define NT_STATUS_PIPE_EMPTY (0xC0000000 | 0x00d9)
 | 
				
			||||||
 | 
					#define NT_STATUS_CANT_ACCESS_DOMAIN_INFO (0xC0000000 | 0x00da)
 | 
				
			||||||
 | 
					#define NT_STATUS_CANT_TERMINATE_SELF (0xC0000000 | 0x00db)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_SERVER_STATE (0xC0000000 | 0x00dc)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_DOMAIN_STATE (0xC0000000 | 0x00dd)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_DOMAIN_ROLE (0xC0000000 | 0x00de)
 | 
				
			||||||
 | 
					#define NT_STATUS_NO_SUCH_DOMAIN (0xC0000000 | 0x00df)
 | 
				
			||||||
 | 
					#define NT_STATUS_DOMAIN_EXISTS (0xC0000000 | 0x00e0)
 | 
				
			||||||
 | 
					#define NT_STATUS_DOMAIN_LIMIT_EXCEEDED (0xC0000000 | 0x00e1)
 | 
				
			||||||
 | 
					#define NT_STATUS_OPLOCK_NOT_GRANTED (0xC0000000 | 0x00e2)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_OPLOCK_PROTOCOL (0xC0000000 | 0x00e3)
 | 
				
			||||||
 | 
					#define NT_STATUS_INTERNAL_DB_CORRUPTION (0xC0000000 | 0x00e4)
 | 
				
			||||||
 | 
					#define NT_STATUS_INTERNAL_ERROR (0xC0000000 | 0x00e5)
 | 
				
			||||||
 | 
					#define NT_STATUS_GENERIC_NOT_MAPPED (0xC0000000 | 0x00e6)
 | 
				
			||||||
 | 
					#define NT_STATUS_BAD_DESCRIPTOR_FORMAT (0xC0000000 | 0x00e7)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_USER_BUFFER (0xC0000000 | 0x00e8)
 | 
				
			||||||
 | 
					#define NT_STATUS_UNEXPECTED_IO_ERROR (0xC0000000 | 0x00e9)
 | 
				
			||||||
 | 
					#define NT_STATUS_UNEXPECTED_MM_CREATE_ERR (0xC0000000 | 0x00ea)
 | 
				
			||||||
 | 
					#define NT_STATUS_UNEXPECTED_MM_MAP_ERROR (0xC0000000 | 0x00eb)
 | 
				
			||||||
 | 
					#define NT_STATUS_UNEXPECTED_MM_EXTEND_ERR (0xC0000000 | 0x00ec)
 | 
				
			||||||
 | 
					#define NT_STATUS_NOT_LOGON_PROCESS (0xC0000000 | 0x00ed)
 | 
				
			||||||
 | 
					#define NT_STATUS_LOGON_SESSION_EXISTS (0xC0000000 | 0x00ee)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_PARAMETER_1 (0xC0000000 | 0x00ef)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_PARAMETER_2 (0xC0000000 | 0x00f0)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_PARAMETER_3 (0xC0000000 | 0x00f1)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_PARAMETER_4 (0xC0000000 | 0x00f2)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_PARAMETER_5 (0xC0000000 | 0x00f3)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_PARAMETER_6 (0xC0000000 | 0x00f4)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_PARAMETER_7 (0xC0000000 | 0x00f5)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_PARAMETER_8 (0xC0000000 | 0x00f6)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_PARAMETER_9 (0xC0000000 | 0x00f7)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_PARAMETER_10 (0xC0000000 | 0x00f8)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_PARAMETER_11 (0xC0000000 | 0x00f9)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_PARAMETER_12 (0xC0000000 | 0x00fa)
 | 
				
			||||||
 | 
					#define NT_STATUS_REDIRECTOR_NOT_STARTED (0xC0000000 | 0x00fb)
 | 
				
			||||||
 | 
					#define NT_STATUS_REDIRECTOR_STARTED (0xC0000000 | 0x00fc)
 | 
				
			||||||
 | 
					#define NT_STATUS_STACK_OVERFLOW (0xC0000000 | 0x00fd)
 | 
				
			||||||
 | 
					#define NT_STATUS_NO_SUCH_PACKAGE (0xC0000000 | 0x00fe)
 | 
				
			||||||
 | 
					#define NT_STATUS_BAD_FUNCTION_TABLE (0xC0000000 | 0x00ff)
 | 
				
			||||||
 | 
					#define NT_STATUS_DIRECTORY_NOT_EMPTY (0xC0000000 | 0x0101)
 | 
				
			||||||
 | 
					#define NT_STATUS_FILE_CORRUPT_ERROR (0xC0000000 | 0x0102)
 | 
				
			||||||
 | 
					#define NT_STATUS_NOT_A_DIRECTORY (0xC0000000 | 0x0103)
 | 
				
			||||||
 | 
					#define NT_STATUS_BAD_LOGON_SESSION_STATE (0xC0000000 | 0x0104)
 | 
				
			||||||
 | 
					#define NT_STATUS_LOGON_SESSION_COLLISION (0xC0000000 | 0x0105)
 | 
				
			||||||
 | 
					#define NT_STATUS_NAME_TOO_LONG (0xC0000000 | 0x0106)
 | 
				
			||||||
 | 
					#define NT_STATUS_FILES_OPEN (0xC0000000 | 0x0107)
 | 
				
			||||||
 | 
					#define NT_STATUS_CONNECTION_IN_USE (0xC0000000 | 0x0108)
 | 
				
			||||||
 | 
					#define NT_STATUS_MESSAGE_NOT_FOUND (0xC0000000 | 0x0109)
 | 
				
			||||||
 | 
					#define NT_STATUS_PROCESS_IS_TERMINATING (0xC0000000 | 0x010a)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_LOGON_TYPE (0xC0000000 | 0x010b)
 | 
				
			||||||
 | 
					#define NT_STATUS_NO_GUID_TRANSLATION (0xC0000000 | 0x010c)
 | 
				
			||||||
 | 
					#define NT_STATUS_CANNOT_IMPERSONATE (0xC0000000 | 0x010d)
 | 
				
			||||||
 | 
					#define NT_STATUS_IMAGE_ALREADY_LOADED (0xC0000000 | 0x010e)
 | 
				
			||||||
 | 
					#define NT_STATUS_ABIOS_NOT_PRESENT (0xC0000000 | 0x010f)
 | 
				
			||||||
 | 
					#define NT_STATUS_ABIOS_LID_NOT_EXIST (0xC0000000 | 0x0110)
 | 
				
			||||||
 | 
					#define NT_STATUS_ABIOS_LID_ALREADY_OWNED (0xC0000000 | 0x0111)
 | 
				
			||||||
 | 
					#define NT_STATUS_ABIOS_NOT_LID_OWNER (0xC0000000 | 0x0112)
 | 
				
			||||||
 | 
					#define NT_STATUS_ABIOS_INVALID_COMMAND (0xC0000000 | 0x0113)
 | 
				
			||||||
 | 
					#define NT_STATUS_ABIOS_INVALID_LID (0xC0000000 | 0x0114)
 | 
				
			||||||
 | 
					#define NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE (0xC0000000 | 0x0115)
 | 
				
			||||||
 | 
					#define NT_STATUS_ABIOS_INVALID_SELECTOR (0xC0000000 | 0x0116)
 | 
				
			||||||
 | 
					#define NT_STATUS_NO_LDT (0xC0000000 | 0x0117)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_LDT_SIZE (0xC0000000 | 0x0118)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_LDT_OFFSET (0xC0000000 | 0x0119)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_LDT_DESCRIPTOR (0xC0000000 | 0x011a)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_IMAGE_NE_FORMAT (0xC0000000 | 0x011b)
 | 
				
			||||||
 | 
					#define NT_STATUS_RXACT_INVALID_STATE (0xC0000000 | 0x011c)
 | 
				
			||||||
 | 
					#define NT_STATUS_RXACT_COMMIT_FAILURE (0xC0000000 | 0x011d)
 | 
				
			||||||
 | 
					#define NT_STATUS_MAPPED_FILE_SIZE_ZERO (0xC0000000 | 0x011e)
 | 
				
			||||||
 | 
					#define NT_STATUS_TOO_MANY_OPENED_FILES (0xC0000000 | 0x011f)
 | 
				
			||||||
 | 
					#define NT_STATUS_CANCELLED (0xC0000000 | 0x0120)
 | 
				
			||||||
 | 
					#define NT_STATUS_CANNOT_DELETE (0xC0000000 | 0x0121)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_COMPUTER_NAME (0xC0000000 | 0x0122)
 | 
				
			||||||
 | 
					#define NT_STATUS_FILE_DELETED (0xC0000000 | 0x0123)
 | 
				
			||||||
 | 
					#define NT_STATUS_SPECIAL_ACCOUNT (0xC0000000 | 0x0124)
 | 
				
			||||||
 | 
					#define NT_STATUS_SPECIAL_GROUP (0xC0000000 | 0x0125)
 | 
				
			||||||
 | 
					#define NT_STATUS_SPECIAL_USER (0xC0000000 | 0x0126)
 | 
				
			||||||
 | 
					#define NT_STATUS_MEMBERS_PRIMARY_GROUP (0xC0000000 | 0x0127)
 | 
				
			||||||
 | 
					#define NT_STATUS_FILE_CLOSED (0xC0000000 | 0x0128)
 | 
				
			||||||
 | 
					#define NT_STATUS_TOO_MANY_THREADS (0xC0000000 | 0x0129)
 | 
				
			||||||
 | 
					#define NT_STATUS_THREAD_NOT_IN_PROCESS (0xC0000000 | 0x012a)
 | 
				
			||||||
 | 
					#define NT_STATUS_TOKEN_ALREADY_IN_USE (0xC0000000 | 0x012b)
 | 
				
			||||||
 | 
					#define NT_STATUS_PAGEFILE_QUOTA_EXCEEDED (0xC0000000 | 0x012c)
 | 
				
			||||||
 | 
					#define NT_STATUS_COMMITMENT_LIMIT (0xC0000000 | 0x012d)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_IMAGE_LE_FORMAT (0xC0000000 | 0x012e)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_IMAGE_NOT_MZ (0xC0000000 | 0x012f)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_IMAGE_PROTECT (0xC0000000 | 0x0130)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_IMAGE_WIN_16 (0xC0000000 | 0x0131)
 | 
				
			||||||
 | 
					#define NT_STATUS_LOGON_SERVER_CONFLICT (0xC0000000 | 0x0132)
 | 
				
			||||||
 | 
					#define NT_STATUS_TIME_DIFFERENCE_AT_DC (0xC0000000 | 0x0133)
 | 
				
			||||||
 | 
					#define NT_STATUS_SYNCHRONIZATION_REQUIRED (0xC0000000 | 0x0134)
 | 
				
			||||||
 | 
					#define NT_STATUS_DLL_NOT_FOUND (0xC0000000 | 0x0135)
 | 
				
			||||||
 | 
					#define NT_STATUS_OPEN_FAILED (0xC0000000 | 0x0136)
 | 
				
			||||||
 | 
					#define NT_STATUS_IO_PRIVILEGE_FAILED (0xC0000000 | 0x0137)
 | 
				
			||||||
 | 
					#define NT_STATUS_ORDINAL_NOT_FOUND (0xC0000000 | 0x0138)
 | 
				
			||||||
 | 
					#define NT_STATUS_ENTRYPOINT_NOT_FOUND (0xC0000000 | 0x0139)
 | 
				
			||||||
 | 
					#define NT_STATUS_CONTROL_C_EXIT (0xC0000000 | 0x013a)
 | 
				
			||||||
 | 
					#define NT_STATUS_LOCAL_DISCONNECT (0xC0000000 | 0x013b)
 | 
				
			||||||
 | 
					#define NT_STATUS_REMOTE_DISCONNECT (0xC0000000 | 0x013c)
 | 
				
			||||||
 | 
					#define NT_STATUS_REMOTE_RESOURCES (0xC0000000 | 0x013d)
 | 
				
			||||||
 | 
					#define NT_STATUS_LINK_FAILED (0xC0000000 | 0x013e)
 | 
				
			||||||
 | 
					#define NT_STATUS_LINK_TIMEOUT (0xC0000000 | 0x013f)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_CONNECTION (0xC0000000 | 0x0140)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_ADDRESS (0xC0000000 | 0x0141)
 | 
				
			||||||
 | 
					#define NT_STATUS_DLL_INIT_FAILED (0xC0000000 | 0x0142)
 | 
				
			||||||
 | 
					#define NT_STATUS_MISSING_SYSTEMFILE (0xC0000000 | 0x0143)
 | 
				
			||||||
 | 
					#define NT_STATUS_UNHANDLED_EXCEPTION (0xC0000000 | 0x0144)
 | 
				
			||||||
 | 
					#define NT_STATUS_APP_INIT_FAILURE (0xC0000000 | 0x0145)
 | 
				
			||||||
 | 
					#define NT_STATUS_PAGEFILE_CREATE_FAILED (0xC0000000 | 0x0146)
 | 
				
			||||||
 | 
					#define NT_STATUS_NO_PAGEFILE (0xC0000000 | 0x0147)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_LEVEL (0xC0000000 | 0x0148)
 | 
				
			||||||
 | 
					#define NT_STATUS_WRONG_PASSWORD_CORE (0xC0000000 | 0x0149)
 | 
				
			||||||
 | 
					#define NT_STATUS_ILLEGAL_FLOAT_CONTEXT (0xC0000000 | 0x014a)
 | 
				
			||||||
 | 
					#define NT_STATUS_PIPE_BROKEN (0xC0000000 | 0x014b)
 | 
				
			||||||
 | 
					#define NT_STATUS_REGISTRY_CORRUPT (0xC0000000 | 0x014c)
 | 
				
			||||||
 | 
					#define NT_STATUS_REGISTRY_IO_FAILED (0xC0000000 | 0x014d)
 | 
				
			||||||
 | 
					#define NT_STATUS_NO_EVENT_PAIR (0xC0000000 | 0x014e)
 | 
				
			||||||
 | 
					#define NT_STATUS_UNRECOGNIZED_VOLUME (0xC0000000 | 0x014f)
 | 
				
			||||||
 | 
					#define NT_STATUS_SERIAL_NO_DEVICE_INITED (0xC0000000 | 0x0150)
 | 
				
			||||||
 | 
					#define NT_STATUS_NO_SUCH_ALIAS (0xC0000000 | 0x0151)
 | 
				
			||||||
 | 
					#define NT_STATUS_MEMBER_NOT_IN_ALIAS (0xC0000000 | 0x0152)
 | 
				
			||||||
 | 
					#define NT_STATUS_MEMBER_IN_ALIAS (0xC0000000 | 0x0153)
 | 
				
			||||||
 | 
					#define NT_STATUS_ALIAS_EXISTS (0xC0000000 | 0x0154)
 | 
				
			||||||
 | 
					#define NT_STATUS_LOGON_NOT_GRANTED (0xC0000000 | 0x0155)
 | 
				
			||||||
 | 
					#define NT_STATUS_TOO_MANY_SECRETS (0xC0000000 | 0x0156)
 | 
				
			||||||
 | 
					#define NT_STATUS_SECRET_TOO_LONG (0xC0000000 | 0x0157)
 | 
				
			||||||
 | 
					#define NT_STATUS_INTERNAL_DB_ERROR (0xC0000000 | 0x0158)
 | 
				
			||||||
 | 
					#define NT_STATUS_FULLSCREEN_MODE (0xC0000000 | 0x0159)
 | 
				
			||||||
 | 
					#define NT_STATUS_TOO_MANY_CONTEXT_IDS (0xC0000000 | 0x015a)
 | 
				
			||||||
 | 
					#define NT_STATUS_LOGON_TYPE_NOT_GRANTED (0xC0000000 | 0x015b)
 | 
				
			||||||
 | 
					#define NT_STATUS_NOT_REGISTRY_FILE (0xC0000000 | 0x015c)
 | 
				
			||||||
 | 
					#define NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED (0xC0000000 | 0x015d)
 | 
				
			||||||
 | 
					#define NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR (0xC0000000 | 0x015e)
 | 
				
			||||||
 | 
					#define NT_STATUS_FT_MISSING_MEMBER (0xC0000000 | 0x015f)
 | 
				
			||||||
 | 
					#define NT_STATUS_ILL_FORMED_SERVICE_ENTRY (0xC0000000 | 0x0160)
 | 
				
			||||||
 | 
					#define NT_STATUS_ILLEGAL_CHARACTER (0xC0000000 | 0x0161)
 | 
				
			||||||
 | 
					#define NT_STATUS_UNMAPPABLE_CHARACTER (0xC0000000 | 0x0162)
 | 
				
			||||||
 | 
					#define NT_STATUS_UNDEFINED_CHARACTER (0xC0000000 | 0x0163)
 | 
				
			||||||
 | 
					#define NT_STATUS_FLOPPY_VOLUME (0xC0000000 | 0x0164)
 | 
				
			||||||
 | 
					#define NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND (0xC0000000 | 0x0165)
 | 
				
			||||||
 | 
					#define NT_STATUS_FLOPPY_WRONG_CYLINDER (0xC0000000 | 0x0166)
 | 
				
			||||||
 | 
					#define NT_STATUS_FLOPPY_UNKNOWN_ERROR (0xC0000000 | 0x0167)
 | 
				
			||||||
 | 
					#define NT_STATUS_FLOPPY_BAD_REGISTERS (0xC0000000 | 0x0168)
 | 
				
			||||||
 | 
					#define NT_STATUS_DISK_RECALIBRATE_FAILED (0xC0000000 | 0x0169)
 | 
				
			||||||
 | 
					#define NT_STATUS_DISK_OPERATION_FAILED (0xC0000000 | 0x016a)
 | 
				
			||||||
 | 
					#define NT_STATUS_DISK_RESET_FAILED (0xC0000000 | 0x016b)
 | 
				
			||||||
 | 
					#define NT_STATUS_SHARED_IRQ_BUSY (0xC0000000 | 0x016c)
 | 
				
			||||||
 | 
					#define NT_STATUS_FT_ORPHANING (0xC0000000 | 0x016d)
 | 
				
			||||||
 | 
					#define NT_STATUS_PARTITION_FAILURE (0xC0000000 | 0x0172)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_BLOCK_LENGTH (0xC0000000 | 0x0173)
 | 
				
			||||||
 | 
					#define NT_STATUS_DEVICE_NOT_PARTITIONED (0xC0000000 | 0x0174)
 | 
				
			||||||
 | 
					#define NT_STATUS_UNABLE_TO_LOCK_MEDIA (0xC0000000 | 0x0175)
 | 
				
			||||||
 | 
					#define NT_STATUS_UNABLE_TO_UNLOAD_MEDIA (0xC0000000 | 0x0176)
 | 
				
			||||||
 | 
					#define NT_STATUS_EOM_OVERFLOW (0xC0000000 | 0x0177)
 | 
				
			||||||
 | 
					#define NT_STATUS_NO_MEDIA (0xC0000000 | 0x0178)
 | 
				
			||||||
 | 
					#define NT_STATUS_NO_SUCH_MEMBER (0xC0000000 | 0x017a)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_MEMBER (0xC0000000 | 0x017b)
 | 
				
			||||||
 | 
					#define NT_STATUS_KEY_DELETED (0xC0000000 | 0x017c)
 | 
				
			||||||
 | 
					#define NT_STATUS_NO_LOG_SPACE (0xC0000000 | 0x017d)
 | 
				
			||||||
 | 
					#define NT_STATUS_TOO_MANY_SIDS (0xC0000000 | 0x017e)
 | 
				
			||||||
 | 
					#define NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED (0xC0000000 | 0x017f)
 | 
				
			||||||
 | 
					#define NT_STATUS_KEY_HAS_CHILDREN (0xC0000000 | 0x0180)
 | 
				
			||||||
 | 
					#define NT_STATUS_CHILD_MUST_BE_VOLATILE (0xC0000000 | 0x0181)
 | 
				
			||||||
 | 
					#define NT_STATUS_DEVICE_CONFIGURATION_ERROR (0xC0000000 | 0x0182)
 | 
				
			||||||
 | 
					#define NT_STATUS_DRIVER_INTERNAL_ERROR (0xC0000000 | 0x0183)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_DEVICE_STATE (0xC0000000 | 0x0184)
 | 
				
			||||||
 | 
					#define NT_STATUS_IO_DEVICE_ERROR (0xC0000000 | 0x0185)
 | 
				
			||||||
 | 
					#define NT_STATUS_DEVICE_PROTOCOL_ERROR (0xC0000000 | 0x0186)
 | 
				
			||||||
 | 
					#define NT_STATUS_BACKUP_CONTROLLER (0xC0000000 | 0x0187)
 | 
				
			||||||
 | 
					#define NT_STATUS_LOG_FILE_FULL (0xC0000000 | 0x0188)
 | 
				
			||||||
 | 
					#define NT_STATUS_TOO_LATE (0xC0000000 | 0x0189)
 | 
				
			||||||
 | 
					#define NT_STATUS_NO_TRUST_LSA_SECRET (0xC0000000 | 0x018a)
 | 
				
			||||||
 | 
					#define NT_STATUS_NO_TRUST_SAM_ACCOUNT (0xC0000000 | 0x018b)
 | 
				
			||||||
 | 
					#define NT_STATUS_TRUSTED_DOMAIN_FAILURE (0xC0000000 | 0x018c)
 | 
				
			||||||
 | 
					#define NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE (0xC0000000 | 0x018d)
 | 
				
			||||||
 | 
					#define NT_STATUS_EVENTLOG_FILE_CORRUPT (0xC0000000 | 0x018e)
 | 
				
			||||||
 | 
					#define NT_STATUS_EVENTLOG_CANT_START (0xC0000000 | 0x018f)
 | 
				
			||||||
 | 
					#define NT_STATUS_TRUST_FAILURE (0xC0000000 | 0x0190)
 | 
				
			||||||
 | 
					#define NT_STATUS_MUTANT_LIMIT_EXCEEDED (0xC0000000 | 0x0191)
 | 
				
			||||||
 | 
					#define NT_STATUS_NETLOGON_NOT_STARTED (0xC0000000 | 0x0192)
 | 
				
			||||||
 | 
					#define NT_STATUS_ACCOUNT_EXPIRED (0xC0000000 | 0x0193)
 | 
				
			||||||
 | 
					#define NT_STATUS_POSSIBLE_DEADLOCK (0xC0000000 | 0x0194)
 | 
				
			||||||
 | 
					#define NT_STATUS_NETWORK_CREDENTIAL_CONFLICT (0xC0000000 | 0x0195)
 | 
				
			||||||
 | 
					#define NT_STATUS_REMOTE_SESSION_LIMIT (0xC0000000 | 0x0196)
 | 
				
			||||||
 | 
					#define NT_STATUS_EVENTLOG_FILE_CHANGED (0xC0000000 | 0x0197)
 | 
				
			||||||
 | 
					#define NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT (0xC0000000 | 0x0198)
 | 
				
			||||||
 | 
					#define NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT (0xC0000000 | 0x0199)
 | 
				
			||||||
 | 
					#define NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT (0xC0000000 | 0x019a)
 | 
				
			||||||
 | 
					#define NT_STATUS_DOMAIN_TRUST_INCONSISTENT (0xC0000000 | 0x019b)
 | 
				
			||||||
 | 
					#define NT_STATUS_FS_DRIVER_REQUIRED (0xC0000000 | 0x019c)
 | 
				
			||||||
 | 
					#define NT_STATUS_NO_USER_SESSION_KEY (0xC0000000 | 0x0202)
 | 
				
			||||||
 | 
					#define NT_STATUS_USER_SESSION_DELETED (0xC0000000 | 0x0203)
 | 
				
			||||||
 | 
					#define NT_STATUS_RESOURCE_LANG_NOT_FOUND (0xC0000000 | 0x0204)
 | 
				
			||||||
 | 
					#define NT_STATUS_INSUFF_SERVER_RESOURCES (0xC0000000 | 0x0205)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_BUFFER_SIZE (0xC0000000 | 0x0206)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_ADDRESS_COMPONENT (0xC0000000 | 0x0207)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_ADDRESS_WILDCARD (0xC0000000 | 0x0208)
 | 
				
			||||||
 | 
					#define NT_STATUS_TOO_MANY_ADDRESSES (0xC0000000 | 0x0209)
 | 
				
			||||||
 | 
					#define NT_STATUS_ADDRESS_ALREADY_EXISTS (0xC0000000 | 0x020a)
 | 
				
			||||||
 | 
					#define NT_STATUS_ADDRESS_CLOSED (0xC0000000 | 0x020b)
 | 
				
			||||||
 | 
					#define NT_STATUS_CONNECTION_DISCONNECTED (0xC0000000 | 0x020c)
 | 
				
			||||||
 | 
					#define NT_STATUS_CONNECTION_RESET (0xC0000000 | 0x020d)
 | 
				
			||||||
 | 
					#define NT_STATUS_TOO_MANY_NODES (0xC0000000 | 0x020e)
 | 
				
			||||||
 | 
					#define NT_STATUS_TRANSACTION_ABORTED (0xC0000000 | 0x020f)
 | 
				
			||||||
 | 
					#define NT_STATUS_TRANSACTION_TIMED_OUT (0xC0000000 | 0x0210)
 | 
				
			||||||
 | 
					#define NT_STATUS_TRANSACTION_NO_RELEASE (0xC0000000 | 0x0211)
 | 
				
			||||||
 | 
					#define NT_STATUS_TRANSACTION_NO_MATCH (0xC0000000 | 0x0212)
 | 
				
			||||||
 | 
					#define NT_STATUS_TRANSACTION_RESPONDED (0xC0000000 | 0x0213)
 | 
				
			||||||
 | 
					#define NT_STATUS_TRANSACTION_INVALID_ID (0xC0000000 | 0x0214)
 | 
				
			||||||
 | 
					#define NT_STATUS_TRANSACTION_INVALID_TYPE (0xC0000000 | 0x0215)
 | 
				
			||||||
 | 
					#define NT_STATUS_NOT_SERVER_SESSION (0xC0000000 | 0x0216)
 | 
				
			||||||
 | 
					#define NT_STATUS_NOT_CLIENT_SESSION (0xC0000000 | 0x0217)
 | 
				
			||||||
 | 
					#define NT_STATUS_CANNOT_LOAD_REGISTRY_FILE (0xC0000000 | 0x0218)
 | 
				
			||||||
 | 
					#define NT_STATUS_DEBUG_ATTACH_FAILED (0xC0000000 | 0x0219)
 | 
				
			||||||
 | 
					#define NT_STATUS_SYSTEM_PROCESS_TERMINATED (0xC0000000 | 0x021a)
 | 
				
			||||||
 | 
					#define NT_STATUS_DATA_NOT_ACCEPTED (0xC0000000 | 0x021b)
 | 
				
			||||||
 | 
					#define NT_STATUS_NO_BROWSER_SERVERS_FOUND (0xC0000000 | 0x021c)
 | 
				
			||||||
 | 
					#define NT_STATUS_VDM_HARD_ERROR (0xC0000000 | 0x021d)
 | 
				
			||||||
 | 
					#define NT_STATUS_DRIVER_CANCEL_TIMEOUT (0xC0000000 | 0x021e)
 | 
				
			||||||
 | 
					#define NT_STATUS_REPLY_MESSAGE_MISMATCH (0xC0000000 | 0x021f)
 | 
				
			||||||
 | 
					#define NT_STATUS_MAPPED_ALIGNMENT (0xC0000000 | 0x0220)
 | 
				
			||||||
 | 
					#define NT_STATUS_IMAGE_CHECKSUM_MISMATCH (0xC0000000 | 0x0221)
 | 
				
			||||||
 | 
					#define NT_STATUS_LOST_WRITEBEHIND_DATA (0xC0000000 | 0x0222)
 | 
				
			||||||
 | 
					#define NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID (0xC0000000 | 0x0223)
 | 
				
			||||||
 | 
					#define NT_STATUS_PASSWORD_MUST_CHANGE (0xC0000000 | 0x0224)
 | 
				
			||||||
 | 
					#define NT_STATUS_NOT_FOUND (0xC0000000 | 0x0225)
 | 
				
			||||||
 | 
					#define NT_STATUS_NOT_TINY_STREAM (0xC0000000 | 0x0226)
 | 
				
			||||||
 | 
					#define NT_STATUS_RECOVERY_FAILURE (0xC0000000 | 0x0227)
 | 
				
			||||||
 | 
					#define NT_STATUS_STACK_OVERFLOW_READ (0xC0000000 | 0x0228)
 | 
				
			||||||
 | 
					#define NT_STATUS_FAIL_CHECK (0xC0000000 | 0x0229)
 | 
				
			||||||
 | 
					#define NT_STATUS_DUPLICATE_OBJECTID (0xC0000000 | 0x022a)
 | 
				
			||||||
 | 
					#define NT_STATUS_OBJECTID_EXISTS (0xC0000000 | 0x022b)
 | 
				
			||||||
 | 
					#define NT_STATUS_CONVERT_TO_LARGE (0xC0000000 | 0x022c)
 | 
				
			||||||
 | 
					#define NT_STATUS_RETRY (0xC0000000 | 0x022d)
 | 
				
			||||||
 | 
					#define NT_STATUS_FOUND_OUT_OF_SCOPE (0xC0000000 | 0x022e)
 | 
				
			||||||
 | 
					#define NT_STATUS_ALLOCATE_BUCKET (0xC0000000 | 0x022f)
 | 
				
			||||||
 | 
					#define NT_STATUS_PROPSET_NOT_FOUND (0xC0000000 | 0x0230)
 | 
				
			||||||
 | 
					#define NT_STATUS_MARSHALL_OVERFLOW (0xC0000000 | 0x0231)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_VARIANT (0xC0000000 | 0x0232)
 | 
				
			||||||
 | 
					#define NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND (0xC0000000 | 0x0233)
 | 
				
			||||||
 | 
					#define NT_STATUS_ACCOUNT_LOCKED_OUT (0xC0000000 | 0x0234)
 | 
				
			||||||
 | 
					#define NT_STATUS_HANDLE_NOT_CLOSABLE (0xC0000000 | 0x0235)
 | 
				
			||||||
 | 
					#define NT_STATUS_CONNECTION_REFUSED (0xC0000000 | 0x0236)
 | 
				
			||||||
 | 
					#define NT_STATUS_GRACEFUL_DISCONNECT (0xC0000000 | 0x0237)
 | 
				
			||||||
 | 
					#define NT_STATUS_ADDRESS_ALREADY_ASSOCIATED (0xC0000000 | 0x0238)
 | 
				
			||||||
 | 
					#define NT_STATUS_ADDRESS_NOT_ASSOCIATED (0xC0000000 | 0x0239)
 | 
				
			||||||
 | 
					#define NT_STATUS_CONNECTION_INVALID (0xC0000000 | 0x023a)
 | 
				
			||||||
 | 
					#define NT_STATUS_CONNECTION_ACTIVE (0xC0000000 | 0x023b)
 | 
				
			||||||
 | 
					#define NT_STATUS_NETWORK_UNREACHABLE (0xC0000000 | 0x023c)
 | 
				
			||||||
 | 
					#define NT_STATUS_HOST_UNREACHABLE (0xC0000000 | 0x023d)
 | 
				
			||||||
 | 
					#define NT_STATUS_PROTOCOL_UNREACHABLE (0xC0000000 | 0x023e)
 | 
				
			||||||
 | 
					#define NT_STATUS_PORT_UNREACHABLE (0xC0000000 | 0x023f)
 | 
				
			||||||
 | 
					#define NT_STATUS_REQUEST_ABORTED (0xC0000000 | 0x0240)
 | 
				
			||||||
 | 
					#define NT_STATUS_CONNECTION_ABORTED (0xC0000000 | 0x0241)
 | 
				
			||||||
 | 
					#define NT_STATUS_BAD_COMPRESSION_BUFFER (0xC0000000 | 0x0242)
 | 
				
			||||||
 | 
					#define NT_STATUS_USER_MAPPED_FILE (0xC0000000 | 0x0243)
 | 
				
			||||||
 | 
					#define NT_STATUS_AUDIT_FAILED (0xC0000000 | 0x0244)
 | 
				
			||||||
 | 
					#define NT_STATUS_TIMER_RESOLUTION_NOT_SET (0xC0000000 | 0x0245)
 | 
				
			||||||
 | 
					#define NT_STATUS_CONNECTION_COUNT_LIMIT (0xC0000000 | 0x0246)
 | 
				
			||||||
 | 
					#define NT_STATUS_LOGIN_TIME_RESTRICTION (0xC0000000 | 0x0247)
 | 
				
			||||||
 | 
					#define NT_STATUS_LOGIN_WKSTA_RESTRICTION (0xC0000000 | 0x0248)
 | 
				
			||||||
 | 
					#define NT_STATUS_IMAGE_MP_UP_MISMATCH (0xC0000000 | 0x0249)
 | 
				
			||||||
 | 
					#define NT_STATUS_INSUFFICIENT_LOGON_INFO (0xC0000000 | 0x0250)
 | 
				
			||||||
 | 
					#define NT_STATUS_BAD_DLL_ENTRYPOINT (0xC0000000 | 0x0251)
 | 
				
			||||||
 | 
					#define NT_STATUS_BAD_SERVICE_ENTRYPOINT (0xC0000000 | 0x0252)
 | 
				
			||||||
 | 
					#define NT_STATUS_LPC_REPLY_LOST (0xC0000000 | 0x0253)
 | 
				
			||||||
 | 
					#define NT_STATUS_IP_ADDRESS_CONFLICT1 (0xC0000000 | 0x0254)
 | 
				
			||||||
 | 
					#define NT_STATUS_IP_ADDRESS_CONFLICT2 (0xC0000000 | 0x0255)
 | 
				
			||||||
 | 
					#define NT_STATUS_REGISTRY_QUOTA_LIMIT (0xC0000000 | 0x0256)
 | 
				
			||||||
 | 
					#define NT_STATUS_PATH_NOT_COVERED (0xC0000000 | 0x0257)
 | 
				
			||||||
 | 
					#define NT_STATUS_NO_CALLBACK_ACTIVE (0xC0000000 | 0x0258)
 | 
				
			||||||
 | 
					#define NT_STATUS_LICENSE_QUOTA_EXCEEDED (0xC0000000 | 0x0259)
 | 
				
			||||||
 | 
					#define NT_STATUS_PWD_TOO_SHORT (0xC0000000 | 0x025a)
 | 
				
			||||||
 | 
					#define NT_STATUS_PWD_TOO_RECENT (0xC0000000 | 0x025b)
 | 
				
			||||||
 | 
					#define NT_STATUS_PWD_HISTORY_CONFLICT (0xC0000000 | 0x025c)
 | 
				
			||||||
 | 
					#define NT_STATUS_PLUGPLAY_NO_DEVICE (0xC0000000 | 0x025e)
 | 
				
			||||||
 | 
					#define NT_STATUS_UNSUPPORTED_COMPRESSION (0xC0000000 | 0x025f)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_HW_PROFILE (0xC0000000 | 0x0260)
 | 
				
			||||||
 | 
					#define NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH (0xC0000000 | 0x0261)
 | 
				
			||||||
 | 
					#define NT_STATUS_DRIVER_ORDINAL_NOT_FOUND (0xC0000000 | 0x0262)
 | 
				
			||||||
 | 
					#define NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND (0xC0000000 | 0x0263)
 | 
				
			||||||
 | 
					#define NT_STATUS_RESOURCE_NOT_OWNED (0xC0000000 | 0x0264)
 | 
				
			||||||
 | 
					#define NT_STATUS_TOO_MANY_LINKS (0xC0000000 | 0x0265)
 | 
				
			||||||
 | 
					#define NT_STATUS_QUOTA_LIST_INCONSISTENT (0xC0000000 | 0x0266)
 | 
				
			||||||
 | 
					#define NT_STATUS_FILE_IS_OFFLINE (0xC0000000 | 0x0267)
 | 
				
			||||||
 | 
					#define NT_STATUS_NETWORK_SESSION_EXPIRED  (0xC0000000 | 0x035c)
 | 
				
			||||||
 | 
					#define NT_STATUS_NO_SUCH_JOB (0xC0000000 | 0xEDE)     /* scheduler */
 | 
				
			||||||
 | 
					#define NT_STATUS_NO_PREAUTH_INTEGRITY_HASH_OVERLAP (0xC0000000 | 0x5D0000)
 | 
				
			||||||
 | 
					#define NT_STATUS_PENDING 0x00000103
 | 
				
			||||||
 | 
					#endif				/* _NTERR_H */
 | 
				
			||||||
							
								
								
									
										169
									
								
								fs/cifsd/ntlmssp.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								fs/cifsd/ntlmssp.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,169 @@
 | 
				
			||||||
 | 
					/* SPDX-License-Identifier: LGPL-2.1+ */
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *   Copyright (c) International Business Machines  Corp., 2002,2007
 | 
				
			||||||
 | 
					 *   Author(s): Steve French (sfrench@us.ibm.com)
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef __KSMBD_NTLMSSP_H
 | 
				
			||||||
 | 
					#define __KSMBD_NTLMSSP_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NTLMSSP_SIGNATURE "NTLMSSP"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Security blob target info data */
 | 
				
			||||||
 | 
					#define TGT_Name        "KSMBD"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Size of the crypto key returned on the negotiate SMB in bytes
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define CIFS_CRYPTO_KEY_SIZE	(8)
 | 
				
			||||||
 | 
					#define CIFS_KEY_SIZE	(40)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Size of encrypted user password in bytes
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define CIFS_ENCPWD_SIZE	(16)
 | 
				
			||||||
 | 
					#define CIFS_CPHTXT_SIZE	(16)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Message Types */
 | 
				
			||||||
 | 
					#define NtLmNegotiate     cpu_to_le32(1)
 | 
				
			||||||
 | 
					#define NtLmChallenge     cpu_to_le32(2)
 | 
				
			||||||
 | 
					#define NtLmAuthenticate  cpu_to_le32(3)
 | 
				
			||||||
 | 
					#define UnknownMessage    cpu_to_le32(8)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Negotiate Flags */
 | 
				
			||||||
 | 
					#define NTLMSSP_NEGOTIATE_UNICODE         0x01 /* Text strings are unicode */
 | 
				
			||||||
 | 
					#define NTLMSSP_NEGOTIATE_OEM             0x02 /* Text strings are in OEM */
 | 
				
			||||||
 | 
					#define NTLMSSP_REQUEST_TARGET            0x04 /* Srv returns its auth realm */
 | 
				
			||||||
 | 
					/* define reserved9                       0x08 */
 | 
				
			||||||
 | 
					#define NTLMSSP_NEGOTIATE_SIGN          0x0010 /* Request signing capability */
 | 
				
			||||||
 | 
					#define NTLMSSP_NEGOTIATE_SEAL          0x0020 /* Request confidentiality */
 | 
				
			||||||
 | 
					#define NTLMSSP_NEGOTIATE_DGRAM         0x0040
 | 
				
			||||||
 | 
					#define NTLMSSP_NEGOTIATE_LM_KEY        0x0080 /* Use LM session key */
 | 
				
			||||||
 | 
					/* defined reserved 8                   0x0100 */
 | 
				
			||||||
 | 
					#define NTLMSSP_NEGOTIATE_NTLM          0x0200 /* NTLM authentication */
 | 
				
			||||||
 | 
					#define NTLMSSP_NEGOTIATE_NT_ONLY       0x0400 /* Lanman not allowed */
 | 
				
			||||||
 | 
					#define NTLMSSP_ANONYMOUS               0x0800
 | 
				
			||||||
 | 
					#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x1000 /* reserved6 */
 | 
				
			||||||
 | 
					#define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x2000
 | 
				
			||||||
 | 
					#define NTLMSSP_NEGOTIATE_LOCAL_CALL    0x4000 /* client/server same machine */
 | 
				
			||||||
 | 
					#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN   0x8000 /* Sign. All security levels  */
 | 
				
			||||||
 | 
					#define NTLMSSP_TARGET_TYPE_DOMAIN     0x10000
 | 
				
			||||||
 | 
					#define NTLMSSP_TARGET_TYPE_SERVER     0x20000
 | 
				
			||||||
 | 
					#define NTLMSSP_TARGET_TYPE_SHARE      0x40000
 | 
				
			||||||
 | 
					#define NTLMSSP_NEGOTIATE_EXTENDED_SEC 0x80000 /* NB:not related to NTLMv2 pwd*/
 | 
				
			||||||
 | 
					/* #define NTLMSSP_REQUEST_INIT_RESP     0x100000 */
 | 
				
			||||||
 | 
					#define NTLMSSP_NEGOTIATE_IDENTIFY    0x100000
 | 
				
			||||||
 | 
					#define NTLMSSP_REQUEST_ACCEPT_RESP   0x200000 /* reserved5 */
 | 
				
			||||||
 | 
					#define NTLMSSP_REQUEST_NON_NT_KEY    0x400000
 | 
				
			||||||
 | 
					#define NTLMSSP_NEGOTIATE_TARGET_INFO 0x800000
 | 
				
			||||||
 | 
					/* #define reserved4                 0x1000000 */
 | 
				
			||||||
 | 
					#define NTLMSSP_NEGOTIATE_VERSION    0x2000000 /* we do not set */
 | 
				
			||||||
 | 
					/* #define reserved3                 0x4000000 */
 | 
				
			||||||
 | 
					/* #define reserved2                 0x8000000 */
 | 
				
			||||||
 | 
					/* #define reserved1                0x10000000 */
 | 
				
			||||||
 | 
					#define NTLMSSP_NEGOTIATE_128       0x20000000
 | 
				
			||||||
 | 
					#define NTLMSSP_NEGOTIATE_KEY_XCH   0x40000000
 | 
				
			||||||
 | 
					#define NTLMSSP_NEGOTIATE_56        0x80000000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Define AV Pair Field IDs */
 | 
				
			||||||
 | 
					enum av_field_type {
 | 
				
			||||||
 | 
						NTLMSSP_AV_EOL = 0,
 | 
				
			||||||
 | 
						NTLMSSP_AV_NB_COMPUTER_NAME,
 | 
				
			||||||
 | 
						NTLMSSP_AV_NB_DOMAIN_NAME,
 | 
				
			||||||
 | 
						NTLMSSP_AV_DNS_COMPUTER_NAME,
 | 
				
			||||||
 | 
						NTLMSSP_AV_DNS_DOMAIN_NAME,
 | 
				
			||||||
 | 
						NTLMSSP_AV_DNS_TREE_NAME,
 | 
				
			||||||
 | 
						NTLMSSP_AV_FLAGS,
 | 
				
			||||||
 | 
						NTLMSSP_AV_TIMESTAMP,
 | 
				
			||||||
 | 
						NTLMSSP_AV_RESTRICTION,
 | 
				
			||||||
 | 
						NTLMSSP_AV_TARGET_NAME,
 | 
				
			||||||
 | 
						NTLMSSP_AV_CHANNEL_BINDINGS
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Although typedefs are not commonly used for structure definitions */
 | 
				
			||||||
 | 
					/* in the Linux kernel, in this particular case they are useful      */
 | 
				
			||||||
 | 
					/* to more closely match the standards document for NTLMSSP from     */
 | 
				
			||||||
 | 
					/* OpenGroup and to make the code more closely match the standard in */
 | 
				
			||||||
 | 
					/* appearance */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct security_buffer {
 | 
				
			||||||
 | 
						__le16 Length;
 | 
				
			||||||
 | 
						__le16 MaximumLength;
 | 
				
			||||||
 | 
						__le32 BufferOffset;	/* offset to buffer */
 | 
				
			||||||
 | 
					} __packed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct target_info {
 | 
				
			||||||
 | 
						__le16 Type;
 | 
				
			||||||
 | 
						__le16 Length;
 | 
				
			||||||
 | 
						__u8 Content[0];
 | 
				
			||||||
 | 
					} __packed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct negotiate_message {
 | 
				
			||||||
 | 
						__u8 Signature[sizeof(NTLMSSP_SIGNATURE)];
 | 
				
			||||||
 | 
						__le32 MessageType;     /* NtLmNegotiate = 1 */
 | 
				
			||||||
 | 
						__le32 NegotiateFlags;
 | 
				
			||||||
 | 
						struct security_buffer DomainName;	/* RFC 1001 style and ASCII */
 | 
				
			||||||
 | 
						struct security_buffer WorkstationName;	/* RFC 1001 and ASCII */
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * struct security_buffer for version info not present since we
 | 
				
			||||||
 | 
						 * do not set the version is present flag
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						char DomainString[0];
 | 
				
			||||||
 | 
						/* followed by WorkstationString */
 | 
				
			||||||
 | 
					} __packed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct challenge_message {
 | 
				
			||||||
 | 
						__u8 Signature[sizeof(NTLMSSP_SIGNATURE)];
 | 
				
			||||||
 | 
						__le32 MessageType;   /* NtLmChallenge = 2 */
 | 
				
			||||||
 | 
						struct security_buffer TargetName;
 | 
				
			||||||
 | 
						__le32 NegotiateFlags;
 | 
				
			||||||
 | 
						__u8 Challenge[CIFS_CRYPTO_KEY_SIZE];
 | 
				
			||||||
 | 
						__u8 Reserved[8];
 | 
				
			||||||
 | 
						struct security_buffer TargetInfoArray;
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * struct security_buffer for version info not present since we
 | 
				
			||||||
 | 
						 * do not set the version is present flag
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
					} __packed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct authenticate_message {
 | 
				
			||||||
 | 
						__u8 Signature[sizeof(NTLMSSP_SIGNATURE)];
 | 
				
			||||||
 | 
						__le32 MessageType;  /* NtLmsAuthenticate = 3 */
 | 
				
			||||||
 | 
						struct security_buffer LmChallengeResponse;
 | 
				
			||||||
 | 
						struct security_buffer NtChallengeResponse;
 | 
				
			||||||
 | 
						struct security_buffer DomainName;
 | 
				
			||||||
 | 
						struct security_buffer UserName;
 | 
				
			||||||
 | 
						struct security_buffer WorkstationName;
 | 
				
			||||||
 | 
						struct security_buffer SessionKey;
 | 
				
			||||||
 | 
						__le32 NegotiateFlags;
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * struct security_buffer for version info not present since we
 | 
				
			||||||
 | 
						 * do not set the version is present flag
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						char UserString[0];
 | 
				
			||||||
 | 
					} __packed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ntlmv2_resp {
 | 
				
			||||||
 | 
						char ntlmv2_hash[CIFS_ENCPWD_SIZE];
 | 
				
			||||||
 | 
						__le32 blob_signature;
 | 
				
			||||||
 | 
						__u32  reserved;
 | 
				
			||||||
 | 
						__le64  time;
 | 
				
			||||||
 | 
						__u64  client_chal; /* random */
 | 
				
			||||||
 | 
						__u32  reserved2;
 | 
				
			||||||
 | 
						/* array of name entries could follow ending in minimum 4 byte struct */
 | 
				
			||||||
 | 
					} __packed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* per smb session structure/fields */
 | 
				
			||||||
 | 
					struct ntlmssp_auth {
 | 
				
			||||||
 | 
						/* whether session key is per smb session */
 | 
				
			||||||
 | 
						bool		sesskey_per_smbsess;
 | 
				
			||||||
 | 
						/* sent by client in type 1 ntlmsssp exchange */
 | 
				
			||||||
 | 
						__u32		client_flags;
 | 
				
			||||||
 | 
						/* sent by server in type 2 ntlmssp exchange */
 | 
				
			||||||
 | 
						__u32		conn_flags;
 | 
				
			||||||
 | 
						/* sent to server */
 | 
				
			||||||
 | 
						unsigned char	ciphertext[CIFS_CPHTXT_SIZE];
 | 
				
			||||||
 | 
						/* used by ntlmssp */
 | 
				
			||||||
 | 
						char		cryptkey[CIFS_CRYPTO_KEY_SIZE];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					#endif /* __KSMBD_NTLMSSP_H */
 | 
				
			||||||
							
								
								
									
										1693
									
								
								fs/cifsd/oplock.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1693
									
								
								fs/cifsd/oplock.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										138
									
								
								fs/cifsd/oplock.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										138
									
								
								fs/cifsd/oplock.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,138 @@
 | 
				
			||||||
 | 
					/* SPDX-License-Identifier: GPL-2.0-or-later */
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *   Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
 | 
				
			||||||
 | 
					 *   Copyright (C) 2018 Samsung Electronics Co., Ltd.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef __KSMBD_OPLOCK_H
 | 
				
			||||||
 | 
					#define __KSMBD_OPLOCK_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "smb_common.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define OPLOCK_WAIT_TIME	(35*HZ)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* SMB Oplock levels */
 | 
				
			||||||
 | 
					#define OPLOCK_NONE      0
 | 
				
			||||||
 | 
					#define OPLOCK_EXCLUSIVE 1
 | 
				
			||||||
 | 
					#define OPLOCK_BATCH     2
 | 
				
			||||||
 | 
					#define OPLOCK_READ      3  /* level 2 oplock */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* SMB2 Oplock levels */
 | 
				
			||||||
 | 
					#define SMB2_OPLOCK_LEVEL_NONE          0x00
 | 
				
			||||||
 | 
					#define SMB2_OPLOCK_LEVEL_II            0x01
 | 
				
			||||||
 | 
					#define SMB2_OPLOCK_LEVEL_EXCLUSIVE     0x08
 | 
				
			||||||
 | 
					#define SMB2_OPLOCK_LEVEL_BATCH         0x09
 | 
				
			||||||
 | 
					#define SMB2_OPLOCK_LEVEL_LEASE         0xFF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Oplock states */
 | 
				
			||||||
 | 
					#define OPLOCK_STATE_NONE	0x00
 | 
				
			||||||
 | 
					#define OPLOCK_ACK_WAIT		0x01
 | 
				
			||||||
 | 
					#define OPLOCK_CLOSING		0x02
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define OPLOCK_WRITE_TO_READ		0x01
 | 
				
			||||||
 | 
					#define OPLOCK_READ_HANDLE_TO_READ	0x02
 | 
				
			||||||
 | 
					#define OPLOCK_WRITE_TO_NONE		0x04
 | 
				
			||||||
 | 
					#define OPLOCK_READ_TO_NONE		0x08
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SMB2_LEASE_KEY_SIZE		16
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct lease_ctx_info {
 | 
				
			||||||
 | 
						__u8	lease_key[SMB2_LEASE_KEY_SIZE];
 | 
				
			||||||
 | 
						__le32	req_state;
 | 
				
			||||||
 | 
						__le32	flags;
 | 
				
			||||||
 | 
						__le64	duration;
 | 
				
			||||||
 | 
						int dlease;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct lease_table {
 | 
				
			||||||
 | 
						char			client_guid[SMB2_CLIENT_GUID_SIZE];
 | 
				
			||||||
 | 
						struct list_head	lease_list;
 | 
				
			||||||
 | 
						struct list_head	l_entry;
 | 
				
			||||||
 | 
						spinlock_t		lb_lock;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct lease {
 | 
				
			||||||
 | 
						__u8			lease_key[SMB2_LEASE_KEY_SIZE];
 | 
				
			||||||
 | 
						__le32			state;
 | 
				
			||||||
 | 
						__le32			new_state;
 | 
				
			||||||
 | 
						__le32			flags;
 | 
				
			||||||
 | 
						__le64			duration;
 | 
				
			||||||
 | 
						struct lease_table	*l_lb;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct oplock_info {
 | 
				
			||||||
 | 
						struct ksmbd_conn	*conn;
 | 
				
			||||||
 | 
						struct ksmbd_session	*sess;
 | 
				
			||||||
 | 
						struct ksmbd_work	*work;
 | 
				
			||||||
 | 
						struct ksmbd_file	*o_fp;
 | 
				
			||||||
 | 
						int                     level;
 | 
				
			||||||
 | 
						int                     op_state;
 | 
				
			||||||
 | 
						unsigned long		pending_break;
 | 
				
			||||||
 | 
						uint64_t                fid;
 | 
				
			||||||
 | 
						atomic_t		breaking_cnt;
 | 
				
			||||||
 | 
						atomic_t		refcount;
 | 
				
			||||||
 | 
						__u16                   Tid;
 | 
				
			||||||
 | 
						bool			is_lease;
 | 
				
			||||||
 | 
						bool			open_trunc;	/* truncate on open */
 | 
				
			||||||
 | 
						struct lease		*o_lease;
 | 
				
			||||||
 | 
						struct list_head        interim_list;
 | 
				
			||||||
 | 
						struct list_head        op_entry;
 | 
				
			||||||
 | 
						struct list_head        lease_entry;
 | 
				
			||||||
 | 
						wait_queue_head_t oplock_q; /* Other server threads */
 | 
				
			||||||
 | 
						wait_queue_head_t oplock_brk; /* oplock breaking wait */
 | 
				
			||||||
 | 
						struct rcu_head		rcu_head;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct lease_break_info {
 | 
				
			||||||
 | 
						__le32			curr_state;
 | 
				
			||||||
 | 
						__le32			new_state;
 | 
				
			||||||
 | 
						char			lease_key[SMB2_LEASE_KEY_SIZE];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct oplock_break_info {
 | 
				
			||||||
 | 
						int level;
 | 
				
			||||||
 | 
						int open_trunc;
 | 
				
			||||||
 | 
						int fid;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern int smb_grant_oplock(struct ksmbd_work *work, int req_op_level,
 | 
				
			||||||
 | 
							uint64_t pid, struct ksmbd_file *fp, __u16 tid,
 | 
				
			||||||
 | 
							struct lease_ctx_info *lctx, int share_ret);
 | 
				
			||||||
 | 
					extern void smb_break_all_levII_oplock(struct ksmbd_work *work,
 | 
				
			||||||
 | 
						struct ksmbd_file *fp, int is_trunc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int opinfo_write_to_read(struct oplock_info *opinfo);
 | 
				
			||||||
 | 
					int opinfo_read_handle_to_read(struct oplock_info *opinfo);
 | 
				
			||||||
 | 
					int opinfo_write_to_none(struct oplock_info *opinfo);
 | 
				
			||||||
 | 
					int opinfo_read_to_none(struct oplock_info *opinfo);
 | 
				
			||||||
 | 
					void close_id_del_oplock(struct ksmbd_file *fp);
 | 
				
			||||||
 | 
					void smb_break_all_oplock(struct ksmbd_work *work, struct ksmbd_file *fp);
 | 
				
			||||||
 | 
					struct oplock_info *opinfo_get(struct ksmbd_file *fp);
 | 
				
			||||||
 | 
					void opinfo_put(struct oplock_info *opinfo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Lease related functions */
 | 
				
			||||||
 | 
					void create_lease_buf(u8 *rbuf, struct lease *lease);
 | 
				
			||||||
 | 
					struct lease_ctx_info *parse_lease_state(void *open_req);
 | 
				
			||||||
 | 
					__u8 smb2_map_lease_to_oplock(__le32 lease_state);
 | 
				
			||||||
 | 
					int lease_read_to_write(struct oplock_info *opinfo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Durable related functions */
 | 
				
			||||||
 | 
					void create_durable_rsp_buf(char *cc);
 | 
				
			||||||
 | 
					void create_durable_v2_rsp_buf(char *cc, struct ksmbd_file *fp);
 | 
				
			||||||
 | 
					void create_mxac_rsp_buf(char *cc, int maximal_access);
 | 
				
			||||||
 | 
					void create_disk_id_rsp_buf(char *cc, __u64 file_id, __u64 vol_id);
 | 
				
			||||||
 | 
					void create_posix_rsp_buf(char *cc, struct ksmbd_file *fp);
 | 
				
			||||||
 | 
					struct create_context *smb2_find_context_vals(void *open_req, const char *str);
 | 
				
			||||||
 | 
					int ksmbd_durable_verify_and_del_oplock(struct ksmbd_session *curr_sess,
 | 
				
			||||||
 | 
										  struct ksmbd_session *prev_sess,
 | 
				
			||||||
 | 
										  int fid, struct file **filp,
 | 
				
			||||||
 | 
										  uint64_t sess_id);
 | 
				
			||||||
 | 
					struct oplock_info *lookup_lease_in_table(struct ksmbd_conn *conn,
 | 
				
			||||||
 | 
						char *lease_key);
 | 
				
			||||||
 | 
					int find_same_lease_key(struct ksmbd_session *sess, struct ksmbd_inode *ci,
 | 
				
			||||||
 | 
						struct lease_ctx_info *lctx);
 | 
				
			||||||
 | 
					void destroy_lease_table(struct ksmbd_conn *conn);
 | 
				
			||||||
 | 
					int smb2_check_durable_oplock(struct ksmbd_file *fp,
 | 
				
			||||||
 | 
						struct lease_ctx_info *lctx, char *name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* __KSMBD_OPLOCK_H */
 | 
				
			||||||
							
								
								
									
										458
									
								
								fs/cifsd/smb2misc.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										458
									
								
								fs/cifsd/smb2misc.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,458 @@
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: GPL-2.0-or-later
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *   Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
 | 
				
			||||||
 | 
					 *   Copyright (C) 2018 Samsung Electronics Co., Ltd.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "glob.h"
 | 
				
			||||||
 | 
					#include "nterr.h"
 | 
				
			||||||
 | 
					#include "smb2pdu.h"
 | 
				
			||||||
 | 
					#include "smb_common.h"
 | 
				
			||||||
 | 
					#include "smbstatus.h"
 | 
				
			||||||
 | 
					#include "mgmt/user_session.h"
 | 
				
			||||||
 | 
					#include "connection.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int check_smb2_hdr(struct smb2_hdr *hdr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Make sure that this really is an SMB, that it is a response.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (hdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR)
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  The following table defines the expected "StructureSize" of SMB2 requests
 | 
				
			||||||
 | 
					 *  in order by SMB2 command.  This is similar to "wct" in SMB/CIFS requests.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  Note that commands are defined in smb2pdu.h in le16 but the array below is
 | 
				
			||||||
 | 
					 *  indexed by command in host byte order
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static const __le16 smb2_req_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = {
 | 
				
			||||||
 | 
						/* SMB2_NEGOTIATE */ cpu_to_le16(36),
 | 
				
			||||||
 | 
						/* SMB2_SESSION_SETUP */ cpu_to_le16(25),
 | 
				
			||||||
 | 
						/* SMB2_LOGOFF */ cpu_to_le16(4),
 | 
				
			||||||
 | 
						/* SMB2_TREE_CONNECT */ cpu_to_le16(9),
 | 
				
			||||||
 | 
						/* SMB2_TREE_DISCONNECT */ cpu_to_le16(4),
 | 
				
			||||||
 | 
						/* SMB2_CREATE */ cpu_to_le16(57),
 | 
				
			||||||
 | 
						/* SMB2_CLOSE */ cpu_to_le16(24),
 | 
				
			||||||
 | 
						/* SMB2_FLUSH */ cpu_to_le16(24),
 | 
				
			||||||
 | 
						/* SMB2_READ */ cpu_to_le16(49),
 | 
				
			||||||
 | 
						/* SMB2_WRITE */ cpu_to_le16(49),
 | 
				
			||||||
 | 
						/* SMB2_LOCK */ cpu_to_le16(48),
 | 
				
			||||||
 | 
						/* SMB2_IOCTL */ cpu_to_le16(57),
 | 
				
			||||||
 | 
						/* SMB2_CANCEL */ cpu_to_le16(4),
 | 
				
			||||||
 | 
						/* SMB2_ECHO */ cpu_to_le16(4),
 | 
				
			||||||
 | 
						/* SMB2_QUERY_DIRECTORY */ cpu_to_le16(33),
 | 
				
			||||||
 | 
						/* SMB2_CHANGE_NOTIFY */ cpu_to_le16(32),
 | 
				
			||||||
 | 
						/* SMB2_QUERY_INFO */ cpu_to_le16(41),
 | 
				
			||||||
 | 
						/* SMB2_SET_INFO */ cpu_to_le16(33),
 | 
				
			||||||
 | 
						/* use 44 for lease break */
 | 
				
			||||||
 | 
						/* SMB2_OPLOCK_BREAK */ cpu_to_le16(36)
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * The size of the variable area depends on the offset and length fields
 | 
				
			||||||
 | 
					 * located in different fields for various SMB2 requests. SMB2 requests
 | 
				
			||||||
 | 
					 * with no variable length info, show an offset of zero for the offset field.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static const bool has_smb2_data_area[NUMBER_OF_SMB2_COMMANDS] = {
 | 
				
			||||||
 | 
						/* SMB2_NEGOTIATE */ true,
 | 
				
			||||||
 | 
						/* SMB2_SESSION_SETUP */ true,
 | 
				
			||||||
 | 
						/* SMB2_LOGOFF */ false,
 | 
				
			||||||
 | 
						/* SMB2_TREE_CONNECT */	true,
 | 
				
			||||||
 | 
						/* SMB2_TREE_DISCONNECT */ false,
 | 
				
			||||||
 | 
						/* SMB2_CREATE */ true,
 | 
				
			||||||
 | 
						/* SMB2_CLOSE */ false,
 | 
				
			||||||
 | 
						/* SMB2_FLUSH */ false,
 | 
				
			||||||
 | 
						/* SMB2_READ */	true,
 | 
				
			||||||
 | 
						/* SMB2_WRITE */ true,
 | 
				
			||||||
 | 
						/* SMB2_LOCK */	true,
 | 
				
			||||||
 | 
						/* SMB2_IOCTL */ true,
 | 
				
			||||||
 | 
						/* SMB2_CANCEL */ false, /* BB CHECK this not listed in documentation */
 | 
				
			||||||
 | 
						/* SMB2_ECHO */ false,
 | 
				
			||||||
 | 
						/* SMB2_QUERY_DIRECTORY */ true,
 | 
				
			||||||
 | 
						/* SMB2_CHANGE_NOTIFY */ false,
 | 
				
			||||||
 | 
						/* SMB2_QUERY_INFO */ true,
 | 
				
			||||||
 | 
						/* SMB2_SET_INFO */ true,
 | 
				
			||||||
 | 
						/* SMB2_OPLOCK_BREAK */ false
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Returns the pointer to the beginning of the data area. Length of the data
 | 
				
			||||||
 | 
					 * area and the offset to it (from the beginning of the smb are also returned.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static char *smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						*off = 0;
 | 
				
			||||||
 | 
						*len = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* error reqeusts do not have data area */
 | 
				
			||||||
 | 
						if (hdr->Status && hdr->Status != STATUS_MORE_PROCESSING_REQUIRED &&
 | 
				
			||||||
 | 
								(((struct smb2_err_rsp *)hdr)->StructureSize) ==
 | 
				
			||||||
 | 
								SMB2_ERROR_STRUCTURE_SIZE2_LE)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Following commands have data areas so we have to get the location
 | 
				
			||||||
 | 
						 * of the data buffer offset and data buffer length for the particular
 | 
				
			||||||
 | 
						 * command.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						switch (hdr->Command) {
 | 
				
			||||||
 | 
						case SMB2_SESSION_SETUP:
 | 
				
			||||||
 | 
							*off = le16_to_cpu(
 | 
				
			||||||
 | 
							     ((struct smb2_sess_setup_req *)hdr)->SecurityBufferOffset);
 | 
				
			||||||
 | 
							*len = le16_to_cpu(
 | 
				
			||||||
 | 
							     ((struct smb2_sess_setup_req *)hdr)->SecurityBufferLength);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case SMB2_TREE_CONNECT:
 | 
				
			||||||
 | 
							*off = le16_to_cpu(
 | 
				
			||||||
 | 
							     ((struct smb2_tree_connect_req *)hdr)->PathOffset);
 | 
				
			||||||
 | 
							*len = le16_to_cpu(
 | 
				
			||||||
 | 
							     ((struct smb2_tree_connect_req *)hdr)->PathLength);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case SMB2_CREATE:
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (((struct smb2_create_req *)hdr)->CreateContextsLength) {
 | 
				
			||||||
 | 
								*off = le32_to_cpu(((struct smb2_create_req *)
 | 
				
			||||||
 | 
									hdr)->CreateContextsOffset);
 | 
				
			||||||
 | 
								*len = le32_to_cpu(((struct smb2_create_req *)
 | 
				
			||||||
 | 
									hdr)->CreateContextsLength);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							*off = le16_to_cpu(
 | 
				
			||||||
 | 
							     ((struct smb2_create_req *)hdr)->NameOffset);
 | 
				
			||||||
 | 
							*len = le16_to_cpu(
 | 
				
			||||||
 | 
							     ((struct smb2_create_req *)hdr)->NameLength);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						case SMB2_QUERY_INFO:
 | 
				
			||||||
 | 
							*off = le16_to_cpu(
 | 
				
			||||||
 | 
							     ((struct smb2_query_info_req *)hdr)->InputBufferOffset);
 | 
				
			||||||
 | 
							*len = le32_to_cpu(
 | 
				
			||||||
 | 
							     ((struct smb2_query_info_req *)hdr)->InputBufferLength);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case SMB2_SET_INFO:
 | 
				
			||||||
 | 
							*off = le16_to_cpu(
 | 
				
			||||||
 | 
							     ((struct smb2_set_info_req *)hdr)->BufferOffset);
 | 
				
			||||||
 | 
							*len = le32_to_cpu(
 | 
				
			||||||
 | 
							     ((struct smb2_set_info_req *)hdr)->BufferLength);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case SMB2_READ:
 | 
				
			||||||
 | 
							*off = le16_to_cpu(
 | 
				
			||||||
 | 
							     ((struct smb2_read_req *)hdr)->ReadChannelInfoOffset);
 | 
				
			||||||
 | 
							*len = le16_to_cpu(
 | 
				
			||||||
 | 
							     ((struct smb2_read_req *)hdr)->ReadChannelInfoLength);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case SMB2_WRITE:
 | 
				
			||||||
 | 
							if (((struct smb2_write_req *)hdr)->DataOffset) {
 | 
				
			||||||
 | 
								*off = le16_to_cpu(
 | 
				
			||||||
 | 
								     ((struct smb2_write_req *)hdr)->DataOffset);
 | 
				
			||||||
 | 
								*len = le32_to_cpu(
 | 
				
			||||||
 | 
									((struct smb2_write_req *)hdr)->Length);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							*off = le16_to_cpu(
 | 
				
			||||||
 | 
							     ((struct smb2_write_req *)hdr)->WriteChannelInfoOffset);
 | 
				
			||||||
 | 
							*len = le16_to_cpu(
 | 
				
			||||||
 | 
							     ((struct smb2_write_req *)hdr)->WriteChannelInfoLength);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case SMB2_QUERY_DIRECTORY:
 | 
				
			||||||
 | 
							*off = le16_to_cpu(
 | 
				
			||||||
 | 
							     ((struct smb2_query_directory_req *)hdr)->FileNameOffset);
 | 
				
			||||||
 | 
							*len = le16_to_cpu(
 | 
				
			||||||
 | 
							     ((struct smb2_query_directory_req *)hdr)->FileNameLength);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case SMB2_LOCK:
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							int lock_count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * smb2_lock request size is 48 included single
 | 
				
			||||||
 | 
							 * smb2_lock_element structure size.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							lock_count = le16_to_cpu(
 | 
				
			||||||
 | 
								((struct smb2_lock_req *)hdr)->LockCount) - 1;
 | 
				
			||||||
 | 
							if (lock_count > 0) {
 | 
				
			||||||
 | 
								*off = __SMB2_HEADER_STRUCTURE_SIZE + 48;
 | 
				
			||||||
 | 
								*len = sizeof(struct smb2_lock_element) * lock_count;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						case SMB2_IOCTL:
 | 
				
			||||||
 | 
							*off = le32_to_cpu(
 | 
				
			||||||
 | 
							     ((struct smb2_ioctl_req *)hdr)->InputOffset);
 | 
				
			||||||
 | 
							*len = le32_to_cpu(((struct smb2_ioctl_req *)hdr)->InputCount);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							ksmbd_debug(SMB, "no length check for command\n");
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Invalid length or offset probably means data area is invalid, but
 | 
				
			||||||
 | 
						 * we have little choice but to ignore the data area in this case.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (*off > 4096) {
 | 
				
			||||||
 | 
							ksmbd_debug(SMB, "offset %d too large, data area ignored\n",
 | 
				
			||||||
 | 
								*off);
 | 
				
			||||||
 | 
							*len = 0;
 | 
				
			||||||
 | 
							*off = 0;
 | 
				
			||||||
 | 
						} else if (*off < 0) {
 | 
				
			||||||
 | 
							ksmbd_debug(SMB,
 | 
				
			||||||
 | 
								"negative offset %d to data invalid ignore data area\n",
 | 
				
			||||||
 | 
								*off);
 | 
				
			||||||
 | 
							*off = 0;
 | 
				
			||||||
 | 
							*len = 0;
 | 
				
			||||||
 | 
						} else if (*len < 0) {
 | 
				
			||||||
 | 
							ksmbd_debug(SMB,
 | 
				
			||||||
 | 
								"negative data length %d invalid, data area ignored\n",
 | 
				
			||||||
 | 
								*len);
 | 
				
			||||||
 | 
							*len = 0;
 | 
				
			||||||
 | 
						} else if (*len > 128 * 1024) {
 | 
				
			||||||
 | 
							ksmbd_debug(SMB, "data area larger than 128K: %d\n", *len);
 | 
				
			||||||
 | 
							*len = 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* return pointer to beginning of data area, ie offset from SMB start */
 | 
				
			||||||
 | 
						if ((*off != 0) && (*len != 0))
 | 
				
			||||||
 | 
							return (char *)hdr + *off;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Calculate the size of the SMB message based on the fixed header
 | 
				
			||||||
 | 
					 * portion, the number of word parameters and the data portion of the message.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static unsigned int smb2_calc_size(void *buf)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct smb2_pdu *pdu = (struct smb2_pdu *)buf;
 | 
				
			||||||
 | 
						struct smb2_hdr *hdr = &pdu->hdr;
 | 
				
			||||||
 | 
						int offset; /* the offset from the beginning of SMB to data area */
 | 
				
			||||||
 | 
						int data_length; /* the length of the variable length data area */
 | 
				
			||||||
 | 
						/* Structure Size has already been checked to make sure it is 64 */
 | 
				
			||||||
 | 
						int len = le16_to_cpu(hdr->StructureSize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * StructureSize2, ie length of fixed parameter area has already
 | 
				
			||||||
 | 
						 * been checked to make sure it is the correct length.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						len += le16_to_cpu(pdu->StructureSize2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (has_smb2_data_area[le16_to_cpu(hdr->Command)] == false)
 | 
				
			||||||
 | 
							goto calc_size_exit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						smb2_get_data_area_len(&offset, &data_length, hdr);
 | 
				
			||||||
 | 
						ksmbd_debug(SMB, "SMB2 data length %d offset %d\n", data_length,
 | 
				
			||||||
 | 
							offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (data_length > 0) {
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * Check to make sure that data area begins after fixed area,
 | 
				
			||||||
 | 
							 * Note that last byte of the fixed area is part of data area
 | 
				
			||||||
 | 
							 * for some commands, typically those with odd StructureSize,
 | 
				
			||||||
 | 
							 * so we must add one to the calculation.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							if (offset + 1 < len)
 | 
				
			||||||
 | 
								ksmbd_debug(SMB,
 | 
				
			||||||
 | 
									"data area offset %d overlaps SMB2 header %d\n",
 | 
				
			||||||
 | 
										offset + 1, len);
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								len = offset + data_length;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					calc_size_exit:
 | 
				
			||||||
 | 
						ksmbd_debug(SMB, "SMB2 len %d\n", len);
 | 
				
			||||||
 | 
						return len;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline int smb2_query_info_req_len(struct smb2_query_info_req *h)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return le32_to_cpu(h->InputBufferLength) +
 | 
				
			||||||
 | 
							le32_to_cpu(h->OutputBufferLength);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline int smb2_set_info_req_len(struct smb2_set_info_req *h)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return le32_to_cpu(h->BufferLength);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline int smb2_read_req_len(struct smb2_read_req *h)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return le32_to_cpu(h->Length);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline int smb2_write_req_len(struct smb2_write_req *h)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return le32_to_cpu(h->Length);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline int smb2_query_dir_req_len(struct smb2_query_directory_req *h)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return le32_to_cpu(h->OutputBufferLength);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline int smb2_ioctl_req_len(struct smb2_ioctl_req *h)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return le32_to_cpu(h->InputCount) +
 | 
				
			||||||
 | 
							le32_to_cpu(h->OutputCount);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline int smb2_ioctl_resp_len(struct smb2_ioctl_req *h)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return le32_to_cpu(h->MaxInputResponse) +
 | 
				
			||||||
 | 
							le32_to_cpu(h->MaxOutputResponse);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int smb2_validate_credit_charge(struct smb2_hdr *hdr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int req_len = 0, expect_resp_len = 0, calc_credit_num, max_len;
 | 
				
			||||||
 | 
						int credit_charge = le16_to_cpu(hdr->CreditCharge);
 | 
				
			||||||
 | 
						void *__hdr = hdr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (hdr->Command) {
 | 
				
			||||||
 | 
						case SMB2_QUERY_INFO:
 | 
				
			||||||
 | 
							req_len = smb2_query_info_req_len(__hdr);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case SMB2_SET_INFO:
 | 
				
			||||||
 | 
							req_len = smb2_set_info_req_len(__hdr);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case SMB2_READ:
 | 
				
			||||||
 | 
							req_len = smb2_read_req_len(__hdr);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case SMB2_WRITE:
 | 
				
			||||||
 | 
							req_len = smb2_write_req_len(__hdr);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case SMB2_QUERY_DIRECTORY:
 | 
				
			||||||
 | 
							req_len = smb2_query_dir_req_len(__hdr);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case SMB2_IOCTL:
 | 
				
			||||||
 | 
							req_len = smb2_ioctl_req_len(__hdr);
 | 
				
			||||||
 | 
							expect_resp_len = smb2_ioctl_resp_len(__hdr);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						max_len = max(req_len, expect_resp_len);
 | 
				
			||||||
 | 
						calc_credit_num = DIV_ROUND_UP(max_len, SMB2_MAX_BUFFER_SIZE);
 | 
				
			||||||
 | 
						if (!credit_charge && max_len > SMB2_MAX_BUFFER_SIZE) {
 | 
				
			||||||
 | 
							ksmbd_err("credit charge is zero and payload size(%d) is bigger than 64K\n",
 | 
				
			||||||
 | 
								max_len);
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						} else if (credit_charge < calc_credit_num) {
 | 
				
			||||||
 | 
							ksmbd_err("credit charge : %d, calc_credit_num : %d\n",
 | 
				
			||||||
 | 
								credit_charge, calc_credit_num);
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_smb2_check_message(struct ksmbd_work *work)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct smb2_pdu *pdu = REQUEST_BUF(work);
 | 
				
			||||||
 | 
						struct smb2_hdr *hdr = &pdu->hdr;
 | 
				
			||||||
 | 
						int command;
 | 
				
			||||||
 | 
						__u32 clc_len;  /* calculated length */
 | 
				
			||||||
 | 
						__u32 len = get_rfc1002_len(pdu);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (work->next_smb2_rcv_hdr_off) {
 | 
				
			||||||
 | 
							pdu = REQUEST_BUF_NEXT(work);
 | 
				
			||||||
 | 
							hdr = &pdu->hdr;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (le32_to_cpu(hdr->NextCommand) > 0)
 | 
				
			||||||
 | 
							len = le32_to_cpu(hdr->NextCommand);
 | 
				
			||||||
 | 
						else if (work->next_smb2_rcv_hdr_off) {
 | 
				
			||||||
 | 
							len -= work->next_smb2_rcv_hdr_off;
 | 
				
			||||||
 | 
							len = round_up(len, 8);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (check_smb2_hdr(hdr))
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (hdr->StructureSize != SMB2_HEADER_STRUCTURE_SIZE) {
 | 
				
			||||||
 | 
							ksmbd_debug(SMB, "Illegal structure size %u\n",
 | 
				
			||||||
 | 
								le16_to_cpu(hdr->StructureSize));
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						command = le16_to_cpu(hdr->Command);
 | 
				
			||||||
 | 
						if (command >= NUMBER_OF_SMB2_COMMANDS) {
 | 
				
			||||||
 | 
							ksmbd_debug(SMB, "Illegal SMB2 command %d\n", command);
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (smb2_req_struct_sizes[command] != pdu->StructureSize2) {
 | 
				
			||||||
 | 
							if (command != SMB2_OPLOCK_BREAK_HE && (hdr->Status == 0 ||
 | 
				
			||||||
 | 
							    pdu->StructureSize2 != SMB2_ERROR_STRUCTURE_SIZE2_LE)) {
 | 
				
			||||||
 | 
								/* error packets have 9 byte structure size */
 | 
				
			||||||
 | 
								ksmbd_debug(SMB,
 | 
				
			||||||
 | 
									"Illegal request size %u for command %d\n",
 | 
				
			||||||
 | 
									le16_to_cpu(pdu->StructureSize2), command);
 | 
				
			||||||
 | 
								return 1;
 | 
				
			||||||
 | 
							} else if (command == SMB2_OPLOCK_BREAK_HE
 | 
				
			||||||
 | 
									&& (hdr->Status == 0)
 | 
				
			||||||
 | 
									&& (le16_to_cpu(pdu->StructureSize2) !=
 | 
				
			||||||
 | 
										OP_BREAK_STRUCT_SIZE_20)
 | 
				
			||||||
 | 
									&& (le16_to_cpu(pdu->StructureSize2) !=
 | 
				
			||||||
 | 
										OP_BREAK_STRUCT_SIZE_21)) {
 | 
				
			||||||
 | 
								/* special case for SMB2.1 lease break message */
 | 
				
			||||||
 | 
								ksmbd_debug(SMB,
 | 
				
			||||||
 | 
									"Illegal request size %d for oplock break\n",
 | 
				
			||||||
 | 
									le16_to_cpu(pdu->StructureSize2));
 | 
				
			||||||
 | 
								return 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						clc_len = smb2_calc_size(hdr);
 | 
				
			||||||
 | 
						if (len != clc_len) {
 | 
				
			||||||
 | 
							/* server can return one byte more due to implied bcc[0] */
 | 
				
			||||||
 | 
							if (clc_len == len + 1)
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * Some windows servers (win2016) will pad also the final
 | 
				
			||||||
 | 
							 * PDU in a compound to 8 bytes.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							if (ALIGN(clc_len, 8) == len)
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * windows client also pad up to 8 bytes when compounding.
 | 
				
			||||||
 | 
							 * If pad is longer than eight bytes, log the server behavior
 | 
				
			||||||
 | 
							 * (once), since may indicate a problem but allow it and
 | 
				
			||||||
 | 
							 * continue since the frame is parseable.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							if (clc_len < len) {
 | 
				
			||||||
 | 
								ksmbd_debug(SMB,
 | 
				
			||||||
 | 
									"cli req padded more than expected. Length %d not %d for cmd:%d mid:%llu\n",
 | 
				
			||||||
 | 
										len, clc_len, command,
 | 
				
			||||||
 | 
										le64_to_cpu(hdr->MessageId));
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (command == SMB2_LOCK_HE && len == 88)
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ksmbd_debug(SMB,
 | 
				
			||||||
 | 
								"cli req too short, len %d not %d. cmd:%d mid:%llu\n",
 | 
				
			||||||
 | 
									len, clc_len, command,
 | 
				
			||||||
 | 
									le64_to_cpu(hdr->MessageId));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return work->conn->vals->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU ?
 | 
				
			||||||
 | 
							smb2_validate_credit_charge(hdr) : 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int smb2_negotiate_request(struct ksmbd_work *work)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ksmbd_smb_negotiate_common(work, SMB2_NEGOTIATE_HE);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										300
									
								
								fs/cifsd/smb2ops.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										300
									
								
								fs/cifsd/smb2ops.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,300 @@
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: GPL-2.0-or-later
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *   Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
 | 
				
			||||||
 | 
					 *   Copyright (C) 2018 Samsung Electronics Co., Ltd.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <linux/slab.h>
 | 
				
			||||||
 | 
					#include "glob.h"
 | 
				
			||||||
 | 
					#include "smb2pdu.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "auth.h"
 | 
				
			||||||
 | 
					#include "connection.h"
 | 
				
			||||||
 | 
					#include "smb_common.h"
 | 
				
			||||||
 | 
					#include "server.h"
 | 
				
			||||||
 | 
					#include "ksmbd_server.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct smb_version_values smb21_server_values = {
 | 
				
			||||||
 | 
						.version_string = SMB21_VERSION_STRING,
 | 
				
			||||||
 | 
						.protocol_id = SMB21_PROT_ID,
 | 
				
			||||||
 | 
						.capabilities = SMB2_GLOBAL_CAP_LARGE_MTU,
 | 
				
			||||||
 | 
						.max_read_size = SMB21_DEFAULT_IOSIZE,
 | 
				
			||||||
 | 
						.max_write_size = SMB21_DEFAULT_IOSIZE,
 | 
				
			||||||
 | 
						.max_trans_size = SMB21_DEFAULT_IOSIZE,
 | 
				
			||||||
 | 
						.large_lock_type = 0,
 | 
				
			||||||
 | 
						.exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE,
 | 
				
			||||||
 | 
						.shared_lock_type = SMB2_LOCKFLAG_SHARED,
 | 
				
			||||||
 | 
						.unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
 | 
				
			||||||
 | 
						.header_size = sizeof(struct smb2_hdr),
 | 
				
			||||||
 | 
						.max_header_size = MAX_SMB2_HDR_SIZE,
 | 
				
			||||||
 | 
						.read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
 | 
				
			||||||
 | 
						.lock_cmd = SMB2_LOCK,
 | 
				
			||||||
 | 
						.cap_unix = 0,
 | 
				
			||||||
 | 
						.cap_nt_find = SMB2_NT_FIND,
 | 
				
			||||||
 | 
						.cap_large_files = SMB2_LARGE_FILES,
 | 
				
			||||||
 | 
						.create_lease_size = sizeof(struct create_lease),
 | 
				
			||||||
 | 
						.create_durable_size = sizeof(struct create_durable_rsp),
 | 
				
			||||||
 | 
						.create_mxac_size = sizeof(struct create_mxac_rsp),
 | 
				
			||||||
 | 
						.create_disk_id_size = sizeof(struct create_disk_id_rsp),
 | 
				
			||||||
 | 
						.create_posix_size = sizeof(struct create_posix_rsp),
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct smb_version_values smb30_server_values = {
 | 
				
			||||||
 | 
						.version_string = SMB30_VERSION_STRING,
 | 
				
			||||||
 | 
						.protocol_id = SMB30_PROT_ID,
 | 
				
			||||||
 | 
						.capabilities = SMB2_GLOBAL_CAP_LARGE_MTU,
 | 
				
			||||||
 | 
						.max_read_size = SMB3_DEFAULT_IOSIZE,
 | 
				
			||||||
 | 
						.max_write_size = SMB3_DEFAULT_IOSIZE,
 | 
				
			||||||
 | 
						.max_trans_size = SMB3_DEFAULT_TRANS_SIZE,
 | 
				
			||||||
 | 
						.large_lock_type = 0,
 | 
				
			||||||
 | 
						.exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE,
 | 
				
			||||||
 | 
						.shared_lock_type = SMB2_LOCKFLAG_SHARED,
 | 
				
			||||||
 | 
						.unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
 | 
				
			||||||
 | 
						.header_size = sizeof(struct smb2_hdr),
 | 
				
			||||||
 | 
						.max_header_size = MAX_SMB2_HDR_SIZE,
 | 
				
			||||||
 | 
						.read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
 | 
				
			||||||
 | 
						.lock_cmd = SMB2_LOCK,
 | 
				
			||||||
 | 
						.cap_unix = 0,
 | 
				
			||||||
 | 
						.cap_nt_find = SMB2_NT_FIND,
 | 
				
			||||||
 | 
						.cap_large_files = SMB2_LARGE_FILES,
 | 
				
			||||||
 | 
						.create_lease_size = sizeof(struct create_lease),
 | 
				
			||||||
 | 
						.create_durable_size = sizeof(struct create_durable_rsp),
 | 
				
			||||||
 | 
						.create_durable_v2_size = sizeof(struct create_durable_v2_rsp),
 | 
				
			||||||
 | 
						.create_mxac_size = sizeof(struct create_mxac_rsp),
 | 
				
			||||||
 | 
						.create_disk_id_size = sizeof(struct create_disk_id_rsp),
 | 
				
			||||||
 | 
						.create_posix_size = sizeof(struct create_posix_rsp),
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct smb_version_values smb302_server_values = {
 | 
				
			||||||
 | 
						.version_string = SMB302_VERSION_STRING,
 | 
				
			||||||
 | 
						.protocol_id = SMB302_PROT_ID,
 | 
				
			||||||
 | 
						.capabilities = SMB2_GLOBAL_CAP_LARGE_MTU,
 | 
				
			||||||
 | 
						.max_read_size = SMB3_DEFAULT_IOSIZE,
 | 
				
			||||||
 | 
						.max_write_size = SMB3_DEFAULT_IOSIZE,
 | 
				
			||||||
 | 
						.max_trans_size = SMB3_DEFAULT_TRANS_SIZE,
 | 
				
			||||||
 | 
						.large_lock_type = 0,
 | 
				
			||||||
 | 
						.exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE,
 | 
				
			||||||
 | 
						.shared_lock_type = SMB2_LOCKFLAG_SHARED,
 | 
				
			||||||
 | 
						.unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
 | 
				
			||||||
 | 
						.header_size = sizeof(struct smb2_hdr),
 | 
				
			||||||
 | 
						.max_header_size = MAX_SMB2_HDR_SIZE,
 | 
				
			||||||
 | 
						.read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
 | 
				
			||||||
 | 
						.lock_cmd = SMB2_LOCK,
 | 
				
			||||||
 | 
						.cap_unix = 0,
 | 
				
			||||||
 | 
						.cap_nt_find = SMB2_NT_FIND,
 | 
				
			||||||
 | 
						.cap_large_files = SMB2_LARGE_FILES,
 | 
				
			||||||
 | 
						.create_lease_size = sizeof(struct create_lease),
 | 
				
			||||||
 | 
						.create_durable_size = sizeof(struct create_durable_rsp),
 | 
				
			||||||
 | 
						.create_durable_v2_size = sizeof(struct create_durable_v2_rsp),
 | 
				
			||||||
 | 
						.create_mxac_size = sizeof(struct create_mxac_rsp),
 | 
				
			||||||
 | 
						.create_disk_id_size = sizeof(struct create_disk_id_rsp),
 | 
				
			||||||
 | 
						.create_posix_size = sizeof(struct create_posix_rsp),
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct smb_version_values smb311_server_values = {
 | 
				
			||||||
 | 
						.version_string = SMB311_VERSION_STRING,
 | 
				
			||||||
 | 
						.protocol_id = SMB311_PROT_ID,
 | 
				
			||||||
 | 
						.capabilities = SMB2_GLOBAL_CAP_LARGE_MTU,
 | 
				
			||||||
 | 
						.max_read_size = SMB3_DEFAULT_IOSIZE,
 | 
				
			||||||
 | 
						.max_write_size = SMB3_DEFAULT_IOSIZE,
 | 
				
			||||||
 | 
						.max_trans_size = SMB3_DEFAULT_TRANS_SIZE,
 | 
				
			||||||
 | 
						.large_lock_type = 0,
 | 
				
			||||||
 | 
						.exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE,
 | 
				
			||||||
 | 
						.shared_lock_type = SMB2_LOCKFLAG_SHARED,
 | 
				
			||||||
 | 
						.unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
 | 
				
			||||||
 | 
						.header_size = sizeof(struct smb2_hdr),
 | 
				
			||||||
 | 
						.max_header_size = MAX_SMB2_HDR_SIZE,
 | 
				
			||||||
 | 
						.read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
 | 
				
			||||||
 | 
						.lock_cmd = SMB2_LOCK,
 | 
				
			||||||
 | 
						.cap_unix = 0,
 | 
				
			||||||
 | 
						.cap_nt_find = SMB2_NT_FIND,
 | 
				
			||||||
 | 
						.cap_large_files = SMB2_LARGE_FILES,
 | 
				
			||||||
 | 
						.create_lease_size = sizeof(struct create_lease),
 | 
				
			||||||
 | 
						.create_durable_size = sizeof(struct create_durable_rsp),
 | 
				
			||||||
 | 
						.create_durable_v2_size = sizeof(struct create_durable_v2_rsp),
 | 
				
			||||||
 | 
						.create_mxac_size = sizeof(struct create_mxac_rsp),
 | 
				
			||||||
 | 
						.create_disk_id_size = sizeof(struct create_disk_id_rsp),
 | 
				
			||||||
 | 
						.create_posix_size = sizeof(struct create_posix_rsp),
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct smb_version_ops smb2_0_server_ops = {
 | 
				
			||||||
 | 
						.get_cmd_val		=	get_smb2_cmd_val,
 | 
				
			||||||
 | 
						.init_rsp_hdr		=	init_smb2_rsp_hdr,
 | 
				
			||||||
 | 
						.set_rsp_status		=	set_smb2_rsp_status,
 | 
				
			||||||
 | 
						.allocate_rsp_buf       =       smb2_allocate_rsp_buf,
 | 
				
			||||||
 | 
						.set_rsp_credits	=	smb2_set_rsp_credits,
 | 
				
			||||||
 | 
						.check_user_session	=	smb2_check_user_session,
 | 
				
			||||||
 | 
						.get_ksmbd_tcon		=	smb2_get_ksmbd_tcon,
 | 
				
			||||||
 | 
						.is_sign_req		=	smb2_is_sign_req,
 | 
				
			||||||
 | 
						.check_sign_req		=	smb2_check_sign_req,
 | 
				
			||||||
 | 
						.set_sign_rsp		=	smb2_set_sign_rsp
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct smb_version_ops smb3_0_server_ops = {
 | 
				
			||||||
 | 
						.get_cmd_val		=	get_smb2_cmd_val,
 | 
				
			||||||
 | 
						.init_rsp_hdr		=	init_smb2_rsp_hdr,
 | 
				
			||||||
 | 
						.set_rsp_status		=	set_smb2_rsp_status,
 | 
				
			||||||
 | 
						.allocate_rsp_buf       =       smb2_allocate_rsp_buf,
 | 
				
			||||||
 | 
						.set_rsp_credits	=	smb2_set_rsp_credits,
 | 
				
			||||||
 | 
						.check_user_session	=	smb2_check_user_session,
 | 
				
			||||||
 | 
						.get_ksmbd_tcon		=	smb2_get_ksmbd_tcon,
 | 
				
			||||||
 | 
						.is_sign_req		=	smb2_is_sign_req,
 | 
				
			||||||
 | 
						.check_sign_req		=	smb3_check_sign_req,
 | 
				
			||||||
 | 
						.set_sign_rsp		=	smb3_set_sign_rsp,
 | 
				
			||||||
 | 
						.generate_signingkey	=	ksmbd_gen_smb30_signingkey,
 | 
				
			||||||
 | 
						.generate_encryptionkey	=	ksmbd_gen_smb30_encryptionkey,
 | 
				
			||||||
 | 
						.is_transform_hdr	=	smb3_is_transform_hdr,
 | 
				
			||||||
 | 
						.decrypt_req		=	smb3_decrypt_req,
 | 
				
			||||||
 | 
						.encrypt_resp		=	smb3_encrypt_resp
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct smb_version_ops smb3_11_server_ops = {
 | 
				
			||||||
 | 
						.get_cmd_val		=	get_smb2_cmd_val,
 | 
				
			||||||
 | 
						.init_rsp_hdr		=	init_smb2_rsp_hdr,
 | 
				
			||||||
 | 
						.set_rsp_status		=	set_smb2_rsp_status,
 | 
				
			||||||
 | 
						.allocate_rsp_buf       =       smb2_allocate_rsp_buf,
 | 
				
			||||||
 | 
						.set_rsp_credits	=	smb2_set_rsp_credits,
 | 
				
			||||||
 | 
						.check_user_session	=	smb2_check_user_session,
 | 
				
			||||||
 | 
						.get_ksmbd_tcon		=	smb2_get_ksmbd_tcon,
 | 
				
			||||||
 | 
						.is_sign_req		=	smb2_is_sign_req,
 | 
				
			||||||
 | 
						.check_sign_req		=	smb3_check_sign_req,
 | 
				
			||||||
 | 
						.set_sign_rsp		=	smb3_set_sign_rsp,
 | 
				
			||||||
 | 
						.generate_signingkey	=	ksmbd_gen_smb311_signingkey,
 | 
				
			||||||
 | 
						.generate_encryptionkey	=	ksmbd_gen_smb311_encryptionkey,
 | 
				
			||||||
 | 
						.is_transform_hdr	=	smb3_is_transform_hdr,
 | 
				
			||||||
 | 
						.decrypt_req		=	smb3_decrypt_req,
 | 
				
			||||||
 | 
						.encrypt_resp		=	smb3_encrypt_resp
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct smb_version_cmds smb2_0_server_cmds[NUMBER_OF_SMB2_COMMANDS] = {
 | 
				
			||||||
 | 
						[SMB2_NEGOTIATE_HE]	=	{ .proc = smb2_negotiate_request, },
 | 
				
			||||||
 | 
						[SMB2_SESSION_SETUP_HE] =	{ .proc = smb2_sess_setup, },
 | 
				
			||||||
 | 
						[SMB2_TREE_CONNECT_HE]  =	{ .proc = smb2_tree_connect,},
 | 
				
			||||||
 | 
						[SMB2_TREE_DISCONNECT_HE]  =	{ .proc = smb2_tree_disconnect,},
 | 
				
			||||||
 | 
						[SMB2_LOGOFF_HE]	=	{ .proc = smb2_session_logoff,},
 | 
				
			||||||
 | 
						[SMB2_CREATE_HE]	=	{ .proc = smb2_open},
 | 
				
			||||||
 | 
						[SMB2_QUERY_INFO_HE]	=	{ .proc = smb2_query_info},
 | 
				
			||||||
 | 
						[SMB2_QUERY_DIRECTORY_HE] =	{ .proc = smb2_query_dir},
 | 
				
			||||||
 | 
						[SMB2_CLOSE_HE]		=	{ .proc = smb2_close},
 | 
				
			||||||
 | 
						[SMB2_ECHO_HE]		=	{ .proc = smb2_echo},
 | 
				
			||||||
 | 
						[SMB2_SET_INFO_HE]      =       { .proc = smb2_set_info},
 | 
				
			||||||
 | 
						[SMB2_READ_HE]		=	{ .proc = smb2_read},
 | 
				
			||||||
 | 
						[SMB2_WRITE_HE]		=	{ .proc = smb2_write},
 | 
				
			||||||
 | 
						[SMB2_FLUSH_HE]		=	{ .proc = smb2_flush},
 | 
				
			||||||
 | 
						[SMB2_CANCEL_HE]	=	{ .proc = smb2_cancel},
 | 
				
			||||||
 | 
						[SMB2_LOCK_HE]		=	{ .proc = smb2_lock},
 | 
				
			||||||
 | 
						[SMB2_IOCTL_HE]		=	{ .proc = smb2_ioctl},
 | 
				
			||||||
 | 
						[SMB2_OPLOCK_BREAK_HE]	=	{ .proc = smb2_oplock_break},
 | 
				
			||||||
 | 
						[SMB2_CHANGE_NOTIFY_HE]	=	{ .proc = smb2_notify},
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int init_smb2_0_server(struct ksmbd_conn *conn)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return -EOPNOTSUPP;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * init_smb2_1_server() - initialize a smb server connection with smb2.1
 | 
				
			||||||
 | 
					 *			command dispatcher
 | 
				
			||||||
 | 
					 * @conn:	connection instance
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void init_smb2_1_server(struct ksmbd_conn *conn)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						conn->vals = &smb21_server_values;
 | 
				
			||||||
 | 
						conn->ops = &smb2_0_server_ops;
 | 
				
			||||||
 | 
						conn->cmds = smb2_0_server_cmds;
 | 
				
			||||||
 | 
						conn->max_cmds = ARRAY_SIZE(smb2_0_server_cmds);
 | 
				
			||||||
 | 
						conn->max_credits = SMB2_MAX_CREDITS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES)
 | 
				
			||||||
 | 
							conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * init_smb3_0_server() - initialize a smb server connection with smb3.0
 | 
				
			||||||
 | 
					 *			command dispatcher
 | 
				
			||||||
 | 
					 * @conn:	connection instance
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void init_smb3_0_server(struct ksmbd_conn *conn)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						conn->vals = &smb30_server_values;
 | 
				
			||||||
 | 
						conn->ops = &smb3_0_server_ops;
 | 
				
			||||||
 | 
						conn->cmds = smb2_0_server_cmds;
 | 
				
			||||||
 | 
						conn->max_cmds = ARRAY_SIZE(smb2_0_server_cmds);
 | 
				
			||||||
 | 
						conn->max_credits = SMB2_MAX_CREDITS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES)
 | 
				
			||||||
 | 
							conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION &&
 | 
				
			||||||
 | 
							conn->cli_cap & SMB2_GLOBAL_CAP_ENCRYPTION)
 | 
				
			||||||
 | 
							conn->vals->capabilities |= SMB2_GLOBAL_CAP_ENCRYPTION;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * init_smb3_02_server() - initialize a smb server connection with smb3.02
 | 
				
			||||||
 | 
					 *			command dispatcher
 | 
				
			||||||
 | 
					 * @conn:	connection instance
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void init_smb3_02_server(struct ksmbd_conn *conn)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						conn->vals = &smb302_server_values;
 | 
				
			||||||
 | 
						conn->ops = &smb3_0_server_ops;
 | 
				
			||||||
 | 
						conn->cmds = smb2_0_server_cmds;
 | 
				
			||||||
 | 
						conn->max_cmds = ARRAY_SIZE(smb2_0_server_cmds);
 | 
				
			||||||
 | 
						conn->max_credits = SMB2_MAX_CREDITS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES)
 | 
				
			||||||
 | 
							conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION &&
 | 
				
			||||||
 | 
							conn->cli_cap & SMB2_GLOBAL_CAP_ENCRYPTION)
 | 
				
			||||||
 | 
							conn->vals->capabilities |= SMB2_GLOBAL_CAP_ENCRYPTION;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * init_smb3_11_server() - initialize a smb server connection with smb3.11
 | 
				
			||||||
 | 
					 *			command dispatcher
 | 
				
			||||||
 | 
					 * @conn:	connection instance
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int init_smb3_11_server(struct ksmbd_conn *conn)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						conn->vals = &smb311_server_values;
 | 
				
			||||||
 | 
						conn->ops = &smb3_11_server_ops;
 | 
				
			||||||
 | 
						conn->cmds = smb2_0_server_cmds;
 | 
				
			||||||
 | 
						conn->max_cmds = ARRAY_SIZE(smb2_0_server_cmds);
 | 
				
			||||||
 | 
						conn->max_credits = SMB2_MAX_CREDITS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES)
 | 
				
			||||||
 | 
							conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (conn->cipher_type)
 | 
				
			||||||
 | 
							conn->vals->capabilities |= SMB2_GLOBAL_CAP_ENCRYPTION;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						INIT_LIST_HEAD(&conn->preauth_sess_table);
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void init_smb2_max_read_size(unsigned int sz)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						smb21_server_values.max_read_size = sz;
 | 
				
			||||||
 | 
						smb30_server_values.max_read_size = sz;
 | 
				
			||||||
 | 
						smb302_server_values.max_read_size = sz;
 | 
				
			||||||
 | 
						smb311_server_values.max_read_size = sz;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void init_smb2_max_write_size(unsigned int sz)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						smb21_server_values.max_write_size = sz;
 | 
				
			||||||
 | 
						smb30_server_values.max_write_size = sz;
 | 
				
			||||||
 | 
						smb302_server_values.max_write_size = sz;
 | 
				
			||||||
 | 
						smb311_server_values.max_write_size = sz;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void init_smb2_max_trans_size(unsigned int sz)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						smb21_server_values.max_trans_size = sz;
 | 
				
			||||||
 | 
						smb30_server_values.max_trans_size = sz;
 | 
				
			||||||
 | 
						smb302_server_values.max_trans_size = sz;
 | 
				
			||||||
 | 
						smb311_server_values.max_trans_size = sz;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										8486
									
								
								fs/cifsd/smb2pdu.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8486
									
								
								fs/cifsd/smb2pdu.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										1649
									
								
								fs/cifsd/smb2pdu.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1649
									
								
								fs/cifsd/smb2pdu.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										668
									
								
								fs/cifsd/smb_common.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										668
									
								
								fs/cifsd/smb_common.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,668 @@
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: GPL-2.0-or-later
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *   Copyright (C) 2018 Samsung Electronics Co., Ltd.
 | 
				
			||||||
 | 
					 *   Copyright (C) 2018 Namjae Jeon <linkinjeon@kernel.org>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "smb_common.h"
 | 
				
			||||||
 | 
					#include "server.h"
 | 
				
			||||||
 | 
					#include "misc.h"
 | 
				
			||||||
 | 
					#include "smbstatus.h"
 | 
				
			||||||
 | 
					/* @FIXME */
 | 
				
			||||||
 | 
					#include "connection.h"
 | 
				
			||||||
 | 
					#include "ksmbd_work.h"
 | 
				
			||||||
 | 
					#include "mgmt/user_session.h"
 | 
				
			||||||
 | 
					#include "mgmt/user_config.h"
 | 
				
			||||||
 | 
					#include "mgmt/tree_connect.h"
 | 
				
			||||||
 | 
					#include "mgmt/share_config.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*for shortname implementation */
 | 
				
			||||||
 | 
					static const char basechars[43] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_-!@#$%";
 | 
				
			||||||
 | 
					#define MANGLE_BASE       (sizeof(basechars)/sizeof(char)-1)
 | 
				
			||||||
 | 
					#define MAGIC_CHAR '~'
 | 
				
			||||||
 | 
					#define PERIOD '.'
 | 
				
			||||||
 | 
					#define mangle(V) ((char)(basechars[(V) % MANGLE_BASE]))
 | 
				
			||||||
 | 
					#define KSMBD_MIN_SUPPORTED_HEADER_SIZE	(sizeof(struct smb2_hdr))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					LIST_HEAD(global_lock_list);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct smb_protocol {
 | 
				
			||||||
 | 
						int		index;
 | 
				
			||||||
 | 
						char		*name;
 | 
				
			||||||
 | 
						char		*prot;
 | 
				
			||||||
 | 
						__u16		prot_id;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct smb_protocol smb_protos[] = {
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							SMB21_PROT,
 | 
				
			||||||
 | 
							"\2SMB 2.1",
 | 
				
			||||||
 | 
							"SMB2_10",
 | 
				
			||||||
 | 
							SMB21_PROT_ID
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							SMB2X_PROT,
 | 
				
			||||||
 | 
							"\2SMB 2.???",
 | 
				
			||||||
 | 
							"SMB2_22",
 | 
				
			||||||
 | 
							SMB2X_PROT_ID
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							SMB30_PROT,
 | 
				
			||||||
 | 
							"\2SMB 3.0",
 | 
				
			||||||
 | 
							"SMB3_00",
 | 
				
			||||||
 | 
							SMB30_PROT_ID
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							SMB302_PROT,
 | 
				
			||||||
 | 
							"\2SMB 3.02",
 | 
				
			||||||
 | 
							"SMB3_02",
 | 
				
			||||||
 | 
							SMB302_PROT_ID
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							SMB311_PROT,
 | 
				
			||||||
 | 
							"\2SMB 3.1.1",
 | 
				
			||||||
 | 
							"SMB3_11",
 | 
				
			||||||
 | 
							SMB311_PROT_ID
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unsigned int ksmbd_server_side_copy_max_chunk_count(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return 256;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unsigned int ksmbd_server_side_copy_max_chunk_size(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return (2U << 30) - 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unsigned int ksmbd_server_side_copy_max_total_size(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return (2U << 30) - 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline int ksmbd_min_protocol(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return SMB2_PROT;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline int ksmbd_max_protocol(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return SMB311_PROT;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_lookup_protocol_idx(char *str)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int offt = ARRAY_SIZE(smb_protos) - 1;
 | 
				
			||||||
 | 
						int len = strlen(str);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (offt >= 0) {
 | 
				
			||||||
 | 
							if (!strncmp(str, smb_protos[offt].prot, len)) {
 | 
				
			||||||
 | 
								ksmbd_debug(SMB, "selected %s dialect idx = %d\n",
 | 
				
			||||||
 | 
										smb_protos[offt].prot, offt);
 | 
				
			||||||
 | 
								return smb_protos[offt].index;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							offt--;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return -1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * check_message() - check for valid smb2 request header
 | 
				
			||||||
 | 
					 * @buf:       smb2 header to be checked
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * check for valid smb signature and packet direction(request/response)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return:      0 on success, otherwise 1
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int ksmbd_verify_smb_message(struct ksmbd_work *work)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct smb2_hdr *smb2_hdr = REQUEST_BUF(work);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (smb2_hdr->ProtocolId == SMB2_PROTO_NUMBER)
 | 
				
			||||||
 | 
							return ksmbd_smb2_check_message(work);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * is_smb_request() - check for valid smb request type
 | 
				
			||||||
 | 
					 * @conn:	connection instance
 | 
				
			||||||
 | 
					 * @type:	smb request type
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return:      true on success, otherwise false
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					bool ksmbd_smb_request(struct ksmbd_conn *conn)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int type = *(char *)conn->request_buf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (type) {
 | 
				
			||||||
 | 
						case RFC1002_SESSION_MESSAGE:
 | 
				
			||||||
 | 
							/* Regular SMB request */
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						case RFC1002_SESSION_KEEP_ALIVE:
 | 
				
			||||||
 | 
							ksmbd_debug(SMB, "RFC 1002 session keep alive\n");
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							ksmbd_debug(SMB, "RFC 1002 unknown request type 0x%x\n", type);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool supported_protocol(int idx)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (idx == SMB2X_PROT &&
 | 
				
			||||||
 | 
						    (server_conf.min_protocol >= SMB21_PROT ||
 | 
				
			||||||
 | 
						     server_conf.max_protocol <= SMB311_PROT))
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return (server_conf.min_protocol <= idx &&
 | 
				
			||||||
 | 
								idx <= server_conf.max_protocol);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static char *next_dialect(char *dialect, int *next_off)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						dialect = dialect + *next_off;
 | 
				
			||||||
 | 
						*next_off = strlen(dialect);
 | 
				
			||||||
 | 
						return dialect;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int ksmbd_lookup_dialect_by_name(char *cli_dialects, __le16 byte_count)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i, seq_num, bcount, next;
 | 
				
			||||||
 | 
						char *dialect;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = ARRAY_SIZE(smb_protos) - 1; i >= 0; i--) {
 | 
				
			||||||
 | 
							seq_num = 0;
 | 
				
			||||||
 | 
							next = 0;
 | 
				
			||||||
 | 
							dialect = cli_dialects;
 | 
				
			||||||
 | 
							bcount = le16_to_cpu(byte_count);
 | 
				
			||||||
 | 
							do {
 | 
				
			||||||
 | 
								dialect = next_dialect(dialect, &next);
 | 
				
			||||||
 | 
								ksmbd_debug(SMB, "client requested dialect %s\n",
 | 
				
			||||||
 | 
									dialect);
 | 
				
			||||||
 | 
								if (!strcmp(dialect, smb_protos[i].name)) {
 | 
				
			||||||
 | 
									if (supported_protocol(smb_protos[i].index)) {
 | 
				
			||||||
 | 
										ksmbd_debug(SMB,
 | 
				
			||||||
 | 
											"selected %s dialect\n",
 | 
				
			||||||
 | 
											smb_protos[i].name);
 | 
				
			||||||
 | 
										if (smb_protos[i].index == SMB1_PROT)
 | 
				
			||||||
 | 
											return seq_num;
 | 
				
			||||||
 | 
										return smb_protos[i].prot_id;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								seq_num++;
 | 
				
			||||||
 | 
								bcount -= (++next);
 | 
				
			||||||
 | 
							} while (bcount > 0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return BAD_PROT_ID;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_lookup_dialect_by_id(__le16 *cli_dialects, __le16 dialects_count)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						int count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = ARRAY_SIZE(smb_protos) - 1; i >= 0; i--) {
 | 
				
			||||||
 | 
							count = le16_to_cpu(dialects_count);
 | 
				
			||||||
 | 
							while (--count >= 0) {
 | 
				
			||||||
 | 
								ksmbd_debug(SMB, "client requested dialect 0x%x\n",
 | 
				
			||||||
 | 
									le16_to_cpu(cli_dialects[count]));
 | 
				
			||||||
 | 
								if (le16_to_cpu(cli_dialects[count]) !=
 | 
				
			||||||
 | 
										smb_protos[i].prot_id)
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (supported_protocol(smb_protos[i].index)) {
 | 
				
			||||||
 | 
									ksmbd_debug(SMB, "selected %s dialect\n",
 | 
				
			||||||
 | 
										smb_protos[i].name);
 | 
				
			||||||
 | 
									return smb_protos[i].prot_id;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return BAD_PROT_ID;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_negotiate_smb_dialect(void *buf)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						__le32 proto;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						proto = ((struct smb2_hdr *)buf)->ProtocolId;
 | 
				
			||||||
 | 
						if (proto == SMB2_PROTO_NUMBER) {
 | 
				
			||||||
 | 
							struct smb2_negotiate_req *req;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							req = (struct smb2_negotiate_req *)buf;
 | 
				
			||||||
 | 
							return ksmbd_lookup_dialect_by_id(req->Dialects,
 | 
				
			||||||
 | 
											  req->DialectCount);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						proto = *(__le32 *)((struct smb_hdr *)buf)->Protocol;
 | 
				
			||||||
 | 
						if (proto == SMB1_PROTO_NUMBER) {
 | 
				
			||||||
 | 
							struct smb_negotiate_req *req;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							req = (struct smb_negotiate_req *)buf;
 | 
				
			||||||
 | 
							return ksmbd_lookup_dialect_by_name(req->DialectsArray,
 | 
				
			||||||
 | 
											    req->ByteCount);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return BAD_PROT_ID;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SMB_COM_NEGOTIATE	0x72
 | 
				
			||||||
 | 
					int ksmbd_init_smb_server(struct ksmbd_work *work)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ksmbd_conn *conn = work->conn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (conn->need_neg == false)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						init_smb3_11_server(conn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (conn->ops->get_cmd_val(work) != SMB_COM_NEGOTIATE)
 | 
				
			||||||
 | 
							conn->need_neg = false;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool ksmbd_pdu_size_has_room(unsigned int pdu)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return (pdu >= KSMBD_MIN_SUPPORTED_HEADER_SIZE - 4);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work,
 | 
				
			||||||
 | 
									      int info_level,
 | 
				
			||||||
 | 
									      struct ksmbd_file *dir,
 | 
				
			||||||
 | 
									      struct ksmbd_dir_info *d_info,
 | 
				
			||||||
 | 
									      char *search_pattern,
 | 
				
			||||||
 | 
									      int (*fn)(struct ksmbd_conn *,
 | 
				
			||||||
 | 
											int,
 | 
				
			||||||
 | 
											struct ksmbd_dir_info *,
 | 
				
			||||||
 | 
											struct ksmbd_kstat *))
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i, rc = 0;
 | 
				
			||||||
 | 
						struct ksmbd_conn *conn = work->conn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < 2; i++) {
 | 
				
			||||||
 | 
							struct kstat kstat;
 | 
				
			||||||
 | 
							struct ksmbd_kstat ksmbd_kstat;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!dir->dot_dotdot[i]) { /* fill dot entry info */
 | 
				
			||||||
 | 
								if (i == 0) {
 | 
				
			||||||
 | 
									d_info->name = ".";
 | 
				
			||||||
 | 
									d_info->name_len = 1;
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									d_info->name = "..";
 | 
				
			||||||
 | 
									d_info->name_len = 2;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (!match_pattern(d_info->name, search_pattern)) {
 | 
				
			||||||
 | 
									dir->dot_dotdot[i] = 1;
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								ksmbd_kstat.kstat = &kstat;
 | 
				
			||||||
 | 
								ksmbd_vfs_fill_dentry_attrs(work,
 | 
				
			||||||
 | 
									dir->filp->f_path.dentry->d_parent,
 | 
				
			||||||
 | 
									&ksmbd_kstat);
 | 
				
			||||||
 | 
								rc = fn(conn, info_level, d_info, &ksmbd_kstat);
 | 
				
			||||||
 | 
								if (rc)
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								if (d_info->out_buf_len <= 0)
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								dir->dot_dotdot[i] = 1;
 | 
				
			||||||
 | 
								if (d_info->flags & SMB2_RETURN_SINGLE_ENTRY) {
 | 
				
			||||||
 | 
									d_info->out_buf_len = 0;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return rc;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * ksmbd_extract_shortname() - get shortname from long filename
 | 
				
			||||||
 | 
					 * @conn:	connection instance
 | 
				
			||||||
 | 
					 * @longname:	source long filename
 | 
				
			||||||
 | 
					 * @shortname:	destination short filename
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return:	shortname length or 0 when source long name is '.' or '..'
 | 
				
			||||||
 | 
					 * TODO: Though this function comforms the restriction of 8.3 Filename spec,
 | 
				
			||||||
 | 
					 * but the result is different with Windows 7's one. need to check.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int ksmbd_extract_shortname(struct ksmbd_conn *conn,
 | 
				
			||||||
 | 
								    const char *longname,
 | 
				
			||||||
 | 
								    char *shortname)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const char *p;
 | 
				
			||||||
 | 
						char base[9], extension[4];
 | 
				
			||||||
 | 
						char out[13] = {0};
 | 
				
			||||||
 | 
						int baselen = 0;
 | 
				
			||||||
 | 
						int extlen = 0, len = 0;
 | 
				
			||||||
 | 
						unsigned int csum = 0;
 | 
				
			||||||
 | 
						const unsigned char *ptr;
 | 
				
			||||||
 | 
						bool dot_present = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p = longname;
 | 
				
			||||||
 | 
						if ((*p == '.') || (!(strcmp(p, "..")))) {
 | 
				
			||||||
 | 
							/*no mangling required */
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p = strrchr(longname, '.');
 | 
				
			||||||
 | 
						if (p == longname) { /*name starts with a dot*/
 | 
				
			||||||
 | 
							strscpy(extension, "___", strlen("___"));
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							if (p != NULL) {
 | 
				
			||||||
 | 
								p++;
 | 
				
			||||||
 | 
								while (*p && extlen < 3) {
 | 
				
			||||||
 | 
									if (*p != '.')
 | 
				
			||||||
 | 
										extension[extlen++] = toupper(*p);
 | 
				
			||||||
 | 
									p++;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								extension[extlen] = '\0';
 | 
				
			||||||
 | 
							} else
 | 
				
			||||||
 | 
								dot_present = false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p = longname;
 | 
				
			||||||
 | 
						if (*p == '.') {
 | 
				
			||||||
 | 
							p++;
 | 
				
			||||||
 | 
							longname++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						while (*p && (baselen < 5)) {
 | 
				
			||||||
 | 
							if (*p != '.')
 | 
				
			||||||
 | 
								base[baselen++] = toupper(*p);
 | 
				
			||||||
 | 
							p++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						base[baselen] = MAGIC_CHAR;
 | 
				
			||||||
 | 
						memcpy(out, base, baselen+1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ptr = longname;
 | 
				
			||||||
 | 
						len = strlen(longname);
 | 
				
			||||||
 | 
						for (; len > 0; len--, ptr++)
 | 
				
			||||||
 | 
							csum += *ptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						csum = csum % (MANGLE_BASE * MANGLE_BASE);
 | 
				
			||||||
 | 
						out[baselen+1] = mangle(csum/MANGLE_BASE);
 | 
				
			||||||
 | 
						out[baselen+2] = mangle(csum);
 | 
				
			||||||
 | 
						out[baselen+3] = PERIOD;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (dot_present)
 | 
				
			||||||
 | 
							memcpy(&out[baselen+4], extension, 4);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							out[baselen+4] = '\0';
 | 
				
			||||||
 | 
						smbConvertToUTF16((__le16 *)shortname, out, PATH_MAX,
 | 
				
			||||||
 | 
								conn->local_nls, 0);
 | 
				
			||||||
 | 
						len = strlen(out) * 2;
 | 
				
			||||||
 | 
						return len;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int __smb2_negotiate(struct ksmbd_conn *conn)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return (conn->dialect >= SMB20_PROT_ID &&
 | 
				
			||||||
 | 
								conn->dialect <= SMB311_PROT_ID);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int smb_handle_negotiate(struct ksmbd_work *work)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct smb_negotiate_rsp *neg_rsp = RESPONSE_BUF(work);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ksmbd_debug(SMB, "Unsupported SMB protocol\n");
 | 
				
			||||||
 | 
						neg_rsp->hdr.Status.CifsError = STATUS_INVALID_LOGON_TYPE;
 | 
				
			||||||
 | 
						return -EINVAL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_smb_negotiate_common(struct ksmbd_work *work, unsigned int command)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ksmbd_conn *conn = work->conn;
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						conn->dialect = ksmbd_negotiate_smb_dialect(REQUEST_BUF(work));
 | 
				
			||||||
 | 
						ksmbd_debug(SMB, "conn->dialect 0x%x\n", conn->dialect);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (command == SMB2_NEGOTIATE_HE) {
 | 
				
			||||||
 | 
							struct smb2_hdr *smb2_hdr = REQUEST_BUF(work);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (smb2_hdr->ProtocolId != SMB2_PROTO_NUMBER) {
 | 
				
			||||||
 | 
								ksmbd_debug(SMB, "Downgrade to SMB1 negotiation\n");
 | 
				
			||||||
 | 
								command = SMB_COM_NEGOTIATE;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (command == SMB2_NEGOTIATE_HE) {
 | 
				
			||||||
 | 
							ret = smb2_handle_negotiate(work);
 | 
				
			||||||
 | 
							init_smb2_neg_rsp(work);
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (command == SMB_COM_NEGOTIATE) {
 | 
				
			||||||
 | 
							if (__smb2_negotiate(conn)) {
 | 
				
			||||||
 | 
								conn->need_neg = true;
 | 
				
			||||||
 | 
								init_smb3_11_server(conn);
 | 
				
			||||||
 | 
								init_smb2_neg_rsp(work);
 | 
				
			||||||
 | 
								ksmbd_debug(SMB, "Upgrade to SMB2 negotiation\n");
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return smb_handle_negotiate(work);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ksmbd_err("Unknown SMB negotiation command: %u\n", command);
 | 
				
			||||||
 | 
						return -EINVAL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum SHARED_MODE_ERRORS {
 | 
				
			||||||
 | 
						SHARE_DELETE_ERROR,
 | 
				
			||||||
 | 
						SHARE_READ_ERROR,
 | 
				
			||||||
 | 
						SHARE_WRITE_ERROR,
 | 
				
			||||||
 | 
						FILE_READ_ERROR,
 | 
				
			||||||
 | 
						FILE_WRITE_ERROR,
 | 
				
			||||||
 | 
						FILE_DELETE_ERROR,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const char * const shared_mode_errors[] = {
 | 
				
			||||||
 | 
						"Current access mode does not permit SHARE_DELETE",
 | 
				
			||||||
 | 
						"Current access mode does not permit SHARE_READ",
 | 
				
			||||||
 | 
						"Current access mode does not permit SHARE_WRITE",
 | 
				
			||||||
 | 
						"Desired access mode does not permit FILE_READ",
 | 
				
			||||||
 | 
						"Desired access mode does not permit FILE_WRITE",
 | 
				
			||||||
 | 
						"Desired access mode does not permit FILE_DELETE",
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void smb_shared_mode_error(int error,
 | 
				
			||||||
 | 
									  struct ksmbd_file *prev_fp,
 | 
				
			||||||
 | 
									  struct ksmbd_file *curr_fp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						ksmbd_debug(SMB, "%s\n", shared_mode_errors[error]);
 | 
				
			||||||
 | 
						ksmbd_debug(SMB, "Current mode: 0x%x Desired mode: 0x%x\n",
 | 
				
			||||||
 | 
							  prev_fp->saccess, curr_fp->daccess);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_smb_check_shared_mode(struct file *filp, struct ksmbd_file *curr_fp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int rc = 0;
 | 
				
			||||||
 | 
						struct ksmbd_file *prev_fp;
 | 
				
			||||||
 | 
						struct list_head *cur;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Lookup fp in master fp list, and check desired access and
 | 
				
			||||||
 | 
						 * shared mode between previous open and current open.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						read_lock(&curr_fp->f_ci->m_lock);
 | 
				
			||||||
 | 
						list_for_each(cur, &curr_fp->f_ci->m_fp_list) {
 | 
				
			||||||
 | 
							prev_fp = list_entry(cur, struct ksmbd_file, node);
 | 
				
			||||||
 | 
							if (file_inode(filp) != FP_INODE(prev_fp))
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (filp == prev_fp->filp)
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (ksmbd_stream_fd(prev_fp) && ksmbd_stream_fd(curr_fp))
 | 
				
			||||||
 | 
								if (strcmp(prev_fp->stream.name, curr_fp->stream.name))
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (prev_fp->is_durable) {
 | 
				
			||||||
 | 
								prev_fp->is_durable = 0;
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (prev_fp->attrib_only != curr_fp->attrib_only)
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!(prev_fp->saccess & FILE_SHARE_DELETE_LE) &&
 | 
				
			||||||
 | 
									curr_fp->daccess & FILE_DELETE_LE) {
 | 
				
			||||||
 | 
								smb_shared_mode_error(SHARE_DELETE_ERROR,
 | 
				
			||||||
 | 
										      prev_fp,
 | 
				
			||||||
 | 
										      curr_fp);
 | 
				
			||||||
 | 
								rc = -EPERM;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * Only check FILE_SHARE_DELETE if stream opened and
 | 
				
			||||||
 | 
							 * normal file opened.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							if (ksmbd_stream_fd(prev_fp) && !ksmbd_stream_fd(curr_fp))
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!(prev_fp->saccess & FILE_SHARE_READ_LE) &&
 | 
				
			||||||
 | 
									curr_fp->daccess & (FILE_EXECUTE_LE |
 | 
				
			||||||
 | 
										FILE_READ_DATA_LE)) {
 | 
				
			||||||
 | 
								smb_shared_mode_error(SHARE_READ_ERROR,
 | 
				
			||||||
 | 
										      prev_fp,
 | 
				
			||||||
 | 
										      curr_fp);
 | 
				
			||||||
 | 
								rc = -EPERM;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!(prev_fp->saccess & FILE_SHARE_WRITE_LE) &&
 | 
				
			||||||
 | 
									curr_fp->daccess & (FILE_WRITE_DATA_LE |
 | 
				
			||||||
 | 
										FILE_APPEND_DATA_LE)) {
 | 
				
			||||||
 | 
								smb_shared_mode_error(SHARE_WRITE_ERROR,
 | 
				
			||||||
 | 
										      prev_fp,
 | 
				
			||||||
 | 
										      curr_fp);
 | 
				
			||||||
 | 
								rc = -EPERM;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (prev_fp->daccess & (FILE_EXECUTE_LE |
 | 
				
			||||||
 | 
										FILE_READ_DATA_LE) &&
 | 
				
			||||||
 | 
									!(curr_fp->saccess & FILE_SHARE_READ_LE)) {
 | 
				
			||||||
 | 
								smb_shared_mode_error(FILE_READ_ERROR,
 | 
				
			||||||
 | 
										      prev_fp,
 | 
				
			||||||
 | 
										      curr_fp);
 | 
				
			||||||
 | 
								rc = -EPERM;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (prev_fp->daccess & (FILE_WRITE_DATA_LE |
 | 
				
			||||||
 | 
										FILE_APPEND_DATA_LE) &&
 | 
				
			||||||
 | 
									!(curr_fp->saccess & FILE_SHARE_WRITE_LE)) {
 | 
				
			||||||
 | 
								smb_shared_mode_error(FILE_WRITE_ERROR,
 | 
				
			||||||
 | 
										      prev_fp,
 | 
				
			||||||
 | 
										      curr_fp);
 | 
				
			||||||
 | 
								rc = -EPERM;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (prev_fp->daccess & FILE_DELETE_LE &&
 | 
				
			||||||
 | 
									!(curr_fp->saccess & FILE_SHARE_DELETE_LE)) {
 | 
				
			||||||
 | 
								smb_shared_mode_error(FILE_DELETE_ERROR,
 | 
				
			||||||
 | 
										      prev_fp,
 | 
				
			||||||
 | 
										      curr_fp);
 | 
				
			||||||
 | 
								rc = -EPERM;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						read_unlock(&curr_fp->f_ci->m_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return rc;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool is_asterisk(char *p)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return p && p[0] == '*';
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_override_fsids(struct ksmbd_work *work)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ksmbd_session *sess = work->sess;
 | 
				
			||||||
 | 
						struct ksmbd_share_config *share = work->tcon->share_conf;
 | 
				
			||||||
 | 
						struct cred *cred;
 | 
				
			||||||
 | 
						struct group_info *gi;
 | 
				
			||||||
 | 
						unsigned int uid;
 | 
				
			||||||
 | 
						unsigned int gid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						uid = user_uid(sess->user);
 | 
				
			||||||
 | 
						gid = user_gid(sess->user);
 | 
				
			||||||
 | 
						if (share->force_uid != KSMBD_SHARE_INVALID_UID)
 | 
				
			||||||
 | 
							uid = share->force_uid;
 | 
				
			||||||
 | 
						if (share->force_gid != KSMBD_SHARE_INVALID_GID)
 | 
				
			||||||
 | 
							gid = share->force_gid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cred = prepare_kernel_cred(NULL);
 | 
				
			||||||
 | 
						if (!cred)
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cred->fsuid = make_kuid(current_user_ns(), uid);
 | 
				
			||||||
 | 
						cred->fsgid = make_kgid(current_user_ns(), gid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gi = groups_alloc(0);
 | 
				
			||||||
 | 
						if (!gi) {
 | 
				
			||||||
 | 
							abort_creds(cred);
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						set_groups(cred, gi);
 | 
				
			||||||
 | 
						put_group_info(gi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!uid_eq(cred->fsuid, GLOBAL_ROOT_UID))
 | 
				
			||||||
 | 
							cred->cap_effective = cap_drop_fs_set(cred->cap_effective);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						WARN_ON(work->saved_cred != NULL);
 | 
				
			||||||
 | 
						work->saved_cred = override_creds(cred);
 | 
				
			||||||
 | 
						if (!work->saved_cred) {
 | 
				
			||||||
 | 
							abort_creds(cred);
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ksmbd_revert_fsids(struct ksmbd_work *work)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const struct cred *cred;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						WARN_ON(work->saved_cred == NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cred = current_cred();
 | 
				
			||||||
 | 
						revert_creds(work->saved_cred);
 | 
				
			||||||
 | 
						put_cred(cred);
 | 
				
			||||||
 | 
						work->saved_cred = NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					__le32 smb_map_generic_desired_access(__le32 daccess)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (daccess & FILE_GENERIC_READ_LE) {
 | 
				
			||||||
 | 
							daccess |= cpu_to_le32(GENERIC_READ_FLAGS);
 | 
				
			||||||
 | 
							daccess &= ~FILE_GENERIC_READ_LE;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (daccess & FILE_GENERIC_WRITE_LE) {
 | 
				
			||||||
 | 
							daccess |= cpu_to_le32(GENERIC_WRITE_FLAGS);
 | 
				
			||||||
 | 
							daccess &= ~FILE_GENERIC_WRITE_LE;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (daccess & FILE_GENERIC_EXECUTE_LE) {
 | 
				
			||||||
 | 
							daccess |= cpu_to_le32(GENERIC_EXECUTE_FLAGS);
 | 
				
			||||||
 | 
							daccess &= ~FILE_GENERIC_EXECUTE_LE;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (daccess & FILE_GENERIC_ALL_LE) {
 | 
				
			||||||
 | 
							daccess |= cpu_to_le32(GENERIC_ALL_FLAGS);
 | 
				
			||||||
 | 
							daccess &= ~FILE_GENERIC_ALL_LE;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return daccess;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										546
									
								
								fs/cifsd/smb_common.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										546
									
								
								fs/cifsd/smb_common.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,546 @@
 | 
				
			||||||
 | 
					/* SPDX-License-Identifier: GPL-2.0-or-later */
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *   Copyright (C) 2018 Samsung Electronics Co., Ltd.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef __SMB_COMMON_H__
 | 
				
			||||||
 | 
					#define __SMB_COMMON_H__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <linux/kernel.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "glob.h"
 | 
				
			||||||
 | 
					#include "nterr.h"
 | 
				
			||||||
 | 
					#include "smb2pdu.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ksmbd's Specific ERRNO */
 | 
				
			||||||
 | 
					#define ESHARE			50000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SMB1_PROT		0
 | 
				
			||||||
 | 
					#define SMB2_PROT		1
 | 
				
			||||||
 | 
					#define SMB21_PROT		2
 | 
				
			||||||
 | 
					/* multi-protocol negotiate request */
 | 
				
			||||||
 | 
					#define SMB2X_PROT		3
 | 
				
			||||||
 | 
					#define SMB30_PROT		4
 | 
				
			||||||
 | 
					#define SMB302_PROT		5
 | 
				
			||||||
 | 
					#define SMB311_PROT		6
 | 
				
			||||||
 | 
					#define BAD_PROT		0xFFFF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SMB1_VERSION_STRING	"1.0"
 | 
				
			||||||
 | 
					#define SMB20_VERSION_STRING	"2.0"
 | 
				
			||||||
 | 
					#define SMB21_VERSION_STRING	"2.1"
 | 
				
			||||||
 | 
					#define SMB30_VERSION_STRING	"3.0"
 | 
				
			||||||
 | 
					#define SMB302_VERSION_STRING	"3.02"
 | 
				
			||||||
 | 
					#define SMB311_VERSION_STRING	"3.1.1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Dialects */
 | 
				
			||||||
 | 
					#define SMB10_PROT_ID		0x00
 | 
				
			||||||
 | 
					#define SMB20_PROT_ID		0x0202
 | 
				
			||||||
 | 
					#define SMB21_PROT_ID		0x0210
 | 
				
			||||||
 | 
					/* multi-protocol negotiate request */
 | 
				
			||||||
 | 
					#define SMB2X_PROT_ID		0x02FF
 | 
				
			||||||
 | 
					#define SMB30_PROT_ID		0x0300
 | 
				
			||||||
 | 
					#define SMB302_PROT_ID		0x0302
 | 
				
			||||||
 | 
					#define SMB311_PROT_ID		0x0311
 | 
				
			||||||
 | 
					#define BAD_PROT_ID		0xFFFF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SMB_ECHO_INTERVAL	(60*HZ)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CIFS_DEFAULT_IOSIZE	(64 * 1024)
 | 
				
			||||||
 | 
					#define MAX_CIFS_SMALL_BUFFER_SIZE 448 /* big enough for most */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern struct list_head global_lock_list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IS_SMB2(x)		((x)->vals->protocol_id != SMB10_PROT_ID)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define HEADER_SIZE(conn)		((conn)->vals->header_size)
 | 
				
			||||||
 | 
					#define HEADER_SIZE_NO_BUF_LEN(conn)	((conn)->vals->header_size - 4)
 | 
				
			||||||
 | 
					#define MAX_HEADER_SIZE(conn)		((conn)->vals->max_header_size)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* RFC 1002 session packet types */
 | 
				
			||||||
 | 
					#define RFC1002_SESSION_MESSAGE			0x00
 | 
				
			||||||
 | 
					#define RFC1002_SESSION_REQUEST			0x81
 | 
				
			||||||
 | 
					#define RFC1002_POSITIVE_SESSION_RESPONSE	0x82
 | 
				
			||||||
 | 
					#define RFC1002_NEGATIVE_SESSION_RESPONSE	0x83
 | 
				
			||||||
 | 
					#define RFC1002_RETARGET_SESSION_RESPONSE	0x84
 | 
				
			||||||
 | 
					#define RFC1002_SESSION_KEEP_ALIVE		0x85
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Responses when opening a file. */
 | 
				
			||||||
 | 
					#define F_SUPERSEDED	0
 | 
				
			||||||
 | 
					#define F_OPENED	1
 | 
				
			||||||
 | 
					#define F_CREATED	2
 | 
				
			||||||
 | 
					#define F_OVERWRITTEN	3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * File Attribute flags
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define ATTR_READONLY			0x0001
 | 
				
			||||||
 | 
					#define ATTR_HIDDEN			0x0002
 | 
				
			||||||
 | 
					#define ATTR_SYSTEM			0x0004
 | 
				
			||||||
 | 
					#define ATTR_VOLUME			0x0008
 | 
				
			||||||
 | 
					#define ATTR_DIRECTORY			0x0010
 | 
				
			||||||
 | 
					#define ATTR_ARCHIVE			0x0020
 | 
				
			||||||
 | 
					#define ATTR_DEVICE			0x0040
 | 
				
			||||||
 | 
					#define ATTR_NORMAL			0x0080
 | 
				
			||||||
 | 
					#define ATTR_TEMPORARY			0x0100
 | 
				
			||||||
 | 
					#define ATTR_SPARSE			0x0200
 | 
				
			||||||
 | 
					#define ATTR_REPARSE			0x0400
 | 
				
			||||||
 | 
					#define ATTR_COMPRESSED			0x0800
 | 
				
			||||||
 | 
					#define ATTR_OFFLINE			0x1000
 | 
				
			||||||
 | 
					#define ATTR_NOT_CONTENT_INDEXED	0x2000
 | 
				
			||||||
 | 
					#define ATTR_ENCRYPTED			0x4000
 | 
				
			||||||
 | 
					#define ATTR_POSIX_SEMANTICS		0x01000000
 | 
				
			||||||
 | 
					#define ATTR_BACKUP_SEMANTICS		0x02000000
 | 
				
			||||||
 | 
					#define ATTR_DELETE_ON_CLOSE		0x04000000
 | 
				
			||||||
 | 
					#define ATTR_SEQUENTIAL_SCAN		0x08000000
 | 
				
			||||||
 | 
					#define ATTR_RANDOM_ACCESS		0x10000000
 | 
				
			||||||
 | 
					#define ATTR_NO_BUFFERING		0x20000000
 | 
				
			||||||
 | 
					#define ATTR_WRITE_THROUGH		0x80000000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ATTR_READONLY_LE		cpu_to_le32(ATTR_READONLY)
 | 
				
			||||||
 | 
					#define ATTR_HIDDEN_LE			cpu_to_le32(ATTR_HIDDEN)
 | 
				
			||||||
 | 
					#define ATTR_SYSTEM_LE			cpu_to_le32(ATTR_SYSTEM)
 | 
				
			||||||
 | 
					#define ATTR_DIRECTORY_LE		cpu_to_le32(ATTR_DIRECTORY)
 | 
				
			||||||
 | 
					#define ATTR_ARCHIVE_LE			cpu_to_le32(ATTR_ARCHIVE)
 | 
				
			||||||
 | 
					#define ATTR_NORMAL_LE			cpu_to_le32(ATTR_NORMAL)
 | 
				
			||||||
 | 
					#define ATTR_TEMPORARY_LE		cpu_to_le32(ATTR_TEMPORARY)
 | 
				
			||||||
 | 
					#define ATTR_SPARSE_FILE_LE		cpu_to_le32(ATTR_SPARSE)
 | 
				
			||||||
 | 
					#define ATTR_REPARSE_POINT_LE		cpu_to_le32(ATTR_REPARSE)
 | 
				
			||||||
 | 
					#define ATTR_COMPRESSED_LE		cpu_to_le32(ATTR_COMPRESSED)
 | 
				
			||||||
 | 
					#define ATTR_OFFLINE_LE			cpu_to_le32(ATTR_OFFLINE)
 | 
				
			||||||
 | 
					#define ATTR_NOT_CONTENT_INDEXED_LE	cpu_to_le32(ATTR_NOT_CONTENT_INDEXED)
 | 
				
			||||||
 | 
					#define ATTR_ENCRYPTED_LE		cpu_to_le32(ATTR_ENCRYPTED)
 | 
				
			||||||
 | 
					#define ATTR_INTEGRITY_STREAML_LE	cpu_to_le32(0x00008000)
 | 
				
			||||||
 | 
					#define ATTR_NO_SCRUB_DATA_LE		cpu_to_le32(0x00020000)
 | 
				
			||||||
 | 
					#define ATTR_MASK_LE			cpu_to_le32(0x00007FB7)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* List of FileSystemAttributes - see 2.5.1 of MS-FSCC */
 | 
				
			||||||
 | 
					#define FILE_SUPPORTS_SPARSE_VDL	0x10000000 /* faster nonsparse extend */
 | 
				
			||||||
 | 
					#define FILE_SUPPORTS_BLOCK_REFCOUNTING	0x08000000 /* allow ioctl dup extents */
 | 
				
			||||||
 | 
					#define FILE_SUPPORT_INTEGRITY_STREAMS	0x04000000
 | 
				
			||||||
 | 
					#define FILE_SUPPORTS_USN_JOURNAL	0x02000000
 | 
				
			||||||
 | 
					#define FILE_SUPPORTS_OPEN_BY_FILE_ID	0x01000000
 | 
				
			||||||
 | 
					#define FILE_SUPPORTS_EXTENDED_ATTRIBUTES 0x00800000
 | 
				
			||||||
 | 
					#define FILE_SUPPORTS_HARD_LINKS	0x00400000
 | 
				
			||||||
 | 
					#define FILE_SUPPORTS_TRANSACTIONS	0x00200000
 | 
				
			||||||
 | 
					#define FILE_SEQUENTIAL_WRITE_ONCE	0x00100000
 | 
				
			||||||
 | 
					#define FILE_READ_ONLY_VOLUME		0x00080000
 | 
				
			||||||
 | 
					#define FILE_NAMED_STREAMS		0x00040000
 | 
				
			||||||
 | 
					#define FILE_SUPPORTS_ENCRYPTION	0x00020000
 | 
				
			||||||
 | 
					#define FILE_SUPPORTS_OBJECT_IDS	0x00010000
 | 
				
			||||||
 | 
					#define FILE_VOLUME_IS_COMPRESSED	0x00008000
 | 
				
			||||||
 | 
					#define FILE_SUPPORTS_REMOTE_STORAGE	0x00000100
 | 
				
			||||||
 | 
					#define FILE_SUPPORTS_REPARSE_POINTS	0x00000080
 | 
				
			||||||
 | 
					#define FILE_SUPPORTS_SPARSE_FILES	0x00000040
 | 
				
			||||||
 | 
					#define FILE_VOLUME_QUOTAS		0x00000020
 | 
				
			||||||
 | 
					#define FILE_FILE_COMPRESSION		0x00000010
 | 
				
			||||||
 | 
					#define FILE_PERSISTENT_ACLS		0x00000008
 | 
				
			||||||
 | 
					#define FILE_UNICODE_ON_DISK		0x00000004
 | 
				
			||||||
 | 
					#define FILE_CASE_PRESERVED_NAMES	0x00000002
 | 
				
			||||||
 | 
					#define FILE_CASE_SENSITIVE_SEARCH	0x00000001
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define FILE_READ_DATA        0x00000001  /* Data can be read from the file   */
 | 
				
			||||||
 | 
					#define FILE_WRITE_DATA       0x00000002  /* Data can be written to the file  */
 | 
				
			||||||
 | 
					#define FILE_APPEND_DATA      0x00000004  /* Data can be appended to the file */
 | 
				
			||||||
 | 
					#define FILE_READ_EA          0x00000008  /* Extended attributes associated   */
 | 
				
			||||||
 | 
					/* with the file can be read        */
 | 
				
			||||||
 | 
					#define FILE_WRITE_EA         0x00000010  /* Extended attributes associated   */
 | 
				
			||||||
 | 
					/* with the file can be written     */
 | 
				
			||||||
 | 
					#define FILE_EXECUTE          0x00000020  /*Data can be read into memory from */
 | 
				
			||||||
 | 
					/* the file using system paging I/O */
 | 
				
			||||||
 | 
					#define FILE_DELETE_CHILD     0x00000040
 | 
				
			||||||
 | 
					#define FILE_READ_ATTRIBUTES  0x00000080  /* Attributes associated with the   */
 | 
				
			||||||
 | 
					/* file can be read                 */
 | 
				
			||||||
 | 
					#define FILE_WRITE_ATTRIBUTES 0x00000100  /* Attributes associated with the   */
 | 
				
			||||||
 | 
					/* file can be written              */
 | 
				
			||||||
 | 
					#define DELETE                0x00010000  /* The file can be deleted          */
 | 
				
			||||||
 | 
					#define READ_CONTROL          0x00020000  /* The access control list and      */
 | 
				
			||||||
 | 
					/* ownership associated with the    */
 | 
				
			||||||
 | 
					/* file can be read                 */
 | 
				
			||||||
 | 
					#define WRITE_DAC             0x00040000  /* The access control list and      */
 | 
				
			||||||
 | 
					/* ownership associated with the    */
 | 
				
			||||||
 | 
					/* file can be written.             */
 | 
				
			||||||
 | 
					#define WRITE_OWNER           0x00080000  /* Ownership information associated */
 | 
				
			||||||
 | 
					/* with the file can be written     */
 | 
				
			||||||
 | 
					#define SYNCHRONIZE           0x00100000  /* The file handle can waited on to */
 | 
				
			||||||
 | 
					/* synchronize with the completion  */
 | 
				
			||||||
 | 
					/* of an input/output request       */
 | 
				
			||||||
 | 
					#define GENERIC_ALL           0x10000000
 | 
				
			||||||
 | 
					#define GENERIC_EXECUTE       0x20000000
 | 
				
			||||||
 | 
					#define GENERIC_WRITE         0x40000000
 | 
				
			||||||
 | 
					#define GENERIC_READ          0x80000000
 | 
				
			||||||
 | 
					/* In summary - Relevant file       */
 | 
				
			||||||
 | 
					/* access flags from CIFS are       */
 | 
				
			||||||
 | 
					/* file_read_data, file_write_data  */
 | 
				
			||||||
 | 
					/* file_execute, file_read_attributes*/
 | 
				
			||||||
 | 
					/* write_dac, and delete.           */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define FILE_READ_RIGHTS (FILE_READ_DATA | FILE_READ_EA | FILE_READ_ATTRIBUTES)
 | 
				
			||||||
 | 
					#define FILE_WRITE_RIGHTS (FILE_WRITE_DATA | FILE_APPEND_DATA \
 | 
				
			||||||
 | 
							| FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES)
 | 
				
			||||||
 | 
					#define FILE_EXEC_RIGHTS (FILE_EXECUTE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SET_FILE_READ_RIGHTS (FILE_READ_DATA | FILE_READ_EA \
 | 
				
			||||||
 | 
							| FILE_READ_ATTRIBUTES \
 | 
				
			||||||
 | 
							| DELETE | READ_CONTROL | WRITE_DAC \
 | 
				
			||||||
 | 
							| WRITE_OWNER | SYNCHRONIZE)
 | 
				
			||||||
 | 
					#define SET_FILE_WRITE_RIGHTS (FILE_WRITE_DATA | FILE_APPEND_DATA \
 | 
				
			||||||
 | 
							| FILE_WRITE_EA \
 | 
				
			||||||
 | 
							| FILE_DELETE_CHILD \
 | 
				
			||||||
 | 
							| FILE_WRITE_ATTRIBUTES \
 | 
				
			||||||
 | 
							| DELETE | READ_CONTROL | WRITE_DAC \
 | 
				
			||||||
 | 
							| WRITE_OWNER | SYNCHRONIZE)
 | 
				
			||||||
 | 
					#define SET_FILE_EXEC_RIGHTS (FILE_READ_EA | FILE_WRITE_EA | FILE_EXECUTE \
 | 
				
			||||||
 | 
							| FILE_READ_ATTRIBUTES \
 | 
				
			||||||
 | 
							| FILE_WRITE_ATTRIBUTES \
 | 
				
			||||||
 | 
							| DELETE | READ_CONTROL | WRITE_DAC \
 | 
				
			||||||
 | 
							| WRITE_OWNER | SYNCHRONIZE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SET_MINIMUM_RIGHTS (FILE_READ_EA | FILE_READ_ATTRIBUTES \
 | 
				
			||||||
 | 
							| READ_CONTROL | SYNCHRONIZE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* generic flags for file open */
 | 
				
			||||||
 | 
					#define GENERIC_READ_FLAGS	(READ_CONTROL | FILE_READ_DATA | \
 | 
				
			||||||
 | 
							FILE_READ_ATTRIBUTES | \
 | 
				
			||||||
 | 
							FILE_READ_EA | SYNCHRONIZE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define GENERIC_WRITE_FLAGS	(READ_CONTROL | FILE_WRITE_DATA | \
 | 
				
			||||||
 | 
							FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | \
 | 
				
			||||||
 | 
							FILE_APPEND_DATA | SYNCHRONIZE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define GENERIC_EXECUTE_FLAGS	(READ_CONTROL | FILE_EXECUTE | \
 | 
				
			||||||
 | 
							FILE_READ_ATTRIBUTES | SYNCHRONIZE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define GENERIC_ALL_FLAGS	(DELETE | READ_CONTROL | WRITE_DAC | \
 | 
				
			||||||
 | 
							WRITE_OWNER | SYNCHRONIZE | FILE_READ_DATA | \
 | 
				
			||||||
 | 
							FILE_WRITE_DATA | FILE_APPEND_DATA | \
 | 
				
			||||||
 | 
							FILE_READ_EA | FILE_WRITE_EA | \
 | 
				
			||||||
 | 
							FILE_EXECUTE | FILE_DELETE_CHILD | \
 | 
				
			||||||
 | 
							FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SMB1_PROTO_NUMBER		cpu_to_le32(0x424d53ff)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SMB1_CLIENT_GUID_SIZE		(16)
 | 
				
			||||||
 | 
					struct smb_hdr {
 | 
				
			||||||
 | 
						__be32 smb_buf_length;
 | 
				
			||||||
 | 
						__u8 Protocol[4];
 | 
				
			||||||
 | 
						__u8 Command;
 | 
				
			||||||
 | 
						union {
 | 
				
			||||||
 | 
							struct {
 | 
				
			||||||
 | 
								__u8 ErrorClass;
 | 
				
			||||||
 | 
								__u8 Reserved;
 | 
				
			||||||
 | 
								__le16 Error;
 | 
				
			||||||
 | 
							} __packed DosError;
 | 
				
			||||||
 | 
							__le32 CifsError;
 | 
				
			||||||
 | 
						} __packed Status;
 | 
				
			||||||
 | 
						__u8 Flags;
 | 
				
			||||||
 | 
						__le16 Flags2;          /* note: le */
 | 
				
			||||||
 | 
						__le16 PidHigh;
 | 
				
			||||||
 | 
						union {
 | 
				
			||||||
 | 
							struct {
 | 
				
			||||||
 | 
								__le32 SequenceNumber;  /* le */
 | 
				
			||||||
 | 
								__u32 Reserved; /* zero */
 | 
				
			||||||
 | 
							} __packed Sequence;
 | 
				
			||||||
 | 
							__u8 SecuritySignature[8];      /* le */
 | 
				
			||||||
 | 
						} __packed Signature;
 | 
				
			||||||
 | 
						__u8 pad[2];
 | 
				
			||||||
 | 
						__le16 Tid;
 | 
				
			||||||
 | 
						__le16 Pid;
 | 
				
			||||||
 | 
						__le16 Uid;
 | 
				
			||||||
 | 
						__le16 Mid;
 | 
				
			||||||
 | 
						__u8 WordCount;
 | 
				
			||||||
 | 
					} __packed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct smb_negotiate_req {
 | 
				
			||||||
 | 
						struct smb_hdr hdr;     /* wct = 0 */
 | 
				
			||||||
 | 
						__le16 ByteCount;
 | 
				
			||||||
 | 
						unsigned char DialectsArray[1];
 | 
				
			||||||
 | 
					} __packed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct smb_negotiate_rsp {
 | 
				
			||||||
 | 
						struct smb_hdr hdr;     /* wct = 17 */
 | 
				
			||||||
 | 
						__le16 DialectIndex; /* 0xFFFF = no dialect acceptable */
 | 
				
			||||||
 | 
						__u8 SecurityMode;
 | 
				
			||||||
 | 
						__le16 MaxMpxCount;
 | 
				
			||||||
 | 
						__le16 MaxNumberVcs;
 | 
				
			||||||
 | 
						__le32 MaxBufferSize;
 | 
				
			||||||
 | 
						__le32 MaxRawSize;
 | 
				
			||||||
 | 
						__le32 SessionKey;
 | 
				
			||||||
 | 
						__le32 Capabilities;    /* see below */
 | 
				
			||||||
 | 
						__le32 SystemTimeLow;
 | 
				
			||||||
 | 
						__le32 SystemTimeHigh;
 | 
				
			||||||
 | 
						__le16 ServerTimeZone;
 | 
				
			||||||
 | 
						__u8 EncryptionKeyLength;
 | 
				
			||||||
 | 
						__le16 ByteCount;
 | 
				
			||||||
 | 
						union {
 | 
				
			||||||
 | 
							unsigned char EncryptionKey[8]; /* cap extended security off */
 | 
				
			||||||
 | 
							/* followed by Domain name - if extended security is off */
 | 
				
			||||||
 | 
							/* followed by 16 bytes of server GUID */
 | 
				
			||||||
 | 
							/* then security blob if cap_extended_security negotiated */
 | 
				
			||||||
 | 
							struct {
 | 
				
			||||||
 | 
								unsigned char GUID[SMB1_CLIENT_GUID_SIZE];
 | 
				
			||||||
 | 
								unsigned char SecurityBlob[1];
 | 
				
			||||||
 | 
							} __packed extended_response;
 | 
				
			||||||
 | 
						} __packed u;
 | 
				
			||||||
 | 
					} __packed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct filesystem_attribute_info {
 | 
				
			||||||
 | 
						__le32 Attributes;
 | 
				
			||||||
 | 
						__le32 MaxPathNameComponentLength;
 | 
				
			||||||
 | 
						__le32 FileSystemNameLen;
 | 
				
			||||||
 | 
						__le16 FileSystemName[1]; /* do not have to save this - get subset? */
 | 
				
			||||||
 | 
					} __packed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct filesystem_device_info {
 | 
				
			||||||
 | 
						__le32 DeviceType;
 | 
				
			||||||
 | 
						__le32 DeviceCharacteristics;
 | 
				
			||||||
 | 
					} __packed; /* device info level 0x104 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct filesystem_vol_info {
 | 
				
			||||||
 | 
						__le64 VolumeCreationTime;
 | 
				
			||||||
 | 
						__le32 SerialNumber;
 | 
				
			||||||
 | 
						__le32 VolumeLabelSize;
 | 
				
			||||||
 | 
						__le16 Reserved;
 | 
				
			||||||
 | 
						__le16 VolumeLabel[1];
 | 
				
			||||||
 | 
					} __packed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct filesystem_info {
 | 
				
			||||||
 | 
						__le64 TotalAllocationUnits;
 | 
				
			||||||
 | 
						__le64 FreeAllocationUnits;
 | 
				
			||||||
 | 
						__le32 SectorsPerAllocationUnit;
 | 
				
			||||||
 | 
						__le32 BytesPerSector;
 | 
				
			||||||
 | 
					} __packed;     /* size info, level 0x103 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define EXTENDED_INFO_MAGIC 0x43667364	/* Cfsd */
 | 
				
			||||||
 | 
					#define STRING_LENGTH 28
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct fs_extended_info {
 | 
				
			||||||
 | 
						__le32 magic;
 | 
				
			||||||
 | 
						__le32 version;
 | 
				
			||||||
 | 
						__le32 release;
 | 
				
			||||||
 | 
						__u64 rel_date;
 | 
				
			||||||
 | 
						char    version_string[STRING_LENGTH];
 | 
				
			||||||
 | 
					} __packed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct object_id_info {
 | 
				
			||||||
 | 
						char objid[16];
 | 
				
			||||||
 | 
						struct fs_extended_info extended_info;
 | 
				
			||||||
 | 
					} __packed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct file_directory_info {
 | 
				
			||||||
 | 
						__le32 NextEntryOffset;
 | 
				
			||||||
 | 
						__u32 FileIndex;
 | 
				
			||||||
 | 
						__le64 CreationTime;
 | 
				
			||||||
 | 
						__le64 LastAccessTime;
 | 
				
			||||||
 | 
						__le64 LastWriteTime;
 | 
				
			||||||
 | 
						__le64 ChangeTime;
 | 
				
			||||||
 | 
						__le64 EndOfFile;
 | 
				
			||||||
 | 
						__le64 AllocationSize;
 | 
				
			||||||
 | 
						__le32 ExtFileAttributes;
 | 
				
			||||||
 | 
						__le32 FileNameLength;
 | 
				
			||||||
 | 
						char FileName[1];
 | 
				
			||||||
 | 
					} __packed;   /* level 0x101 FF resp data */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct file_names_info {
 | 
				
			||||||
 | 
						__le32 NextEntryOffset;
 | 
				
			||||||
 | 
						__u32 FileIndex;
 | 
				
			||||||
 | 
						__le32 FileNameLength;
 | 
				
			||||||
 | 
						char FileName[1];
 | 
				
			||||||
 | 
					} __packed;   /* level 0xc FF resp data */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct file_full_directory_info {
 | 
				
			||||||
 | 
						__le32 NextEntryOffset;
 | 
				
			||||||
 | 
						__u32 FileIndex;
 | 
				
			||||||
 | 
						__le64 CreationTime;
 | 
				
			||||||
 | 
						__le64 LastAccessTime;
 | 
				
			||||||
 | 
						__le64 LastWriteTime;
 | 
				
			||||||
 | 
						__le64 ChangeTime;
 | 
				
			||||||
 | 
						__le64 EndOfFile;
 | 
				
			||||||
 | 
						__le64 AllocationSize;
 | 
				
			||||||
 | 
						__le32 ExtFileAttributes;
 | 
				
			||||||
 | 
						__le32 FileNameLength;
 | 
				
			||||||
 | 
						__le32 EaSize;
 | 
				
			||||||
 | 
						char FileName[1];
 | 
				
			||||||
 | 
					} __packed; /* level 0x102 FF resp */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct file_both_directory_info {
 | 
				
			||||||
 | 
						__le32 NextEntryOffset;
 | 
				
			||||||
 | 
						__u32 FileIndex;
 | 
				
			||||||
 | 
						__le64 CreationTime;
 | 
				
			||||||
 | 
						__le64 LastAccessTime;
 | 
				
			||||||
 | 
						__le64 LastWriteTime;
 | 
				
			||||||
 | 
						__le64 ChangeTime;
 | 
				
			||||||
 | 
						__le64 EndOfFile;
 | 
				
			||||||
 | 
						__le64 AllocationSize;
 | 
				
			||||||
 | 
						__le32 ExtFileAttributes;
 | 
				
			||||||
 | 
						__le32 FileNameLength;
 | 
				
			||||||
 | 
						__le32 EaSize; /* length of the xattrs */
 | 
				
			||||||
 | 
						__u8   ShortNameLength;
 | 
				
			||||||
 | 
						__u8   Reserved;
 | 
				
			||||||
 | 
						__u8   ShortName[24];
 | 
				
			||||||
 | 
						char FileName[1];
 | 
				
			||||||
 | 
					} __packed; /* level 0x104 FFrsp data */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct file_id_both_directory_info {
 | 
				
			||||||
 | 
						__le32 NextEntryOffset;
 | 
				
			||||||
 | 
						__u32 FileIndex;
 | 
				
			||||||
 | 
						__le64 CreationTime;
 | 
				
			||||||
 | 
						__le64 LastAccessTime;
 | 
				
			||||||
 | 
						__le64 LastWriteTime;
 | 
				
			||||||
 | 
						__le64 ChangeTime;
 | 
				
			||||||
 | 
						__le64 EndOfFile;
 | 
				
			||||||
 | 
						__le64 AllocationSize;
 | 
				
			||||||
 | 
						__le32 ExtFileAttributes;
 | 
				
			||||||
 | 
						__le32 FileNameLength;
 | 
				
			||||||
 | 
						__le32 EaSize; /* length of the xattrs */
 | 
				
			||||||
 | 
						__u8   ShortNameLength;
 | 
				
			||||||
 | 
						__u8   Reserved;
 | 
				
			||||||
 | 
						__u8   ShortName[24];
 | 
				
			||||||
 | 
						__le16 Reserved2;
 | 
				
			||||||
 | 
						__le64 UniqueId;
 | 
				
			||||||
 | 
						char FileName[1];
 | 
				
			||||||
 | 
					} __packed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct file_id_full_dir_info {
 | 
				
			||||||
 | 
						__le32 NextEntryOffset;
 | 
				
			||||||
 | 
						__u32 FileIndex;
 | 
				
			||||||
 | 
						__le64 CreationTime;
 | 
				
			||||||
 | 
						__le64 LastAccessTime;
 | 
				
			||||||
 | 
						__le64 LastWriteTime;
 | 
				
			||||||
 | 
						__le64 ChangeTime;
 | 
				
			||||||
 | 
						__le64 EndOfFile;
 | 
				
			||||||
 | 
						__le64 AllocationSize;
 | 
				
			||||||
 | 
						__le32 ExtFileAttributes;
 | 
				
			||||||
 | 
						__le32 FileNameLength;
 | 
				
			||||||
 | 
						__le32 EaSize; /* EA size */
 | 
				
			||||||
 | 
						__le32 Reserved;
 | 
				
			||||||
 | 
						__le64 UniqueId; /* inode num - le since Samba puts ino in low 32 bit*/
 | 
				
			||||||
 | 
						char FileName[1];
 | 
				
			||||||
 | 
					} __packed; /* level 0x105 FF rsp data */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct smb_version_values {
 | 
				
			||||||
 | 
						char		*version_string;
 | 
				
			||||||
 | 
						__u16		protocol_id;
 | 
				
			||||||
 | 
						__le16		lock_cmd;
 | 
				
			||||||
 | 
						__u32		capabilities;
 | 
				
			||||||
 | 
						__u32		max_read_size;
 | 
				
			||||||
 | 
						__u32		max_write_size;
 | 
				
			||||||
 | 
						__u32		max_trans_size;
 | 
				
			||||||
 | 
						__u32		large_lock_type;
 | 
				
			||||||
 | 
						__u32		exclusive_lock_type;
 | 
				
			||||||
 | 
						__u32		shared_lock_type;
 | 
				
			||||||
 | 
						__u32		unlock_lock_type;
 | 
				
			||||||
 | 
						size_t		header_size;
 | 
				
			||||||
 | 
						size_t		max_header_size;
 | 
				
			||||||
 | 
						size_t		read_rsp_size;
 | 
				
			||||||
 | 
						unsigned int	cap_unix;
 | 
				
			||||||
 | 
						unsigned int	cap_nt_find;
 | 
				
			||||||
 | 
						unsigned int	cap_large_files;
 | 
				
			||||||
 | 
						__u16		signing_enabled;
 | 
				
			||||||
 | 
						__u16		signing_required;
 | 
				
			||||||
 | 
						size_t		create_lease_size;
 | 
				
			||||||
 | 
						size_t		create_durable_size;
 | 
				
			||||||
 | 
						size_t		create_durable_v2_size;
 | 
				
			||||||
 | 
						size_t		create_mxac_size;
 | 
				
			||||||
 | 
						size_t		create_disk_id_size;
 | 
				
			||||||
 | 
						size_t		create_posix_size;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct filesystem_posix_info {
 | 
				
			||||||
 | 
						/* For undefined recommended transfer size return -1 in that field */
 | 
				
			||||||
 | 
						__le32 OptimalTransferSize;  /* bsize on some os, iosize on other os */
 | 
				
			||||||
 | 
						__le32 BlockSize;
 | 
				
			||||||
 | 
						/* The next three fields are in terms of the block size.
 | 
				
			||||||
 | 
						 * (above). If block size is unknown, 4096 would be a
 | 
				
			||||||
 | 
						 * reasonable block size for a server to report.
 | 
				
			||||||
 | 
						 * Note that returning the blocks/blocksavail removes need
 | 
				
			||||||
 | 
						 * to make a second call (to QFSInfo level 0x103 to get this info.
 | 
				
			||||||
 | 
						 * UserBlockAvail is typically less than or equal to BlocksAvail,
 | 
				
			||||||
 | 
						 * if no distinction is made return the same value in each
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						__le64 TotalBlocks;
 | 
				
			||||||
 | 
						__le64 BlocksAvail;       /* bfree */
 | 
				
			||||||
 | 
						__le64 UserBlocksAvail;   /* bavail */
 | 
				
			||||||
 | 
						/* For undefined Node fields or FSID return -1 */
 | 
				
			||||||
 | 
						__le64 TotalFileNodes;
 | 
				
			||||||
 | 
						__le64 FreeFileNodes;
 | 
				
			||||||
 | 
						__le64 FileSysIdentifier;   /* fsid */
 | 
				
			||||||
 | 
						/* NB Namelen comes from FILE_SYSTEM_ATTRIBUTE_INFO call */
 | 
				
			||||||
 | 
						/* NB flags can come from FILE_SYSTEM_DEVICE_INFO call   */
 | 
				
			||||||
 | 
					} __packed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct smb_version_ops {
 | 
				
			||||||
 | 
						uint16_t (*get_cmd_val)(struct ksmbd_work *swork);
 | 
				
			||||||
 | 
						int (*init_rsp_hdr)(struct ksmbd_work *swork);
 | 
				
			||||||
 | 
						void (*set_rsp_status)(struct ksmbd_work *swork, __le32 err);
 | 
				
			||||||
 | 
						int (*allocate_rsp_buf)(struct ksmbd_work *work);
 | 
				
			||||||
 | 
						int (*set_rsp_credits)(struct ksmbd_work *work);
 | 
				
			||||||
 | 
						int (*check_user_session)(struct ksmbd_work *work);
 | 
				
			||||||
 | 
						int (*get_ksmbd_tcon)(struct ksmbd_work *work);
 | 
				
			||||||
 | 
						bool (*is_sign_req)(struct ksmbd_work *work, unsigned int command);
 | 
				
			||||||
 | 
						int (*check_sign_req)(struct ksmbd_work *work);
 | 
				
			||||||
 | 
						void (*set_sign_rsp)(struct ksmbd_work *work);
 | 
				
			||||||
 | 
						int (*generate_signingkey)(struct ksmbd_session *sess);
 | 
				
			||||||
 | 
						int (*generate_encryptionkey)(struct ksmbd_session *sess);
 | 
				
			||||||
 | 
						int (*is_transform_hdr)(void *buf);
 | 
				
			||||||
 | 
						int (*decrypt_req)(struct ksmbd_work *work);
 | 
				
			||||||
 | 
						int (*encrypt_resp)(struct ksmbd_work *work);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct smb_version_cmds {
 | 
				
			||||||
 | 
						int (*proc)(struct ksmbd_work *swork);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_min_protocol(void);
 | 
				
			||||||
 | 
					int ksmbd_max_protocol(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_lookup_protocol_idx(char *str);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_verify_smb_message(struct ksmbd_work *work);
 | 
				
			||||||
 | 
					bool ksmbd_smb_request(struct ksmbd_conn *conn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_lookup_dialect_by_id(__le16 *cli_dialects, __le16 dialects_count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_negotiate_smb_dialect(void *buf);
 | 
				
			||||||
 | 
					int ksmbd_init_smb_server(struct ksmbd_work *work);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool ksmbd_pdu_size_has_room(unsigned int pdu);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_kstat;
 | 
				
			||||||
 | 
					int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work,
 | 
				
			||||||
 | 
									      int info_level,
 | 
				
			||||||
 | 
									      struct ksmbd_file *dir,
 | 
				
			||||||
 | 
									      struct ksmbd_dir_info *d_info,
 | 
				
			||||||
 | 
									      char *search_pattern,
 | 
				
			||||||
 | 
									      int (*fn)(struct ksmbd_conn *,
 | 
				
			||||||
 | 
											int,
 | 
				
			||||||
 | 
											struct ksmbd_dir_info *,
 | 
				
			||||||
 | 
											struct ksmbd_kstat *));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_extract_shortname(struct ksmbd_conn *conn,
 | 
				
			||||||
 | 
								    const char *longname,
 | 
				
			||||||
 | 
								    char *shortname);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_smb_negotiate_common(struct ksmbd_work *work, unsigned int command);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ksmbd_smb_check_shared_mode(struct file *filp, struct ksmbd_file *curr_fp);
 | 
				
			||||||
 | 
					int ksmbd_override_fsids(struct ksmbd_work *work);
 | 
				
			||||||
 | 
					void ksmbd_revert_fsids(struct ksmbd_work *work);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unsigned int ksmbd_server_side_copy_max_chunk_count(void);
 | 
				
			||||||
 | 
					unsigned int ksmbd_server_side_copy_max_chunk_size(void);
 | 
				
			||||||
 | 
					unsigned int ksmbd_server_side_copy_max_total_size(void);
 | 
				
			||||||
 | 
					bool is_asterisk(char *p);
 | 
				
			||||||
 | 
					__le32 smb_map_generic_desired_access(__le32 daccess);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline unsigned int get_rfc1002_len(void *buf)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return be32_to_cpu(*((__be32 *)buf)) & 0xffffff;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void inc_rfc1001_len(void *buf, int count)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						be32_add_cpu((__be32 *)buf, count);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif /* __SMB_COMMON_H__ */
 | 
				
			||||||
							
								
								
									
										1309
									
								
								fs/cifsd/smbacl.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1309
									
								
								fs/cifsd/smbacl.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										202
									
								
								fs/cifsd/smbacl.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										202
									
								
								fs/cifsd/smbacl.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,202 @@
 | 
				
			||||||
 | 
					/* SPDX-License-Identifier: LGPL-2.1+ */
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *   Copyright (c) International Business Machines  Corp., 2007
 | 
				
			||||||
 | 
					 *   Author(s): Steve French (sfrench@us.ibm.com)
 | 
				
			||||||
 | 
					 *   Modified by Namjae Jeon (linkinjeon@kernel.org)
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef _SMBACL_H
 | 
				
			||||||
 | 
					#define _SMBACL_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <linux/fs.h>
 | 
				
			||||||
 | 
					#include <linux/namei.h>
 | 
				
			||||||
 | 
					#include <linux/posix_acl.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "mgmt/tree_connect.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NUM_AUTHS (6)	/* number of authority fields */
 | 
				
			||||||
 | 
					#define SID_MAX_SUB_AUTHORITIES (15) /* max number of sub authority fields */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ACCESS_ALLOWED	0
 | 
				
			||||||
 | 
					#define ACCESS_DENIED	1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SIDOWNER 1
 | 
				
			||||||
 | 
					#define SIDGROUP 2
 | 
				
			||||||
 | 
					#define SIDCREATOR_OWNER 3
 | 
				
			||||||
 | 
					#define SIDCREATOR_GROUP 4
 | 
				
			||||||
 | 
					#define SIDUNIX_USER 5
 | 
				
			||||||
 | 
					#define SIDUNIX_GROUP 6
 | 
				
			||||||
 | 
					#define SIDNFS_USER 7
 | 
				
			||||||
 | 
					#define SIDNFS_GROUP 8
 | 
				
			||||||
 | 
					#define SIDNFS_MODE 9
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Revision for ACLs */
 | 
				
			||||||
 | 
					#define SD_REVISION	1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Control flags for Security Descriptor */
 | 
				
			||||||
 | 
					#define OWNER_DEFAULTED		0x0001
 | 
				
			||||||
 | 
					#define GROUP_DEFAULTED		0x0002
 | 
				
			||||||
 | 
					#define DACL_PRESENT		0x0004
 | 
				
			||||||
 | 
					#define DACL_DEFAULTED		0x0008
 | 
				
			||||||
 | 
					#define SACL_PRESENT		0x0010
 | 
				
			||||||
 | 
					#define SACL_DEFAULTED		0x0020
 | 
				
			||||||
 | 
					#define DACL_TRUSTED		0x0040
 | 
				
			||||||
 | 
					#define SERVER_SECURITY		0x0080
 | 
				
			||||||
 | 
					#define DACL_AUTO_INHERIT_REQ	0x0100
 | 
				
			||||||
 | 
					#define SACL_AUTO_INHERIT_REQ	0x0200
 | 
				
			||||||
 | 
					#define DACL_AUTO_INHERITED	0x0400
 | 
				
			||||||
 | 
					#define SACL_AUTO_INHERITED	0x0800
 | 
				
			||||||
 | 
					#define DACL_PROTECTED		0x1000
 | 
				
			||||||
 | 
					#define SACL_PROTECTED		0x2000
 | 
				
			||||||
 | 
					#define RM_CONTROL_VALID	0x4000
 | 
				
			||||||
 | 
					#define SELF_RELATIVE		0x8000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ACE types - see MS-DTYP 2.4.4.1 */
 | 
				
			||||||
 | 
					#define ACCESS_ALLOWED_ACE_TYPE 0x00
 | 
				
			||||||
 | 
					#define ACCESS_DENIED_ACE_TYPE  0x01
 | 
				
			||||||
 | 
					#define SYSTEM_AUDIT_ACE_TYPE   0x02
 | 
				
			||||||
 | 
					#define SYSTEM_ALARM_ACE_TYPE   0x03
 | 
				
			||||||
 | 
					#define ACCESS_ALLOWED_COMPOUND_ACE_TYPE 0x04
 | 
				
			||||||
 | 
					#define ACCESS_ALLOWED_OBJECT_ACE_TYPE  0x05
 | 
				
			||||||
 | 
					#define ACCESS_DENIED_OBJECT_ACE_TYPE   0x06
 | 
				
			||||||
 | 
					#define SYSTEM_AUDIT_OBJECT_ACE_TYPE    0x07
 | 
				
			||||||
 | 
					#define SYSTEM_ALARM_OBJECT_ACE_TYPE    0x08
 | 
				
			||||||
 | 
					#define ACCESS_ALLOWED_CALLBACK_ACE_TYPE 0x09
 | 
				
			||||||
 | 
					#define ACCESS_DENIED_CALLBACK_ACE_TYPE 0x0A
 | 
				
			||||||
 | 
					#define ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE 0x0B
 | 
				
			||||||
 | 
					#define ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE  0x0C
 | 
				
			||||||
 | 
					#define SYSTEM_AUDIT_CALLBACK_ACE_TYPE  0x0D
 | 
				
			||||||
 | 
					#define SYSTEM_ALARM_CALLBACK_ACE_TYPE  0x0E /* Reserved */
 | 
				
			||||||
 | 
					#define SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE 0x0F
 | 
				
			||||||
 | 
					#define SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE 0x10 /* reserved */
 | 
				
			||||||
 | 
					#define SYSTEM_MANDATORY_LABEL_ACE_TYPE 0x11
 | 
				
			||||||
 | 
					#define SYSTEM_RESOURCE_ATTRIBUTE_ACE_TYPE 0x12
 | 
				
			||||||
 | 
					#define SYSTEM_SCOPED_POLICY_ID_ACE_TYPE 0x13
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ACE flags */
 | 
				
			||||||
 | 
					#define OBJECT_INHERIT_ACE		0x01
 | 
				
			||||||
 | 
					#define CONTAINER_INHERIT_ACE		0x02
 | 
				
			||||||
 | 
					#define NO_PROPAGATE_INHERIT_ACE	0x04
 | 
				
			||||||
 | 
					#define INHERIT_ONLY_ACE		0x08
 | 
				
			||||||
 | 
					#define INHERITED_ACE			0x10
 | 
				
			||||||
 | 
					#define SUCCESSFUL_ACCESS_ACE_FLAG	0x40
 | 
				
			||||||
 | 
					#define FAILED_ACCESS_ACE_FLAG		0x80
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Maximum size of a string representation of a SID:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The fields are unsigned values in decimal. So:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * u8:  max 3 bytes in decimal
 | 
				
			||||||
 | 
					 * u32: max 10 bytes in decimal
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * "S-" + 3 bytes for version field + 15 for authority field + NULL terminator
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * For authority field, max is when all 6 values are non-zero and it must be
 | 
				
			||||||
 | 
					 * represented in hex. So "-0x" + 12 hex digits.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Add 11 bytes for each subauthority field (10 bytes each + 1 for '-')
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define SID_STRING_BASE_SIZE (2 + 3 + 15 + 1)
 | 
				
			||||||
 | 
					#define SID_STRING_SUBAUTH_SIZE (11) /* size of a single subauth string */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define DOMAIN_USER_RID_LE	cpu_to_le32(513)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ksmbd_conn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct smb_ntsd {
 | 
				
			||||||
 | 
						__le16 revision; /* revision level */
 | 
				
			||||||
 | 
						__le16 type;
 | 
				
			||||||
 | 
						__le32 osidoffset;
 | 
				
			||||||
 | 
						__le32 gsidoffset;
 | 
				
			||||||
 | 
						__le32 sacloffset;
 | 
				
			||||||
 | 
						__le32 dacloffset;
 | 
				
			||||||
 | 
					} __packed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct smb_sid {
 | 
				
			||||||
 | 
						__u8 revision; /* revision level */
 | 
				
			||||||
 | 
						__u8 num_subauth;
 | 
				
			||||||
 | 
						__u8 authority[NUM_AUTHS];
 | 
				
			||||||
 | 
						__le32 sub_auth[SID_MAX_SUB_AUTHORITIES]; /* sub_auth[num_subauth] */
 | 
				
			||||||
 | 
					} __packed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* size of a struct cifs_sid, sans sub_auth array */
 | 
				
			||||||
 | 
					#define CIFS_SID_BASE_SIZE (1 + 1 + NUM_AUTHS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct smb_acl {
 | 
				
			||||||
 | 
						__le16 revision; /* revision level */
 | 
				
			||||||
 | 
						__le16 size;
 | 
				
			||||||
 | 
						__le32 num_aces;
 | 
				
			||||||
 | 
					} __packed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct smb_ace {
 | 
				
			||||||
 | 
						__u8 type;
 | 
				
			||||||
 | 
						__u8 flags;
 | 
				
			||||||
 | 
						__le16 size;
 | 
				
			||||||
 | 
						__le32 access_req;
 | 
				
			||||||
 | 
						struct smb_sid sid; /* ie UUID of user or group who gets these perms */
 | 
				
			||||||
 | 
					} __packed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct smb_fattr {
 | 
				
			||||||
 | 
						kuid_t	cf_uid;
 | 
				
			||||||
 | 
						kgid_t	cf_gid;
 | 
				
			||||||
 | 
						umode_t	cf_mode;
 | 
				
			||||||
 | 
						__le32 daccess;
 | 
				
			||||||
 | 
						struct posix_acl *cf_acls;
 | 
				
			||||||
 | 
						struct posix_acl *cf_dacls;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct posix_ace_state {
 | 
				
			||||||
 | 
						u32 allow;
 | 
				
			||||||
 | 
						u32 deny;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct posix_user_ace_state {
 | 
				
			||||||
 | 
						union {
 | 
				
			||||||
 | 
							kuid_t uid;
 | 
				
			||||||
 | 
							kgid_t gid;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						struct posix_ace_state perms;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct posix_ace_state_array {
 | 
				
			||||||
 | 
						int n;
 | 
				
			||||||
 | 
						struct posix_user_ace_state aces[];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * while processing the nfsv4 ace, this maintains the partial permissions
 | 
				
			||||||
 | 
					 * calculated so far:
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct posix_acl_state {
 | 
				
			||||||
 | 
						struct posix_ace_state owner;
 | 
				
			||||||
 | 
						struct posix_ace_state group;
 | 
				
			||||||
 | 
						struct posix_ace_state other;
 | 
				
			||||||
 | 
						struct posix_ace_state everyone;
 | 
				
			||||||
 | 
						struct posix_ace_state mask; /* deny unused in this case */
 | 
				
			||||||
 | 
						struct posix_ace_state_array *users;
 | 
				
			||||||
 | 
						struct posix_ace_state_array *groups;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int parse_sec_desc(struct smb_ntsd *pntsd, int acl_len,
 | 
				
			||||||
 | 
							struct smb_fattr *fattr);
 | 
				
			||||||
 | 
					int build_sec_desc(struct smb_ntsd *pntsd, struct smb_ntsd *ppntsd,
 | 
				
			||||||
 | 
							int addition_info, __u32 *secdesclen, struct smb_fattr *fattr);
 | 
				
			||||||
 | 
					int init_acl_state(struct posix_acl_state *state, int cnt);
 | 
				
			||||||
 | 
					void free_acl_state(struct posix_acl_state *state);
 | 
				
			||||||
 | 
					void posix_state_to_acl(struct posix_acl_state *state,
 | 
				
			||||||
 | 
							struct posix_acl_entry *pace);
 | 
				
			||||||
 | 
					int compare_sids(const struct smb_sid *ctsid, const struct smb_sid *cwsid);
 | 
				
			||||||
 | 
					bool smb_inherit_flags(int flags, bool is_dir);
 | 
				
			||||||
 | 
					int smb_inherit_dacl(struct ksmbd_conn *conn, struct dentry *dentry,
 | 
				
			||||||
 | 
							unsigned int uid, unsigned int gid);
 | 
				
			||||||
 | 
					int smb_check_perm_dacl(struct ksmbd_conn *conn, struct dentry *dentry,
 | 
				
			||||||
 | 
							__le32 *pdaccess, int uid);
 | 
				
			||||||
 | 
					int store_init_posix_acl(struct inode *inode, umode_t perm);
 | 
				
			||||||
 | 
					int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon,
 | 
				
			||||||
 | 
							struct dentry *dentry, struct smb_ntsd *pntsd, int ntsd_len,
 | 
				
			||||||
 | 
							bool type_check);
 | 
				
			||||||
 | 
					void id_to_sid(unsigned int cid, uint sidtype, struct smb_sid *ssid);
 | 
				
			||||||
 | 
					void ksmbd_init_domain(u32 *sub_auth);
 | 
				
			||||||
 | 
					#endif /* _SMBACL_H */
 | 
				
			||||||
							
								
								
									
										235
									
								
								fs/cifsd/smberr.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										235
									
								
								fs/cifsd/smberr.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,235 @@
 | 
				
			||||||
 | 
					/* SPDX-License-Identifier: LGPL-2.1+ */
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *   Copyright (c) International Business Machines  Corp., 2002,2004
 | 
				
			||||||
 | 
					 *   Author(s): Steve French (sfrench@us.ibm.com)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   See Error Codes section of the SNIA CIFS Specification
 | 
				
			||||||
 | 
					 *   for more information
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#ifndef __KSMBD_SMBERR_H
 | 
				
			||||||
 | 
					#define __KSMBD_SMBERR_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SUCCESS	0x00	/* The request was successful. */
 | 
				
			||||||
 | 
					#define ERRDOS	0x01	/* Error is from the core DOS operating system set */
 | 
				
			||||||
 | 
					#define ERRSRV	0x02	/* Error is generated by the file server daemon */
 | 
				
			||||||
 | 
					#define ERRHRD	0x03	/* Error is a hardware error. */
 | 
				
			||||||
 | 
					#define ERRCMD	0xFF	/* Command was not in the "SMB" format. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* The following error codes may be generated with the SUCCESS error class.*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*#define SUCCESS	0	The request was successful. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* The following error codes may be generated with the ERRDOS error class.*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ERRbadfunc		1	/*
 | 
				
			||||||
 | 
										 * Invalid function. The server did not
 | 
				
			||||||
 | 
										 * recognize or could not perform a
 | 
				
			||||||
 | 
										 * system call generated by the server,
 | 
				
			||||||
 | 
										 * e.g., set the DIRECTORY attribute on
 | 
				
			||||||
 | 
										 * a data file, invalid seek mode.
 | 
				
			||||||
 | 
										 */
 | 
				
			||||||
 | 
					#define ERRbadfile		2	/*
 | 
				
			||||||
 | 
										 * File not found. The last component
 | 
				
			||||||
 | 
										 * of a file's pathname could not be
 | 
				
			||||||
 | 
										 * found.
 | 
				
			||||||
 | 
										 */
 | 
				
			||||||
 | 
					#define ERRbadpath		3	/*
 | 
				
			||||||
 | 
										 * Directory invalid. A directory
 | 
				
			||||||
 | 
										 * component in a pathname could not be
 | 
				
			||||||
 | 
										 * found.
 | 
				
			||||||
 | 
										 */
 | 
				
			||||||
 | 
					#define ERRnofids		4	/*
 | 
				
			||||||
 | 
										 * Too many open files. The server has
 | 
				
			||||||
 | 
										 * no file handles available.
 | 
				
			||||||
 | 
										 */
 | 
				
			||||||
 | 
					#define ERRnoaccess		5	/*
 | 
				
			||||||
 | 
										 * Access denied, the client's context
 | 
				
			||||||
 | 
										 * does not permit the requested
 | 
				
			||||||
 | 
										 * function. This includes the
 | 
				
			||||||
 | 
										 * following conditions: invalid rename
 | 
				
			||||||
 | 
										 * command, write to Fid open for read
 | 
				
			||||||
 | 
										 * only, read on Fid open for write
 | 
				
			||||||
 | 
										 * only, attempt to delete a non-empty
 | 
				
			||||||
 | 
										 * directory
 | 
				
			||||||
 | 
										 */
 | 
				
			||||||
 | 
					#define ERRbadfid		6	/*
 | 
				
			||||||
 | 
										 * Invalid file handle. The file handle
 | 
				
			||||||
 | 
										 * specified was not recognized by the
 | 
				
			||||||
 | 
										 * server.
 | 
				
			||||||
 | 
										 */
 | 
				
			||||||
 | 
					#define ERRbadmcb		7	/* Memory control blocks destroyed. */
 | 
				
			||||||
 | 
					#define ERRnomem		8	/*
 | 
				
			||||||
 | 
										 * Insufficient server memory to
 | 
				
			||||||
 | 
										 * perform the requested function.
 | 
				
			||||||
 | 
										 */
 | 
				
			||||||
 | 
					#define ERRbadmem		9	/* Invalid memory block address. */
 | 
				
			||||||
 | 
					#define ERRbadenv		10	/* Invalid environment. */
 | 
				
			||||||
 | 
					#define ERRbadformat		11	/* Invalid format. */
 | 
				
			||||||
 | 
					#define ERRbadaccess		12	/* Invalid open mode. */
 | 
				
			||||||
 | 
					#define ERRbaddata		13	/*
 | 
				
			||||||
 | 
										 * Invalid data (generated only by
 | 
				
			||||||
 | 
										 * IOCTL calls within the server).
 | 
				
			||||||
 | 
										 */
 | 
				
			||||||
 | 
					#define ERRbaddrive		15	/* Invalid drive specified. */
 | 
				
			||||||
 | 
					#define ERRremcd		16	/*
 | 
				
			||||||
 | 
										 * A Delete Directory request attempted
 | 
				
			||||||
 | 
										 * to remove the server's current
 | 
				
			||||||
 | 
										 * directory.
 | 
				
			||||||
 | 
										 */
 | 
				
			||||||
 | 
					#define ERRdiffdevice		17	/*
 | 
				
			||||||
 | 
										 * Not same device (e.g., a cross
 | 
				
			||||||
 | 
										 * volume rename was attempted
 | 
				
			||||||
 | 
										 */
 | 
				
			||||||
 | 
					#define ERRnofiles		18	/*
 | 
				
			||||||
 | 
										 * A File Search command can find no
 | 
				
			||||||
 | 
										 * more files matching the specified
 | 
				
			||||||
 | 
										 * criteria.
 | 
				
			||||||
 | 
										 */
 | 
				
			||||||
 | 
					#define ERRwriteprot		19	/* media is write protected */
 | 
				
			||||||
 | 
					#define ERRgeneral		31
 | 
				
			||||||
 | 
					#define ERRbadshare		32	/*
 | 
				
			||||||
 | 
										 * The sharing mode specified for an
 | 
				
			||||||
 | 
										 * Open conflicts with existing FIDs on
 | 
				
			||||||
 | 
										 * the file.
 | 
				
			||||||
 | 
										 */
 | 
				
			||||||
 | 
					#define ERRlock			33	/*
 | 
				
			||||||
 | 
										 * A Lock request conflicted with an
 | 
				
			||||||
 | 
										 * existing lock or specified an
 | 
				
			||||||
 | 
										 * invalid mode, or an Unlock requested
 | 
				
			||||||
 | 
										 * attempted to remove a lock held by
 | 
				
			||||||
 | 
										 * another process.
 | 
				
			||||||
 | 
										 */
 | 
				
			||||||
 | 
					#define ERRunsup		50
 | 
				
			||||||
 | 
					#define ERRnosuchshare		67
 | 
				
			||||||
 | 
					#define ERRfilexists		80	/*
 | 
				
			||||||
 | 
										 * The file named in the request
 | 
				
			||||||
 | 
										 * already exists.
 | 
				
			||||||
 | 
										 */
 | 
				
			||||||
 | 
					#define ERRinvparm		87
 | 
				
			||||||
 | 
					#define ERRdiskfull		112
 | 
				
			||||||
 | 
					#define ERRinvname		123
 | 
				
			||||||
 | 
					#define ERRinvlevel		124
 | 
				
			||||||
 | 
					#define ERRdirnotempty		145
 | 
				
			||||||
 | 
					#define ERRnotlocked		158
 | 
				
			||||||
 | 
					#define ERRcancelviolation	173
 | 
				
			||||||
 | 
					#define ERRnoatomiclocks	174
 | 
				
			||||||
 | 
					#define ERRalreadyexists	183
 | 
				
			||||||
 | 
					#define ERRbadpipe		230
 | 
				
			||||||
 | 
					#define ERRpipebusy		231
 | 
				
			||||||
 | 
					#define ERRpipeclosing		232
 | 
				
			||||||
 | 
					#define ERRnotconnected		233
 | 
				
			||||||
 | 
					#define ERRmoredata		234
 | 
				
			||||||
 | 
					#define ERReasnotsupported	282
 | 
				
			||||||
 | 
					#define ErrQuota		0x200	/*
 | 
				
			||||||
 | 
										 * The operation would cause a quota
 | 
				
			||||||
 | 
										 * limit to be exceeded.
 | 
				
			||||||
 | 
										 */
 | 
				
			||||||
 | 
					#define ErrNotALink		0x201	/*
 | 
				
			||||||
 | 
										 * A link operation was performed on a
 | 
				
			||||||
 | 
										 * pathname that was not a link.
 | 
				
			||||||
 | 
										 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Below errors are used internally (do not come over the wire) for passthrough
 | 
				
			||||||
 | 
					 * from STATUS codes to POSIX only
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define ERRsymlink              0xFFFD
 | 
				
			||||||
 | 
					#define ErrTooManyLinks         0xFFFE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Following error codes may be generated with the ERRSRV error class.*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ERRerror		1	/*
 | 
				
			||||||
 | 
										 * Non-specific error code. It is
 | 
				
			||||||
 | 
										 * returned under the following
 | 
				
			||||||
 | 
										 * conditions: resource other than disk
 | 
				
			||||||
 | 
										 * space exhausted (e.g. TIDs), first
 | 
				
			||||||
 | 
										 * SMB command was not negotiate,
 | 
				
			||||||
 | 
										 * multiple negotiates attempted, and
 | 
				
			||||||
 | 
										 * internal server error.
 | 
				
			||||||
 | 
										 */
 | 
				
			||||||
 | 
					#define ERRbadpw		2	/*
 | 
				
			||||||
 | 
										 * Bad password - name/password pair in
 | 
				
			||||||
 | 
										 * a TreeConnect or Session Setup are
 | 
				
			||||||
 | 
										 * invalid.
 | 
				
			||||||
 | 
										 */
 | 
				
			||||||
 | 
					#define ERRbadtype		3	/*
 | 
				
			||||||
 | 
										 * used for indicating DFS referral
 | 
				
			||||||
 | 
										 * needed
 | 
				
			||||||
 | 
										 */
 | 
				
			||||||
 | 
					#define ERRaccess		4	/*
 | 
				
			||||||
 | 
										 * The client does not have the
 | 
				
			||||||
 | 
										 * necessary access rights within the
 | 
				
			||||||
 | 
										 * specified context for requested
 | 
				
			||||||
 | 
										 * function.
 | 
				
			||||||
 | 
										 */
 | 
				
			||||||
 | 
					#define ERRinvtid		5	/*
 | 
				
			||||||
 | 
										 * The Tid specified in a command was
 | 
				
			||||||
 | 
										 * invalid.
 | 
				
			||||||
 | 
										 */
 | 
				
			||||||
 | 
					#define ERRinvnetname		6	/*
 | 
				
			||||||
 | 
										 * Invalid network name in tree
 | 
				
			||||||
 | 
										 * connect.
 | 
				
			||||||
 | 
										 */
 | 
				
			||||||
 | 
					#define ERRinvdevice		7	/*
 | 
				
			||||||
 | 
										 * Invalid device - printer request
 | 
				
			||||||
 | 
										 * made to non-printer connection or
 | 
				
			||||||
 | 
										 * non-printer request made to printer
 | 
				
			||||||
 | 
										 * connection.
 | 
				
			||||||
 | 
										 */
 | 
				
			||||||
 | 
					#define ERRqfull		49	/*
 | 
				
			||||||
 | 
										 * Print queue full (files) -- returned
 | 
				
			||||||
 | 
										 * by open print file.
 | 
				
			||||||
 | 
										 */
 | 
				
			||||||
 | 
					#define ERRqtoobig		50	/* Print queue full -- no space. */
 | 
				
			||||||
 | 
					#define ERRqeof			51	/* EOF on print queue dump */
 | 
				
			||||||
 | 
					#define ERRinvpfid		52	/* Invalid print file FID. */
 | 
				
			||||||
 | 
					#define ERRsmbcmd		64	/*
 | 
				
			||||||
 | 
										 * The server did not recognize the
 | 
				
			||||||
 | 
										 * command received.
 | 
				
			||||||
 | 
										 */
 | 
				
			||||||
 | 
					#define ERRsrverror		65	/*
 | 
				
			||||||
 | 
										 * The server encountered an internal
 | 
				
			||||||
 | 
										 * error, e.g., system file
 | 
				
			||||||
 | 
										 * unavailable.
 | 
				
			||||||
 | 
										 */
 | 
				
			||||||
 | 
					#define ERRbadBID		66	/* (obsolete) */
 | 
				
			||||||
 | 
					#define ERRfilespecs		67	/*
 | 
				
			||||||
 | 
										 * The Fid and pathname parameters
 | 
				
			||||||
 | 
										 * contained an invalid combination of
 | 
				
			||||||
 | 
										 * values.
 | 
				
			||||||
 | 
										 */
 | 
				
			||||||
 | 
					#define ERRbadLink		68	/* (obsolete) */
 | 
				
			||||||
 | 
					#define ERRbadpermits		69	/*
 | 
				
			||||||
 | 
										 * The access permissions specified for
 | 
				
			||||||
 | 
										 * a file or directory are not a valid
 | 
				
			||||||
 | 
										 * combination.
 | 
				
			||||||
 | 
										 */
 | 
				
			||||||
 | 
					#define ERRbadPID		70
 | 
				
			||||||
 | 
					#define ERRsetattrmode		71	/* attribute (mode) is invalid */
 | 
				
			||||||
 | 
					#define ERRpaused		81	/* Server is paused */
 | 
				
			||||||
 | 
					#define ERRmsgoff		82	/* reserved - messaging off */
 | 
				
			||||||
 | 
					#define ERRnoroom		83	/* reserved - no room for message */
 | 
				
			||||||
 | 
					#define ERRrmuns		87	/* reserved - too many remote names */
 | 
				
			||||||
 | 
					#define ERRtimeout		88	/* operation timed out */
 | 
				
			||||||
 | 
					#define ERRnoresource		89	/* No resources available for request */
 | 
				
			||||||
 | 
					#define ERRtoomanyuids		90	/*
 | 
				
			||||||
 | 
										 * Too many UIDs active on this session
 | 
				
			||||||
 | 
										 */
 | 
				
			||||||
 | 
					#define ERRbaduid		91	/*
 | 
				
			||||||
 | 
										 * The UID is not known as a valid user
 | 
				
			||||||
 | 
										 */
 | 
				
			||||||
 | 
					#define ERRusempx		250	/* temporarily unable to use raw */
 | 
				
			||||||
 | 
					#define ERRusestd		251	/*
 | 
				
			||||||
 | 
										 * temporarily unable to use either raw
 | 
				
			||||||
 | 
										 * or mpx
 | 
				
			||||||
 | 
										 */
 | 
				
			||||||
 | 
					#define ERR_NOTIFY_ENUM_DIR	1024
 | 
				
			||||||
 | 
					#define ERRnoSuchUser		2238	/* user account does not exist */
 | 
				
			||||||
 | 
					#define ERRaccountexpired	2239
 | 
				
			||||||
 | 
					#define ERRbadclient		2240	/* can not logon from this client */
 | 
				
			||||||
 | 
					#define ERRbadLogonTime		2241	/* logon hours do not allow this */
 | 
				
			||||||
 | 
					#define ERRpasswordExpired	2242
 | 
				
			||||||
 | 
					#define ERRnetlogonNotStarted	2455
 | 
				
			||||||
 | 
					#define ERRnosupport		0xFFFF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* __KSMBD_SMBERR_H */
 | 
				
			||||||
							
								
								
									
										90
									
								
								fs/cifsd/smbfsctl.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								fs/cifsd/smbfsctl.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,90 @@
 | 
				
			||||||
 | 
					/* SPDX-License-Identifier: LGPL-2.1+ */
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *   fs/cifs/smbfsctl.h: SMB, CIFS, SMB2 FSCTL definitions
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   Copyright (c) International Business Machines  Corp., 2002,2009
 | 
				
			||||||
 | 
					 *   Author(s): Steve French (sfrench@us.ibm.com)
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* IOCTL information */
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * List of ioctl/fsctl function codes that are or could be useful in the
 | 
				
			||||||
 | 
					 * future to remote clients like cifs or SMB2 client.  There is probably
 | 
				
			||||||
 | 
					 * a slightly larger set of fsctls that NTFS local filesystem could handle,
 | 
				
			||||||
 | 
					 * including the seven below that we do not have struct definitions for.
 | 
				
			||||||
 | 
					 * Even with protocol definitions for most of these now available, we still
 | 
				
			||||||
 | 
					 * need to do some experimentation to identify which are practical to do
 | 
				
			||||||
 | 
					 * remotely.  Some of the following, such as the encryption/compression ones
 | 
				
			||||||
 | 
					 * could be invoked from tools via a specialized hook into the VFS rather
 | 
				
			||||||
 | 
					 * than via the standard vfs entry points
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef __KSMBD_SMBFSCTL_H
 | 
				
			||||||
 | 
					#define __KSMBD_SMBFSCTL_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define FSCTL_DFS_GET_REFERRALS      0x00060194
 | 
				
			||||||
 | 
					#define FSCTL_DFS_GET_REFERRALS_EX   0x000601B0
 | 
				
			||||||
 | 
					#define FSCTL_REQUEST_OPLOCK_LEVEL_1 0x00090000
 | 
				
			||||||
 | 
					#define FSCTL_REQUEST_OPLOCK_LEVEL_2 0x00090004
 | 
				
			||||||
 | 
					#define FSCTL_REQUEST_BATCH_OPLOCK   0x00090008
 | 
				
			||||||
 | 
					#define FSCTL_LOCK_VOLUME            0x00090018
 | 
				
			||||||
 | 
					#define FSCTL_UNLOCK_VOLUME          0x0009001C
 | 
				
			||||||
 | 
					#define FSCTL_IS_PATHNAME_VALID      0x0009002C /* BB add struct */
 | 
				
			||||||
 | 
					#define FSCTL_GET_COMPRESSION        0x0009003C /* BB add struct */
 | 
				
			||||||
 | 
					#define FSCTL_SET_COMPRESSION        0x0009C040 /* BB add struct */
 | 
				
			||||||
 | 
					#define FSCTL_QUERY_FAT_BPB          0x00090058 /* BB add struct */
 | 
				
			||||||
 | 
					/* Verify the next FSCTL number, we had it as 0x00090090 before */
 | 
				
			||||||
 | 
					#define FSCTL_FILESYSTEM_GET_STATS   0x00090060 /* BB add struct */
 | 
				
			||||||
 | 
					#define FSCTL_GET_NTFS_VOLUME_DATA   0x00090064 /* BB add struct */
 | 
				
			||||||
 | 
					#define FSCTL_GET_RETRIEVAL_POINTERS 0x00090073 /* BB add struct */
 | 
				
			||||||
 | 
					#define FSCTL_IS_VOLUME_DIRTY        0x00090078 /* BB add struct */
 | 
				
			||||||
 | 
					#define FSCTL_ALLOW_EXTENDED_DASD_IO 0x00090083 /* BB add struct */
 | 
				
			||||||
 | 
					#define FSCTL_REQUEST_FILTER_OPLOCK  0x0009008C
 | 
				
			||||||
 | 
					#define FSCTL_FIND_FILES_BY_SID      0x0009008F /* BB add struct */
 | 
				
			||||||
 | 
					#define FSCTL_SET_OBJECT_ID          0x00090098 /* BB add struct */
 | 
				
			||||||
 | 
					#define FSCTL_GET_OBJECT_ID          0x0009009C /* BB add struct */
 | 
				
			||||||
 | 
					#define FSCTL_DELETE_OBJECT_ID       0x000900A0 /* BB add struct */
 | 
				
			||||||
 | 
					#define FSCTL_SET_REPARSE_POINT      0x000900A4 /* BB add struct */
 | 
				
			||||||
 | 
					#define FSCTL_GET_REPARSE_POINT      0x000900A8 /* BB add struct */
 | 
				
			||||||
 | 
					#define FSCTL_DELETE_REPARSE_POINT   0x000900AC /* BB add struct */
 | 
				
			||||||
 | 
					#define FSCTL_SET_OBJECT_ID_EXTENDED 0x000900BC /* BB add struct */
 | 
				
			||||||
 | 
					#define FSCTL_CREATE_OR_GET_OBJECT_ID 0x000900C0 /* BB add struct */
 | 
				
			||||||
 | 
					#define FSCTL_SET_SPARSE             0x000900C4 /* BB add struct */
 | 
				
			||||||
 | 
					#define FSCTL_SET_ZERO_DATA          0x000980C8 /* BB add struct */
 | 
				
			||||||
 | 
					#define FSCTL_SET_ENCRYPTION         0x000900D7 /* BB add struct */
 | 
				
			||||||
 | 
					#define FSCTL_ENCRYPTION_FSCTL_IO    0x000900DB /* BB add struct */
 | 
				
			||||||
 | 
					#define FSCTL_WRITE_RAW_ENCRYPTED    0x000900DF /* BB add struct */
 | 
				
			||||||
 | 
					#define FSCTL_READ_RAW_ENCRYPTED     0x000900E3 /* BB add struct */
 | 
				
			||||||
 | 
					#define FSCTL_READ_FILE_USN_DATA     0x000900EB /* BB add struct */
 | 
				
			||||||
 | 
					#define FSCTL_WRITE_USN_CLOSE_RECORD 0x000900EF /* BB add struct */
 | 
				
			||||||
 | 
					#define FSCTL_SIS_COPYFILE           0x00090100 /* BB add struct */
 | 
				
			||||||
 | 
					#define FSCTL_RECALL_FILE            0x00090117 /* BB add struct */
 | 
				
			||||||
 | 
					#define FSCTL_QUERY_SPARING_INFO     0x00090138 /* BB add struct */
 | 
				
			||||||
 | 
					#define FSCTL_SET_ZERO_ON_DEALLOC    0x00090194 /* BB add struct */
 | 
				
			||||||
 | 
					#define FSCTL_SET_SHORT_NAME_BEHAVIOR 0x000901B4 /* BB add struct */
 | 
				
			||||||
 | 
					#define FSCTL_QUERY_ALLOCATED_RANGES 0x000940CF /* BB add struct */
 | 
				
			||||||
 | 
					#define FSCTL_SET_DEFECT_MANAGEMENT  0x00098134 /* BB add struct */
 | 
				
			||||||
 | 
					#define FSCTL_SIS_LINK_FILES         0x0009C104
 | 
				
			||||||
 | 
					#define FSCTL_PIPE_PEEK              0x0011400C /* BB add struct */
 | 
				
			||||||
 | 
					#define FSCTL_PIPE_TRANSCEIVE        0x0011C017 /* BB add struct */
 | 
				
			||||||
 | 
					/* strange that the number for this op is not sequential with previous op */
 | 
				
			||||||
 | 
					#define FSCTL_PIPE_WAIT              0x00110018 /* BB add struct */
 | 
				
			||||||
 | 
					#define FSCTL_REQUEST_RESUME_KEY     0x00140078
 | 
				
			||||||
 | 
					#define FSCTL_LMR_GET_LINK_TRACK_INF 0x001400E8 /* BB add struct */
 | 
				
			||||||
 | 
					#define FSCTL_LMR_SET_LINK_TRACK_INF 0x001400EC /* BB add struct */
 | 
				
			||||||
 | 
					#define FSCTL_VALIDATE_NEGOTIATE_INFO 0x00140204
 | 
				
			||||||
 | 
					#define FSCTL_QUERY_NETWORK_INTERFACE_INFO 0x001401FC
 | 
				
			||||||
 | 
					#define FSCTL_COPYCHUNK              0x001440F2
 | 
				
			||||||
 | 
					#define FSCTL_COPYCHUNK_WRITE        0x001480F2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IO_REPARSE_TAG_MOUNT_POINT   0xA0000003
 | 
				
			||||||
 | 
					#define IO_REPARSE_TAG_HSM           0xC0000004
 | 
				
			||||||
 | 
					#define IO_REPARSE_TAG_SIS           0x80000007
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* WSL reparse tags */
 | 
				
			||||||
 | 
					#define IO_REPARSE_TAG_LX_SYMLINK_LE	cpu_to_le32(0xA000001D)
 | 
				
			||||||
 | 
					#define IO_REPARSE_TAG_AF_UNIX_LE	cpu_to_le32(0x80000023)
 | 
				
			||||||
 | 
					#define IO_REPARSE_TAG_LX_FIFO_LE	cpu_to_le32(0x80000024)
 | 
				
			||||||
 | 
					#define IO_REPARSE_TAG_LX_CHR_LE	cpu_to_le32(0x80000025)
 | 
				
			||||||
 | 
					#define IO_REPARSE_TAG_LX_BLK_LE	cpu_to_le32(0x80000026)
 | 
				
			||||||
 | 
					#endif /* __KSMBD_SMBFSCTL_H */
 | 
				
			||||||
							
								
								
									
										1822
									
								
								fs/cifsd/smbstatus.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1822
									
								
								fs/cifsd/smbstatus.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										34
									
								
								fs/cifsd/time_wrappers.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								fs/cifsd/time_wrappers.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,34 @@
 | 
				
			||||||
 | 
					/* SPDX-License-Identifier: GPL-2.0-or-later */
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *   Copyright (C) 2019 Samsung Electronics Co., Ltd.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef __KSMBD_TIME_WRAPPERS_H
 | 
				
			||||||
 | 
					#define __KSMBD_TIME_WRAPPERS_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * A bunch of ugly hacks to workaoround all the API differences
 | 
				
			||||||
 | 
					 * between different kernel versions.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NTFS_TIME_OFFSET	((u64)(369*365 + 89) * 24 * 3600 * 10000000)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Convert the Unix UTC into NT UTC. */
 | 
				
			||||||
 | 
					static inline u64 ksmbd_UnixTimeToNT(struct timespec64 t)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/* Convert to 100ns intervals and then add the NTFS time offset. */
 | 
				
			||||||
 | 
						return (u64) t.tv_sec * 10000000 + t.tv_nsec / 100 + NTFS_TIME_OFFSET;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct timespec64 ksmbd_NTtimeToUnix(__le64 ntutc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define KSMBD_TIME_TO_TM	time64_to_tm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline long long ksmbd_systime(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct timespec64 ts;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ktime_get_real_ts64(&ts);
 | 
				
			||||||
 | 
						return ksmbd_UnixTimeToNT(ts);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif /* __KSMBD_TIME_WRAPPERS_H */
 | 
				
			||||||
							
								
								
									
										391
									
								
								fs/cifsd/unicode.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										391
									
								
								fs/cifsd/unicode.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,391 @@
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: GPL-2.0-or-later
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *   Some of the source code in this file came from fs/cifs/cifs_unicode.c
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   Copyright (c) International Business Machines  Corp., 2000,2009
 | 
				
			||||||
 | 
					 *   Modified by Steve French (sfrench@us.ibm.com)
 | 
				
			||||||
 | 
					 *   Modified by Namjae Jeon (linkinjeon@kernel.org)
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#include <linux/fs.h>
 | 
				
			||||||
 | 
					#include <linux/slab.h>
 | 
				
			||||||
 | 
					#include <asm/unaligned.h>
 | 
				
			||||||
 | 
					#include "glob.h"
 | 
				
			||||||
 | 
					#include "unicode.h"
 | 
				
			||||||
 | 
					#include "uniupr.h"
 | 
				
			||||||
 | 
					#include "smb_common.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * smb_utf16_bytes() - how long will a string be after conversion?
 | 
				
			||||||
 | 
					 * @from:	pointer to input string
 | 
				
			||||||
 | 
					 * @maxbytes:	don't go past this many bytes of input string
 | 
				
			||||||
 | 
					 * @codepage:	destination codepage
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Walk a utf16le string and return the number of bytes that the string will
 | 
				
			||||||
 | 
					 * be after being converted to the given charset, not including any null
 | 
				
			||||||
 | 
					 * termination required. Don't walk past maxbytes in the source buffer.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return:	string length after conversion
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int smb_utf16_bytes(const __le16 *from,
 | 
				
			||||||
 | 
								   int maxbytes,
 | 
				
			||||||
 | 
								   const struct nls_table *codepage)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						int charlen, outlen = 0;
 | 
				
			||||||
 | 
						int maxwords = maxbytes / 2;
 | 
				
			||||||
 | 
						char tmp[NLS_MAX_CHARSET_SIZE];
 | 
				
			||||||
 | 
						__u16 ftmp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < maxwords; i++) {
 | 
				
			||||||
 | 
							ftmp = get_unaligned_le16(&from[i]);
 | 
				
			||||||
 | 
							if (ftmp == 0)
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							charlen = codepage->uni2char(ftmp, tmp, NLS_MAX_CHARSET_SIZE);
 | 
				
			||||||
 | 
							if (charlen > 0)
 | 
				
			||||||
 | 
								outlen += charlen;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								outlen++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return outlen;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * cifs_mapchar() - convert a host-endian char to proper char in codepage
 | 
				
			||||||
 | 
					 * @target:	where converted character should be copied
 | 
				
			||||||
 | 
					 * @src_char:	2 byte host-endian source character
 | 
				
			||||||
 | 
					 * @cp:		codepage to which character should be converted
 | 
				
			||||||
 | 
					 * @mapchar:	should character be mapped according to mapchars mount option?
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This function handles the conversion of a single character. It is the
 | 
				
			||||||
 | 
					 * responsibility of the caller to ensure that the target buffer is large
 | 
				
			||||||
 | 
					 * enough to hold the result of the conversion (at least NLS_MAX_CHARSET_SIZE).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return:	string length after conversion
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					cifs_mapchar(char *target, const __u16 src_char, const struct nls_table *cp,
 | 
				
			||||||
 | 
						     bool mapchar)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int len = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!mapchar)
 | 
				
			||||||
 | 
							goto cp_convert;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * BB: Cannot handle remapping UNI_SLASH until all the calls to
 | 
				
			||||||
 | 
						 *     build_path_from_dentry are modified, as they use slash as
 | 
				
			||||||
 | 
						 *     separator.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						switch (src_char) {
 | 
				
			||||||
 | 
						case UNI_COLON:
 | 
				
			||||||
 | 
							*target = ':';
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case UNI_ASTERISK:
 | 
				
			||||||
 | 
							*target = '*';
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case UNI_QUESTION:
 | 
				
			||||||
 | 
							*target = '?';
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case UNI_PIPE:
 | 
				
			||||||
 | 
							*target = '|';
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case UNI_GRTRTHAN:
 | 
				
			||||||
 | 
							*target = '>';
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case UNI_LESSTHAN:
 | 
				
			||||||
 | 
							*target = '<';
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							goto cp_convert;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					out:
 | 
				
			||||||
 | 
						return len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cp_convert:
 | 
				
			||||||
 | 
						len = cp->uni2char(src_char, target, NLS_MAX_CHARSET_SIZE);
 | 
				
			||||||
 | 
						if (len <= 0) {
 | 
				
			||||||
 | 
							*target = '?';
 | 
				
			||||||
 | 
							len = 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						goto out;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * is_char_allowed() - check for valid character
 | 
				
			||||||
 | 
					 * @ch:		input character to be checked
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return:	1 if char is allowed, otherwise 0
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline int is_char_allowed(char *ch)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/* check for control chars, wildcards etc. */
 | 
				
			||||||
 | 
						if (!(*ch & 0x80) &&
 | 
				
			||||||
 | 
							(*ch <= 0x1f ||
 | 
				
			||||||
 | 
							 *ch == '?' || *ch == '"' || *ch == '<' ||
 | 
				
			||||||
 | 
							 *ch == '>' || *ch == '|'))
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * smb_from_utf16() - convert utf16le string to local charset
 | 
				
			||||||
 | 
					 * @to:		destination buffer
 | 
				
			||||||
 | 
					 * @from:	source buffer
 | 
				
			||||||
 | 
					 * @tolen:	destination buffer size (in bytes)
 | 
				
			||||||
 | 
					 * @fromlen:	source buffer size (in bytes)
 | 
				
			||||||
 | 
					 * @codepage:	codepage to which characters should be converted
 | 
				
			||||||
 | 
					 * @mapchar:	should characters be remapped according to the mapchars option?
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Convert a little-endian utf16le string (as sent by the server) to a string
 | 
				
			||||||
 | 
					 * in the provided codepage. The tolen and fromlen parameters are to ensure
 | 
				
			||||||
 | 
					 * that the code doesn't walk off of the end of the buffer (which is always
 | 
				
			||||||
 | 
					 * a danger if the alignment of the source buffer is off). The destination
 | 
				
			||||||
 | 
					 * string is always properly null terminated and fits in the destination
 | 
				
			||||||
 | 
					 * buffer. Returns the length of the destination string in bytes (including
 | 
				
			||||||
 | 
					 * null terminator).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Note that some windows versions actually send multiword UTF-16 characters
 | 
				
			||||||
 | 
					 * instead of straight UTF16-2. The linux nls routines however aren't able to
 | 
				
			||||||
 | 
					 * deal with those characters properly. In the event that we get some of
 | 
				
			||||||
 | 
					 * those characters, they won't be translated properly.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return:	string length after conversion
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int smb_from_utf16(char *to,
 | 
				
			||||||
 | 
								  const __le16 *from,
 | 
				
			||||||
 | 
								  int tolen,
 | 
				
			||||||
 | 
								  int fromlen,
 | 
				
			||||||
 | 
								  const struct nls_table *codepage,
 | 
				
			||||||
 | 
								  bool mapchar)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i, charlen, safelen;
 | 
				
			||||||
 | 
						int outlen = 0;
 | 
				
			||||||
 | 
						int nullsize = nls_nullsize(codepage);
 | 
				
			||||||
 | 
						int fromwords = fromlen / 2;
 | 
				
			||||||
 | 
						char tmp[NLS_MAX_CHARSET_SIZE];
 | 
				
			||||||
 | 
						__u16 ftmp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * because the chars can be of varying widths, we need to take care
 | 
				
			||||||
 | 
						 * not to overflow the destination buffer when we get close to the
 | 
				
			||||||
 | 
						 * end of it. Until we get to this offset, we don't need to check
 | 
				
			||||||
 | 
						 * for overflow however.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						safelen = tolen - (NLS_MAX_CHARSET_SIZE + nullsize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < fromwords; i++) {
 | 
				
			||||||
 | 
							ftmp = get_unaligned_le16(&from[i]);
 | 
				
			||||||
 | 
							if (ftmp == 0)
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * check to see if converting this character might make the
 | 
				
			||||||
 | 
							 * conversion bleed into the null terminator
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							if (outlen >= safelen) {
 | 
				
			||||||
 | 
								charlen = cifs_mapchar(tmp, ftmp, codepage, mapchar);
 | 
				
			||||||
 | 
								if ((outlen + charlen) > (tolen - nullsize))
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* put converted char into 'to' buffer */
 | 
				
			||||||
 | 
							charlen = cifs_mapchar(&to[outlen], ftmp, codepage, mapchar);
 | 
				
			||||||
 | 
							outlen += charlen;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* properly null-terminate string */
 | 
				
			||||||
 | 
						for (i = 0; i < nullsize; i++)
 | 
				
			||||||
 | 
							to[outlen++] = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return outlen;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * smb_strtoUTF16() - Convert character string to unicode string
 | 
				
			||||||
 | 
					 * @to:		destination buffer
 | 
				
			||||||
 | 
					 * @from:	source buffer
 | 
				
			||||||
 | 
					 * @len:	destination buffer size (in bytes)
 | 
				
			||||||
 | 
					 * @codepage:	codepage to which characters should be converted
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return:	string length after conversion
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					smb_strtoUTF16(__le16 *to, const char *from, int len,
 | 
				
			||||||
 | 
						      const struct nls_table *codepage)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int charlen;
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						wchar_t wchar_to; /* needed to quiet sparse */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* special case for utf8 to handle no plane0 chars */
 | 
				
			||||||
 | 
						if (!strcmp(codepage->charset, "utf8")) {
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * convert utf8 -> utf16, we assume we have enough space
 | 
				
			||||||
 | 
							 * as caller should have assumed conversion does not overflow
 | 
				
			||||||
 | 
							 * in destination len is length in wchar_t units (16bits)
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							i  = utf8s_to_utf16s(from, len, UTF16_LITTLE_ENDIAN,
 | 
				
			||||||
 | 
									       (wchar_t *) to, len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* if success terminate and exit */
 | 
				
			||||||
 | 
							if (i >= 0)
 | 
				
			||||||
 | 
								goto success;
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * if fails fall back to UCS encoding as this
 | 
				
			||||||
 | 
							 * function should not return negative values
 | 
				
			||||||
 | 
							 * currently can fail only if source contains
 | 
				
			||||||
 | 
							 * invalid encoded characters
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; len > 0 && *from; i++, from += charlen, len -= charlen) {
 | 
				
			||||||
 | 
							charlen = codepage->char2uni(from, len, &wchar_to);
 | 
				
			||||||
 | 
							if (charlen < 1) {
 | 
				
			||||||
 | 
								/* A question mark */
 | 
				
			||||||
 | 
								wchar_to = 0x003f;
 | 
				
			||||||
 | 
								charlen = 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							put_unaligned_le16(wchar_to, &to[i]);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					success:
 | 
				
			||||||
 | 
						put_unaligned_le16(0, &to[i]);
 | 
				
			||||||
 | 
						return i;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * smb_strndup_from_utf16() - copy a string from wire format to the local
 | 
				
			||||||
 | 
					 *		codepage
 | 
				
			||||||
 | 
					 * @src:	source string
 | 
				
			||||||
 | 
					 * @maxlen:	don't walk past this many bytes in the source string
 | 
				
			||||||
 | 
					 * @is_unicode:	is this a unicode string?
 | 
				
			||||||
 | 
					 * @codepage:	destination codepage
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Take a string given by the server, convert it to the local codepage and
 | 
				
			||||||
 | 
					 * put it in a new buffer. Returns a pointer to the new string or NULL on
 | 
				
			||||||
 | 
					 * error.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return:	destination string buffer or error ptr
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					char *
 | 
				
			||||||
 | 
					smb_strndup_from_utf16(const char *src, const int maxlen,
 | 
				
			||||||
 | 
								const bool is_unicode, const struct nls_table *codepage)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int len, ret;
 | 
				
			||||||
 | 
						char *dst;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (is_unicode) {
 | 
				
			||||||
 | 
							len = smb_utf16_bytes((__le16 *) src, maxlen, codepage);
 | 
				
			||||||
 | 
							len += nls_nullsize(codepage);
 | 
				
			||||||
 | 
							dst = kmalloc(len, GFP_KERNEL);
 | 
				
			||||||
 | 
							if (!dst)
 | 
				
			||||||
 | 
								return ERR_PTR(-ENOMEM);
 | 
				
			||||||
 | 
							ret = smb_from_utf16(dst, (__le16 *) src, len, maxlen, codepage,
 | 
				
			||||||
 | 
								       false);
 | 
				
			||||||
 | 
							if (ret < 0) {
 | 
				
			||||||
 | 
								kfree(dst);
 | 
				
			||||||
 | 
								return ERR_PTR(-EINVAL);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							len = strnlen(src, maxlen);
 | 
				
			||||||
 | 
							len++;
 | 
				
			||||||
 | 
							dst = kmalloc(len, GFP_KERNEL);
 | 
				
			||||||
 | 
							if (!dst)
 | 
				
			||||||
 | 
								return ERR_PTR(-ENOMEM);
 | 
				
			||||||
 | 
							strscpy(dst, src, len);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return dst;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Convert 16 bit Unicode pathname to wire format from string in current code
 | 
				
			||||||
 | 
					 * page. Conversion may involve remapping up the six characters that are
 | 
				
			||||||
 | 
					 * only legal in POSIX-like OS (if they are present in the string). Path
 | 
				
			||||||
 | 
					 * names are little endian 16 bit Unicode on the wire
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * smbConvertToUTF16() - convert string from local charset to utf16
 | 
				
			||||||
 | 
					 * @target:	destination buffer
 | 
				
			||||||
 | 
					 * @source:	source buffer
 | 
				
			||||||
 | 
					 * @srclen:	source buffer size (in bytes)
 | 
				
			||||||
 | 
					 * @cp:		codepage to which characters should be converted
 | 
				
			||||||
 | 
					 * @mapchar:	should characters be remapped according to the mapchars option?
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Convert 16 bit Unicode pathname to wire format from string in current code
 | 
				
			||||||
 | 
					 * page. Conversion may involve remapping up the six characters that are
 | 
				
			||||||
 | 
					 * only legal in POSIX-like OS (if they are present in the string). Path
 | 
				
			||||||
 | 
					 * names are little endian 16 bit Unicode on the wire
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return:	char length after conversion
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					smbConvertToUTF16(__le16 *target, const char *source, int srclen,
 | 
				
			||||||
 | 
							 const struct nls_table *cp, int mapchars)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i, j, charlen;
 | 
				
			||||||
 | 
						char src_char;
 | 
				
			||||||
 | 
						__le16 dst_char;
 | 
				
			||||||
 | 
						wchar_t tmp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!mapchars)
 | 
				
			||||||
 | 
							return smb_strtoUTF16(target, source, srclen, cp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0, j = 0; i < srclen; j++) {
 | 
				
			||||||
 | 
							src_char = source[i];
 | 
				
			||||||
 | 
							charlen = 1;
 | 
				
			||||||
 | 
							switch (src_char) {
 | 
				
			||||||
 | 
							case 0:
 | 
				
			||||||
 | 
								put_unaligned(0, &target[j]);
 | 
				
			||||||
 | 
								return j;
 | 
				
			||||||
 | 
							case ':':
 | 
				
			||||||
 | 
								dst_char = cpu_to_le16(UNI_COLON);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case '*':
 | 
				
			||||||
 | 
								dst_char = cpu_to_le16(UNI_ASTERISK);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case '?':
 | 
				
			||||||
 | 
								dst_char = cpu_to_le16(UNI_QUESTION);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case '<':
 | 
				
			||||||
 | 
								dst_char = cpu_to_le16(UNI_LESSTHAN);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case '>':
 | 
				
			||||||
 | 
								dst_char = cpu_to_le16(UNI_GRTRTHAN);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case '|':
 | 
				
			||||||
 | 
								dst_char = cpu_to_le16(UNI_PIPE);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * FIXME: We can not handle remapping backslash (UNI_SLASH)
 | 
				
			||||||
 | 
							 * until all the calls to build_path_from_dentry are modified,
 | 
				
			||||||
 | 
							 * as they use backslash as separator.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								charlen = cp->char2uni(source + i, srclen - i, &tmp);
 | 
				
			||||||
 | 
								dst_char = cpu_to_le16(tmp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								/*
 | 
				
			||||||
 | 
								 * if no match, use question mark, which at least in
 | 
				
			||||||
 | 
								 * some cases serves as wild card
 | 
				
			||||||
 | 
								 */
 | 
				
			||||||
 | 
								if (charlen < 1) {
 | 
				
			||||||
 | 
									dst_char = cpu_to_le16(0x003f);
 | 
				
			||||||
 | 
									charlen = 1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * character may take more than one byte in the source string,
 | 
				
			||||||
 | 
							 * but will take exactly two bytes in the target string
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							i += charlen;
 | 
				
			||||||
 | 
							put_unaligned(dst_char, &target[j]);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return j;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										374
									
								
								fs/cifsd/unicode.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										374
									
								
								fs/cifsd/unicode.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,374 @@
 | 
				
			||||||
 | 
					/* SPDX-License-Identifier: GPL-2.0-or-later */
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Some of the source code in this file came from fs/cifs/cifs_unicode.c
 | 
				
			||||||
 | 
					 * cifs_unicode:  Unicode kernel case support
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Function:
 | 
				
			||||||
 | 
					 *     Convert a unicode character to upper or lower case using
 | 
				
			||||||
 | 
					 *     compressed tables.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   Copyright (c) International Business Machines  Corp., 2000,2009
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Notes:
 | 
				
			||||||
 | 
					 *     These APIs are based on the C library functions.  The semantics
 | 
				
			||||||
 | 
					 *     should match the C functions but with expanded size operands.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *     The upper/lower functions are based on a table created by mkupr.
 | 
				
			||||||
 | 
					 *     This is a compressed table of upper and lower case conversion.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#ifndef _CIFS_UNICODE_H
 | 
				
			||||||
 | 
					#define _CIFS_UNICODE_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <asm/byteorder.h>
 | 
				
			||||||
 | 
					#include <linux/types.h>
 | 
				
			||||||
 | 
					#include <linux/nls.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define  UNIUPR_NOLOWER		/* Example to not expand lower case tables */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Windows maps these to the user defined 16 bit Unicode range since they are
 | 
				
			||||||
 | 
					 * reserved symbols (along with \ and /), otherwise illegal to store
 | 
				
			||||||
 | 
					 * in filenames in NTFS
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define UNI_ASTERISK    ((__u16) ('*' + 0xF000))
 | 
				
			||||||
 | 
					#define UNI_QUESTION    ((__u16) ('?' + 0xF000))
 | 
				
			||||||
 | 
					#define UNI_COLON       ((__u16) (':' + 0xF000))
 | 
				
			||||||
 | 
					#define UNI_GRTRTHAN    ((__u16) ('>' + 0xF000))
 | 
				
			||||||
 | 
					#define UNI_LESSTHAN    ((__u16) ('<' + 0xF000))
 | 
				
			||||||
 | 
					#define UNI_PIPE        ((__u16) ('|' + 0xF000))
 | 
				
			||||||
 | 
					#define UNI_SLASH       ((__u16) ('\\' + 0xF000))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Just define what we want from uniupr.h.  We don't want to define the tables
 | 
				
			||||||
 | 
					 * in each source file.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#ifndef	UNICASERANGE_DEFINED
 | 
				
			||||||
 | 
					struct UniCaseRange {
 | 
				
			||||||
 | 
						wchar_t start;
 | 
				
			||||||
 | 
						wchar_t end;
 | 
				
			||||||
 | 
						signed char *table;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					#endif				/* UNICASERANGE_DEFINED */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef UNIUPR_NOUPPER
 | 
				
			||||||
 | 
					extern signed char SmbUniUpperTable[512];
 | 
				
			||||||
 | 
					extern const struct UniCaseRange SmbUniUpperRange[];
 | 
				
			||||||
 | 
					#endif				/* UNIUPR_NOUPPER */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef UNIUPR_NOLOWER
 | 
				
			||||||
 | 
					extern signed char CifsUniLowerTable[512];
 | 
				
			||||||
 | 
					extern const struct UniCaseRange CifsUniLowerRange[];
 | 
				
			||||||
 | 
					#endif				/* UNIUPR_NOLOWER */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __KERNEL__
 | 
				
			||||||
 | 
					int smb_strtoUTF16(__le16 *to, const char *from, int len,
 | 
				
			||||||
 | 
						const struct nls_table *codepage);
 | 
				
			||||||
 | 
					char *smb_strndup_from_utf16(const char *src, const int maxlen,
 | 
				
			||||||
 | 
							const bool is_unicode,
 | 
				
			||||||
 | 
							const struct nls_table *codepage);
 | 
				
			||||||
 | 
					extern int smbConvertToUTF16(__le16 *target, const char *source, int srclen,
 | 
				
			||||||
 | 
							const struct nls_table *cp, int mapchars);
 | 
				
			||||||
 | 
					extern char *extract_sharename(char *treename);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					wchar_t cifs_toupper(wchar_t in);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * UniStrcat:  Concatenate the second string to the first
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Returns:
 | 
				
			||||||
 | 
					 *     Address of the first string
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
						static inline wchar_t *
 | 
				
			||||||
 | 
					UniStrcat(wchar_t *ucs1, const wchar_t *ucs2)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						wchar_t *anchor = ucs1;	/* save a pointer to start of ucs1 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (*ucs1++)
 | 
				
			||||||
 | 
						/*NULL*/;	/* To end of first string */
 | 
				
			||||||
 | 
						ucs1--;			/* Return to the null */
 | 
				
			||||||
 | 
						while ((*ucs1++ = *ucs2++))
 | 
				
			||||||
 | 
						/*NULL*/;	/* copy string 2 over */
 | 
				
			||||||
 | 
						return anchor;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * UniStrchr:  Find a character in a string
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Returns:
 | 
				
			||||||
 | 
					 *     Address of first occurrence of character in string
 | 
				
			||||||
 | 
					 *     or NULL if the character is not in the string
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
						static inline wchar_t *
 | 
				
			||||||
 | 
					UniStrchr(const wchar_t *ucs, wchar_t uc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						while ((*ucs != uc) && *ucs)
 | 
				
			||||||
 | 
							ucs++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (*ucs == uc)
 | 
				
			||||||
 | 
							return (wchar_t *) ucs;
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * UniStrcmp:  Compare two strings
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Returns:
 | 
				
			||||||
 | 
					 *     < 0:  First string is less than second
 | 
				
			||||||
 | 
					 *     = 0:  Strings are equal
 | 
				
			||||||
 | 
					 *     > 0:  First string is greater than second
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
						static inline int
 | 
				
			||||||
 | 
					UniStrcmp(const wchar_t *ucs1, const wchar_t *ucs2)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						while ((*ucs1 == *ucs2) && *ucs1) {
 | 
				
			||||||
 | 
							ucs1++;
 | 
				
			||||||
 | 
							ucs2++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return (int) *ucs1 - (int) *ucs2;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * UniStrcpy:  Copy a string
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
						static inline wchar_t *
 | 
				
			||||||
 | 
					UniStrcpy(wchar_t *ucs1, const wchar_t *ucs2)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						wchar_t *anchor = ucs1;	/* save the start of result string */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while ((*ucs1++ = *ucs2++))
 | 
				
			||||||
 | 
						/*NULL*/;
 | 
				
			||||||
 | 
						return anchor;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * UniStrlen:  Return the length of a string (in 16 bit Unicode chars not bytes)
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
						static inline size_t
 | 
				
			||||||
 | 
					UniStrlen(const wchar_t *ucs1)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (*ucs1++)
 | 
				
			||||||
 | 
							i++;
 | 
				
			||||||
 | 
						return i;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * UniStrnlen:  Return the length (in 16 bit Unicode chars not bytes) of a
 | 
				
			||||||
 | 
					 *		string (length limited)
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
						static inline size_t
 | 
				
			||||||
 | 
					UniStrnlen(const wchar_t *ucs1, int maxlen)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (*ucs1++) {
 | 
				
			||||||
 | 
							i++;
 | 
				
			||||||
 | 
							if (i >= maxlen)
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return i;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * UniStrncat:  Concatenate length limited string
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
						static inline wchar_t *
 | 
				
			||||||
 | 
					UniStrncat(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						wchar_t *anchor = ucs1;	/* save pointer to string 1 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (*ucs1++)
 | 
				
			||||||
 | 
						/*NULL*/;
 | 
				
			||||||
 | 
						ucs1--;			/* point to null terminator of s1 */
 | 
				
			||||||
 | 
						while (n-- && (*ucs1 = *ucs2)) {	/* copy s2 after s1 */
 | 
				
			||||||
 | 
							ucs1++;
 | 
				
			||||||
 | 
							ucs2++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						*ucs1 = 0;		/* Null terminate the result */
 | 
				
			||||||
 | 
						return anchor;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * UniStrncmp:  Compare length limited string
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
						static inline int
 | 
				
			||||||
 | 
					UniStrncmp(const wchar_t *ucs1, const wchar_t *ucs2, size_t n)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!n)
 | 
				
			||||||
 | 
							return 0;	/* Null strings are equal */
 | 
				
			||||||
 | 
						while ((*ucs1 == *ucs2) && *ucs1 && --n) {
 | 
				
			||||||
 | 
							ucs1++;
 | 
				
			||||||
 | 
							ucs2++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return (int) *ucs1 - (int) *ucs2;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * UniStrncmp_le:  Compare length limited string - native to little-endian
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
						static inline int
 | 
				
			||||||
 | 
					UniStrncmp_le(const wchar_t *ucs1, const wchar_t *ucs2, size_t n)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!n)
 | 
				
			||||||
 | 
							return 0;	/* Null strings are equal */
 | 
				
			||||||
 | 
						while ((*ucs1 == __le16_to_cpu(*ucs2)) && *ucs1 && --n) {
 | 
				
			||||||
 | 
							ucs1++;
 | 
				
			||||||
 | 
							ucs2++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return (int) *ucs1 - (int) __le16_to_cpu(*ucs2);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * UniStrncpy:  Copy length limited string with pad
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
						static inline wchar_t *
 | 
				
			||||||
 | 
					UniStrncpy(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						wchar_t *anchor = ucs1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (n-- && *ucs2)	/* Copy the strings */
 | 
				
			||||||
 | 
							*ucs1++ = *ucs2++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						n++;
 | 
				
			||||||
 | 
						while (n--)		/* Pad with nulls */
 | 
				
			||||||
 | 
							*ucs1++ = 0;
 | 
				
			||||||
 | 
						return anchor;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * UniStrncpy_le:  Copy length limited string with pad to little-endian
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
						static inline wchar_t *
 | 
				
			||||||
 | 
					UniStrncpy_le(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						wchar_t *anchor = ucs1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (n-- && *ucs2)	/* Copy the strings */
 | 
				
			||||||
 | 
							*ucs1++ = __le16_to_cpu(*ucs2++);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						n++;
 | 
				
			||||||
 | 
						while (n--)		/* Pad with nulls */
 | 
				
			||||||
 | 
							*ucs1++ = 0;
 | 
				
			||||||
 | 
						return anchor;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * UniStrstr:  Find a string in a string
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Returns:
 | 
				
			||||||
 | 
					 *     Address of first match found
 | 
				
			||||||
 | 
					 *     NULL if no matching string is found
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
						static inline wchar_t *
 | 
				
			||||||
 | 
					UniStrstr(const wchar_t *ucs1, const wchar_t *ucs2)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const wchar_t *anchor1 = ucs1;
 | 
				
			||||||
 | 
						const wchar_t *anchor2 = ucs2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (*ucs1) {
 | 
				
			||||||
 | 
							if (*ucs1 == *ucs2) {
 | 
				
			||||||
 | 
								/* Partial match found */
 | 
				
			||||||
 | 
								ucs1++;
 | 
				
			||||||
 | 
								ucs2++;
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								if (!*ucs2)	/* Match found */
 | 
				
			||||||
 | 
									return (wchar_t *) anchor1;
 | 
				
			||||||
 | 
								ucs1 = ++anchor1;	/* No match */
 | 
				
			||||||
 | 
								ucs2 = anchor2;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!*ucs2)		/* Both end together */
 | 
				
			||||||
 | 
							return (wchar_t *) anchor1;	/* Match found */
 | 
				
			||||||
 | 
						return NULL;		/* No match */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef UNIUPR_NOUPPER
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * UniToupper:  Convert a unicode character to upper case
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
						static inline wchar_t
 | 
				
			||||||
 | 
					UniToupper(register wchar_t uc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						register const struct UniCaseRange *rp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (uc < sizeof(SmbUniUpperTable)) {
 | 
				
			||||||
 | 
							/* Latin characters */
 | 
				
			||||||
 | 
							return uc + SmbUniUpperTable[uc];	/* Use base tables */
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rp = SmbUniUpperRange;	/* Use range tables */
 | 
				
			||||||
 | 
						while (rp->start) {
 | 
				
			||||||
 | 
							if (uc < rp->start)	/* Before start of range */
 | 
				
			||||||
 | 
								return uc;	/* Uppercase = input */
 | 
				
			||||||
 | 
							if (uc <= rp->end)	/* In range */
 | 
				
			||||||
 | 
								return uc + rp->table[uc - rp->start];
 | 
				
			||||||
 | 
							rp++;	/* Try next range */
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return uc;		/* Past last range */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * UniStrupr:  Upper case a unicode string
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
						static inline __le16 *
 | 
				
			||||||
 | 
					UniStrupr(register __le16 *upin)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						register __le16 *up;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						up = upin;
 | 
				
			||||||
 | 
						while (*up) {		/* For all characters */
 | 
				
			||||||
 | 
							*up = cpu_to_le16(UniToupper(le16_to_cpu(*up)));
 | 
				
			||||||
 | 
							up++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return upin;		/* Return input pointer */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif				/* UNIUPR_NOUPPER */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef UNIUPR_NOLOWER
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * UniTolower:  Convert a unicode character to lower case
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
						static inline wchar_t
 | 
				
			||||||
 | 
					UniTolower(register wchar_t uc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						register const struct UniCaseRange *rp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (uc < sizeof(CifsUniLowerTable)) {
 | 
				
			||||||
 | 
							/* Latin characters */
 | 
				
			||||||
 | 
							return uc + CifsUniLowerTable[uc];	/* Use base tables */
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rp = CifsUniLowerRange;	/* Use range tables */
 | 
				
			||||||
 | 
						while (rp->start) {
 | 
				
			||||||
 | 
							if (uc < rp->start)	/* Before start of range */
 | 
				
			||||||
 | 
								return uc;	/* Uppercase = input */
 | 
				
			||||||
 | 
							if (uc <= rp->end)	/* In range */
 | 
				
			||||||
 | 
								return uc + rp->table[uc - rp->start];
 | 
				
			||||||
 | 
							rp++;	/* Try next range */
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return uc;		/* Past last range */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * UniStrlwr:  Lower case a unicode string
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
						static inline wchar_t *
 | 
				
			||||||
 | 
					UniStrlwr(register wchar_t *upin)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						register wchar_t *up;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						up = upin;
 | 
				
			||||||
 | 
						while (*up) {		/* For all characters */
 | 
				
			||||||
 | 
							*up = UniTolower(*up);
 | 
				
			||||||
 | 
							up++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return upin;		/* Return input pointer */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* _CIFS_UNICODE_H */
 | 
				
			||||||
							
								
								
									
										268
									
								
								fs/cifsd/uniupr.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										268
									
								
								fs/cifsd/uniupr.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,268 @@
 | 
				
			||||||
 | 
					/* SPDX-License-Identifier: GPL-2.0-or-later */
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *   Some of the source code in this file came from fs/cifs/uniupr.h
 | 
				
			||||||
 | 
					 *   Copyright (c) International Business Machines  Corp., 2000,2002
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * uniupr.h - Unicode compressed case ranges
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#ifndef __KSMBD_UNIUPR_H
 | 
				
			||||||
 | 
					#define __KSMBD_UNIUPR_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef UNIUPR_NOUPPER
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Latin upper case
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					signed char SmbUniUpperTable[512] = {
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 000-00f */
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 010-01f */
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 020-02f */
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 030-03f */
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 040-04f */
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 050-05f */
 | 
				
			||||||
 | 
						0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
 | 
				
			||||||
 | 
									-32, -32, -32, -32, -32,	/* 060-06f */
 | 
				
			||||||
 | 
						-32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
 | 
				
			||||||
 | 
									-32, 0, 0, 0, 0, 0,	/* 070-07f */
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 080-08f */
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 090-09f */
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 0a0-0af */
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 0b0-0bf */
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 0c0-0cf */
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 0d0-0df */
 | 
				
			||||||
 | 
						-32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
 | 
				
			||||||
 | 
								 -32, -32, -32, -32, -32, -32,	/* 0e0-0ef */
 | 
				
			||||||
 | 
						-32, -32, -32, -32, -32, -32, -32, 0, -32, -32,
 | 
				
			||||||
 | 
								 -32, -32, -32, -32, -32, 121,	/* 0f0-0ff */
 | 
				
			||||||
 | 
						0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 100-10f */
 | 
				
			||||||
 | 
						0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 110-11f */
 | 
				
			||||||
 | 
						0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 120-12f */
 | 
				
			||||||
 | 
						0, 0, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, 0,	/* 130-13f */
 | 
				
			||||||
 | 
						-1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1,	/* 140-14f */
 | 
				
			||||||
 | 
						0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 150-15f */
 | 
				
			||||||
 | 
						0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 160-16f */
 | 
				
			||||||
 | 
						0, -1, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, 0,	/* 170-17f */
 | 
				
			||||||
 | 
						0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0,	/* 180-18f */
 | 
				
			||||||
 | 
						0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0,	/* 190-19f */
 | 
				
			||||||
 | 
						0, -1, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0,	/* 1a0-1af */
 | 
				
			||||||
 | 
						-1, 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0,	/* 1b0-1bf */
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, -1, -2, 0, -1, -2, 0, -1, -2, 0, -1, 0,	/* 1c0-1cf */
 | 
				
			||||||
 | 
						-1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, -79, 0, -1, /* 1d0-1df */
 | 
				
			||||||
 | 
						0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 1e0-1ef */
 | 
				
			||||||
 | 
						0, 0, -1, -2, 0, -1, 0, 0, 0, -1, 0, -1, 0, -1, 0, -1,	/* 1f0-1ff */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Upper case range - Greek */
 | 
				
			||||||
 | 
					static signed char UniCaseRangeU03a0[47] = {
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -38, -37, -37, -37,	/* 3a0-3af */
 | 
				
			||||||
 | 
						0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
 | 
				
			||||||
 | 
										 -32, -32, -32, -32,	/* 3b0-3bf */
 | 
				
			||||||
 | 
						-32, -32, -31, -32, -32, -32, -32, -32, -32, -32, -32, -32, -64,
 | 
				
			||||||
 | 
						-63, -63,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Upper case range - Cyrillic */
 | 
				
			||||||
 | 
					static signed char UniCaseRangeU0430[48] = {
 | 
				
			||||||
 | 
						-32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
 | 
				
			||||||
 | 
										 -32, -32, -32, -32,	/* 430-43f */
 | 
				
			||||||
 | 
						-32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
 | 
				
			||||||
 | 
										 -32, -32, -32, -32,	/* 440-44f */
 | 
				
			||||||
 | 
						0, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80,
 | 
				
			||||||
 | 
										 -80, -80, 0, -80, -80,	/* 450-45f */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Upper case range - Extended cyrillic */
 | 
				
			||||||
 | 
					static signed char UniCaseRangeU0490[61] = {
 | 
				
			||||||
 | 
						0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 490-49f */
 | 
				
			||||||
 | 
						0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 4a0-4af */
 | 
				
			||||||
 | 
						0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 4b0-4bf */
 | 
				
			||||||
 | 
						0, 0, -1, 0, -1, 0, 0, 0, -1, 0, 0, 0, -1,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Upper case range - Extended latin and greek */
 | 
				
			||||||
 | 
					static signed char UniCaseRangeU1e00[509] = {
 | 
				
			||||||
 | 
						0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 1e00-1e0f */
 | 
				
			||||||
 | 
						0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 1e10-1e1f */
 | 
				
			||||||
 | 
						0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 1e20-1e2f */
 | 
				
			||||||
 | 
						0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 1e30-1e3f */
 | 
				
			||||||
 | 
						0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 1e40-1e4f */
 | 
				
			||||||
 | 
						0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 1e50-1e5f */
 | 
				
			||||||
 | 
						0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 1e60-1e6f */
 | 
				
			||||||
 | 
						0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 1e70-1e7f */
 | 
				
			||||||
 | 
						0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 1e80-1e8f */
 | 
				
			||||||
 | 
						0, -1, 0, -1, 0, -1, 0, 0, 0, 0, 0, -59, 0, -1, 0, -1,	/* 1e90-1e9f */
 | 
				
			||||||
 | 
						0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 1ea0-1eaf */
 | 
				
			||||||
 | 
						0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 1eb0-1ebf */
 | 
				
			||||||
 | 
						0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 1ec0-1ecf */
 | 
				
			||||||
 | 
						0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 1ed0-1edf */
 | 
				
			||||||
 | 
						0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 1ee0-1eef */
 | 
				
			||||||
 | 
						0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0,	/* 1ef0-1eff */
 | 
				
			||||||
 | 
						8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0,	/* 1f00-1f0f */
 | 
				
			||||||
 | 
						8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 1f10-1f1f */
 | 
				
			||||||
 | 
						8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0,	/* 1f20-1f2f */
 | 
				
			||||||
 | 
						8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0,	/* 1f30-1f3f */
 | 
				
			||||||
 | 
						8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 1f40-1f4f */
 | 
				
			||||||
 | 
						0, 8, 0, 8, 0, 8, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0,	/* 1f50-1f5f */
 | 
				
			||||||
 | 
						8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0,	/* 1f60-1f6f */
 | 
				
			||||||
 | 
						74, 74, 86, 86, 86, 86, 100, 100, 0, 0, 112, 112,
 | 
				
			||||||
 | 
									 126, 126, 0, 0,	/* 1f70-1f7f */
 | 
				
			||||||
 | 
						8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0,	/* 1f80-1f8f */
 | 
				
			||||||
 | 
						8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0,	/* 1f90-1f9f */
 | 
				
			||||||
 | 
						8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0,	/* 1fa0-1faf */
 | 
				
			||||||
 | 
						8, 8, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 1fb0-1fbf */
 | 
				
			||||||
 | 
						0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 1fc0-1fcf */
 | 
				
			||||||
 | 
						8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 1fd0-1fdf */
 | 
				
			||||||
 | 
						8, 8, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 1fe0-1fef */
 | 
				
			||||||
 | 
						0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Upper case range - Wide latin */
 | 
				
			||||||
 | 
					static signed char UniCaseRangeUff40[27] = {
 | 
				
			||||||
 | 
						0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
 | 
				
			||||||
 | 
								 -32, -32, -32, -32, -32,	/* ff40-ff4f */
 | 
				
			||||||
 | 
						-32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Upper Case Range
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					const struct UniCaseRange SmbUniUpperRange[] = {
 | 
				
			||||||
 | 
						{0x03a0, 0x03ce, UniCaseRangeU03a0},
 | 
				
			||||||
 | 
						{0x0430, 0x045f, UniCaseRangeU0430},
 | 
				
			||||||
 | 
						{0x0490, 0x04cc, UniCaseRangeU0490},
 | 
				
			||||||
 | 
						{0x1e00, 0x1ffc, UniCaseRangeU1e00},
 | 
				
			||||||
 | 
						{0xff40, 0xff5a, UniCaseRangeUff40},
 | 
				
			||||||
 | 
						{0}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef UNIUPR_NOLOWER
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Latin lower case
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					signed char CifsUniLowerTable[512] = {
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 000-00f */
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 010-01f */
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 020-02f */
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 030-03f */
 | 
				
			||||||
 | 
						0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
 | 
				
			||||||
 | 
										 32, 32, 32,	/* 040-04f */
 | 
				
			||||||
 | 
						32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, 0,
 | 
				
			||||||
 | 
										 0, 0, 0,	/* 050-05f */
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 060-06f */
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 070-07f */
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 080-08f */
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 090-09f */
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 0a0-0af */
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 0b0-0bf */
 | 
				
			||||||
 | 
						32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
 | 
				
			||||||
 | 
									 32, 32, 32, 32,	/* 0c0-0cf */
 | 
				
			||||||
 | 
						32, 32, 32, 32, 32, 32, 32, 0, 32, 32, 32, 32,
 | 
				
			||||||
 | 
										 32, 32, 32, 0,	/* 0d0-0df */
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 0e0-0ef */
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 0f0-0ff */
 | 
				
			||||||
 | 
						1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 100-10f */
 | 
				
			||||||
 | 
						1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 110-11f */
 | 
				
			||||||
 | 
						1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 120-12f */
 | 
				
			||||||
 | 
						0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1,	/* 130-13f */
 | 
				
			||||||
 | 
						0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0,	/* 140-14f */
 | 
				
			||||||
 | 
						1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 150-15f */
 | 
				
			||||||
 | 
						1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 160-16f */
 | 
				
			||||||
 | 
						1, 0, 1, 0, 1, 0, 1, 0, -121, 1, 0, 1, 0, 1, 0,
 | 
				
			||||||
 | 
											 0,	/* 170-17f */
 | 
				
			||||||
 | 
						0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 79,
 | 
				
			||||||
 | 
											 0,	/* 180-18f */
 | 
				
			||||||
 | 
						0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,	/* 190-19f */
 | 
				
			||||||
 | 
						1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1,	/* 1a0-1af */
 | 
				
			||||||
 | 
						0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,	/* 1b0-1bf */
 | 
				
			||||||
 | 
						0, 0, 0, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 1, 0, 1,	/* 1c0-1cf */
 | 
				
			||||||
 | 
						0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0,	/* 1d0-1df */
 | 
				
			||||||
 | 
						1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 1e0-1ef */
 | 
				
			||||||
 | 
						0, 2, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 1f0-1ff */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Lower case range - Greek */
 | 
				
			||||||
 | 
					static signed char UniCaseRangeL0380[44] = {
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 38, 0, 37, 37, 37, 0, 64, 0, 63, 63,	/* 380-38f */
 | 
				
			||||||
 | 
						0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
 | 
				
			||||||
 | 
											 32, 32, 32,	/* 390-39f */
 | 
				
			||||||
 | 
						32, 32, 0, 32, 32, 32, 32, 32, 32, 32, 32, 32,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Lower case range - Cyrillic */
 | 
				
			||||||
 | 
					static signed char UniCaseRangeL0400[48] = {
 | 
				
			||||||
 | 
						0, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
 | 
				
			||||||
 | 
										 0, 80, 80,	/* 400-40f */
 | 
				
			||||||
 | 
						32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
 | 
				
			||||||
 | 
										 32, 32, 32,	/* 410-41f */
 | 
				
			||||||
 | 
						32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
 | 
				
			||||||
 | 
										 32, 32, 32,	/* 420-42f */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Lower case range - Extended cyrillic */
 | 
				
			||||||
 | 
					static signed char UniCaseRangeL0490[60] = {
 | 
				
			||||||
 | 
						1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 490-49f */
 | 
				
			||||||
 | 
						1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 4a0-4af */
 | 
				
			||||||
 | 
						1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 4b0-4bf */
 | 
				
			||||||
 | 
						0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Lower case range - Extended latin and greek */
 | 
				
			||||||
 | 
					static signed char UniCaseRangeL1e00[504] = {
 | 
				
			||||||
 | 
						1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 1e00-1e0f */
 | 
				
			||||||
 | 
						1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 1e10-1e1f */
 | 
				
			||||||
 | 
						1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 1e20-1e2f */
 | 
				
			||||||
 | 
						1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 1e30-1e3f */
 | 
				
			||||||
 | 
						1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 1e40-1e4f */
 | 
				
			||||||
 | 
						1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 1e50-1e5f */
 | 
				
			||||||
 | 
						1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 1e60-1e6f */
 | 
				
			||||||
 | 
						1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 1e70-1e7f */
 | 
				
			||||||
 | 
						1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 1e80-1e8f */
 | 
				
			||||||
 | 
						1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,	/* 1e90-1e9f */
 | 
				
			||||||
 | 
						1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 1ea0-1eaf */
 | 
				
			||||||
 | 
						1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 1eb0-1ebf */
 | 
				
			||||||
 | 
						1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 1ec0-1ecf */
 | 
				
			||||||
 | 
						1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 1ed0-1edf */
 | 
				
			||||||
 | 
						1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 1ee0-1eef */
 | 
				
			||||||
 | 
						1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0,	/* 1ef0-1eff */
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8,	/* 1f00-1f0f */
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, 0, 0,	/* 1f10-1f1f */
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8,	/* 1f20-1f2f */
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8,	/* 1f30-1f3f */
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, 0, 0,	/* 1f40-1f4f */
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0, 0, -8, 0, -8, 0, -8, 0, -8,	/* 1f50-1f5f */
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8,	/* 1f60-1f6f */
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 1f70-1f7f */
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8,	/* 1f80-1f8f */
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8,	/* 1f90-1f9f */
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8,	/* 1fa0-1faf */
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -74, -74, -9, 0, 0, 0,	/* 1fb0-1fbf */
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0, -86, -86, -86, -86, -9, 0,
 | 
				
			||||||
 | 
												 0, 0,	/* 1fc0-1fcf */
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -100, -100, 0, 0, 0, 0,	/* 1fd0-1fdf */
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -112, -112, -7, 0,
 | 
				
			||||||
 | 
												 0, 0,	/* 1fe0-1fef */
 | 
				
			||||||
 | 
						0, 0, 0, 0, 0, 0, 0, 0,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Lower case range - Wide latin */
 | 
				
			||||||
 | 
					static signed char UniCaseRangeLff20[27] = {
 | 
				
			||||||
 | 
						0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
 | 
				
			||||||
 | 
												 32,	/* ff20-ff2f */
 | 
				
			||||||
 | 
						32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Lower Case Range
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					const struct UniCaseRange CifsUniLowerRange[] = {
 | 
				
			||||||
 | 
						{0x0380, 0x03ab, UniCaseRangeL0380},
 | 
				
			||||||
 | 
						{0x0400, 0x042f, UniCaseRangeL0400},
 | 
				
			||||||
 | 
						{0x0490, 0x04cb, UniCaseRangeL0490},
 | 
				
			||||||
 | 
						{0x1e00, 0x1ff7, UniCaseRangeL1e00},
 | 
				
			||||||
 | 
						{0xff20, 0xff3a, UniCaseRangeLff20},
 | 
				
			||||||
 | 
						{0}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* __KSMBD_UNIUPR_H */
 | 
				
			||||||
		Loading…
	
		Reference in a new issue