mirror of
https://github.com/samba-team/samba.git
synced 2025-11-25 00:23:52 +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 commit is contained in:
committed by
Gerald (Jerry) Carter
parent
07a70f8f86
commit
203b4911c1
@@ -7,7 +7,6 @@ get_auth_data_fn(const char * pServer,
|
|||||||
int maxLenUsername,
|
int maxLenUsername,
|
||||||
char * pPassword,
|
char * pPassword,
|
||||||
int maxLenPassword)
|
int maxLenPassword)
|
||||||
|
|
||||||
{
|
{
|
||||||
char temp[128];
|
char temp[128];
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,16 @@ static void browse(char * path,
|
|||||||
int indent);
|
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
|
int
|
||||||
main(int argc, char * argv[])
|
main(int argc, char * argv[])
|
||||||
@@ -31,6 +41,7 @@ main(int argc, char * argv[])
|
|||||||
int debug = 0;
|
int debug = 0;
|
||||||
int debug_stderr = 0;
|
int debug_stderr = 0;
|
||||||
int no_auth = 0;
|
int no_auth = 0;
|
||||||
|
int context_auth = 0;
|
||||||
int scan = 0;
|
int scan = 0;
|
||||||
int iterations = -1;
|
int iterations = -1;
|
||||||
int again;
|
int again;
|
||||||
@@ -63,6 +74,10 @@ main(int argc, char * argv[])
|
|||||||
"noauth", 'A', POPT_ARG_NONE, &no_auth,
|
"noauth", 'A', POPT_ARG_NONE, &no_auth,
|
||||||
0, "Do not request authentication data", "integer"
|
0, "Do not request authentication data", "integer"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"contextauth", 'C', POPT_ARG_NONE, &context_auth,
|
||||||
|
0, "Use new authentication function with context", "integer"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
NULL
|
NULL
|
||||||
}
|
}
|
||||||
@@ -94,12 +109,21 @@ main(int argc, char * argv[])
|
|||||||
|
|
||||||
/* Set mandatory options (is that a contradiction in terms?) */
|
/* Set mandatory options (is that a contradiction in terms?) */
|
||||||
context->debug = debug;
|
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 we've been asked to log to stderr instead of stdout... */
|
||||||
if (debug_stderr) {
|
if (debug_stderr) {
|
||||||
/* ... then set the option to do so */
|
/* ... 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 */
|
/* Initialize the context using the previously specified options */
|
||||||
@@ -161,6 +185,29 @@ no_auth_data_fn(const char * pServer,
|
|||||||
return;
|
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)
|
static void browse(char * path, int scan, int indent)
|
||||||
{
|
{
|
||||||
char * p;
|
char * p;
|
||||||
|
|||||||
@@ -79,6 +79,18 @@ struct smbc_internal_data {
|
|||||||
* Log to standard error instead of the more typical standard output
|
* Log to standard error instead of the more typical standard output
|
||||||
*/
|
*/
|
||||||
BOOL _debug_stderr;
|
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
|
/**@ingroup callback
|
||||||
* Authentication callback function type.
|
* Authentication callback function type (traditional method)
|
||||||
*
|
*
|
||||||
* Type for the the authentication function called by the library to
|
* Type for the the authentication function called by the library to
|
||||||
* obtain authentication credentals
|
* obtain authentication credentals
|
||||||
@@ -237,6 +237,43 @@ typedef void (*smbc_get_auth_data_fn)(const char *srv,
|
|||||||
char *wg, int wglen,
|
char *wg, int wglen,
|
||||||
char *un, int unlen,
|
char *un, int unlen,
|
||||||
char *pw, int pwlen);
|
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
|
/**@ingroup callback
|
||||||
@@ -422,9 +459,10 @@ struct _SMBCCTX {
|
|||||||
int (*unlink_print_job)(SMBCCTX *c, const char *fname, int id);
|
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
|
** Callbacks
|
||||||
* at dereference for increased speed.
|
* These callbacks _always_ have to be initialized because they will
|
||||||
|
* not be checked at dereference for increased speed.
|
||||||
*/
|
*/
|
||||||
struct _smbc_callbacks {
|
struct _smbc_callbacks {
|
||||||
/** authentication function callback: called upon auth requests
|
/** authentication function callback: called upon auth requests
|
||||||
@@ -578,6 +616,41 @@ SMBCCTX * smbc_new_context(void);
|
|||||||
int smbc_free_context(SMBCCTX * context, int shutdown_ctx);
|
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
|
/**@ingroup misc
|
||||||
* Initialize a SBMCCTX (a context).
|
* 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()
|
* @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
|
* - EBADF NULL context given
|
||||||
* - ENOMEM Out of memory
|
* - ENOMEM Out of memory
|
||||||
* - ENOENT The smb.conf file would not load
|
* - ENOENT The smb.conf file would not load
|
||||||
*
|
*
|
||||||
* @see smbc_new_context()
|
* @see smbc_new_context()
|
||||||
*
|
*
|
||||||
* @note my_context = smbc_init_context(smbc_new_context()) is perfectly safe,
|
* @note my_context = smbc_init_context(smbc_new_context())
|
||||||
* but it might leak memory on smbc_context_init() failure. Avoid this.
|
* is perfectly safe, but it might leak memory on
|
||||||
* You'll have to call smbc_free_context() yourself on failure.
|
* smbc_context_init() failure. Avoid this.
|
||||||
|
* You'll have to call smbc_free_context() yourself
|
||||||
|
* on failure.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SMBCCTX * smbc_init_context(SMBCCTX * context);
|
SMBCCTX * smbc_init_context(SMBCCTX * context);
|
||||||
|
|||||||
@@ -552,10 +552,21 @@ find_server(SMBCCTX *context,
|
|||||||
workgroup, username);
|
workgroup, username);
|
||||||
|
|
||||||
if (!auth_called && !srv && (!username[0] || !password[0])) {
|
if (!auth_called && !srv && (!username[0] || !password[0])) {
|
||||||
context->callbacks.auth_fn(server, share,
|
if (context->internal->_auth_fn_with_context != NULL) {
|
||||||
|
context->internal->_auth_fn_with_context(
|
||||||
|
context,
|
||||||
|
server, share,
|
||||||
workgroup, sizeof(fstring),
|
workgroup, sizeof(fstring),
|
||||||
username, sizeof(fstring),
|
username, sizeof(fstring),
|
||||||
password, 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
|
* However, smbc_auth_fn may have picked up info relating to
|
||||||
* an existing connection, so try for an existing connection
|
* an existing connection, so try for an existing connection
|
||||||
@@ -657,10 +668,20 @@ smbc_server(SMBCCTX *context,
|
|||||||
*/
|
*/
|
||||||
if (srv->cli.cnum == (uint16) -1) {
|
if (srv->cli.cnum == (uint16) -1) {
|
||||||
/* Ensure we have accurate auth info */
|
/* Ensure we have accurate auth info */
|
||||||
context->callbacks.auth_fn(server, share,
|
if (context->internal->_auth_fn_with_context != NULL) {
|
||||||
|
context->internal->_auth_fn_with_context(
|
||||||
|
context,
|
||||||
|
server, share,
|
||||||
workgroup, sizeof(fstring),
|
workgroup, sizeof(fstring),
|
||||||
username, sizeof(fstring),
|
username, sizeof(fstring),
|
||||||
password, 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, "?????",
|
if (! cli_send_tconX(&srv->cli, share, "?????",
|
||||||
password, strlen(password)+1)) {
|
password, strlen(password)+1)) {
|
||||||
@@ -901,10 +922,20 @@ smbc_attr_server(SMBCCTX *context,
|
|||||||
/* We didn't find a cached connection. Get the password */
|
/* We didn't find a cached connection. Get the password */
|
||||||
if (*password == '\0') {
|
if (*password == '\0') {
|
||||||
/* ... then retrieve it now. */
|
/* ... then retrieve it now. */
|
||||||
context->callbacks.auth_fn(server, share,
|
if (context->internal->_auth_fn_with_context != NULL) {
|
||||||
|
context->internal->_auth_fn_with_context(
|
||||||
|
context,
|
||||||
|
server, share,
|
||||||
workgroup, sizeof(fstring),
|
workgroup, sizeof(fstring),
|
||||||
username, sizeof(fstring),
|
username, sizeof(fstring),
|
||||||
password, sizeof(fstring));
|
password, sizeof(fstring));
|
||||||
|
} else {
|
||||||
|
context->callbacks.auth_fn(
|
||||||
|
server, share,
|
||||||
|
workgroup, sizeof(fstring),
|
||||||
|
username, sizeof(fstring),
|
||||||
|
password, sizeof(fstring));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
zero_ip(&ip);
|
zero_ip(&ip);
|
||||||
@@ -5976,11 +6007,54 @@ smbc_option_set(SMBCCTX *context,
|
|||||||
/*
|
/*
|
||||||
* Log to standard error instead of standard output.
|
* 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
|
* Initialise the library etc
|
||||||
*
|
*
|
||||||
@@ -6006,7 +6080,8 @@ smbc_init_context(SMBCCTX *context)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!context->callbacks.auth_fn ||
|
if ((!context->callbacks.auth_fn &&
|
||||||
|
!context->internal->_auth_fn_with_context) ||
|
||||||
context->debug < 0 ||
|
context->debug < 0 ||
|
||||||
context->debug > 100) {
|
context->debug > 100) {
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user