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
smb_setopt_int(int fd,int level,int name,int val)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
smb_setopts(int fd)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
conn_tcp6(struct smb_ctx * ctx,const struct sockaddr * sa,int port)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
conn_tcp4(struct smb_ctx * ctx,const struct sockaddr * sa,int port)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
conn_nbt(struct smb_ctx * ctx,const struct sockaddr * saarg,char * name)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
smb_iod_connect(smb_ctx_t * ctx)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