From: Derrell Lipman Date: Wed, 22 Mar 2006 22:05:19 +0000 (+0000) Subject: r14664: r13868@cabra: derrell | 2006-03-22 17:04:30 -0500 X-Git-Tag: samba-4.0.0alpha6~801^2~8706 X-Git-Url: http://git.samba.org/samba.git/?p=ira%2Fwip.git;a=commitdiff_plain;h=e836508704dd964e22e8bfc0f8e9ec520a2c94f2 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. (This used to be commit 203b4911c16bd7e10198a6f0e63960f2813025ef) --- 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; @@ -63,6 +74,10 @@ main(int argc, char * argv[]) "noauth", 'A', POPT_ARG_NONE, &no_auth, 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/source3/include/libsmb_internal.h b/source3/include/libsmb_internal.h index 04264303288..5aca12554f3 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 6d3a0cda09d..ba92259f701 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 */ @@ -578,6 +616,41 @@ SMBCCTX * smbc_new_context(void); 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). * @@ -585,16 +658,19 @@ int smbc_free_context(SMBCCTX * context, int shutdown_ctx); * * @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 b8070283dac..2436cc9136f 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) {