mirror of
https://github.com/samba-team/samba.git
synced 2025-08-05 12:22:11 +03:00
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 203b4911c1
)
This commit is contained in:
committed by
Gerald (Jerry) Carter
parent
853ad11aaf
commit
e836508704
@ -7,7 +7,6 @@ get_auth_data_fn(const char * pServer,
|
||||
int maxLenUsername,
|
||||
char * pPassword,
|
||||
int maxLenPassword)
|
||||
|
||||
{
|
||||
char temp[128];
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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,11 +6007,54 @@ 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;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialise the library etc
|
||||
*
|
||||
@ -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) {
|
||||
|
||||
|
Reference in New Issue
Block a user