s3:auth_generic: add auth_generic_client_start_by_name()
[samba.git] / source3 / libsmb / libsmb_server.c
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  */
44 int
45 SMBC_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  */
77 int
78 SMBC_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  ***************************************************************/
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)
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
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)
166 {
167         /* Default function just uses provided data.  Nothing to do. */
168 }
169
170
171
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)
180 {
181         SMBCSRV *srv;
182         int auth_called = 0;
183
184         if (!pp_workgroup || !pp_username || !pp_password) {
185                 return NULL;
186         }
187
188 check_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
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)
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
630 done:
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
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)
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  */
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)
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 }