smbd:smb2: add a modify flag to dispatch table
[Samba.git] / source3 / libsmb / libsmb_server.c
blob06c0211fa675611a22b6aea20bbbcd7ad524ac85
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.
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.
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.
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/>.
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"
38 * Check a server for being alive and well.
39 * returns 0 if the server is in shape. Returns 1 on error
41 * Also useable outside libsmbclient to enable external cache
42 * to do some checks too.
44 int
45 SMBC_check_server(SMBCCTX * context,
46 SMBCSRV * server)
48 time_t now;
50 if (!cli_state_is_connected(server->cli)) {
51 return 1;
54 now = time_mono(NULL);
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,
62 data_blob_const(data, sizeof(data)));
63 if (!NT_STATUS_IS_OK(status)) {
64 return 1;
66 server->last_echo_time = now;
68 return 0;
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.
75 * Also useable outside libsmbclient
77 int
78 SMBC_remove_unused_server(SMBCCTX * context,
79 SMBCSRV * srv)
81 SMBCFILE * file;
83 /* are we being fooled ? */
84 if (!context || !context->internal->initialized || !srv) {
85 return 1;
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;
99 DLIST_REMOVE(context->internal->servers, srv);
101 cli_shutdown(srv->cli);
102 srv->cli = NULL;
104 DEBUG(3, ("smbc_remove_usused_server: %p removed.\n", srv));
106 smbc_getFunctionRemoveCachedServer(context)(context, srv);
108 SAFE_FREE(srv);
109 return 0;
112 /****************************************************************
113 * Call the auth_fn with fixed size (fstring) buffers.
114 ***************************************************************/
115 static void
116 SMBC_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)
124 fstring workgroup;
125 fstring username;
126 fstring password;
127 smbc_get_auth_data_with_context_fn auth_with_context_fn;
129 strlcpy(workgroup, *pp_workgroup, sizeof(workgroup));
130 strlcpy(username, *pp_username, sizeof(username));
131 strlcpy(password, *pp_password, sizeof(password));
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)
137 (* auth_with_context_fn)(context,
138 server, share,
139 workgroup, sizeof(workgroup),
140 username, sizeof(username),
141 password, sizeof(password));
143 else
145 smbc_getFunctionAuthData(context)(server, share,
146 workgroup, sizeof(workgroup),
147 username, sizeof(username),
148 password, sizeof(password));
151 TALLOC_FREE(*pp_workgroup);
152 TALLOC_FREE(*pp_username);
153 TALLOC_FREE(*pp_password);
155 *pp_workgroup = talloc_strdup(ctx, workgroup);
156 *pp_username = talloc_strdup(ctx, username);
157 *pp_password = talloc_strdup(ctx, password);
161 void
162 SMBC_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)
167 /* Default function just uses provided data. Nothing to do. */
172 SMBCSRV *
173 SMBC_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)
181 SMBCSRV *srv;
182 int auth_called = 0;
184 if (!pp_workgroup || !pp_username || !pp_password) {
185 return NULL;
188 check_server_cache:
190 srv = smbc_getFunctionGetCachedServer(context)(context,
191 server, share,
192 *pp_workgroup,
193 *pp_username);
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);
201 * However, smbc_auth_fn may have picked up info relating to
202 * an existing connection, so try for an existing connection
203 * again ...
205 auth_called = 1;
206 goto check_server_cache;
210 if (srv) {
211 if (smbc_getFunctionCheckServer(context)(context, srv)) {
213 * This server is no good anymore
214 * Try to remove it and check for more possible
215 * servers in the cache
217 if (smbc_getFunctionRemoveUnusedServer(context)(context,
218 srv)) {
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.
225 smbc_getFunctionRemoveCachedServer(context)(context,
226 srv);
230 * Maybe there are more cached connections to this
231 * server
233 goto check_server_cache;
236 return srv;
239 return NULL;
243 * Connect to a server, possibly on an existing connection
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.
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.
253 static SMBCSRV *
254 SMBC_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)
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;
278 ZERO_STRUCT(c);
279 *in_cache = false;
281 if (server[0] == 0) {
282 errno = EPERM;
283 return NULL;
286 /* Look for a cached connection */
287 srv = SMBC_find_server(ctx, context, server, share,
288 pp_workgroup, pp_username, pp_password);
291 * If we found a connection and we're only allowed one share per
292 * server...
294 if (srv &&
295 share != NULL && *share != '\0' &&
296 smbc_getOptionOneSharePerServer(context)) {
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.
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.
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);
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;
332 * We don't need to renegotiate encryption
333 * here as the encryption context is not per
334 * tid.
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;
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);
360 if (!NT_STATUS_IS_OK(status)) {
361 DEBUG(4, ("Could not retrieve "
362 "case sensitivity flag: %s.\n",
363 nt_errstr(status)));
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.
370 if (smbc_getOptionCaseSensitive(context)) {
371 cli_set_case_sensitive(c, True);
372 } else {
373 cli_set_case_sensitive(c, False);
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(
383 (fs_attrs & FILE_CASE_SENSITIVE_SEARCH
384 ? True
385 : False));
389 * Regenerate the dev value since it's based on both
390 * server and share
392 if (srv) {
393 const char *remote_name =
394 smbXcli_conn_remote_name(srv->cli->conn);
396 srv->dev = (dev_t)(str_checksum(remote_name) ^
397 str_checksum(srv->cli->share));
402 /* If we have a connection... */
403 if (srv) {
405 /* ... then we're done here. Give 'em what they came for. */
406 *in_cache = true;
407 goto done;
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;
416 if (!*pp_workgroup || !*pp_username || !*pp_password) {
417 errno = ENOMEM;
418 return NULL;
421 DEBUG(4,("SMBC_server: server_n=[%s] server=[%s]\n", server_n, server));
423 DEBUG(4,(" -> server_n=[%s] server=[%s]\n", server_n, server));
425 status = NT_STATUS_UNSUCCESSFUL;
427 if (smbc_getOptionUseKerberos(context)) {
428 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
431 if (smbc_getOptionFallbackAfterKerberos(context)) {
432 flags |= CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
435 if (smbc_getOptionUseCCache(context)) {
436 flags |= CLI_FULL_CONNECTION_USE_CCACHE;
439 if (smbc_getOptionUseNTHash(context)) {
440 flags |= CLI_FULL_CONNECTION_USE_NT_HASH;
443 if (context->internal->smb_encryption_level != SMBC_ENCRYPTLEVEL_NONE) {
444 signing_state = SMB_SIGNING_REQUIRED;
447 if (port == 0) {
448 if (share == NULL || *share == '\0' || is_ipc) {
450 * Try 139 first for IPC$
452 status = cli_connect_nb(server_n, NULL, NBT_SMB_PORT, 0x20,
453 smbc_getNetbiosName(context),
454 signing_state, flags, &c);
458 if (!NT_STATUS_IS_OK(status)) {
460 * No IPC$ or 139 did not work
462 status = cli_connect_nb(server_n, NULL, port, 0x20,
463 smbc_getNetbiosName(context),
464 signing_state, flags, &c);
467 if (!NT_STATUS_IS_OK(status)) {
468 errno = map_errno_from_nt_status(status);
469 return NULL;
472 cli_set_timeout(c, smbc_getTimeout(context));
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;
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);
488 username_used = *pp_username;
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))) {
497 /* Failed. Try an anonymous login, if allowed by flags. */
498 username_used = "";
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))) {
506 cli_shutdown(c);
507 errno = EPERM;
508 return NULL;
512 DEBUG(4,(" session setup ok\n"));
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. */
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;
538 /* must be a normal share */
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;
548 DEBUG(4,(" tconx ok\n"));
550 if (smbXcli_conn_protocol(c->conn) >= PROTOCOL_SMB2_02) {
551 tcon = c->smb2.tcon;
552 } else {
553 tcon = c->smb1.tcon;
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);
564 if (!NT_STATUS_IS_OK(status)) {
565 DEBUG(4, ("Could not retrieve case sensitivity flag: %s.\n",
566 nt_errstr(status)));
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.
573 if (smbc_getOptionCaseSensitive(context)) {
574 cli_set_case_sensitive(c, True);
575 } else {
576 cli_set_case_sensitive(c, False);
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);
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))) {
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.
599 DEBUG(4,(" SMB encrypt failed\n"));
601 if (context->internal->smb_encryption_level == 2) {
602 cli_shutdown(c);
603 errno = EPERM;
604 return NULL;
607 DEBUG(4,(" SMB encrypt ok\n"));
611 * Ok, we have got a nice connection
612 * Let's allocate a server structure.
615 srv = SMB_MALLOC_P(SMBCSRV);
616 if (!srv) {
617 cli_shutdown(c);
618 errno = ENOMEM;
619 return NULL;
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;
630 done:
631 if (!pp_workgroup || !*pp_workgroup || !**pp_workgroup) {
632 workgroup = talloc_strdup(ctx, smbc_getWorkgroup(context));
633 } else {
634 workgroup = *pp_workgroup;
636 if(!workgroup) {
637 if (c != NULL) {
638 cli_shutdown(c);
640 SAFE_FREE(srv);
641 return NULL;
644 /* set the credentials to make DFS work */
645 smbc_set_credentials_with_fallback(context,
646 workgroup,
647 *pp_username,
648 *pp_password);
650 return srv;
653 SMBCSRV *
654 SMBC_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)
664 SMBCSRV *srv=NULL;
665 bool in_cache = false;
667 srv = SMBC_server_internal(ctx, context, connect_if_not_found,
668 server, port, share, pp_workgroup,
669 pp_username, pp_password, &in_cache);
671 if (!srv) {
672 return NULL;
674 if (in_cache) {
675 return srv;
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;
691 SAFE_FREE(srv);
692 return NULL;
695 DEBUG(2, ("Server connect ok: //%s/%s: %p\n",
696 server, share, srv));
698 DLIST_ADD(context->internal->servers, srv);
699 return srv;
703 * Connect to a server for getting/setting attributes, possibly on an existing
704 * connection. This works similarly to SMBC_server().
706 SMBCSRV *
707 SMBC_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)
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;
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.
729 srv = SMBC_server(ctx, context, true, server, port, share,
730 pp_workgroup, pp_username, pp_password);
731 if (!srv) {
732 return NULL;
734 server = smbXcli_conn_remote_name(srv->cli->conn);
735 share = srv->cli->share;
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.
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;
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;
760 flags = 0;
761 if (smbc_getOptionUseKerberos(context)) {
762 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
764 if (smbc_getOptionUseCCache(context)) {
765 flags |= CLI_FULL_CONNECTION_USE_CCACHE;
767 if (context->internal->smb_encryption_level != SMBC_ENCRYPTLEVEL_NONE) {
768 signing_state = SMB_SIGNING_REQUIRED;
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;
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))) {
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.
800 DEBUG(4,(" SMB encrypt failed on IPC$\n"));
802 if (context->internal->smb_encryption_level == 2) {
803 cli_shutdown(ipc_cli);
804 errno = EPERM;
805 return NULL;
808 DEBUG(4,(" SMB encrypt ok on IPC$\n"));
811 ipc_srv = SMB_MALLOC_P(SMBCSRV);
812 if (!ipc_srv) {
813 errno = ENOMEM;
814 cli_shutdown(ipc_cli);
815 return NULL;
818 ZERO_STRUCTP(ipc_srv);
819 DLIST_ADD(ipc_srv->cli, ipc_cli);
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;
832 * Some systems don't support
833 * SEC_FLAG_MAXIMUM_ALLOWED, but NT sends 0x2000000
834 * so we might as well do it too.
837 nt_status = rpccli_lsa_open_policy(
838 pipe_hnd,
839 talloc_tos(),
840 True,
841 GENERIC_EXECUTE_ACCESS,
842 &ipc_srv->pol);
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;
851 /* now add it to the cache (internal or external) */
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;
863 cli_shutdown(ipc_srv->cli);
864 free(ipc_srv);
865 return NULL;
868 DLIST_ADD(context->internal->servers, ipc_srv);
871 return ipc_srv;