1 /*
2 * Copyright (c) 2000-2001 Boris Popov
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Boris Popov.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 /*
34 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
35 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
36 */
37
38 /*
39 * SMB Session Setup, and related.
40 */
41
42 #include <errno.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <unistd.h>
46 #include <strings.h>
47 #include <netdb.h>
48 #include <libintl.h>
49 #include <xti.h>
50 #include <assert.h>
51
52 #include <sys/types.h>
53 #include <sys/time.h>
54 #include <sys/byteorder.h>
55 #include <sys/socket.h>
56 #include <sys/fcntl.h>
57
58 #include <netinet/in.h>
59 #include <netinet/tcp.h>
60 #include <arpa/inet.h>
61
62 #include <netsmb/mchain.h>
63 #include <netsmb/netbios.h>
64 #include <netsmb/smb_dev.h>
65 #include <netsmb/smb.h>
66
67 #include <netsmb/smb_lib.h>
68 #include <netsmb/nb_lib.h>
69
70 #include "private.h"
71 #include "charsets.h"
72 #include "ntlm.h"
73 #include "smb_crypt.h"
74
75
76 static int
77 smb__ssnsetup(struct smb_ctx *ctx,
78 struct mbdata *mbc1, struct mbdata *mbc2,
79 uint32_t *statusp, uint16_t *actionp);
80
81 /*
82 * Session Setup: NULL session (anonymous)
83 */
84 int
smb_ssnsetup_null(struct smb_ctx * ctx)85 smb_ssnsetup_null(struct smb_ctx *ctx)
86 {
87 int err;
88 uint32_t ntstatus;
89 uint16_t action = 0;
90
91 if (ctx->ct_clnt_caps & SMB_CAP_EXT_SECURITY) {
92 /* Should not get here with... */
93 err = EINVAL;
94 goto out;
95 }
96
97 err = smb__ssnsetup(ctx, NULL, NULL, &ntstatus, &action);
98 if (err)
99 goto out;
100
101 DPRINT("status 0x%x action 0x%x", ntstatus, (int)action);
102 if (ntstatus != 0)
103 err = EAUTH;
104
105 out:
106 return (err);
107 }
108
109
110 /*
111 * SMB Session Setup, using NTLMv1 (and maybe LMv1)
112 */
113 int
smb_ssnsetup_ntlm1(struct smb_ctx * ctx)114 smb_ssnsetup_ntlm1(struct smb_ctx *ctx)
115 {
116 struct mbdata lm_mbc, nt_mbc;
117 int err;
118 uint32_t ntstatus;
119 uint16_t action = 0;
120
121 if (ctx->ct_clnt_caps & SMB_CAP_EXT_SECURITY) {
122 /* Should not get here with... */
123 err = EINVAL;
124 goto out;
125 }
126
127 /* Make mb_done calls at out safe. */
128 bzero(&lm_mbc, sizeof (lm_mbc));
129 bzero(&nt_mbc, sizeof (nt_mbc));
130
131 /* Put the LM,NTLM responses (as mbdata). */
132 err = ntlm_put_v1_responses(ctx, &lm_mbc, &nt_mbc);
133 if (err)
134 goto out;
135
136 if ((ctx->ct_vcflags & SMBV_WILL_SIGN) != 0 &&
137 (ctx->ct_hflags2 & SMB_FLAGS2_SECURITY_SIGNATURE) == 0) {
138 err = ntlm_build_mac_key(ctx, &nt_mbc);
139 if (err)
140 goto out;
141 /* OK, start signing! */
142 ctx->ct_hflags2 |= SMB_FLAGS2_SECURITY_SIGNATURE;
143 }
144
145 err = smb__ssnsetup(ctx, &lm_mbc, &nt_mbc, &ntstatus, &action);
146 if (err)
147 goto out;
148
149 DPRINT("status 0x%x action 0x%x", ntstatus, (int)action);
150 if (ntstatus != 0)
151 err = EAUTH;
152
153 out:
154 mb_done(&lm_mbc);
155 mb_done(&nt_mbc);
156
157 return (err);
158 }
159
160 /*
161 * SMB Session Setup, using NTLMv2 (and LMv2)
162 */
163 int
smb_ssnsetup_ntlm2(struct smb_ctx * ctx)164 smb_ssnsetup_ntlm2(struct smb_ctx *ctx)
165 {
166 struct mbdata lm_mbc, nt_mbc, ti_mbc;
167 int err;
168 uint32_t ntstatus;
169 uint16_t action = 0;
170
171 if (ctx->ct_clnt_caps & SMB_CAP_EXT_SECURITY) {
172 /* Should not get here with... */
173 err = EINVAL;
174 goto out;
175 }
176
177 /* Make mb_done calls at out safe. */
178 bzero(&lm_mbc, sizeof (lm_mbc));
179 bzero(&nt_mbc, sizeof (nt_mbc));
180 bzero(&ti_mbc, sizeof (ti_mbc));
181
182 /* Build the NTLMv2 "target info" blob (as mbdata) */
183 err = ntlm_build_target_info(ctx, NULL, &ti_mbc);
184 if (err)
185 goto out;
186
187 /* Put the LMv2, NTLMv2 responses (as mbdata). */
188 err = ntlm_put_v2_responses(ctx, &ti_mbc, &lm_mbc, &nt_mbc);
189 if (err)
190 goto out;
191
192 if ((ctx->ct_vcflags & SMBV_WILL_SIGN) != 0 &&
193 (ctx->ct_hflags2 & SMB_FLAGS2_SECURITY_SIGNATURE) == 0) {
194 err = ntlm_build_mac_key(ctx, &nt_mbc);
195 if (err)
196 goto out;
197 /* OK, start signing! */
198 ctx->ct_hflags2 |= SMB_FLAGS2_SECURITY_SIGNATURE;
199 }
200
201 err = smb__ssnsetup(ctx, &lm_mbc, &nt_mbc, &ntstatus, &action);
202 if (err)
203 goto out;
204
205 DPRINT("status 0x%x action 0x%x", ntstatus, (int)action);
206 if (ntstatus != 0)
207 err = EAUTH;
208
209 out:
210 mb_done(&ti_mbc);
211 mb_done(&lm_mbc);
212 mb_done(&nt_mbc);
213
214 return (err);
215 }
216
217 int
smb_ssnsetup_spnego(struct smb_ctx * ctx,struct mbdata * hint_mb)218 smb_ssnsetup_spnego(struct smb_ctx *ctx, struct mbdata *hint_mb)
219 {
220 struct mbdata send_mb, recv_mb;
221 int err;
222 uint32_t ntstatus;
223 uint16_t action = 0;
224
225 err = ssp_ctx_create_client(ctx, hint_mb);
226 if (err)
227 goto out;
228
229 bzero(&send_mb, sizeof (send_mb));
230 bzero(&recv_mb, sizeof (recv_mb));
231
232 /* NULL input indicates first call. */
233 err = ssp_ctx_next_token(ctx, NULL, &send_mb);
234 if (err)
235 goto out;
236
237 for (;;) {
238 err = smb__ssnsetup(ctx, &send_mb, &recv_mb,
239 &ntstatus, &action);
240 if (err)
241 goto out;
242 if (ntstatus == 0)
243 break; /* normal loop termination */
244 if (ntstatus != NT_STATUS_MORE_PROCESSING_REQUIRED) {
245 err = EAUTH;
246 goto out;
247 }
248
249 /* middle calls get both in, out */
250 err = ssp_ctx_next_token(ctx, &recv_mb, &send_mb);
251 if (err)
252 goto out;
253 }
254 DPRINT("status 0x%x action 0x%x", ntstatus, (int)action);
255
256 /* NULL output indicates last call. */
257 (void) ssp_ctx_next_token(ctx, &recv_mb, NULL);
258
259 out:
260 ssp_ctx_destroy(ctx);
261
262 return (err);
263 }
264
265 /*
266 * Session Setup function used for all the forms we support.
267 * To allow this sharing, the crypto stuff is computed by
268 * callers and passed in as mbdata chains. Also, the args
269 * have different meanings for extended security vs. old.
270 * Some may be used as either IN or OUT parameters.
271 *
272 * For NTLM (v1, v2), all parameters are inputs
273 * mbc1: [in] LM password hash
274 * mbc2: [in] NT password hash
275 * For Extended security (spnego)
276 * mbc1: [in] outgoing blob data
277 * mbc2: [out] received blob data
278 * For both forms, these are optional:
279 * statusp: [out] NT status
280 * actionp: [out] Logon Action (i.e. SMB_ACT_GUEST)
281 */
282 static int
smb__ssnsetup(struct smb_ctx * ctx,struct mbdata * mbc1,struct mbdata * mbc2,uint32_t * statusp,uint16_t * actionp)283 smb__ssnsetup(struct smb_ctx *ctx,
284 struct mbdata *mbc1, struct mbdata *mbc2,
285 uint32_t *statusp, uint16_t *actionp)
286 {
287 static const char NativeOS[] = "Solaris";
288 static const char LanMan[] = "NETSMB";
289 struct smb_sopt *sv = &ctx->ct_sopt;
290 struct smb_iods *is = &ctx->ct_iods;
291 struct smb_rq *rqp = NULL;
292 struct mbdata *mbp;
293 struct mbuf *m;
294 int err, uc;
295 uint32_t caps;
296 uint16_t bc, len1, len2, sblen;
297 uint8_t wc;
298
299 caps = ctx->ct_clnt_caps;
300 uc = ctx->ct_hflags2 & SMB_FLAGS2_UNICODE;
301
302 err = smb_rq_init(ctx, SMB_COM_SESSION_SETUP_ANDX, &rqp);
303 if (err)
304 goto out;
305
306 /*
307 * Build the SMB request.
308 */
309 mbp = &rqp->rq_rq;
310 smb_rq_wstart(rqp);
311 mb_put_uint16le(mbp, 0xff); /* 0: AndXCommand */
312 mb_put_uint16le(mbp, 0); /* 1: AndXOffset */
313 mb_put_uint16le(mbp, sv->sv_maxtx); /* 2: MaxBufferSize */
314 mb_put_uint16le(mbp, sv->sv_maxmux); /* 3: MaxMpxCount */
315 mb_put_uint16le(mbp, 1); /* 4: VcNumber */
316 mb_put_uint32le(mbp, sv->sv_skey); /* 5,6: Session Key */
317
318 if (caps & SMB_CAP_EXT_SECURITY) {
319 len1 = mbc1 ? mbc1->mb_count : 0;
320 mb_put_uint16le(mbp, len1); /* 7: Sec. Blob Len */
321 mb_put_uint32le(mbp, 0); /* 8,9: reserved */
322 mb_put_uint32le(mbp, caps); /* 10,11: Capabilities */
323 smb_rq_wend(rqp); /* 12: Byte Count */
324 smb_rq_bstart(rqp);
325 if (mbc1 && mbc1->mb_top) {
326 mb_put_mbuf(mbp, mbc1->mb_top); /* sec. blob */
327 mbc1->mb_top = NULL; /* consumed */
328 }
329 /* mbc2 is required below */
330 if (mbc2 == NULL) {
331 err = EINVAL;
332 goto out;
333 }
334 } else {
335 len1 = mbc1 ? mbc1->mb_count : 0;
336 len2 = mbc2 ? mbc2->mb_count : 0;
337 mb_put_uint16le(mbp, len1); /* 7: LM pass. len */
338 mb_put_uint16le(mbp, len2); /* 8: NT pass. len */
339 mb_put_uint32le(mbp, 0); /* 9,10: reserved */
340 mb_put_uint32le(mbp, caps); /* 11,12: Capabilities */
341 smb_rq_wend(rqp); /* 13: Byte Count */
342 smb_rq_bstart(rqp);
343 if (mbc1 && mbc1->mb_top) {
344 mb_put_mbuf(mbp, mbc1->mb_top); /* LM password */
345 mbc1->mb_top = NULL; /* consumed */
346 }
347 if (mbc2 && mbc2->mb_top) {
348 mb_put_mbuf(mbp, mbc2->mb_top); /* NT password */
349 mbc2->mb_top = NULL; /* consumed */
350 }
351 mb_put_string(mbp, ctx->ct_user, uc);
352 mb_put_string(mbp, ctx->ct_domain, uc);
353 }
354 mb_put_string(mbp, NativeOS, uc);
355 mb_put_string(mbp, LanMan, uc);
356 smb_rq_bend(rqp);
357
358 err = smb_rq_internal(ctx, rqp);
359 if (err)
360 goto out;
361
362 if (statusp)
363 *statusp = rqp->rq_status;
364
365 /*
366 * If we have a real error, the response probably has
367 * no more data, so don't try to parse any more.
368 * Note: err=0, means rq_status is valid.
369 */
370 if (rqp->rq_status != 0 &&
371 rqp->rq_status != NT_STATUS_MORE_PROCESSING_REQUIRED) {
372 goto out;
373 }
374
375 /*
376 * Parse the reply
377 */
378 uc = rqp->rq_hflags2 & SMB_FLAGS2_UNICODE;
379 is->is_smbuid = rqp->rq_uid;
380 mbp = &rqp->rq_rp;
381
382 err = md_get_uint8(mbp, &wc);
383 if (err)
384 goto out;
385
386 err = EBADRPC; /* for any problems in this section */
387 if (caps & SMB_CAP_EXT_SECURITY) {
388 if (wc != 4)
389 goto out;
390 md_get_uint16le(mbp, NULL); /* secondary cmd */
391 md_get_uint16le(mbp, NULL); /* andxoffset */
392 md_get_uint16le(mbp, actionp); /* action */
393 md_get_uint16le(mbp, &sblen); /* sec. blob len */
394 md_get_uint16le(mbp, &bc); /* byte count */
395 /*
396 * Get the security blob, after
397 * sanity-checking the length.
398 */
399 if (sblen == 0 || bc < sblen)
400 goto out;
401 err = md_get_mbuf(mbp, sblen, &m);
402 if (err)
403 goto out;
404 mb_initm(mbc2, m);
405 mbc2->mb_count = sblen;
406 } else {
407 if (wc != 3)
408 goto out;
409 md_get_uint16le(mbp, NULL); /* secondary cmd */
410 md_get_uint16le(mbp, NULL); /* andxoffset */
411 md_get_uint16le(mbp, actionp); /* action */
412 err = md_get_uint16le(mbp, &bc); /* byte count */
413 if (err)
414 goto out;
415 }
416
417 /*
418 * Native OS, LANMGR, & Domain follow here.
419 * Parse these strings and store for later.
420 * If unicode, they should be aligned.
421 *
422 * Note that with Extended security, we may use
423 * multiple calls to this function. Only parse
424 * these strings on the last one (status == 0).
425 * Ditto for the CAP_LARGE work-around.
426 */
427 if (rqp->rq_status != 0)
428 goto out;
429
430 /* Ignore any parsing errors for these strings. */
431 err = md_get_string(mbp, &ctx->ct_srv_OS, uc);
432 DPRINT("server OS: %s", err ? "?" : ctx->ct_srv_OS);
433 err = md_get_string(mbp, &ctx->ct_srv_LM, uc);
434 DPRINT("server LM: %s", err ? "?" : ctx->ct_srv_LM);
435 /*
436 * There's sometimes a server domain folloing
437 * at this point, but we don't need it.
438 */
439
440 /* Success! (See Ignore any ... above) */
441 err = 0;
442
443 /*
444 * Windows systems don't suport CAP_LARGE_READX,WRITEX
445 * when signing is enabled, so adjust sv_caps.
446 */
447 if (ctx->ct_srv_OS &&
448 0 == strncmp(ctx->ct_srv_OS, "Windows ", 8)) {
449 DPRINT("Server is Windows");
450 if (ctx->ct_vcflags & SMBV_WILL_SIGN) {
451 DPRINT("disable CAP_LARGE_(r/w)");
452 ctx->ct_sopt.sv_caps &=
453 ~(SMB_CAP_LARGE_READX | SMB_CAP_LARGE_WRITEX);
454 }
455 }
456
457 out:
458 if (rqp)
459 smb_rq_done(rqp);
460
461 return (err);
462 }
463