0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/module.h>
0010 #include <linux/types.h>
0011 #include <linux/kernel.h>
0012 #include <linux/mm.h>
0013 #include <linux/slab.h>
0014 #include <linux/oid_registry.h>
0015
0016 #include "glob.h"
0017
0018 #include "asn1.h"
0019 #include "connection.h"
0020 #include "auth.h"
0021 #include "ksmbd_spnego_negtokeninit.asn1.h"
0022 #include "ksmbd_spnego_negtokentarg.asn1.h"
0023
0024 #define NTLMSSP_OID_LEN 10
0025
0026 static char NTLMSSP_OID_STR[NTLMSSP_OID_LEN] = { 0x2b, 0x06, 0x01, 0x04, 0x01,
0027 0x82, 0x37, 0x02, 0x02, 0x0a };
0028
0029 int
0030 ksmbd_decode_negTokenInit(unsigned char *security_blob, int length,
0031 struct ksmbd_conn *conn)
0032 {
0033 return asn1_ber_decoder(&ksmbd_spnego_negtokeninit_decoder, conn,
0034 security_blob, length);
0035 }
0036
0037 int
0038 ksmbd_decode_negTokenTarg(unsigned char *security_blob, int length,
0039 struct ksmbd_conn *conn)
0040 {
0041 return asn1_ber_decoder(&ksmbd_spnego_negtokentarg_decoder, conn,
0042 security_blob, length);
0043 }
0044
0045 static int compute_asn_hdr_len_bytes(int len)
0046 {
0047 if (len > 0xFFFFFF)
0048 return 4;
0049 else if (len > 0xFFFF)
0050 return 3;
0051 else if (len > 0xFF)
0052 return 2;
0053 else if (len > 0x7F)
0054 return 1;
0055 else
0056 return 0;
0057 }
0058
0059 static void encode_asn_tag(char *buf, unsigned int *ofs, char tag, char seq,
0060 int length)
0061 {
0062 int i;
0063 int index = *ofs;
0064 char hdr_len = compute_asn_hdr_len_bytes(length);
0065 int len = length + 2 + hdr_len;
0066
0067
0068 buf[index++] = tag;
0069
0070 if (!hdr_len) {
0071 buf[index++] = len;
0072 } else {
0073 buf[index++] = 0x80 | hdr_len;
0074 for (i = hdr_len - 1; i >= 0; i--)
0075 buf[index++] = (len >> (i * 8)) & 0xFF;
0076 }
0077
0078
0079 len = len - (index - *ofs);
0080 buf[index++] = seq;
0081
0082 if (!hdr_len) {
0083 buf[index++] = len;
0084 } else {
0085 buf[index++] = 0x80 | hdr_len;
0086 for (i = hdr_len - 1; i >= 0; i--)
0087 buf[index++] = (len >> (i * 8)) & 0xFF;
0088 }
0089
0090 *ofs += (index - *ofs);
0091 }
0092
0093 int build_spnego_ntlmssp_neg_blob(unsigned char **pbuffer, u16 *buflen,
0094 char *ntlm_blob, int ntlm_blob_len)
0095 {
0096 char *buf;
0097 unsigned int ofs = 0;
0098 int neg_result_len = 4 + compute_asn_hdr_len_bytes(1) * 2 + 1;
0099 int oid_len = 4 + compute_asn_hdr_len_bytes(NTLMSSP_OID_LEN) * 2 +
0100 NTLMSSP_OID_LEN;
0101 int ntlmssp_len = 4 + compute_asn_hdr_len_bytes(ntlm_blob_len) * 2 +
0102 ntlm_blob_len;
0103 int total_len = 4 + compute_asn_hdr_len_bytes(neg_result_len +
0104 oid_len + ntlmssp_len) * 2 +
0105 neg_result_len + oid_len + ntlmssp_len;
0106
0107 buf = kmalloc(total_len, GFP_KERNEL);
0108 if (!buf)
0109 return -ENOMEM;
0110
0111
0112 encode_asn_tag(buf, &ofs, 0xa1, 0x30, neg_result_len + oid_len +
0113 ntlmssp_len);
0114
0115
0116 encode_asn_tag(buf, &ofs, 0xa0, 0x0a, 1);
0117 buf[ofs++] = 1;
0118
0119
0120 encode_asn_tag(buf, &ofs, 0xa1, 0x06, NTLMSSP_OID_LEN);
0121 memcpy(buf + ofs, NTLMSSP_OID_STR, NTLMSSP_OID_LEN);
0122 ofs += NTLMSSP_OID_LEN;
0123
0124
0125 encode_asn_tag(buf, &ofs, 0xa2, 0x04, ntlm_blob_len);
0126 memcpy(buf + ofs, ntlm_blob, ntlm_blob_len);
0127 ofs += ntlm_blob_len;
0128
0129 *pbuffer = buf;
0130 *buflen = total_len;
0131 return 0;
0132 }
0133
0134 int build_spnego_ntlmssp_auth_blob(unsigned char **pbuffer, u16 *buflen,
0135 int neg_result)
0136 {
0137 char *buf;
0138 unsigned int ofs = 0;
0139 int neg_result_len = 4 + compute_asn_hdr_len_bytes(1) * 2 + 1;
0140 int total_len = 4 + compute_asn_hdr_len_bytes(neg_result_len) * 2 +
0141 neg_result_len;
0142
0143 buf = kmalloc(total_len, GFP_KERNEL);
0144 if (!buf)
0145 return -ENOMEM;
0146
0147
0148 encode_asn_tag(buf, &ofs, 0xa1, 0x30, neg_result_len);
0149
0150
0151 encode_asn_tag(buf, &ofs, 0xa0, 0x0a, 1);
0152 if (neg_result)
0153 buf[ofs++] = 2;
0154 else
0155 buf[ofs++] = 0;
0156
0157 *pbuffer = buf;
0158 *buflen = total_len;
0159 return 0;
0160 }
0161
0162 int ksmbd_gssapi_this_mech(void *context, size_t hdrlen, unsigned char tag,
0163 const void *value, size_t vlen)
0164 {
0165 enum OID oid;
0166
0167 oid = look_up_OID(value, vlen);
0168 if (oid != OID_spnego) {
0169 char buf[50];
0170
0171 sprint_oid(value, vlen, buf, sizeof(buf));
0172 ksmbd_debug(AUTH, "Unexpected OID: %s\n", buf);
0173 return -EBADMSG;
0174 }
0175
0176 return 0;
0177 }
0178
0179 int ksmbd_neg_token_init_mech_type(void *context, size_t hdrlen,
0180 unsigned char tag, const void *value,
0181 size_t vlen)
0182 {
0183 struct ksmbd_conn *conn = context;
0184 enum OID oid;
0185 int mech_type;
0186
0187 oid = look_up_OID(value, vlen);
0188 if (oid == OID_ntlmssp) {
0189 mech_type = KSMBD_AUTH_NTLMSSP;
0190 } else if (oid == OID_mskrb5) {
0191 mech_type = KSMBD_AUTH_MSKRB5;
0192 } else if (oid == OID_krb5) {
0193 mech_type = KSMBD_AUTH_KRB5;
0194 } else if (oid == OID_krb5u2u) {
0195 mech_type = KSMBD_AUTH_KRB5U2U;
0196 } else {
0197 char buf[50];
0198
0199 sprint_oid(value, vlen, buf, sizeof(buf));
0200 ksmbd_debug(AUTH, "Unexpected OID: %s\n", buf);
0201 return -EBADMSG;
0202 }
0203
0204 conn->auth_mechs |= mech_type;
0205 if (conn->preferred_auth_mech == 0)
0206 conn->preferred_auth_mech = mech_type;
0207
0208 return 0;
0209 }
0210
0211 int ksmbd_neg_token_init_mech_token(void *context, size_t hdrlen,
0212 unsigned char tag, const void *value,
0213 size_t vlen)
0214 {
0215 struct ksmbd_conn *conn = context;
0216
0217 conn->mechToken = kmalloc(vlen + 1, GFP_KERNEL);
0218 if (!conn->mechToken)
0219 return -ENOMEM;
0220
0221 memcpy(conn->mechToken, value, vlen);
0222 conn->mechToken[vlen] = '\0';
0223 return 0;
0224 }
0225
0226 int ksmbd_neg_token_targ_resp_token(void *context, size_t hdrlen,
0227 unsigned char tag, const void *value,
0228 size_t vlen)
0229 {
0230 struct ksmbd_conn *conn = context;
0231
0232 conn->mechToken = kmalloc(vlen + 1, GFP_KERNEL);
0233 if (!conn->mechToken)
0234 return -ENOMEM;
0235
0236 memcpy(conn->mechToken, value, vlen);
0237 conn->mechToken[vlen] = '\0';
0238 return 0;
0239 }