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 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 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 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 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 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