source: vendor/current/source3/libsmb/libsmb_server.c

Last change on this file was 988, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.3

File size: 27.2 KB
Line 
1/*
2 Unix SMB/Netbios implementation.
3 SMB client library implementation
4 Copyright (C) Andrew Tridgell 1998
5 Copyright (C) Richard Sharpe 2000, 2002
6 Copyright (C) John Terpstra 2000
7 Copyright (C) Tom Jansen (Ninja ISD) 2002
8 Copyright (C) Derrell Lipman 2003-2008
9 Copyright (C) Jeremy Allison 2007, 2008
10 Copyright (C) SATOH Fumiyasu <fumiyas@osstech.co.jp> 2009.
11
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
24*/
25
26#include "includes.h"
27#include "libsmb/libsmb.h"
28#include "libsmbclient.h"
29#include "libsmb_internal.h"
30#include "../librpc/gen_ndr/ndr_lsa.h"
31#include "rpc_client/cli_pipe.h"
32#include "rpc_client/cli_lsarpc.h"
33#include "libcli/security/security.h"
34#include "libsmb/nmblib.h"
35#include "../libcli/smb/smbXcli_base.h"
36
37/*
38 * Check a server for being alive and well.
39 * returns 0 if the server is in shape. Returns 1 on error
40 *
41 * Also useable outside libsmbclient to enable external cache
42 * to do some checks too.
43 */
44int
45SMBC_check_server(SMBCCTX * context,
46 SMBCSRV * server)
47{
48 time_t now;
49
50 if (!cli_state_is_connected(server->cli)) {
51 return 1;
52 }
53
54 now = time_mono(NULL);
55
56 if (server->last_echo_time == (time_t)0 ||
57 now > server->last_echo_time +
58 (server->cli->timeout/1000)) {
59 unsigned char data[16] = {0};
60 NTSTATUS status = cli_echo(server->cli,
61 1,
62 data_blob_const(data, sizeof(data)));
63 if (!NT_STATUS_IS_OK(status)) {
64 return 1;
65 }
66 server->last_echo_time = now;
67 }
68 return 0;
69}
70
71/*
72 * Remove a server from the cached server list it's unused.
73 * On success, 0 is returned. 1 is returned if the server could not be removed.
74 *
75 * Also useable outside libsmbclient
76 */
77int
78SMBC_remove_unused_server(SMBCCTX * context,
79 SMBCSRV * srv)
80{
81 SMBCFILE * file;
82
83 /* are we being fooled ? */
84 if (!context || !context->internal->initialized || !srv) {
85 return 1;
86 }
87
88 /* Check all open files/directories for a relation with this server */
89 for (file = context->internal->files; file; file = file->next) {
90 if (file->srv == srv) {
91 /* Still used */
92 DEBUG(3, ("smbc_remove_usused_server: "
93 "%p still used by %p.\n",
94 srv, file));
95 return 1;
96 }
97 }
98
99 DLIST_REMOVE(context->internal->servers, srv);
100
101 cli_shutdown(srv->cli);
102 srv->cli = NULL;
103
104 DEBUG(3, ("smbc_remove_usused_server: %p removed.\n", srv));
105
106 smbc_getFunctionRemoveCachedServer(context)(context, srv);
107
108 SAFE_FREE(srv);
109 return 0;
110}
111
112/****************************************************************
113 * Call the auth_fn with fixed size (fstring) buffers.
114 ***************************************************************/
115static void
116SMBC_call_auth_fn(TALLOC_CTX *ctx,
117 SMBCCTX *context,
118 const char *server,
119 const char *share,
120 char **pp_workgroup,
121 char **pp_username,
122 char **pp_password)
123{
124 fstring workgroup;
125 fstring username;
126 fstring password;
127 smbc_get_auth_data_with_context_fn auth_with_context_fn;
128
129 strlcpy(workgroup, *pp_workgroup, sizeof(workgroup));
130 strlcpy(username, *pp_username, sizeof(username));
131 strlcpy(password, *pp_password, sizeof(password));
132
133 /* See if there's an authentication with context function provided */
134 auth_with_context_fn = smbc_getFunctionAuthDataWithContext(context);
135 if (auth_with_context_fn)
136 {
137 (* auth_with_context_fn)(context,
138 server, share,
139 workgroup, sizeof(workgroup),
140 username, sizeof(username),
141 password, sizeof(password));
142 }
143 else
144 {
145 smbc_getFunctionAuthData(context)(server, share,
146 workgroup, sizeof(workgroup),
147 username, sizeof(username),
148 password, sizeof(password));
149 }
150
151 TALLOC_FREE(*pp_workgroup);
152 TALLOC_FREE(*pp_username);
153 TALLOC_FREE(*pp_password);
154
155 *pp_workgroup = talloc_strdup(ctx, workgroup);
156 *pp_username = talloc_strdup(ctx, username);
157 *pp_password = talloc_strdup(ctx, password);
158}
159
160
161void
162SMBC_get_auth_data(const char *server, const char *share,
163 char *workgroup_buf, int workgroup_buf_len,
164 char *username_buf, int username_buf_len,
165 char *password_buf, int password_buf_len)
166{
167 /* Default function just uses provided data. Nothing to do. */
168}
169
170
171
172SMBCSRV *
173SMBC_find_server(TALLOC_CTX *ctx,
174 SMBCCTX *context,
175 const char *server,
176 const char *share,
177 char **pp_workgroup,
178 char **pp_username,
179 char **pp_password)
180{
181 SMBCSRV *srv;
182 int auth_called = 0;
183
184 if (!pp_workgroup || !pp_username || !pp_password) {
185 return NULL;
186 }
187
188check_server_cache:
189
190 srv = smbc_getFunctionGetCachedServer(context)(context,
191 server, share,
192 *pp_workgroup,
193 *pp_username);
194
195 if (!auth_called && !srv && (!*pp_username || !(*pp_username)[0] ||
196 !*pp_password || !(*pp_password)[0])) {
197 SMBC_call_auth_fn(ctx, context, server, share,
198 pp_workgroup, pp_username, pp_password);
199
200 /*
201 * However, smbc_auth_fn may have picked up info relating to
202 * an existing connection, so try for an existing connection
203 * again ...
204 */
205 auth_called = 1;
206 goto check_server_cache;
207
208 }
209
210 if (srv) {
211 if (smbc_getFunctionCheckServer(context)(context, srv)) {
212 /*
213 * This server is no good anymore
214 * Try to remove it and check for more possible
215 * servers in the cache
216 */
217 if (smbc_getFunctionRemoveUnusedServer(context)(context,
218 srv)) {
219 /*
220 * We could not remove the server completely,
221 * remove it from the cache so we will not get
222 * it again. It will be removed when the last
223 * file/dir is closed.
224 */
225 smbc_getFunctionRemoveCachedServer(context)(context,
226 srv);
227 }
228
229 /*
230 * Maybe there are more cached connections to this
231 * server
232 */
233 goto check_server_cache;
234 }
235
236 return srv;
237 }
238
239 return NULL;
240}
241
242/*
243 * Connect to a server, possibly on an existing connection
244 *
245 * Here, what we want to do is: If the server and username
246 * match an existing connection, reuse that, otherwise, establish a
247 * new connection.
248 *
249 * If we have to create a new connection, call the auth_fn to get the
250 * info we need, unless the username and password were passed in.
251 */
252
253static SMBCSRV *
254SMBC_server_internal(TALLOC_CTX *ctx,
255 SMBCCTX *context,
256 bool connect_if_not_found,
257 const char *server,
258 uint16_t port,
259 const char *share,
260 char **pp_workgroup,
261 char **pp_username,
262 char **pp_password,
263 bool *in_cache)
264{
265 SMBCSRV *srv=NULL;
266 char *workgroup = NULL;
267 struct cli_state *c = NULL;
268 const char *server_n = server;
269 int is_ipc = (share != NULL && strcmp(share, "IPC$") == 0);
270 uint32_t fs_attrs = 0;
271 const char *username_used;
272 NTSTATUS status;
273 char *newserver, *newshare;
274 int flags = 0;
275 struct smbXcli_tcon *tcon = NULL;
276 int signing_state = SMB_SIGNING_DEFAULT;
277
278 ZERO_STRUCT(c);
279 *in_cache = false;
280
281 if (server[0] == 0) {
282 errno = EPERM;
283 return NULL;
284 }
285
286 /* Look for a cached connection */
287 srv = SMBC_find_server(ctx, context, server, share,
288 pp_workgroup, pp_username, pp_password);
289
290 /*
291 * If we found a connection and we're only allowed one share per
292 * server...
293 */
294 if (srv &&
295 share != NULL && *share != '\0' &&
296 smbc_getOptionOneSharePerServer(context)) {
297
298 /*
299 * ... then if there's no current connection to the share,
300 * connect to it. SMBC_find_server(), or rather the function
301 * pointed to by context->get_cached_srv_fn which
302 * was called by SMBC_find_server(), will have issued a tree
303 * disconnect if the requested share is not the same as the
304 * one that was already connected.
305 */
306
307 /*
308 * Use srv->cli->desthost and srv->cli->share instead of
309 * server and share below to connect to the actual share,
310 * i.e., a normal share or a referred share from
311 * 'msdfs proxy' share.
312 */
313 if (!cli_state_has_tcon(srv->cli)) {
314 /* Ensure we have accurate auth info */
315 SMBC_call_auth_fn(ctx, context,
316 smbXcli_conn_remote_name(srv->cli->conn),
317 srv->cli->share,
318 pp_workgroup,
319 pp_username,
320 pp_password);
321
322 if (!*pp_workgroup || !*pp_username || !*pp_password) {
323 errno = ENOMEM;
324 cli_shutdown(srv->cli);
325 srv->cli = NULL;
326 smbc_getFunctionRemoveCachedServer(context)(context,
327 srv);
328 return NULL;
329 }
330
331 /*
332 * We don't need to renegotiate encryption
333 * here as the encryption context is not per
334 * tid.
335 */
336
337 status = cli_tree_connect(srv->cli,
338 srv->cli->share,
339 "?????",
340 *pp_password,
341 strlen(*pp_password)+1);
342 if (!NT_STATUS_IS_OK(status)) {
343 errno = map_errno_from_nt_status(status);
344 cli_shutdown(srv->cli);
345 srv->cli = NULL;
346 smbc_getFunctionRemoveCachedServer(context)(context,
347 srv);
348 srv = NULL;
349 }
350
351 /* Determine if this share supports case sensitivity */
352 if (is_ipc) {
353 DEBUG(4,
354 ("IPC$ so ignore case sensitivity\n"));
355 status = NT_STATUS_OK;
356 } else {
357 status = cli_get_fs_attr_info(c, &fs_attrs);
358 }
359
360 if (!NT_STATUS_IS_OK(status)) {
361 DEBUG(4, ("Could not retrieve "
362 "case sensitivity flag: %s.\n",
363 nt_errstr(status)));
364
365 /*
366 * We can't determine the case sensitivity of
367 * the share. We have no choice but to use the
368 * user-specified case sensitivity setting.
369 */
370 if (smbc_getOptionCaseSensitive(context)) {
371 cli_set_case_sensitive(c, True);
372 } else {
373 cli_set_case_sensitive(c, False);
374 }
375 } else if (!is_ipc) {
376 DEBUG(4,
377 ("Case sensitive: %s\n",
378 (fs_attrs & FILE_CASE_SENSITIVE_SEARCH
379 ? "True"
380 : "False")));
381 cli_set_case_sensitive(
382 c,
383 (fs_attrs & FILE_CASE_SENSITIVE_SEARCH
384 ? True
385 : False));
386 }
387
388 /*
389 * Regenerate the dev value since it's based on both
390 * server and share
391 */
392 if (srv) {
393 const char *remote_name =
394 smbXcli_conn_remote_name(srv->cli->conn);
395
396 srv->dev = (dev_t)(str_checksum(remote_name) ^
397 str_checksum(srv->cli->share));
398 }
399 }
400 }
401
402 /* If we have a connection... */
403 if (srv) {
404
405 /* ... then we're done here. Give 'em what they came for. */
406 *in_cache = true;
407 goto done;
408 }
409
410 /* If we're not asked to connect when a connection doesn't exist... */
411 if (! connect_if_not_found) {
412 /* ... then we're done here. */
413 return NULL;
414 }
415
416 if (!*pp_workgroup || !*pp_username || !*pp_password) {
417 errno = ENOMEM;
418 return NULL;
419 }
420
421 DEBUG(4,("SMBC_server: server_n=[%s] server=[%s]\n", server_n, server));
422
423 DEBUG(4,(" -> server_n=[%s] server=[%s]\n", server_n, server));
424
425 status = NT_STATUS_UNSUCCESSFUL;
426
427 if (smbc_getOptionUseKerberos(context)) {
428 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
429 }
430
431 if (smbc_getOptionFallbackAfterKerberos(context)) {
432 flags |= CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
433 }
434
435 if (smbc_getOptionUseCCache(context)) {
436 flags |= CLI_FULL_CONNECTION_USE_CCACHE;
437 }
438
439 if (smbc_getOptionUseNTHash(context)) {
440 flags |= CLI_FULL_CONNECTION_USE_NT_HASH;
441 }
442
443 if (context->internal->smb_encryption_level != SMBC_ENCRYPTLEVEL_NONE) {
444 signing_state = SMB_SIGNING_REQUIRED;
445 }
446
447 if (port == 0) {
448 if (share == NULL || *share == '\0' || is_ipc) {
449 /*
450 * Try 139 first for IPC$
451 */
452 status = cli_connect_nb(server_n, NULL, NBT_SMB_PORT, 0x20,
453 smbc_getNetbiosName(context),
454 signing_state, flags, &c);
455 }
456 }
457
458 if (!NT_STATUS_IS_OK(status)) {
459 /*
460 * No IPC$ or 139 did not work
461 */
462 status = cli_connect_nb(server_n, NULL, port, 0x20,
463 smbc_getNetbiosName(context),
464 signing_state, flags, &c);
465 }
466
467 if (!NT_STATUS_IS_OK(status)) {
468 errno = map_errno_from_nt_status(status);
469 return NULL;
470 }
471
472 cli_set_timeout(c, smbc_getTimeout(context));
473
474 status = smbXcli_negprot(c->conn, c->timeout,
475 lp_client_min_protocol(),
476 lp_client_max_protocol());
477 if (!NT_STATUS_IS_OK(status)) {
478 cli_shutdown(c);
479 errno = ETIMEDOUT;
480 return NULL;
481 }
482
483 if (smbXcli_conn_protocol(c->conn) >= PROTOCOL_SMB2_02) {
484 /* Ensure we ask for some initial credits. */
485 smb2cli_conn_set_max_credits(c->conn, DEFAULT_SMB2_MAX_CREDITS);
486 }
487
488 username_used = *pp_username;
489
490 if (!NT_STATUS_IS_OK(cli_session_setup(c, username_used,
491 *pp_password,
492 strlen(*pp_password),
493 *pp_password,
494 strlen(*pp_password),
495 *pp_workgroup))) {
496
497 /* Failed. Try an anonymous login, if allowed by flags. */
498 username_used = "";
499
500 if (smbc_getOptionNoAutoAnonymousLogin(context) ||
501 !NT_STATUS_IS_OK(cli_session_setup(c, username_used,
502 *pp_password, 1,
503 *pp_password, 0,
504 *pp_workgroup))) {
505
506 cli_shutdown(c);
507 errno = EPERM;
508 return NULL;
509 }
510 }
511
512 DEBUG(4,(" session setup ok\n"));
513
514 /* here's the fun part....to support 'msdfs proxy' shares
515 (on Samba or windows) we have to issues a TRANS_GET_DFS_REFERRAL
516 here before trying to connect to the original share.
517 cli_check_msdfs_proxy() will fail if it is a normal share. */
518
519 if (smbXcli_conn_dfs_supported(c->conn) &&
520 cli_check_msdfs_proxy(ctx, c, share,
521 &newserver, &newshare,
522 /* FIXME: cli_check_msdfs_proxy() does
523 not support smbc_smb_encrypt_level type */
524 context->internal->smb_encryption_level ?
525 true : false,
526 *pp_username,
527 *pp_password,
528 *pp_workgroup)) {
529 cli_shutdown(c);
530 srv = SMBC_server_internal(ctx, context, connect_if_not_found,
531 newserver, port, newshare, pp_workgroup,
532 pp_username, pp_password, in_cache);
533 TALLOC_FREE(newserver);
534 TALLOC_FREE(newshare);
535 return srv;
536 }
537
538 /* must be a normal share */
539
540 status = cli_tree_connect(c, share, "?????", *pp_password,
541 strlen(*pp_password)+1);
542 if (!NT_STATUS_IS_OK(status)) {
543 errno = map_errno_from_nt_status(status);
544 cli_shutdown(c);
545 return NULL;
546 }
547
548 DEBUG(4,(" tconx ok\n"));
549
550 if (smbXcli_conn_protocol(c->conn) >= PROTOCOL_SMB2_02) {
551 tcon = c->smb2.tcon;
552 } else {
553 tcon = c->smb1.tcon;
554 }
555
556 /* Determine if this share supports case sensitivity */
557 if (is_ipc) {
558 DEBUG(4, ("IPC$ so ignore case sensitivity\n"));
559 status = NT_STATUS_OK;
560 } else {
561 status = cli_get_fs_attr_info(c, &fs_attrs);
562 }
563
564 if (!NT_STATUS_IS_OK(status)) {
565 DEBUG(4, ("Could not retrieve case sensitivity flag: %s.\n",
566 nt_errstr(status)));
567
568 /*
569 * We can't determine the case sensitivity of the share. We
570 * have no choice but to use the user-specified case
571 * sensitivity setting.
572 */
573 if (smbc_getOptionCaseSensitive(context)) {
574 cli_set_case_sensitive(c, True);
575 } else {
576 cli_set_case_sensitive(c, False);
577 }
578 } else if (!is_ipc) {
579 DEBUG(4, ("Case sensitive: %s\n",
580 (fs_attrs & FILE_CASE_SENSITIVE_SEARCH
581 ? "True"
582 : "False")));
583 smbXcli_tcon_set_fs_attributes(tcon, fs_attrs);
584 }
585
586 if (context->internal->smb_encryption_level) {
587 /* Attempt UNIX smb encryption. */
588 if (!NT_STATUS_IS_OK(cli_force_encryption(c,
589 username_used,
590 *pp_password,
591 *pp_workgroup))) {
592
593 /*
594 * context->smb_encryption_level == 1
595 * means don't fail if encryption can't be negotiated,
596 * == 2 means fail if encryption can't be negotiated.
597 */
598
599 DEBUG(4,(" SMB encrypt failed\n"));
600
601 if (context->internal->smb_encryption_level == 2) {
602 cli_shutdown(c);
603 errno = EPERM;
604 return NULL;
605 }
606 }
607 DEBUG(4,(" SMB encrypt ok\n"));
608 }
609
610 /*
611 * Ok, we have got a nice connection
612 * Let's allocate a server structure.
613 */
614
615 srv = SMB_MALLOC_P(SMBCSRV);
616 if (!srv) {
617 cli_shutdown(c);
618 errno = ENOMEM;
619 return NULL;
620 }
621
622 ZERO_STRUCTP(srv);
623 DLIST_ADD(srv->cli, c);
624 srv->dev = (dev_t)(str_checksum(server) ^ str_checksum(share));
625 srv->no_pathinfo = False;
626 srv->no_pathinfo2 = False;
627 srv->no_pathinfo3 = False;
628 srv->no_nt_session = False;
629
630done:
631 if (!pp_workgroup || !*pp_workgroup || !**pp_workgroup) {
632 workgroup = talloc_strdup(ctx, smbc_getWorkgroup(context));
633 } else {
634 workgroup = *pp_workgroup;
635 }
636 if(!workgroup) {
637 if (c != NULL) {
638 cli_shutdown(c);
639 }
640 SAFE_FREE(srv);
641 return NULL;
642 }
643
644 /* set the credentials to make DFS work */
645 smbc_set_credentials_with_fallback(context,
646 workgroup,
647 *pp_username,
648 *pp_password);
649
650 return srv;
651}
652
653SMBCSRV *
654SMBC_server(TALLOC_CTX *ctx,
655 SMBCCTX *context,
656 bool connect_if_not_found,
657 const char *server,
658 uint16_t port,
659 const char *share,
660 char **pp_workgroup,
661 char **pp_username,
662 char **pp_password)
663{
664 SMBCSRV *srv=NULL;
665 bool in_cache = false;
666
667 srv = SMBC_server_internal(ctx, context, connect_if_not_found,
668 server, port, share, pp_workgroup,
669 pp_username, pp_password, &in_cache);
670
671 if (!srv) {
672 return NULL;
673 }
674 if (in_cache) {
675 return srv;
676 }
677
678 /* Now add it to the cache (internal or external) */
679 /* Let the cache function set errno if it wants to */
680 errno = 0;
681 if (smbc_getFunctionAddCachedServer(context)(context, srv,
682 server, share,
683 *pp_workgroup,
684 *pp_username)) {
685 int saved_errno = errno;
686 DEBUG(3, (" Failed to add server to cache\n"));
687 errno = saved_errno;
688 if (errno == 0) {
689 errno = ENOMEM;
690 }
691 SAFE_FREE(srv);
692 return NULL;
693 }
694
695 DEBUG(2, ("Server connect ok: //%s/%s: %p\n",
696 server, share, srv));
697
698 DLIST_ADD(context->internal->servers, srv);
699 return srv;
700}
701
702/*
703 * Connect to a server for getting/setting attributes, possibly on an existing
704 * connection. This works similarly to SMBC_server().
705 */
706SMBCSRV *
707SMBC_attr_server(TALLOC_CTX *ctx,
708 SMBCCTX *context,
709 const char *server,
710 uint16_t port,
711 const char *share,
712 char **pp_workgroup,
713 char **pp_username,
714 char **pp_password)
715{
716 int flags;
717 struct cli_state *ipc_cli = NULL;
718 struct rpc_pipe_client *pipe_hnd = NULL;
719 NTSTATUS nt_status;
720 SMBCSRV *srv=NULL;
721 SMBCSRV *ipc_srv=NULL;
722
723 /*
724 * Use srv->cli->desthost and srv->cli->share instead of
725 * server and share below to connect to the actual share,
726 * i.e., a normal share or a referred share from
727 * 'msdfs proxy' share.
728 */
729 srv = SMBC_server(ctx, context, true, server, port, share,
730 pp_workgroup, pp_username, pp_password);
731 if (!srv) {
732 return NULL;
733 }
734 server = smbXcli_conn_remote_name(srv->cli->conn);
735 share = srv->cli->share;
736
737 /*
738 * See if we've already created this special connection. Reference
739 * our "special" share name '*IPC$', which is an impossible real share
740 * name due to the leading asterisk.
741 */
742 ipc_srv = SMBC_find_server(ctx, context, server, "*IPC$",
743 pp_workgroup, pp_username, pp_password);
744 if (!ipc_srv) {
745 int signing_state = SMB_SIGNING_DEFAULT;
746
747 /* We didn't find a cached connection. Get the password */
748 if (!*pp_password || (*pp_password)[0] == '\0') {
749 /* ... then retrieve it now. */
750 SMBC_call_auth_fn(ctx, context, server, share,
751 pp_workgroup,
752 pp_username,
753 pp_password);
754 if (!*pp_workgroup || !*pp_username || !*pp_password) {
755 errno = ENOMEM;
756 return NULL;
757 }
758 }
759
760 flags = 0;
761 if (smbc_getOptionUseKerberos(context)) {
762 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
763 }
764 if (smbc_getOptionUseCCache(context)) {
765 flags |= CLI_FULL_CONNECTION_USE_CCACHE;
766 }
767 if (context->internal->smb_encryption_level != SMBC_ENCRYPTLEVEL_NONE) {
768 signing_state = SMB_SIGNING_REQUIRED;
769 }
770
771 nt_status = cli_full_connection(&ipc_cli,
772 lp_netbios_name(), server,
773 NULL, 0, "IPC$", "?????",
774 *pp_username,
775 *pp_workgroup,
776 *pp_password,
777 flags,
778 signing_state);
779 if (! NT_STATUS_IS_OK(nt_status)) {
780 DEBUG(1,("cli_full_connection failed! (%s)\n",
781 nt_errstr(nt_status)));
782 errno = ENOTSUP;
783 return NULL;
784 }
785
786 if (context->internal->smb_encryption_level) {
787 /* Attempt UNIX smb encryption. */
788 if (!NT_STATUS_IS_OK(cli_force_encryption(ipc_cli,
789 *pp_username,
790 *pp_password,
791 *pp_workgroup))) {
792
793 /*
794 * context->smb_encryption_level ==
795 * 1 means don't fail if encryption can't be
796 * negotiated, == 2 means fail if encryption
797 * can't be negotiated.
798 */
799
800 DEBUG(4,(" SMB encrypt failed on IPC$\n"));
801
802 if (context->internal->smb_encryption_level == 2) {
803 cli_shutdown(ipc_cli);
804 errno = EPERM;
805 return NULL;
806 }
807 }
808 DEBUG(4,(" SMB encrypt ok on IPC$\n"));
809 }
810
811 ipc_srv = SMB_MALLOC_P(SMBCSRV);
812 if (!ipc_srv) {
813 errno = ENOMEM;
814 cli_shutdown(ipc_cli);
815 return NULL;
816 }
817
818 ZERO_STRUCTP(ipc_srv);
819 DLIST_ADD(ipc_srv->cli, ipc_cli);
820
821 nt_status = cli_rpc_pipe_open_noauth(
822 ipc_srv->cli, &ndr_table_lsarpc, &pipe_hnd);
823 if (!NT_STATUS_IS_OK(nt_status)) {
824 DEBUG(1, ("cli_nt_session_open fail!\n"));
825 errno = ENOTSUP;
826 cli_shutdown(ipc_srv->cli);
827 free(ipc_srv);
828 return NULL;
829 }
830
831 /*
832 * Some systems don't support
833 * SEC_FLAG_MAXIMUM_ALLOWED, but NT sends 0x2000000
834 * so we might as well do it too.
835 */
836
837 nt_status = rpccli_lsa_open_policy(
838 pipe_hnd,
839 talloc_tos(),
840 True,
841 GENERIC_EXECUTE_ACCESS,
842 &ipc_srv->pol);
843
844 if (!NT_STATUS_IS_OK(nt_status)) {
845 errno = SMBC_errno(context, ipc_srv->cli);
846 cli_shutdown(ipc_srv->cli);
847 free(ipc_srv);
848 return NULL;
849 }
850
851 /* now add it to the cache (internal or external) */
852
853 errno = 0; /* let cache function set errno if it likes */
854 if (smbc_getFunctionAddCachedServer(context)(context, ipc_srv,
855 server,
856 "*IPC$",
857 *pp_workgroup,
858 *pp_username)) {
859 DEBUG(3, (" Failed to add server to cache\n"));
860 if (errno == 0) {
861 errno = ENOMEM;
862 }
863 cli_shutdown(ipc_srv->cli);
864 free(ipc_srv);
865 return NULL;
866 }
867
868 DLIST_ADD(context->internal->servers, ipc_srv);
869 }
870
871 return ipc_srv;
872}
Note: See TracBrowser for help on using the repository browser.