summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
Diffstat (limited to 'source3')
-rw-r--r--source3/include/libsmb_internal.h12
-rw-r--r--source3/include/libsmbclient.h96
-rw-r--r--source3/libsmb/libsmbclient.c103
3 files changed, 187 insertions, 24 deletions
diff --git a/source3/include/libsmb_internal.h b/source3/include/libsmb_internal.h
index 0426430328..5aca12554f 100644
--- a/source3/include/libsmb_internal.h
+++ b/source3/include/libsmb_internal.h
@@ -79,6 +79,18 @@ struct smbc_internal_data {
* Log to standard error instead of the more typical standard output
*/
BOOL _debug_stderr;
+
+ /*
+ * Authentication function which includes the context. This will be
+ * used if set; otherwise context->callbacks.auth_fn() will be used.
+ */
+ smbc_get_auth_data_with_context_fn _auth_fn_with_context;
+
+ /*
+ * An opaque (to this library) user data handle which can be set
+ * and retrieved with smbc_option_set() and smbc_option_get().
+ */
+ void * _user_data;
};
diff --git a/source3/include/libsmbclient.h b/source3/include/libsmbclient.h
index 6d3a0cda09..ba92259f70 100644
--- a/source3/include/libsmbclient.h
+++ b/source3/include/libsmbclient.h
@@ -204,7 +204,7 @@ typedef struct _SMBCCTX SMBCCTX;
/**@ingroup callback
- * Authentication callback function type.
+ * Authentication callback function type (traditional method)
*
* Type for the the authentication function called by the library to
* obtain authentication credentals
@@ -237,6 +237,43 @@ typedef void (*smbc_get_auth_data_fn)(const char *srv,
char *wg, int wglen,
char *un, int unlen,
char *pw, int pwlen);
+/**@ingroup callback
+ * Authentication callback function type (method that includes context)
+ *
+ * Type for the the authentication function called by the library to
+ * obtain authentication credentals
+ *
+ * @param c Pointer to the smb context
+ *
+ * @param srv Server being authenticated to
+ *
+ * @param shr Share being authenticated to
+ *
+ * @param wg Pointer to buffer containing a "hint" for the
+ * workgroup to be authenticated. Should be filled in
+ * with the correct workgroup if the hint is wrong.
+ *
+ * @param wglen The size of the workgroup buffer in bytes
+ *
+ * @param un Pointer to buffer containing a "hint" for the
+ * user name to be use for authentication. Should be
+ * filled in with the correct workgroup if the hint is
+ * wrong.
+ *
+ * @param unlen The size of the username buffer in bytes
+ *
+ * @param pw Pointer to buffer containing to which password
+ * copied
+ *
+ * @param pwlen The size of the password buffer in bytes
+ *
+ */
+typedef void (*smbc_get_auth_data_with_context_fn)(SMBCCTX *c,
+ const char *srv,
+ const char *shr,
+ char *wg, int wglen,
+ char *un, int unlen,
+ char *pw, int pwlen);
/**@ingroup callback
@@ -422,14 +459,15 @@ struct _SMBCCTX {
int (*unlink_print_job)(SMBCCTX *c, const char *fname, int id);
- /** Callbacks
- * These callbacks _always_ have to be initialized because they will not be checked
- * at dereference for increased speed.
- */
+ /*
+ ** Callbacks
+ * These callbacks _always_ have to be initialized because they will
+ * not be checked at dereference for increased speed.
+ */
struct _smbc_callbacks {
/** authentication function callback: called upon auth requests
*/
- smbc_get_auth_data_fn auth_fn;
+ smbc_get_auth_data_fn auth_fn;
/** check if a server is still good
*/
@@ -579,22 +617,60 @@ int smbc_free_context(SMBCCTX * context, int shutdown_ctx);
/**@ingroup misc
+ * Each time the context structure is changed, we have binary backward
+ * compatibility issues. Instead of modifying the public portions of the
+ * context structure to add new options, instead, we put them in the internal
+ * portion of the context structure and provide a set function for these new
+ * options.
+ *
+ * @param context A pointer to a SMBCCTX obtained from smbc_new_context()
+ *
+ * @param option_name
+ * The name of the option for which the value is to be set
+ *
+ * @param option_value
+ * The new value of the option being set
+ *
+ */
+void
+smbc_option_set(SMBCCTX *context,
+ char *option_name,
+ void *option_value);
+/*
+ * Retrieve the current value of an option
+ *
+ * @param context A pointer to a SMBCCTX obtained from smbc_new_context()
+ *
+ * @param option_name
+ * The name of the option for which the value is to be
+ * retrieved
+ *
+ * @return The value of the specified option.
+ */
+void *
+smbc_option_get(SMBCCTX *context,
+ char *option_name);
+
+/**@ingroup misc
* Initialize a SBMCCTX (a context).
*
* Must be called before using any SMBCCTX API function
*
* @param context A pointer to a SMBCCTX obtained from smbc_new_context()
*
- * @return A pointer to the given SMBCCTX on success, NULL on error with errno set:
+ * @return A pointer to the given SMBCCTX on success,
+ * NULL on error with errno set:
* - EBADF NULL context given
* - ENOMEM Out of memory
* - ENOENT The smb.conf file would not load
*
* @see smbc_new_context()
*
- * @note my_context = smbc_init_context(smbc_new_context()) is perfectly safe,
- * but it might leak memory on smbc_context_init() failure. Avoid this.
- * You'll have to call smbc_free_context() yourself on failure.
+ * @note my_context = smbc_init_context(smbc_new_context())
+ * is perfectly safe, but it might leak memory on
+ * smbc_context_init() failure. Avoid this.
+ * You'll have to call smbc_free_context() yourself
+ * on failure.
*/
SMBCCTX * smbc_init_context(SMBCCTX * context);
diff --git a/source3/libsmb/libsmbclient.c b/source3/libsmb/libsmbclient.c
index b8070283da..2436cc9136 100644
--- a/source3/libsmb/libsmbclient.c
+++ b/source3/libsmb/libsmbclient.c
@@ -552,10 +552,21 @@ find_server(SMBCCTX *context,
workgroup, username);
if (!auth_called && !srv && (!username[0] || !password[0])) {
- context->callbacks.auth_fn(server, share,
- workgroup, sizeof(fstring),
- username, sizeof(fstring),
- password, sizeof(fstring));
+ if (context->internal->_auth_fn_with_context != NULL) {
+ context->internal->_auth_fn_with_context(
+ context,
+ server, share,
+ workgroup, sizeof(fstring),
+ username, sizeof(fstring),
+ password, sizeof(fstring));
+ } else {
+ context->callbacks.auth_fn(
+ server, share,
+ workgroup, sizeof(fstring),
+ username, sizeof(fstring),
+ password, sizeof(fstring));
+ }
+
/*
* However, smbc_auth_fn may have picked up info relating to
* an existing connection, so try for an existing connection
@@ -657,10 +668,20 @@ smbc_server(SMBCCTX *context,
*/
if (srv->cli.cnum == (uint16) -1) {
/* Ensure we have accurate auth info */
- context->callbacks.auth_fn(server, share,
- workgroup, sizeof(fstring),
- username, sizeof(fstring),
- password, sizeof(fstring));
+ if (context->internal->_auth_fn_with_context != NULL) {
+ context->internal->_auth_fn_with_context(
+ context,
+ server, share,
+ workgroup, sizeof(fstring),
+ username, sizeof(fstring),
+ password, sizeof(fstring));
+ } else {
+ context->callbacks.auth_fn(
+ server, share,
+ workgroup, sizeof(fstring),
+ username, sizeof(fstring),
+ password, sizeof(fstring));
+ }
if (! cli_send_tconX(&srv->cli, share, "?????",
password, strlen(password)+1)) {
@@ -901,10 +922,20 @@ smbc_attr_server(SMBCCTX *context,
/* We didn't find a cached connection. Get the password */
if (*password == '\0') {
/* ... then retrieve it now. */
- context->callbacks.auth_fn(server, share,
- workgroup, sizeof(fstring),
- username, sizeof(fstring),
- password, sizeof(fstring));
+ if (context->internal->_auth_fn_with_context != NULL) {
+ context->internal->_auth_fn_with_context(
+ context,
+ server, share,
+ workgroup, sizeof(fstring),
+ username, sizeof(fstring),
+ password, sizeof(fstring));
+ } else {
+ context->callbacks.auth_fn(
+ server, share,
+ workgroup, sizeof(fstring),
+ username, sizeof(fstring),
+ password, sizeof(fstring));
+ }
}
zero_ip(&ip);
@@ -5976,8 +6007,51 @@ smbc_option_set(SMBCCTX *context,
/*
* Log to standard error instead of standard output.
*/
- context->internal->_debug_stderr = True;
+ context->internal->_debug_stderr =
+ (option_value == NULL ? False : True);
+ } else if (strcmp(option_name, "auth_function") == 0) {
+ /*
+ * Use the new-style authentication function which includes
+ * the context.
+ */
+ context->internal->_auth_fn_with_context = option_value;
+ } else if (strcmp(option_name, "user_data") == 0) {
+ /*
+ * Save a user data handle which may be retrieved by the user
+ * with smbc_option_get()
+ */
+ context->internal->_user_data = option_value;
+ }
+}
+
+
+/*
+ * Retrieve the current value of an option
+ */
+void *
+smbc_option_get(SMBCCTX *context,
+ char *option_name)
+{
+ if (strcmp(option_name, "debug_stderr") == 0) {
+ /*
+ * Log to standard error instead of standard output.
+ */
+ return (void *) context->internal->_debug_stderr;
+ } else if (strcmp(option_name, "auth_function") == 0) {
+ /*
+ * Use the new-style authentication function which includes
+ * the context.
+ */
+ return (void *) context->internal->_auth_fn_with_context;
+ } else if (strcmp(option_name, "user_data") == 0) {
+ /*
+ * Save a user data handle which may be retrieved by the user
+ * with smbc_option_get()
+ */
+ return context->internal->_user_data;
}
+
+ return NULL;
}
@@ -6006,7 +6080,8 @@ smbc_init_context(SMBCCTX *context)
return 0;
}
- if (!context->callbacks.auth_fn ||
+ if ((!context->callbacks.auth_fn &&
+ !context->internal->_auth_fn_with_context) ||
context->debug < 0 ||
context->debug > 100) {