smbfs - Fix mount_smbfs authentication error (but 'ls' still broken)
[dragonfly.git] / sys / netproto / smb / smb_crypt.c
1 /*
2  * Copyright (c) 2000-2001, Boris Popov
3  * All rights reserved.
4  *
5  * Copyright (c) 2003, 2004 Tim J. Robbins.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *    This product includes software developed by Boris Popov.
19  * 4. Neither the name of the author nor the names of any co-contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  *
35  * $FreeBSD: src/sys/netsmb/smb_crypt.c,v 1.1.2.3 2001/09/03 08:55:11 bp Exp $
36  * $DragonFly: src/sys/netproto/smb/smb_crypt.c,v 1.5 2008/01/05 14:02:40 swildner Exp $
37  */
38 #include <sys/param.h>
39 #include <sys/malloc.h>
40 #include <sys/kernel.h>
41 #include <sys/systm.h>
42 #include <sys/conf.h>
43 #include <sys/proc.h>
44 #include <sys/fcntl.h>
45 #include <sys/socket.h>
46 #include <sys/socketvar.h>
47 #include <sys/sysctl.h>
48
49 #include <sys/endian.h>
50 #include <sys/mbuf.h>
51 #include <sys/mchain.h>
52
53 #include <sys/md4.h>
54 #include <sys/md5.h>
55 #include <sys/iconv.h>
56
57 #include "smb.h"
58 #include "smb_conn.h"
59 #include "smb_subr.h"
60 #include "smb_rq.h"
61 #include "smb_dev.h"
62
63 #include "opt_netsmb.h"
64
65 #ifdef NETSMBCRYPTO
66
67 #include <crypto/des/des.h>
68
69 static u_char N8[] = {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25};
70
71
72 static void
73 smb_E(const u_char *key, u_char *data, u_char *dest)
74 {
75         des_key_schedule *ksp;
76         u_char kk[8];
77
78         kk[0] = key[0] & 0xfe;
79         kk[1] = key[0] << 7 | (key[1] >> 1 & 0xfe);
80         kk[2] = key[1] << 6 | (key[2] >> 2 & 0xfe);
81         kk[3] = key[2] << 5 | (key[3] >> 3 & 0xfe);
82         kk[4] = key[3] << 4 | (key[4] >> 4 & 0xfe);
83         kk[5] = key[4] << 3 | (key[5] >> 5 & 0xfe);
84         kk[6] = key[5] << 2 | (key[6] >> 6 & 0xfe);
85         kk[7] = key[6] << 1;
86         ksp = kmalloc(sizeof(des_key_schedule), M_SMBTEMP, M_WAITOK);
87         des_set_key((des_cblock *)kk, *ksp);
88         des_ecb_encrypt((des_cblock *)data, (des_cblock *)dest, *ksp, 1);
89         kfree(ksp, M_SMBTEMP);
90 }
91 #endif
92
93
94 int
95 smb_encrypt(const u_char *apwd, u_char *C8, u_char *RN)
96 {
97 #ifdef NETSMBCRYPTO
98         u_char *p, *P14, *S21;
99
100         p = kmalloc(14 + 21, M_SMBTEMP, M_WAITOK | M_ZERO);
101         P14 = p;
102         S21 = p + 14;
103         bcopy(apwd, P14, min(14, strlen(apwd)));
104         /*
105          * S21 = concat(Ex(P14, N8), zeros(5));
106          */
107         smb_E(P14, N8, S21);
108         smb_E(P14 + 7, N8, S21 + 8);
109
110         smb_E(S21, C8, RN);
111         smb_E(S21 + 7, C8, RN + 8);
112         smb_E(S21 + 14, C8, RN + 16);
113         kfree(p, M_SMBTEMP);
114         return 0;
115 #else
116         SMBERROR("password encryption is not available\n");
117         bzero(RN, 24);
118         return EAUTH;
119 #endif
120 }
121
122 int
123 smb_ntencrypt(const u_char *apwd, u_char *C8, u_char *RN)
124 {
125 #ifdef NETSMBCRYPTO
126         u_char S21[21];
127         u_int16_t *unipwd;
128         MD4_CTX *ctxp;
129         int len;
130
131         len = strlen(apwd);
132         unipwd = kmalloc((len + 1) * sizeof(u_int16_t), M_SMBTEMP, M_WAITOK);
133         /*
134          * S21 = concat(MD4(U(apwd)), zeros(5));
135          */
136         smb_strtouni(unipwd, apwd);
137         ctxp = kmalloc(sizeof(MD4_CTX), M_SMBTEMP, M_WAITOK);
138         MD4Init(ctxp);
139         MD4Update(ctxp, (u_char*)unipwd, len * sizeof(u_int16_t));
140         kfree(unipwd, M_SMBTEMP);
141         bzero(S21, 21);
142         MD4Final(S21, ctxp);
143         kfree(ctxp, M_SMBTEMP);
144
145         smb_E(S21, C8, RN);
146         smb_E(S21 + 7, C8, RN + 8);
147         smb_E(S21 + 14, C8, RN + 16);
148         return 0;
149 #else
150         SMBERROR("password encryption is not available\n");
151         bzero(RN, 24);
152         return EAUTH;
153 #endif
154 }
155
156 /*
157  * Calculate message authentication code (MAC) key for virtual circuit.
158  */
159 int
160 smb_calcmackey(struct smb_vc *vcp)
161 {
162 #ifdef NETSMBCRYPTO
163         const char *pwd;
164         u_int16_t *unipwd;
165         int len;
166         MD4_CTX md4;
167         u_char S16[16], S21[21];
168
169         KASSERT(vcp->vc_hflags2 & SMB_FLAGS2_SECURITY_SIGNATURE,
170             ("signatures not enabled"));
171
172         if (vcp->vc_mackey != NULL) {
173                 kfree(vcp->vc_mackey, M_SMBTEMP);
174                 vcp->vc_mackey = NULL;
175                 vcp->vc_mackeylen = 0;
176                 vcp->vc_seqno = 0;
177         }
178
179         /*
180          * The partial MAC key is the concatenation of the 16 byte session
181          * key and the 24 byte challenge response.
182          */
183         vcp->vc_mackeylen = 16 + 24;
184         vcp->vc_mackey = kmalloc(vcp->vc_mackeylen, M_SMBTEMP, M_WAITOK);
185
186         /*
187          * Calculate session key:
188          *      MD4(MD4(U(PN)))
189          */
190         pwd = smb_vc_getpass(vcp);
191         len = strlen(pwd);
192         unipwd = kmalloc((len + 1) * sizeof(u_int16_t), M_SMBTEMP, M_WAITOK);
193         smb_strtouni(unipwd, pwd);
194         MD4Init(&md4);
195         MD4Update(&md4, (u_char *)unipwd, len * sizeof(u_int16_t));
196         MD4Final(S16, &md4);
197         MD4Init(&md4);
198         MD4Update(&md4, S16, 16);
199         MD4Final(vcp->vc_mackey, &md4);
200         kfree(unipwd, M_SMBTEMP);
201
202         /*
203          * Calculate response to challenge:
204          *      Ex(concat(MD4(U(pass)), zeros(5)), C8)
205          */
206         bzero(S21, 21);
207         bcopy(S16, S21, 16);
208         smb_E(S21, vcp->vc_ch, vcp->vc_mackey + 16);
209         smb_E(S21 + 7, vcp->vc_ch, vcp->vc_mackey + 24);
210         smb_E(S21 + 14, vcp->vc_ch, vcp->vc_mackey + 32);
211
212         return (0);
213 #else
214         panic("smb_calcmackey: encryption not available");
215         return (0);
216 #endif  /* NETSMBCRYPTO */
217 }
218
219 /*
220  * Sign request with MAC.
221  */
222 int
223 smb_rq_sign(struct smb_rq *rqp)
224 {
225 #ifdef NETSMBCRYPTO
226         struct smb_vc *vcp = rqp->sr_vc;
227         struct mbchain *mbp;
228         struct mbuf *mb;
229         MD5_CTX md5;
230         u_char digest[16];
231
232         KASSERT(vcp->vc_hflags2 & SMB_FLAGS2_SECURITY_SIGNATURE,
233             ("signatures not enabled"));
234
235         if (vcp->vc_mackey == NULL)
236                 /* XXX Should assert that cmd == SMB_COM_NEGOTIATE. */
237                 return (0);
238
239         /*
240          * This is a bit of a kludge. If the request is non-TRANSACTION,
241          * or it is the first request of a transaction, give it the next
242          * sequence number, and expect the reply to have the sequence number
243          * following that one. Otherwise, it is a secondary request in
244          * a transaction, and it gets the same sequence numbers as the
245          * primary request.
246          */
247         if (rqp->sr_t2 == NULL ||
248             (rqp->sr_t2->t2_flags & SMBT2_SECONDARY) == 0) {
249                 rqp->sr_seqno = vcp->vc_seqno++;
250                 rqp->sr_rseqno = vcp->vc_seqno++;
251         } else {
252                 /*
253                  * Sequence numbers are already in the struct because
254                  * smb_t2_request_int() uses the same one for all the
255                  * requests in the transaction.
256                  * (At least we hope so.)
257                  */
258                 KASSERT(rqp->sr_t2 == NULL ||
259                     (rqp->sr_t2->t2_flags & SMBT2_SECONDARY) == 0 ||
260                     rqp->sr_t2->t2_rq == rqp,
261                     ("sec t2 rq not using same smb_rq"));
262         }
263
264         /* Initialize sec. signature field to sequence number + zeros. */
265         *(u_int32_t *)rqp->sr_rqsig = htole32(rqp->sr_seqno);
266         *(u_int32_t *)(rqp->sr_rqsig + 4) = 0;
267
268         /*
269          * Compute HMAC-MD5 of packet data, keyed by MAC key.
270          * Store the first 8 bytes in the sec. signature field.
271          */
272         smb_rq_getrequest(rqp, &mbp);
273         MD5Init(&md5);
274         MD5Update(&md5, vcp->vc_mackey, vcp->vc_mackeylen);
275         for (mb = mbp->mb_top; mb != NULL; mb = mb->m_next)
276                 MD5Update(&md5, mtod(mb, void *), mb->m_len);
277         MD5Final(digest, &md5);
278         bcopy(digest, rqp->sr_rqsig, 8);
279
280         return (0);
281 #else
282         panic("smb_rq_sign: encryption not available");
283         return (0);
284 #endif  /* NETSMBCRYPTO */
285 }
286
287 /*
288  * Verify reply signature.
289  */
290 int
291 smb_rq_verify(struct smb_rq *rqp)
292 {
293 #ifdef NETSMBCRYPTO
294         struct smb_vc *vcp = rqp->sr_vc;
295         struct mdchain *mdp;
296         u_char sigbuf[8];
297         MD5_CTX md5;
298         u_char digest[16];
299         struct mbuf *mb;
300
301         KASSERT(vcp->vc_hflags2 & SMB_FLAGS2_SECURITY_SIGNATURE,
302             ("signatures not enabled"));
303
304         if (vcp->vc_mackey == NULL)
305                 /* XXX Should check that this is a SMB_COM_NEGOTIATE reply. */
306                 return (0);
307
308         /*
309          * Compute HMAC-MD5 of packet data, keyed by MAC key.
310          * We play games to pretend the security signature field
311          * contains their sequence number, to avoid modifying
312          * the packet itself.
313          */
314         smb_rq_getreply(rqp, &mdp);
315         mb = mdp->md_top;
316         KASSERT(mb->m_len >= SMB_HDRLEN, ("forgot to m_pullup"));
317         MD5Init(&md5);
318         MD5Update(&md5, vcp->vc_mackey, vcp->vc_mackeylen);
319         MD5Update(&md5, mtod(mb, void *), 14);
320         *(u_int32_t *)sigbuf = htole32(rqp->sr_rseqno);
321         *(u_int32_t *)(sigbuf + 4) = 0;
322         MD5Update(&md5, sigbuf, 8);
323         MD5Update(&md5, mtod(mb, u_char *) + 22, mb->m_len - 22);
324         for (mb = mb->m_next; mb != NULL; mb = mb->m_next)
325                 MD5Update(&md5, mtod(mb, void *), mb->m_len);
326         MD5Final(digest, &md5);
327
328         /*
329          * Now verify the signature.
330          */
331         if (bcmp(mtod(mdp->md_top, u_char *) + 14, digest, 8) != 0)
332                 return (EAUTH);
333
334         return (0);
335 #else
336         panic("smb_rq_verify: encryption not available");
337         return (0);
338 #endif  /* NETSMBCRYPTO */
339 }