/*
* Is the logging working / configfile read ?
*/
-static int SMBC_initialized = 0;
+static bool SMBC_initialized = false;
+static unsigned int initialized_ctx_count = 0;
+static void *initialized_ctx_count_mutex = NULL;
+/*
+ * Do some module- and library-wide intializations
+ */
+static void
+SMBC_module_init(void * punused)
+{
+ bool conf_loaded = False;
+ char *home = NULL;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ load_case_tables();
+
+ setup_logging("libsmbclient", True);
+
+ /* Here we would open the smb.conf file if needed ... */
+
+ lp_set_in_client(True);
+
+ home = getenv("HOME");
+ if (home) {
+ char *conf = NULL;
+ if (asprintf(&conf, "%s/.smb/smb.conf", home) > 0) {
+ if (lp_load(conf, True, False, False, True)) {
+ conf_loaded = True;
+ } else {
+ DEBUG(5, ("Could not load config file: %s\n",
+ conf));
+ }
+ SAFE_FREE(conf);
+ }
+ }
+
+ if (!conf_loaded) {
+ /*
+ * Well, if that failed, try the get_dyn_CONFIGFILE
+ * Which points to the standard locn, and if that
+ * fails, silently ignore it and use the internal
+ * defaults ...
+ */
+
+ if (!lp_load(get_dyn_CONFIGFILE(), True, False, False, False)) {
+ DEBUG(5, ("Could not load config file: %s\n",
+ get_dyn_CONFIGFILE()));
+ } else if (home) {
+ char *conf;
+ /*
+ * We loaded the global config file. Now lets
+ * load user-specific modifications to the
+ * global config.
+ */
+ if (asprintf(&conf,
+ "%s/.smb/smb.conf.append",
+ home) > 0) {
+ if (!lp_load(conf, True, False, False, False)) {
+ DEBUG(10,
+ ("Could not append config file: "
+ "%s\n",
+ conf));
+ }
+ SAFE_FREE(conf);
+ }
+ }
+ }
+
+ load_interfaces(); /* Load the list of interfaces ... */
+
+ reopen_logs(); /* Get logging working ... */
+
+ /*
+ * Block SIGPIPE (from lib/util_sock.c: write())
+ * It is not needed and should not stop execution
+ */
+ BlockSignals(True, SIGPIPE);
+
+ /* Create the mutex we'll use to protect initialized_ctx_count */
+ if (SMB_THREAD_CREATE_MUTEX("initialized_ctx_count_mutex",
+ initialized_ctx_count_mutex) != 0) {
+ smb_panic("SMBC_module_init: "
+ "failed to create 'initialized_ctx_count' mutex");
+ }
+
+
+ TALLOC_FREE(frame);
+}
+
+
+static void
+SMBC_module_terminate(void)
+{
+ secrets_shutdown();
+ gfree_all();
+ SMBC_initialized = false;
+}
/*
{
SMBCCTX *context;
+ /* The first call to this function should initialize the module */
+ SMB_THREAD_ONCE(&SMBC_initialized, SMBC_module_init, NULL);
+
/*
* All newly added context fields should be placed in
* SMBC_internal_data, not directly in SMBCCTX.
smbc_setOptionFullTimeNames(context, False);
smbc_setOptionOpenShareMode(context, SMBC_SHAREMODE_DENY_NONE);
smbc_setOptionSmbEncryptionLevel(context, SMBC_ENCRYPTLEVEL_NONE);
+ smbc_setOptionUseCCache(context, True);
+ smbc_setOptionCaseSensitive(context, False);
smbc_setOptionBrowseMaxLmbCount(context, 3); /* # LMBs to query */
smbc_setOptionUrlEncodeReaddirEntries(context, False);
smbc_setOptionOneSharePerServer(context, False);
+ if (getenv("LIBSMBCLIENT_NO_CCACHE") == NULL) {
+ smbc_setOptionUseCCache(context, true);
+ }
smbc_setFunctionAuthData(context, SMBC_get_auth_data);
smbc_setFunctionCheckServer(context, SMBC_check_server);
smbc_setFunctionLseek(context, SMBC_lseek_ctx);
smbc_setFunctionFtruncate(context, SMBC_ftruncate_ctx);
smbc_setFunctionStat(context, SMBC_stat_ctx);
+ smbc_setFunctionStatVFS(context, SMBC_statvfs_ctx);
+ smbc_setFunctionFstatVFS(context, SMBC_fstatvfs_ctx);
smbc_setFunctionFstat(context, SMBC_fstat_ctx);
smbc_setFunctionOpendir(context, SMBC_opendir_ctx);
smbc_setFunctionClosedir(context, SMBC_closedir_ctx);
}
/* Things we have to clean up */
- free(smbc_getWorkgroup(context));
smbc_setWorkgroup(context, NULL);
-
- free(smbc_getNetbiosName(context));
smbc_setNetbiosName(context, NULL);
-
- free(smbc_getUser(context));
smbc_setUser(context, NULL);
DEBUG(3, ("Context %p successfully freed\n", context));
+
+ /* Free any DFS auth context. */
+ TALLOC_FREE(context->internal->auth_info);
+
+ SAFE_FREE(context->internal);
SAFE_FREE(context);
+
+ /* Protect access to the count of contexts in use */
+ if (SMB_THREAD_LOCK(initialized_ctx_count_mutex) != 0) {
+ smb_panic("error locking 'initialized_ctx_count'");
+ }
+
+ if (initialized_ctx_count) {
+ initialized_ctx_count--;
+ }
+
+ if (initialized_ctx_count == 0) {
+ SMBC_module_terminate();
+ }
+
+ /* Unlock the mutex */
+ if (SMB_THREAD_UNLOCK(initialized_ctx_count_mutex) != 0) {
+ smb_panic("error unlocking 'initialized_ctx_count'");
+ }
+
return 0;
}
option_value.b = (bool) va_arg(ap, int);
smbc_setOptionFallbackAfterKerberos(context, option_value.b);
+ } else if (strcmp(option_name, "use_ccache") == 0) {
+ option_value.b = (bool) va_arg(ap, int);
+ smbc_setOptionUseCCache(context, option_value.b);
+
} else if (strcmp(option_name, "no_auto_anonymous_login") == 0) {
option_value.b = (bool) va_arg(ap, int);
smbc_setOptionNoAutoAnonymousLogin(context, option_value.b);
return (void *) (bool) smbc_getOptionFallbackAfterKerberos(context);
#endif
+ } else if (strcmp(option_name, "use_ccache") == 0) {
+#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
+ return (void *) (intptr_t) smbc_getOptionUseCCache(context);
+#else
+ return (void *) (bool) smbc_getOptionUseCCache(context);
+#endif
+
} else if (strcmp(option_name, "no_auto_anonymous_login") == 0) {
#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
return (void *) (intptr_t) smbc_getOptionNoAutoAnonymousLogin(context);
smbc_init_context(SMBCCTX *context)
{
int pid;
- char *user = NULL;
- char *home = NULL;
if (!context) {
errno = EBADF;
return NULL;
}
+ if (context->internal->debug_stderr) {
+ /*
+ * Hmmm... Do we want a unique dbf per-thread? For now, we'll just
+ * leave it up to the user. If any one context spefies debug to
+ * stderr then all will be.
+ */
+ dbf = x_stderr;
+ x_setbuf(x_stderr, NULL);
+ }
+
if ((!smbc_getFunctionAuthData(context) &&
!smbc_getFunctionAuthDataWithContext(context)) ||
smbc_getDebug(context) < 0 ||
}
- if (!SMBC_initialized) {
- /*
- * Do some library-wide intializations the first time we get
- * called
- */
- bool conf_loaded = False;
- TALLOC_CTX *frame = talloc_stackframe();
-
- load_case_tables();
-
- setup_logging("libsmbclient", True);
- if (context->internal->debug_stderr) {
- dbf = x_stderr;
- x_setbuf(x_stderr, NULL);
- }
-
- /* Here we would open the smb.conf file if needed ... */
-
- lp_set_in_client(True);
-
- home = getenv("HOME");
- if (home) {
- char *conf = NULL;
- if (asprintf(&conf, "%s/.smb/smb.conf", home) > 0) {
- if (lp_load(conf, True, False, False, True)) {
- conf_loaded = True;
- } else {
- DEBUG(5, ("Could not load config file: %s\n",
- conf));
- }
- SAFE_FREE(conf);
- }
- }
-
- if (!conf_loaded) {
- /*
- * Well, if that failed, try the get_dyn_CONFIGFILE
- * Which points to the standard locn, and if that
- * fails, silently ignore it and use the internal
- * defaults ...
- */
-
- if (!lp_load(get_dyn_CONFIGFILE(), True, False, False, False)) {
- DEBUG(5, ("Could not load config file: %s\n",
- get_dyn_CONFIGFILE()));
- } else if (home) {
- char *conf;
- /*
- * We loaded the global config file. Now lets
- * load user-specific modifications to the
- * global config.
- */
- if (asprintf(&conf,
- "%s/.smb/smb.conf.append",
- home) > 0) {
- if (!lp_load(conf, True, False, False, False)) {
- DEBUG(10,
- ("Could not append config file: "
- "%s\n",
- conf));
- }
- SAFE_FREE(conf);
- }
- }
- }
-
- load_interfaces(); /* Load the list of interfaces ... */
-
- reopen_logs(); /* Get logging working ... */
-
- /*
- * Block SIGPIPE (from lib/util_sock.c: write())
- * It is not needed and should not stop execution
- */
- BlockSignals(True, SIGPIPE);
-
- /* Done with one-time initialisation */
- SMBC_initialized = 1;
-
- TALLOC_FREE(frame);
- }
-
if (!smbc_getUser(context)) {
/*
* FIXME: Is this the best way to get the user info?
*/
- user = getenv("USER");
+ char *user = getenv("USER");
/* walk around as "guest" if no username can be found */
if (!user) {
user = SMB_STRDUP("guest");
}
smbc_setUser(context, user);
+ SAFE_FREE(user);
+
+ if (!smbc_getUser(context)) {
+ errno = ENOMEM;
+ return NULL;
+ }
}
if (!smbc_getNetbiosName(context)) {
}
smbc_setNetbiosName(context, netbios_name);
+ SAFE_FREE(netbios_name);
+
+ if (!smbc_getNetbiosName(context)) {
+ errno = ENOMEM;
+ return NULL;
+ }
}
DEBUG(1, ("Using netbios name %s.\n", smbc_getNetbiosName(context)));
}
smbc_setWorkgroup(context, workgroup);
+ SAFE_FREE(workgroup);
+
+ if (!smbc_getWorkgroup(context)) {
+ errno = ENOMEM;
+ return NULL;
+ }
}
DEBUG(1, ("Using workgroup %s.\n", smbc_getWorkgroup(context)));
if (smbc_getTimeout(context) > 0 && smbc_getTimeout(context) < 1000)
smbc_setTimeout(context, 1000);
- /*
- * FIXME: Should we check the function pointers here?
- */
-
context->internal->initialized = True;
+
+ /* Protect access to the count of contexts in use */
+ if (SMB_THREAD_LOCK(initialized_ctx_count_mutex) != 0) {
+ smb_panic("error locking 'initialized_ctx_count'");
+ }
+
+ initialized_ctx_count++;
+
+ /* Unlock the mutex */
+ if (SMB_THREAD_UNLOCK(initialized_ctx_count_mutex) != 0) {
+ smb_panic("error unlocking 'initialized_ctx_count'");
+ }
return context;
}
return samba_version_string();
}
+/*
+ * Set the credentials so DFS will work when following referrals.
+ * This function is broken and must be removed. No SMBCCTX arg...
+ * JRA.
+ */
+
+void
+smbc_set_credentials(const char *workgroup,
+ const char *user,
+ const char *password,
+ smbc_bool use_kerberos,
+ const char *signing_state)
+{
+ d_printf("smbc_set_credentials is obsolete. Replace with smbc_set_credentials_with_fallback().\n");
+}
+
+void smbc_set_credentials_with_fallback(SMBCCTX *context,
+ const char *workgroup,
+ const char *user,
+ const char *password)
+{
+ smbc_bool use_kerberos = false;
+ const char *signing_state = "off";
+ struct user_auth_info *auth_info = NULL;
+
+ if (! context) {
+ return;
+ }
+
+ if (! workgroup || ! *workgroup) {
+ workgroup = smbc_getWorkgroup(context);
+ }
+
+ if (! user) {
+ user = smbc_getUser(context);
+ }
+
+ if (! password) {
+ password = "";
+ }
+
+ auth_info = user_auth_info_init(NULL);
+
+ if (! auth_info) {
+ DEBUG(0, ("smbc_set_credentials_with_fallback: allocation fail\n"));
+ return;
+ }
+
+ if (smbc_getOptionUseKerberos(context)) {
+ use_kerberos = True;
+ }
+
+ if (lp_client_signing()) {
+ signing_state = "on";
+ }
+
+ if (lp_client_signing() == Required) {
+ signing_state = "force";
+ }
+
+ set_cmdline_auth_info_username(auth_info, user);
+ set_cmdline_auth_info_password(auth_info, password);
+ set_cmdline_auth_info_use_kerberos(auth_info, use_kerberos);
+ set_cmdline_auth_info_signing_state(auth_info, signing_state);
+ set_cmdline_auth_info_fallback_after_kerberos(auth_info,
+ smbc_getOptionFallbackAfterKerberos(context));
+ set_cmdline_auth_info_use_ccache(
+ auth_info, smbc_getOptionUseCCache(context));
+ set_global_myworkgroup(workgroup);
+
+ TALLOC_FREE(context->internal->auth_info);
+
+ context->internal->auth_info = auth_info;
+}