summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDerrell Lipman <derrell@samba.org>2006-03-22 22:05:19 +0000
committerDerrell Lipman <derrell@samba.org>2006-03-22 22:05:19 +0000
commitd8cd752d01f93f2974862afb9510ae279c349bc9 (patch)
tree4ce5da32dfa6859c2d5643dadba191edb04f4177
parentacc814ababd0333737d76a278b77521d5f421c73 (diff)
downloadsamba-d8cd752d01f93f2974862afb9510ae279c349bc9.tar.gz
samba-d8cd752d01f93f2974862afb9510ae279c349bc9.tar.xz
samba-d8cd752d01f93f2974862afb9510ae279c349bc9.zip
r14664: r13868@cabra: derrell | 2006-03-22 17:04:30 -0500
Implement enhancement request 3505. Two additional features are added here. There is now a method of saving an opaque user data handle in the smbc_ context, and there is now a way to request that the context be passed to the authentication function. See examples/libsmbclient/testbrowse.c for an example of using these features.
-rw-r--r--examples/libsmbclient/get_auth_data_fn.h1
-rw-r--r--examples/libsmbclient/testbrowse.c51
-rw-r--r--source/include/libsmb_internal.h12
-rw-r--r--source/include/libsmbclient.h96
-rw-r--r--source/libsmb/libsmbclient.c103
5 files changed, 236 insertions, 27 deletions
diff --git a/examples/libsmbclient/get_auth_data_fn.h b/examples/libsmbclient/get_auth_data_fn.h
index 2954039f0aa..eb493885af2 100644
--- a/examples/libsmbclient/get_auth_data_fn.h
+++ b/examples/libsmbclient/get_auth_data_fn.h
@@ -7,7 +7,6 @@ get_auth_data_fn(const char * pServer,
int maxLenUsername,
char * pPassword,
int maxLenPassword)
-
{
char temp[128];
diff --git a/examples/libsmbclient/testbrowse.c b/examples/libsmbclient/testbrowse.c
index ca126c9510f..96f78aad85a 100644
--- a/examples/libsmbclient/testbrowse.c
+++ b/examples/libsmbclient/testbrowse.c
@@ -24,6 +24,16 @@ static void browse(char * path,
int indent);
+static void
+get_auth_data_with_context_fn(SMBCCTX * context,
+ const char * pServer,
+ const char * pShare,
+ char * pWorkgroup,
+ int maxLenWorkgroup,
+ char * pUsername,
+ int maxLenUsername,
+ char * pPassword,
+ int maxLenPassword);
int
main(int argc, char * argv[])
@@ -31,6 +41,7 @@ main(int argc, char * argv[])
int debug = 0;
int debug_stderr = 0;
int no_auth = 0;
+ int context_auth = 0;
int scan = 0;
int iterations = -1;
int again;
@@ -64,6 +75,10 @@ main(int argc, char * argv[])
0, "Do not request authentication data", "integer"
},
{
+ "contextauth", 'C', POPT_ARG_NONE, &context_auth,
+ 0, "Use new authentication function with context", "integer"
+ },
+ {
NULL
}
};
@@ -94,12 +109,21 @@ main(int argc, char * argv[])
/* Set mandatory options (is that a contradiction in terms?) */
context->debug = debug;
- context->callbacks.auth_fn = (no_auth ? no_auth_data_fn : get_auth_data_fn);
+ if (context_auth) {
+ context->callbacks.auth_fn = NULL;
+ smbc_option_set(context,
+ "auth_function",
+ (void *) get_auth_data_with_context_fn);
+ smbc_option_set(context, "user_data", "hello world");
+ } else {
+ context->callbacks.auth_fn =
+ (no_auth ? no_auth_data_fn : get_auth_data_fn);
+ }
/* If we've been asked to log to stderr instead of stdout... */
if (debug_stderr) {
/* ... then set the option to do so */
- smbc_option_set(context, "debug_stderr");
+ smbc_option_set(context, "debug_stderr", (void *) 1);
}
/* Initialize the context using the previously specified options */
@@ -161,6 +185,29 @@ no_auth_data_fn(const char * pServer,
return;
}
+
+static void
+get_auth_data_with_context_fn(SMBCCTX * context,
+ const char * pServer,
+ const char * pShare,
+ char * pWorkgroup,
+ int maxLenWorkgroup,
+ char * pUsername,
+ int maxLenUsername,
+ char * pPassword,
+ int maxLenPassword)
+{
+ printf("Authenticating with context 0x%lx", context);
+ if (context != NULL) {
+ char *user_data = smbc_option_get(context, "user_data");
+ printf(" with user data %s", user_data);
+ }
+ printf("\n");
+
+ get_auth_data_fn(pServer, pShare, pWorkgroup, maxLenWorkgroup,
+ pUsername, maxLenUsername, pPassword, maxLenPassword);
+}
+
static void browse(char * path, int scan, int indent)
{
char * p;
diff --git a/source/include/libsmb_internal.h b/source/include/libsmb_internal.h
index 04264303288..5aca12554f3 100644
--- a/source/include/libsmb_internal.h
+++ b/source/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/source/include/libsmbclient.h b/source/include/libsmbclient.h
index 6d3a0cda09d..ba92259f701 100644
--- a/source/include/libsmbclient.h
+++ b/source/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/source/libsmb/libsmbclient.c b/source/libsmb/libsmbclient.c
index b8070283dac..2436cc9136f 100644
--- a/source/libsmb/libsmbclient.c
+++ b/source/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) {