1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 * Copyright 2013 Nexenta Systems, Inc. All rights reserved. 26 */ 27 28 /* 29 * Functions to setup connections (TCP and/or NetBIOS) 30 * This has the fall-back logic for IP6, IP4, NBT 31 */ 32 33 #include <errno.h> 34 #include <stdio.h> 35 #include <string.h> 36 #include <strings.h> 37 #include <stdlib.h> 38 #include <unistd.h> 39 #include <netdb.h> 40 #include <libintl.h> 41 #include <xti.h> 42 #include <assert.h> 43 44 #include <sys/types.h> 45 #include <sys/time.h> 46 #include <sys/byteorder.h> 47 #include <sys/socket.h> 48 #include <sys/fcntl.h> 49 50 #include <netinet/in.h> 51 #include <netinet/tcp.h> 52 #include <arpa/inet.h> 53 54 #include <netsmb/smb.h> 55 #include <netsmb/smb_lib.h> 56 #include <netsmb/netbios.h> 57 #include <netsmb/nb_lib.h> 58 #include <netsmb/smb_dev.h> 59 60 #include "charsets.h" 61 #include "private.h" 62 63 /* 64 * SMB messages are up to 64K. 65 * Let's leave room for two. 66 */ 67 static int smb_tcpsndbuf = 0x20000; 68 static int smb_tcprcvbuf = 0x20000; 69 static int smb_connect_timeout = 30; /* seconds */ 70 int smb_recv_timeout = 30; /* seconds */ 71 72 int conn_tcp6(struct smb_ctx *, const struct sockaddr *, int); 73 int conn_tcp4(struct smb_ctx *, const struct sockaddr *, int); 74 int conn_nbt(struct smb_ctx *, const struct sockaddr *, char *); 75 76 /* 77 * Internal set sockopt for int-sized options. 78 * Borrowed from: libnsl/rpc/ti_opts.c 79 */ 80 static int 81 smb_setopt_int(int fd, int level, int name, int val) 82 { 83 struct t_optmgmt oreq, ores; 84 struct { 85 struct t_opthdr oh; 86 int ival; 87 } opts; 88 89 /* opt header */ 90 opts.oh.len = sizeof (opts); 91 opts.oh.level = level; 92 opts.oh.name = name; 93 opts.oh.status = 0; 94 opts.ival = val; 95 96 oreq.flags = T_NEGOTIATE; 97 oreq.opt.buf = (void *)&opts; 98 oreq.opt.len = sizeof (opts); 99 100 ores.flags = 0; 101 ores.opt.buf = NULL; 102 ores.opt.maxlen = 0; 103 104 if (t_optmgmt(fd, &oreq, &ores) < 0) { 105 DPRINT("t_opgmgnt, t_errno = %d", t_errno); 106 if (t_errno == TSYSERR) 107 return (errno); 108 return (EPROTO); 109 } 110 if (ores.flags != T_SUCCESS) { 111 DPRINT("flags 0x%x, status 0x%x", 112 (int)ores.flags, (int)opts.oh.status); 113 return (EPROTO); 114 } 115 116 return (0); 117 } 118 119 static int 120 smb_setopts(int fd) 121 { 122 int err; 123 124 /* 125 * Set various socket/TCP options. 126 * Failures here are not fatal - 127 * just log a complaint. 128 * 129 * We don't need these two: 130 * SO_RCVTIMEO, SO_SNDTIMEO 131 */ 132 133 err = smb_setopt_int(fd, SOL_SOCKET, SO_SNDBUF, smb_tcpsndbuf); 134 if (err) { 135 DPRINT("set SO_SNDBUF, err %d", err); 136 } 137 138 err = smb_setopt_int(fd, SOL_SOCKET, SO_RCVBUF, smb_tcprcvbuf); 139 if (err) { 140 DPRINT("set SO_RCVBUF, err %d", err); 141 } 142 143 err = smb_setopt_int(fd, SOL_SOCKET, SO_KEEPALIVE, 1); 144 if (err) { 145 DPRINT("set SO_KEEPALIVE, err %d", err); 146 } 147 148 err = smb_setopt_int(fd, IPPROTO_TCP, TCP_NODELAY, 1); 149 if (err) { 150 DPRINT("set TCP_NODELAY, err %d", err); 151 } 152 153 /* Set the connect timeout (in milliseconds). */ 154 err = smb_setopt_int(fd, IPPROTO_TCP, 155 TCP_CONN_ABORT_THRESHOLD, 156 smb_connect_timeout * 1000); 157 if (err) { 158 DPRINT("set connect timeout, err %d", err); 159 } 160 return (0); 161 } 162 163 164 int 165 conn_tcp6(struct smb_ctx *ctx, const struct sockaddr *sa, int port) 166 { 167 struct sockaddr_in6 sin6; 168 char *dev = "/dev/tcp6"; 169 char paddrbuf[INET6_ADDRSTRLEN]; 170 struct t_call sndcall; 171 int fd, err; 172 173 if (sa->sa_family != AF_INET6) { 174 DPRINT("bad af %d", sa->sa_family); 175 return (EINVAL); 176 } 177 bcopy(sa, &sin6, sizeof (sin6)); 178 sin6.sin6_port = htons(port); 179 180 DPRINT("tcp6: %s (%d)", 181 inet_ntop(AF_INET6, &sin6.sin6_addr, 182 paddrbuf, sizeof (paddrbuf)), port); 183 184 fd = t_open(dev, O_RDWR, NULL); 185 if (fd < 0) { 186 /* Assume t_errno = TSYSERR */ 187 err = errno; 188 perror(dev); 189 return (err); 190 } 191 if ((err = smb_setopts(fd)) != 0) 192 goto errout; 193 if (t_bind(fd, NULL, NULL) < 0) { 194 DPRINT("t_bind t_errno %d", t_errno); 195 if (t_errno == TSYSERR) 196 err = errno; 197 else 198 err = EPROTO; 199 goto errout; 200 } 201 sndcall.addr.maxlen = sizeof (sin6); 202 sndcall.addr.len = sizeof (sin6); 203 sndcall.addr.buf = (void *) &sin6; 204 sndcall.opt.len = 0; 205 sndcall.udata.len = 0; 206 if (t_connect(fd, &sndcall, NULL) < 0) { 207 err = get_xti_err(fd); 208 DPRINT("connect, err %d", err); 209 goto errout; 210 } 211 212 DPRINT("tcp6: connected, fd=%d", fd); 213 ctx->ct_tran_fd = fd; 214 return (0); 215 216 errout: 217 close(fd); 218 return (err); 219 } 220 221 /* 222 * This is used for both SMB over TCP (port 445) 223 * and NetBIOS - see conn_nbt(). 224 */ 225 int 226 conn_tcp4(struct smb_ctx *ctx, const struct sockaddr *sa, int port) 227 { 228 struct sockaddr_in sin; 229 char *dev = "/dev/tcp"; 230 char paddrbuf[INET_ADDRSTRLEN]; 231 struct t_call sndcall; 232 int fd, err; 233 234 if (sa->sa_family != AF_INET) { 235 DPRINT("bad af %d", sa->sa_family); 236 return (EINVAL); 237 } 238 bcopy(sa, &sin, sizeof (sin)); 239 sin.sin_port = htons(port); 240 241 DPRINT("tcp4: %s (%d)", 242 inet_ntop(AF_INET, &sin.sin_addr, 243 paddrbuf, sizeof (paddrbuf)), port); 244 245 fd = t_open(dev, O_RDWR, NULL); 246 if (fd < 0) { 247 /* Assume t_errno = TSYSERR */ 248 err = errno; 249 perror(dev); 250 return (err); 251 } 252 if ((err = smb_setopts(fd)) != 0) 253 goto errout; 254 if (t_bind(fd, NULL, NULL) < 0) { 255 DPRINT("t_bind t_errno %d", t_errno); 256 if (t_errno == TSYSERR) 257 err = errno; 258 else 259 err = EPROTO; 260 goto errout; 261 } 262 sndcall.addr.maxlen = sizeof (sin); 263 sndcall.addr.len = sizeof (sin); 264 sndcall.addr.buf = (void *) &sin; 265 sndcall.opt.len = 0; 266 sndcall.udata.len = 0; 267 if (t_connect(fd, &sndcall, NULL) < 0) { 268 err = get_xti_err(fd); 269 DPRINT("connect, err %d", err); 270 goto errout; 271 } 272 273 DPRINT("tcp4: connected, fd=%d", fd); 274 ctx->ct_tran_fd = fd; 275 return (0); 276 277 errout: 278 close(fd); 279 return (err); 280 } 281 282 /* 283 * Open a NetBIOS connection (session, port 139) 284 * 285 * The optional name parameter, if passed, means 286 * we found the sockaddr via NetBIOS name lookup, 287 * and can just use that for our session request. 288 * Otherwise (if name is NULL), we're connecting 289 * by IP address, and need to come up with the 290 * NetBIOS name by other means. 291 */ 292 int 293 conn_nbt(struct smb_ctx *ctx, const struct sockaddr *saarg, char *name) 294 { 295 struct sockaddr_in sin; 296 struct sockaddr *sa; 297 char server[NB_NAMELEN]; 298 char workgroup[NB_NAMELEN]; 299 int err, nberr, port; 300 301 bcopy(saarg, &sin, sizeof (sin)); 302 sa = (struct sockaddr *)&sin; 303 304 switch (sin.sin_family) { 305 case AF_NETBIOS: /* our fake AF */ 306 sin.sin_family = AF_INET; 307 break; 308 case AF_INET: 309 break; 310 default: 311 DPRINT("bad af %d", sin.sin_family); 312 return (EINVAL); 313 } 314 port = IPPORT_NETBIOS_SSN; 315 316 /* 317 * If we have a NetBIOS name, just use it. 318 * This is the path taken when we've done a 319 * NetBIOS name lookup on this name to get 320 * the IP address in the passed sa. Otherwise, 321 * we're connecting by IP address, and need to 322 * figure out what NetBIOS name to use. 323 */ 324 if (name) { 325 strlcpy(server, name, sizeof (server)); 326 DPRINT("given name: %s", server); 327 } else { 328 /* 329 * 330 * Try a NetBIOS node status query, 331 * which searches for a type=[20] name. 332 * If that doesn't work, just use the 333 * (fake) "*SMBSERVER" name. 334 */ 335 DPRINT("try node status"); 336 server[0] = '\0'; 337 nberr = nbns_getnodestatus(ctx->ct_nb, 338 &sin.sin_addr, server, workgroup); 339 if (nberr == 0 && server[0] != '\0') { 340 /* Found the name. Save for reconnect. */ 341 DPRINT("found name: %s", server); 342 strlcpy(ctx->ct_srvname, server, 343 sizeof (ctx->ct_srvname)); 344 } else { 345 DPRINT("getnodestatus, nberr %d", nberr); 346 strlcpy(server, "*SMBSERVER", sizeof (server)); 347 } 348 } 349 350 /* 351 * Establish the TCP connection. 352 * Careful to close it on errors. 353 */ 354 if ((err = conn_tcp4(ctx, sa, port)) != 0) { 355 DPRINT("TCP connect: err=%d", err); 356 goto out; 357 } 358 359 /* Connected. Do NetBIOS session request. */ 360 err = nb_ssn_request(ctx, server); 361 if (err) 362 DPRINT("ssn_rq, err %d", err); 363 364 out: 365 if (err) { 366 if (ctx->ct_tran_fd != -1) { 367 close(ctx->ct_tran_fd); 368 ctx->ct_tran_fd = -1; 369 } 370 } 371 return (err); 372 } 373 374 /* 375 * Make a new connection, or reconnect. 376 */ 377 int 378 smb_iod_connect(smb_ctx_t *ctx) 379 { 380 struct sockaddr *sa; 381 int err, err2; 382 struct mbdata blob; 383 384 memset(&blob, 0, sizeof (blob)); 385 386 if (ctx->ct_srvname[0] == '\0') { 387 DPRINT("sername not set!"); 388 return (EINVAL); 389 } 390 DPRINT("server: %s", ctx->ct_srvname); 391 392 if (smb_debug) 393 dump_ctx("smb_iod_connect", ctx); 394 395 /* 396 * This may be a reconnect, so 397 * cleanup if necessary. 398 */ 399 if (ctx->ct_tran_fd != -1) { 400 close(ctx->ct_tran_fd); 401 ctx->ct_tran_fd = -1; 402 } 403 404 /* 405 * Get local machine name. 406 * Full name - not a NetBIOS name. 407 */ 408 if (ctx->ct_locname == NULL) { 409 err = smb_getlocalname(&ctx->ct_locname); 410 if (err) { 411 smb_error(dgettext(TEXT_DOMAIN, 412 "can't get local name"), err); 413 return (err); 414 } 415 } 416 417 /* 418 * We're called with each IP address 419 * already copied into ct_srvaddr. 420 */ 421 ctx->ct_flags |= SMBCF_RESOLVED; 422 423 sa = &ctx->ct_srvaddr.sa; 424 switch (sa->sa_family) { 425 426 case AF_INET6: 427 err = conn_tcp6(ctx, sa, IPPORT_SMB); 428 break; 429 430 case AF_INET: 431 err = conn_tcp4(ctx, sa, IPPORT_SMB); 432 /* 433 * If port 445 was not listening, try port 139. 434 * Note: Not doing NetBIOS name lookup here. 435 * We already have the IP address. 436 */ 437 switch (err) { 438 case ECONNRESET: 439 case ECONNREFUSED: 440 err2 = conn_nbt(ctx, sa, NULL); 441 if (err2 == 0) 442 err = 0; 443 } 444 break; 445 446 case AF_NETBIOS: 447 /* Like AF_INET, but use NetBIOS ssn. */ 448 err = conn_nbt(ctx, sa, ctx->ct_srvname); 449 break; 450 451 default: 452 DPRINT("skipped family %d", sa->sa_family); 453 err = EPROTONOSUPPORT; 454 break; 455 } 456 457 458 if (err) { 459 DPRINT("connect, err=%d", err); 460 return (err); 461 } 462 463 /* 464 * Do SMB Negotiate Protocol. 465 */ 466 err = smb_negprot(ctx, &blob); 467 if (err) 468 goto out; 469 470 /* 471 * Empty user name means an explicit request for 472 * NULL session setup, which is a special case. 473 * If negotiate determined that we want to do 474 * SMB signing, we have to turn that off for a 475 * NULL session. [MS-SMB 3.3.5.3]. 476 */ 477 if (ctx->ct_user[0] == '\0') { 478 /* Null user should have null domain too. */ 479 ctx->ct_domain[0] = '\0'; 480 ctx->ct_authflags = SMB_AT_ANON; 481 ctx->ct_clnt_caps &= ~SMB_CAP_EXT_SECURITY; 482 ctx->ct_vcflags &= ~SMBV_WILL_SIGN; 483 } 484 485 /* 486 * Do SMB Session Setup (authenticate) 487 * 488 * If the server negotiated extended security, 489 * run the SPNEGO state machine, otherwise do 490 * one of the old-style variants. 491 */ 492 if (ctx->ct_clnt_caps & SMB_CAP_EXT_SECURITY) { 493 err = smb_ssnsetup_spnego(ctx, &blob); 494 } else { 495 /* 496 * Server did NOT negotiate extended security. 497 * Try NTLMv2, NTLMv1, or ANON (if enabled). 498 */ 499 if (ctx->ct_authflags & SMB_AT_NTLM2) { 500 err = smb_ssnsetup_ntlm2(ctx); 501 } else if (ctx->ct_authflags & SMB_AT_NTLM1) { 502 err = smb_ssnsetup_ntlm1(ctx); 503 } else if (ctx->ct_authflags & SMB_AT_ANON) { 504 err = smb_ssnsetup_null(ctx); 505 } else { 506 /* 507 * Don't return EAUTH, because a new 508 * password prompt will not help. 509 */ 510 DPRINT("No NTLM authflags"); 511 err = ENOTSUP; 512 } 513 } 514 515 out: 516 mb_done(&blob); 517 518 if (err) { 519 close(ctx->ct_tran_fd); 520 ctx->ct_tran_fd = -1; 521 } else { 522 /* Tell library code we have a session. */ 523 ctx->ct_flags |= SMBCF_SSNACTIVE; 524 DPRINT("tran_fd = %d", ctx->ct_tran_fd); 525 } 526 527 return (err); 528 } 529