diff options
Diffstat (limited to 'source4/auth/credentials')
-rw-r--r-- | source4/auth/credentials/config.mk | 16 | ||||
-rw-r--r-- | source4/auth/credentials/credentials.c | 42 | ||||
-rw-r--r-- | source4/auth/credentials/credentials.h | 25 | ||||
-rw-r--r-- | source4/auth/credentials/credentials.i | 33 | ||||
-rw-r--r-- | source4/auth/credentials/credentials.py | 93 | ||||
-rw-r--r-- | source4/auth/credentials/credentials_files.c | 14 | ||||
-rw-r--r-- | source4/auth/credentials/credentials_krb5.c | 35 | ||||
-rw-r--r-- | source4/auth/credentials/credentials_krb5.h | 1 | ||||
-rw-r--r-- | source4/auth/credentials/credentials_ntlm.c | 52 | ||||
-rw-r--r-- | source4/auth/credentials/credentials_wrap.c | 140 | ||||
-rw-r--r-- | source4/auth/credentials/tests/bindings.py | 2 |
11 files changed, 340 insertions, 113 deletions
diff --git a/source4/auth/credentials/config.mk b/source4/auth/credentials/config.mk index 6f3ec3997c..2eeeec20ec 100644 --- a/source4/auth/credentials/config.mk +++ b/source4/auth/credentials/config.mk @@ -1,18 +1,24 @@ ################################# # Start SUBSYSTEM CREDENTIALS [SUBSYSTEM::CREDENTIALS] -PRIVATE_PROTO_HEADER = credentials_proto.h PUBLIC_DEPENDENCIES = \ LIBCLI_AUTH SECRETS LIBCRYPTO KERBEROS UTIL_LDB HEIMDAL_GSSAPI PRIVATE_DEPENDENCIES = \ SECRETS -CREDENTIALS_OBJ_FILES = $(addprefix auth/credentials/, credentials.o credentials_files.o credentials_ntlm.o credentials_krb5.o ../kerberos/kerberos_util.o) -PUBLIC_HEADERS += auth/credentials/credentials.h +CREDENTIALS_OBJ_FILES = $(addprefix $(authsrcdir)/credentials/, credentials.o credentials_files.o credentials_ntlm.o credentials_krb5.o ../kerberos/kerberos_util.o) + +$(eval $(call proto_header_template,$(authsrcdir)/credentials/credentials_proto.h,$(CREDENTIALS_OBJ_FILES:.o=.c))) + +PUBLIC_HEADERS += $(authsrcdir)/credentials/credentials.h [PYTHON::swig_credentials] +LIBRARY_REALNAME = samba/_credentials.$(SHLIBEXT) PUBLIC_DEPENDENCIES = CREDENTIALS LIBCMDLINE_CREDENTIALS -SWIG_FILE = credentials.i -swig_credentials_OBJ_FILES = auth/credentials/credentials_wrap.o +$(eval $(call python_py_module_template,samba/credentials.py,$(authsrcdir)/credentials/credentials.py)) + +swig_credentials_OBJ_FILES = $(authsrcdir)/credentials/credentials_wrap.o + +$(swig_credentials_OBJ_FILES): CFLAGS+=$(CFLAG_NO_UNUSED_MACROS) $(CFLAG_NO_CAST_QUAL) diff --git a/source4/auth/credentials/credentials.c b/source4/auth/credentials/credentials.c index 89dddc9e05..adabe49cb4 100644 --- a/source4/auth/credentials/credentials.c +++ b/source4/auth/credentials/credentials.c @@ -65,7 +65,6 @@ _PUBLIC_ struct cli_credentials *cli_credentials_init(TALLOC_CTX *mem_ctx) cred->tries = 3; cred->callback_running = false; - cred->ev = NULL; cli_credentials_set_kerberos_state(cred, CRED_AUTO_USE_KERBEROS); cli_credentials_set_gensec_features(cred, 0); @@ -307,6 +306,8 @@ _PUBLIC_ bool cli_credentials_set_password(struct cli_credentials *cred, cli_credentials_invalidate_ccache(cred, cred->password_obtained); cred->nt_hash = NULL; + cred->lm_response = data_blob(NULL, 0); + cred->nt_response = data_blob(NULL, 0); return true; } @@ -377,24 +378,6 @@ _PUBLIC_ const struct samr_Password *cli_credentials_get_nt_hash(struct cli_cred } } -_PUBLIC_ bool cli_credentials_set_nt_hash(struct cli_credentials *cred, - const struct samr_Password *nt_hash, - enum credentials_obtained obtained) -{ - if (obtained >= cred->password_obtained) { - cli_credentials_set_password(cred, NULL, obtained); - if (nt_hash) { - cred->nt_hash = talloc(cred, struct samr_Password); - *cred->nt_hash = *nt_hash; - } else { - cred->nt_hash = NULL; - } - return true; - } - - return false; -} - /** * Obtain the 'short' or 'NetBIOS' domain for this credentials context. * @param cred credentials context @@ -675,7 +658,7 @@ _PUBLIC_ void cli_credentials_guess(struct cli_credentials *cred, } if (cli_credentials_get_kerberos_state(cred) != CRED_DONT_USE_KERBEROS) { - cli_credentials_set_ccache(cred, lp_ctx, NULL, CRED_GUESS_FILE); + cli_credentials_set_ccache(cred, event_context_find(cred), lp_ctx, NULL, CRED_GUESS_FILE); } } @@ -775,22 +758,3 @@ _PUBLIC_ bool cli_credentials_wrong_password(struct cli_credentials *cred) return (cred->tries > 0); } - -/* - set the common event context for this set of credentials - */ -_PUBLIC_ void cli_credentials_set_event_context(struct cli_credentials *cred, struct event_context *ev) -{ - cred->ev = ev; -} - -/* - set the common event context for this set of credentials - */ -_PUBLIC_ struct event_context *cli_credentials_get_event_context(struct cli_credentials *cred) -{ - if (cred->ev == NULL) { - cred->ev = event_context_find(cred); - } - return cred->ev; -} diff --git a/source4/auth/credentials/credentials.h b/source4/auth/credentials/credentials.h index afcb300638..79c50ae5af 100644 --- a/source4/auth/credentials/credentials.h +++ b/source4/auth/credentials/credentials.h @@ -26,6 +26,7 @@ #include "librpc/gen_ndr/misc.h" struct ccache_container; +struct event_context; /* In order of priority */ enum credentials_obtained { @@ -79,8 +80,13 @@ struct cli_credentials { const char *bind_dn; + /* Allows authentication from a keytab or similar */ struct samr_Password *nt_hash; + /* Allows NTLM pass-though authentication */ + DATA_BLOB lm_response; + DATA_BLOB nt_response; + struct ccache_container *ccache; struct gssapi_creds_container *client_gss_creds; struct keytab_container *keytab; @@ -121,9 +127,6 @@ struct cli_credentials { /* Whether any callback is currently running */ bool callback_running; - - /* an event context for anyone wanting to use the credentials */ - struct event_context *ev; }; struct ldb_context; @@ -152,12 +155,15 @@ NTSTATUS cli_credentials_get_ntlm_response(struct cli_credentials *cred, TALLOC_ const char *cli_credentials_get_realm(struct cli_credentials *cred); const char *cli_credentials_get_username(struct cli_credentials *cred); int cli_credentials_get_krb5_context(struct cli_credentials *cred, + struct event_context *event_ctx, struct loadparm_context *lp_ctx, struct smb_krb5_context **smb_krb5_context); int cli_credentials_get_ccache(struct cli_credentials *cred, + struct event_context *event_ctx, struct loadparm_context *lp_ctx, struct ccache_container **ccc); int cli_credentials_get_keytab(struct cli_credentials *cred, + struct event_context *event_ctx, struct loadparm_context *lp_ctx, struct keytab_container **_ktc); const char *cli_credentials_get_domain(struct cli_credentials *cred); @@ -168,15 +174,15 @@ void cli_credentials_set_conf(struct cli_credentials *cred, struct loadparm_context *lp_ctx); const char *cli_credentials_get_principal(struct cli_credentials *cred, TALLOC_CTX *mem_ctx); int cli_credentials_get_server_gss_creds(struct cli_credentials *cred, + struct event_context *event_ctx, struct loadparm_context *lp_ctx, struct gssapi_creds_container **_gcc); int cli_credentials_get_client_gss_creds(struct cli_credentials *cred, + struct event_context *event_ctx, struct loadparm_context *lp_ctx, struct gssapi_creds_container **_gcc); -void cli_credentials_set_event_context(struct cli_credentials *cred, struct event_context *ev); void cli_credentials_set_kerberos_state(struct cli_credentials *creds, enum credentials_use_kerberos use_kerberos); -struct event_context *cli_credentials_get_event_context(struct cli_credentials *cred); bool cli_credentials_set_domain(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained); @@ -199,6 +205,7 @@ void cli_credentials_set_netlogon_creds(struct cli_credentials *cred, NTSTATUS cli_credentials_set_krb5_context(struct cli_credentials *cred, struct smb_krb5_context *smb_krb5_context); NTSTATUS cli_credentials_set_stored_principal(struct cli_credentials *cred, + struct event_context *event_ctx, struct loadparm_context *lp_ctx, const char *serviceprincipal); NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred, @@ -219,15 +226,22 @@ void cli_credentials_set_kvno(struct cli_credentials *cred, bool cli_credentials_set_nt_hash(struct cli_credentials *cred, const struct samr_Password *nt_hash, enum credentials_obtained obtained); +bool cli_credentials_set_ntlm_response(struct cli_credentials *cred, + const DATA_BLOB *lm_response, + const DATA_BLOB *nt_response, + enum credentials_obtained obtained); int cli_credentials_set_keytab_name(struct cli_credentials *cred, + struct event_context *event_ctx, struct loadparm_context *lp_ctx, const char *keytab_name, enum credentials_obtained obtained); int cli_credentials_update_keytab(struct cli_credentials *cred, + struct event_context *event_ctx, struct loadparm_context *lp_ctx); void cli_credentials_set_gensec_features(struct cli_credentials *creds, uint32_t gensec_features); uint32_t cli_credentials_get_gensec_features(struct cli_credentials *creds); int cli_credentials_set_ccache(struct cli_credentials *cred, + struct event_context *event_ctx, struct loadparm_context *lp_ctx, const char *name, enum credentials_obtained obtained); @@ -239,6 +253,7 @@ void cli_credentials_invalidate_ccache(struct cli_credentials *cred, void cli_credentials_set_salt_principal(struct cli_credentials *cred, const char *principal); enum credentials_use_kerberos cli_credentials_get_kerberos_state(struct cli_credentials *creds); NTSTATUS cli_credentials_set_secrets(struct cli_credentials *cred, + struct event_context *event_ctx, struct loadparm_context *lp_ctx, struct ldb_context *ldb, const char *base, diff --git a/source4/auth/credentials/credentials.i b/source4/auth/credentials/credentials.i index 152d2e673c..89eb4924b3 100644 --- a/source4/auth/credentials/credentials.i +++ b/source4/auth/credentials/credentials.i @@ -59,36 +59,53 @@ typedef struct cli_credentials { return cli_credentials_init(NULL); } /* username */ + %feature("docstring") get_username "S.get_username() -> username\nObtain username."; const char *get_username(void); + %feature("docstring") set_username "S.set_username(name, obtained=CRED_SPECIFIED) -> None\nChange username."; bool set_username(const char *value, - enum credentials_obtained=CRED_SPECIFIED); + enum credentials_obtained obtained=CRED_SPECIFIED); /* password */ + %feature("docstring") get_password "S.get_password() -> password\n" \ + "Obtain password."; const char *get_password(void); + %feature("docstring") set_password "S.set_password(password, obtained=CRED_SPECIFIED) -> None\n" \ + "Change password."; bool set_password(const char *val, - enum credentials_obtained=CRED_SPECIFIED); + enum credentials_obtained obtained=CRED_SPECIFIED); /* domain */ + %feature("docstring") get_password "S.get_domain() -> domain\nObtain domain name."; const char *get_domain(void); + %feature("docstring") set_domain "S.set_domain(domain, obtained=CRED_SPECIFIED) -> None\n" \ + "Change domain name."; bool set_domain(const char *val, - enum credentials_obtained=CRED_SPECIFIED); + enum credentials_obtained obtained=CRED_SPECIFIED); /* realm */ + %feature("docstring") get_realm "S.get_realm() -> realm\nObtain realm name."; const char *get_realm(void); + %feature("docstring") set_realm "S.set_realm(realm, obtained=CRED_SPECIFIED) -> None\n" \ + "Change realm name."; bool set_realm(const char *val, - enum credentials_obtained=CRED_SPECIFIED); + enum credentials_obtained obtained=CRED_SPECIFIED); - /* Kerberos */ + /* Kerberos */ void set_kerberos_state(enum credentials_use_kerberos use_kerberos); + %feature("docstring") parse_string "S.parse_string(text, obtained=CRED_SPECIFIED) -> None\n" \ + "Parse credentials string."; void parse_string(const char *text, - enum credentials_obtained=CRED_SPECIFIED); + enum credentials_obtained obtained=CRED_SPECIFIED); /* bind dn */ + %feature("docstring") get_bind_dn "S.get_bind_dn() -> bind dn\nObtain bind DN."; const char *get_bind_dn(void); + %feature("docstring") set_bind_dn "S.set_bind_dn(bind_dn) -> None\nChange bind DN."; bool set_bind_dn(const char *bind_dn); - void set_anonymous(); + %feature("docstring") set_anonymous "S.set_anonymous() -> None\nUse anonymous credentials."; + void set_anonymous(); /* workstation name */ const char *get_workstation(void); @@ -104,8 +121,10 @@ typedef struct cli_credentials { bool authentication_requested(void); + %feature("docstring") wrong_password "S.wrong_password() -> bool\nIndicate the returned password was incorrect."; bool wrong_password(void); + %feature("docstring") set_cmdline_callbacks "S.set_cmdline_callbacks() -> bool\nUse command-line to obtain credentials not explicitly set."; bool set_cmdline_callbacks(); } } cli_credentials; diff --git a/source4/auth/credentials/credentials.py b/source4/auth/credentials/credentials.py index ba0000dcda..fd00a8e6f0 100644 --- a/source4/auth/credentials/credentials.py +++ b/source4/auth/credentials/credentials.py @@ -1,5 +1,5 @@ # This file was automatically generated by SWIG (http://www.swig.org). -# Version 1.3.33 +# Version 1.3.35 # # Don't modify this file, modify the SWIG interface instead. @@ -66,6 +66,97 @@ class Credentials(object): __repr__ = _swig_repr def __init__(self, *args, **kwargs): _credentials.Credentials_swiginit(self,_credentials.new_Credentials(*args, **kwargs)) + def get_username(*args, **kwargs): + """ + S.get_username() -> username + Obtain username. + """ + return _credentials.Credentials_get_username(*args, **kwargs) + + def set_username(*args, **kwargs): + """ + S.set_username(name, obtained=CRED_SPECIFIED) -> None + Change username. + """ + return _credentials.Credentials_set_username(*args, **kwargs) + + def get_password(*args, **kwargs): + """ + S.get_password() -> password + Obtain password. + """ + return _credentials.Credentials_get_password(*args, **kwargs) + + def set_password(*args, **kwargs): + """ + S.set_password(password, obtained=CRED_SPECIFIED) -> None + Change password. + """ + return _credentials.Credentials_set_password(*args, **kwargs) + + def set_domain(*args, **kwargs): + """ + S.set_domain(domain, obtained=CRED_SPECIFIED) -> None + Change domain name. + """ + return _credentials.Credentials_set_domain(*args, **kwargs) + + def get_realm(*args, **kwargs): + """ + S.get_realm() -> realm + Obtain realm name. + """ + return _credentials.Credentials_get_realm(*args, **kwargs) + + def set_realm(*args, **kwargs): + """ + S.set_realm(realm, obtained=CRED_SPECIFIED) -> None + Change realm name. + """ + return _credentials.Credentials_set_realm(*args, **kwargs) + + def parse_string(*args, **kwargs): + """ + S.parse_string(text, obtained=CRED_SPECIFIED) -> None + Parse credentials string. + """ + return _credentials.Credentials_parse_string(*args, **kwargs) + + def get_bind_dn(*args, **kwargs): + """ + S.get_bind_dn() -> bind dn + Obtain bind DN. + """ + return _credentials.Credentials_get_bind_dn(*args, **kwargs) + + def set_bind_dn(*args, **kwargs): + """ + S.set_bind_dn(bind_dn) -> None + Change bind DN. + """ + return _credentials.Credentials_set_bind_dn(*args, **kwargs) + + def set_anonymous(*args, **kwargs): + """ + S.set_anonymous() -> None + Use anonymous credentials. + """ + return _credentials.Credentials_set_anonymous(*args, **kwargs) + + def wrong_password(*args, **kwargs): + """ + S.wrong_password() -> bool + Indicate the returned password was incorrect. + """ + return _credentials.Credentials_wrong_password(*args, **kwargs) + + def set_cmdline_callbacks(*args, **kwargs): + """ + S.set_cmdline_callbacks() -> bool + Use command-line to obtain credentials not explicitly set. + """ + return _credentials.Credentials_set_cmdline_callbacks(*args, **kwargs) + __swig_destroy__ = _credentials.delete_Credentials Credentials.get_username = new_instancemethod(_credentials.Credentials_get_username,None,Credentials) Credentials.set_username = new_instancemethod(_credentials.Credentials_set_username,None,Credentials) diff --git a/source4/auth/credentials/credentials_files.c b/source4/auth/credentials/credentials_files.c index 1bbdf8a5ad..ab76ea2cde 100644 --- a/source4/auth/credentials/credentials_files.c +++ b/source4/auth/credentials/credentials_files.c @@ -30,6 +30,7 @@ #include "auth/credentials/credentials.h" #include "auth/credentials/credentials_krb5.h" #include "param/param.h" +#include "lib/events/events.h" /** * Read a file descriptor, and parse it for a password (eg from a file or stdin) @@ -169,6 +170,7 @@ _PUBLIC_ bool cli_credentials_parse_file(struct cli_credentials *cred, const cha * @retval NTSTATUS error detailing any failure */ _PUBLIC_ NTSTATUS cli_credentials_set_secrets(struct cli_credentials *cred, + struct event_context *event_ctx, struct loadparm_context *lp_ctx, struct ldb_context *ldb, const char *base, @@ -305,13 +307,13 @@ _PUBLIC_ NTSTATUS cli_credentials_set_secrets(struct cli_credentials *cred, * (chewing CPU time) from the password */ keytab = ldb_msg_find_attr_as_string(msgs[0], "krb5Keytab", NULL); if (keytab) { - cli_credentials_set_keytab_name(cred, lp_ctx, keytab, CRED_SPECIFIED); + cli_credentials_set_keytab_name(cred, event_ctx, lp_ctx, keytab, CRED_SPECIFIED); } else { keytab = ldb_msg_find_attr_as_string(msgs[0], "privateKeytab", NULL); if (keytab) { keytab = talloc_asprintf(mem_ctx, "FILE:%s", private_path(mem_ctx, lp_ctx, keytab)); if (keytab) { - cli_credentials_set_keytab_name(cred, lp_ctx, keytab, CRED_SPECIFIED); + cli_credentials_set_keytab_name(cred, event_ctx, lp_ctx, keytab, CRED_SPECIFIED); } } } @@ -336,7 +338,7 @@ _PUBLIC_ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cr cred->machine_account_pending = false; filter = talloc_asprintf(cred, SECRETS_PRIMARY_DOMAIN_FILTER, cli_credentials_get_domain(cred)); - return cli_credentials_set_secrets(cred, lp_ctx, NULL, + return cli_credentials_set_secrets(cred, event_context_find(cred), lp_ctx, NULL, SECRETS_PRIMARY_DOMAIN_DN, filter); } @@ -348,6 +350,7 @@ _PUBLIC_ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cr * @retval NTSTATUS error detailing any failure */ NTSTATUS cli_credentials_set_krbtgt(struct cli_credentials *cred, + struct event_context *event_ctx, struct loadparm_context *lp_ctx) { char *filter; @@ -358,7 +361,7 @@ NTSTATUS cli_credentials_set_krbtgt(struct cli_credentials *cred, filter = talloc_asprintf(cred, SECRETS_KRBTGT_SEARCH, cli_credentials_get_realm(cred), cli_credentials_get_domain(cred)); - return cli_credentials_set_secrets(cred, lp_ctx, NULL, + return cli_credentials_set_secrets(cred, event_ctx, lp_ctx, NULL, SECRETS_PRINCIPALS_DN, filter); } @@ -370,6 +373,7 @@ NTSTATUS cli_credentials_set_krbtgt(struct cli_credentials *cred, * @retval NTSTATUS error detailing any failure */ _PUBLIC_ NTSTATUS cli_credentials_set_stored_principal(struct cli_credentials *cred, + struct event_context *event_ctx, struct loadparm_context *lp_ctx, const char *serviceprincipal) { @@ -382,7 +386,7 @@ _PUBLIC_ NTSTATUS cli_credentials_set_stored_principal(struct cli_credentials *c cli_credentials_get_realm(cred), cli_credentials_get_domain(cred), serviceprincipal); - return cli_credentials_set_secrets(cred, lp_ctx, NULL, + return cli_credentials_set_secrets(cred, event_ctx, lp_ctx, NULL, SECRETS_PRINCIPALS_DN, filter); } diff --git a/source4/auth/credentials/credentials_krb5.c b/source4/auth/credentials/credentials_krb5.c index cd9285b09d..3bc1764448 100644 --- a/source4/auth/credentials/credentials_krb5.c +++ b/source4/auth/credentials/credentials_krb5.c @@ -30,6 +30,7 @@ #include "param/param.h" _PUBLIC_ int cli_credentials_get_krb5_context(struct cli_credentials *cred, + struct event_context *event_ctx, struct loadparm_context *lp_ctx, struct smb_krb5_context **smb_krb5_context) { @@ -39,8 +40,7 @@ _PUBLIC_ int cli_credentials_get_krb5_context(struct cli_credentials *cred, return 0; } - ret = smb_krb5_init_context(cred, cli_credentials_get_event_context(cred), - lp_ctx, &cred->smb_krb5_context); + ret = smb_krb5_init_context(cred, event_ctx, lp_ctx, &cred->smb_krb5_context); if (ret) { cred->smb_krb5_context = NULL; return ret; @@ -128,6 +128,7 @@ static int free_dccache(struct ccache_container *ccc) { } _PUBLIC_ int cli_credentials_set_ccache(struct cli_credentials *cred, + struct event_context *event_ctx, struct loadparm_context *lp_ctx, const char *name, enum credentials_obtained obtained) @@ -144,7 +145,7 @@ _PUBLIC_ int cli_credentials_set_ccache(struct cli_credentials *cred, return ENOMEM; } - ret = cli_credentials_get_krb5_context(cred, lp_ctx, + ret = cli_credentials_get_krb5_context(cred, event_ctx, lp_ctx, &ccc->smb_krb5_context); if (ret) { talloc_free(ccc); @@ -203,6 +204,7 @@ _PUBLIC_ int cli_credentials_set_ccache(struct cli_credentials *cred, static int cli_credentials_new_ccache(struct cli_credentials *cred, + struct event_context *event_ctx, struct loadparm_context *lp_ctx, struct ccache_container **_ccc) { @@ -221,7 +223,7 @@ static int cli_credentials_new_ccache(struct cli_credentials *cred, return ENOMEM; } - ret = cli_credentials_get_krb5_context(cred, lp_ctx, + ret = cli_credentials_get_krb5_context(cred, event_ctx, lp_ctx, &ccc->smb_krb5_context); if (ret) { talloc_free(ccc); @@ -253,6 +255,7 @@ static int cli_credentials_new_ccache(struct cli_credentials *cred, } _PUBLIC_ int cli_credentials_get_ccache(struct cli_credentials *cred, + struct event_context *event_ctx, struct loadparm_context *lp_ctx, struct ccache_container **ccc) { @@ -271,7 +274,7 @@ _PUBLIC_ int cli_credentials_get_ccache(struct cli_credentials *cred, return EINVAL; } - ret = cli_credentials_new_ccache(cred, lp_ctx, ccc); + ret = cli_credentials_new_ccache(cred, event_ctx, lp_ctx, ccc); if (ret) { return ret; } @@ -348,6 +351,7 @@ static int free_gssapi_creds(struct gssapi_creds_container *gcc) } _PUBLIC_ int cli_credentials_get_client_gss_creds(struct cli_credentials *cred, + struct event_context *event_ctx, struct loadparm_context *lp_ctx, struct gssapi_creds_container **_gcc) { @@ -360,7 +364,7 @@ _PUBLIC_ int cli_credentials_get_client_gss_creds(struct cli_credentials *cred, *_gcc = cred->client_gss_creds; return 0; } - ret = cli_credentials_get_ccache(cred, lp_ctx, + ret = cli_credentials_get_ccache(cred, event_ctx, lp_ctx, &ccache); if (ret) { DEBUG(1, ("Failed to get CCACHE for GSSAPI client: %s\n", error_message(ret))); @@ -402,6 +406,7 @@ _PUBLIC_ int cli_credentials_get_client_gss_creds(struct cli_credentials *cred, */ int cli_credentials_set_client_gss_creds(struct cli_credentials *cred, + struct event_context *event_ctx, struct loadparm_context *lp_ctx, gss_cred_id_t gssapi_cred, enum credentials_obtained obtained) @@ -419,7 +424,7 @@ _PUBLIC_ int cli_credentials_get_client_gss_creds(struct cli_credentials *cred, return ENOMEM; } - ret = cli_credentials_new_ccache(cred, lp_ctx, &ccc); + ret = cli_credentials_new_ccache(cred, event_ctx, lp_ctx, &ccc); if (ret != 0) { return ret; } @@ -456,6 +461,7 @@ _PUBLIC_ int cli_credentials_get_client_gss_creds(struct cli_credentials *cred, * it will be generated from the password. */ _PUBLIC_ int cli_credentials_get_keytab(struct cli_credentials *cred, + struct event_context *event_ctx, struct loadparm_context *lp_ctx, struct keytab_container **_ktc) { @@ -475,7 +481,7 @@ _PUBLIC_ int cli_credentials_get_keytab(struct cli_credentials *cred, return EINVAL; } - ret = cli_credentials_get_krb5_context(cred, lp_ctx, + ret = cli_credentials_get_krb5_context(cred, event_ctx, lp_ctx, &smb_krb5_context); if (ret) { return ret; @@ -510,6 +516,7 @@ _PUBLIC_ int cli_credentials_get_keytab(struct cli_credentials *cred, * FILE:/etc/krb5.keytab), open it and attach it */ _PUBLIC_ int cli_credentials_set_keytab_name(struct cli_credentials *cred, + struct event_context *event_ctx, struct loadparm_context *lp_ctx, const char *keytab_name, enum credentials_obtained obtained) @@ -523,7 +530,7 @@ _PUBLIC_ int cli_credentials_set_keytab_name(struct cli_credentials *cred, return 0; } - ret = cli_credentials_get_krb5_context(cred, lp_ctx, &smb_krb5_context); + ret = cli_credentials_get_krb5_context(cred, event_ctx, lp_ctx, &smb_krb5_context); if (ret) { return ret; } @@ -549,6 +556,7 @@ _PUBLIC_ int cli_credentials_set_keytab_name(struct cli_credentials *cred, } _PUBLIC_ int cli_credentials_update_keytab(struct cli_credentials *cred, + struct event_context *event_ctx, struct loadparm_context *lp_ctx) { krb5_error_code ret; @@ -562,7 +570,7 @@ _PUBLIC_ int cli_credentials_update_keytab(struct cli_credentials *cred, return ENOMEM; } - ret = cli_credentials_get_krb5_context(cred, lp_ctx, &smb_krb5_context); + ret = cli_credentials_get_krb5_context(cred, event_ctx, lp_ctx, &smb_krb5_context); if (ret) { talloc_free(mem_ctx); return ret; @@ -570,7 +578,7 @@ _PUBLIC_ int cli_credentials_update_keytab(struct cli_credentials *cred, enctype_strings = cli_credentials_get_enctype_strings(cred); - ret = cli_credentials_get_keytab(cred, lp_ctx, &ktc); + ret = cli_credentials_get_keytab(cred, event_ctx, lp_ctx, &ktc); if (ret != 0) { talloc_free(mem_ctx); return ret; @@ -585,6 +593,7 @@ _PUBLIC_ int cli_credentials_update_keytab(struct cli_credentials *cred, /* Get server gss credentials (in gsskrb5, this means the keytab) */ _PUBLIC_ int cli_credentials_get_server_gss_creds(struct cli_credentials *cred, + struct event_context *event_ctx, struct loadparm_context *lp_ctx, struct gssapi_creds_container **_gcc) { @@ -603,12 +612,12 @@ _PUBLIC_ int cli_credentials_get_server_gss_creds(struct cli_credentials *cred, return 0; } - ret = cli_credentials_get_krb5_context(cred, lp_ctx, &smb_krb5_context); + ret = cli_credentials_get_krb5_context(cred, event_ctx, lp_ctx, &smb_krb5_context); if (ret) { return ret; } - ret = cli_credentials_get_keytab(cred, lp_ctx, &ktc); + ret = cli_credentials_get_keytab(cred, event_ctx, lp_ctx, &ktc); if (ret) { DEBUG(1, ("Failed to get keytab for GSSAPI server: %s\n", error_message(ret))); return ret; diff --git a/source4/auth/credentials/credentials_krb5.h b/source4/auth/credentials/credentials_krb5.h index aaa7d7f0da..f672b0ad9a 100644 --- a/source4/auth/credentials/credentials_krb5.h +++ b/source4/auth/credentials/credentials_krb5.h @@ -32,6 +32,7 @@ struct gssapi_creds_container { /* Manually prototyped here to avoid needing gss headers in most callers */ int cli_credentials_set_client_gss_creds(struct cli_credentials *cred, + struct event_context *event_ctx, struct loadparm_context *lp_ctx, gss_cred_id_t gssapi_cred, enum credentials_obtained obtained); diff --git a/source4/auth/credentials/credentials_ntlm.c b/source4/auth/credentials/credentials_ntlm.c index b88f2018df..22e273c35a 100644 --- a/source4/auth/credentials/credentials_ntlm.c +++ b/source4/auth/credentials/credentials_ntlm.c @@ -52,6 +52,20 @@ _PUBLIC_ NTSTATUS cli_credentials_get_ntlm_response(struct cli_credentials *cred const struct samr_Password *nt_hash; lm_session_key = data_blob(NULL, 0); + /* We may already have an NTLM response we prepared earlier. + * This is used for NTLM pass-though authentication */ + if (cred->nt_response.data || cred->lm_response.data) { + *_nt_response = cred->nt_response; + *_lm_response = cred->lm_response; + + if (!cred->lm_response.data) { + *flags = *flags & ~CLI_CRED_LANMAN_AUTH; + } + *_lm_session_key = data_blob(NULL, 0); + *_session_key = data_blob(NULL, 0); + return NT_STATUS_OK; + } + nt_hash = cli_credentials_get_nt_hash(cred, mem_ctx); cli_credentials_get_ntlm_username_domain(cred, mem_ctx, &user, &domain); @@ -215,3 +229,41 @@ _PUBLIC_ NTSTATUS cli_credentials_get_ntlm_response(struct cli_credentials *cred return NT_STATUS_OK; } +_PUBLIC_ bool cli_credentials_set_nt_hash(struct cli_credentials *cred, + const struct samr_Password *nt_hash, + enum credentials_obtained obtained) +{ + if (obtained >= cred->password_obtained) { + cli_credentials_set_password(cred, NULL, obtained); + if (nt_hash) { + cred->nt_hash = talloc(cred, struct samr_Password); + *cred->nt_hash = *nt_hash; + } else { + cred->nt_hash = NULL; + } + return true; + } + + return false; +} + +_PUBLIC_ bool cli_credentials_set_ntlm_response(struct cli_credentials *cred, + const DATA_BLOB *lm_response, + const DATA_BLOB *nt_response, + enum credentials_obtained obtained) +{ + if (obtained >= cred->password_obtained) { + cli_credentials_set_password(cred, NULL, obtained); + if (nt_response) { + cred->nt_response = data_blob_talloc(cred, nt_response->data, nt_response->length); + talloc_steal(cred, cred->nt_response.data); + } + if (nt_response) { + cred->lm_response = data_blob_talloc(cred, lm_response->data, lm_response->length); + } + return true; + } + + return false; +} + diff --git a/source4/auth/credentials/credentials_wrap.c b/source4/auth/credentials/credentials_wrap.c index 6c99802b09..81ba426e45 100644 --- a/source4/auth/credentials/credentials_wrap.c +++ b/source4/auth/credentials/credentials_wrap.c @@ -1,6 +1,6 @@ /* ---------------------------------------------------------------------------- * This file was automatically generated by SWIG (http://www.swig.org). - * Version 1.3.33 + * Version 1.3.35 * * This file is not intended to be easily readable and contains a number of * coding conventions designed to improve portability and efficiency. Do not make @@ -126,7 +126,7 @@ /* This should only be incremented when either the layout of swig_type_info changes, or for whatever reason, the runtime changes incompatibly */ -#define SWIG_RUNTIME_VERSION "3" +#define SWIG_RUNTIME_VERSION "4" /* define SWIG_TYPE_TABLE_NAME as "SWIG_TYPE_TABLE" */ #ifdef SWIG_TYPE_TABLE @@ -161,6 +161,7 @@ /* Flags for pointer conversions */ #define SWIG_POINTER_DISOWN 0x1 +#define SWIG_CAST_NEW_MEMORY 0x2 /* Flags for new pointer objects */ #define SWIG_POINTER_OWN 0x1 @@ -301,10 +302,10 @@ SWIGINTERNINLINE int SWIG_CheckState(int r) { extern "C" { #endif -typedef void *(*swig_converter_func)(void *); +typedef void *(*swig_converter_func)(void *, int *); typedef struct swig_type_info *(*swig_dycast_func)(void **); -/* Structure to store inforomation on one type */ +/* Structure to store information on one type */ typedef struct swig_type_info { const char *name; /* mangled name of this type */ const char *str; /* human readable name of this type */ @@ -431,8 +432,8 @@ SWIG_TypeCheckStruct(swig_type_info *from, swig_type_info *into) { Cast a pointer up an inheritance hierarchy */ SWIGRUNTIMEINLINE void * -SWIG_TypeCast(swig_cast_info *ty, void *ptr) { - return ((!ty) || (!ty->converter)) ? ptr : (*ty->converter)(ptr); +SWIG_TypeCast(swig_cast_info *ty, void *ptr, int *newmemory) { + return ((!ty) || (!ty->converter)) ? ptr : (*ty->converter)(ptr, newmemory); } /* @@ -856,7 +857,7 @@ SWIG_Python_AddErrorMsg(const char* mesg) Py_DECREF(old_str); Py_DECREF(value); } else { - PyErr_Format(PyExc_RuntimeError, mesg); + PyErr_SetString(PyExc_RuntimeError, mesg); } } @@ -1416,7 +1417,7 @@ PySwigObject_dealloc(PyObject *v) { PySwigObject *sobj = (PySwigObject *) v; PyObject *next = sobj->next; - if (sobj->own) { + if (sobj->own == SWIG_POINTER_OWN) { swig_type_info *ty = sobj->ty; PySwigClientData *data = ty ? (PySwigClientData *) ty->clientdata : 0; PyObject *destroy = data ? data->destroy : 0; @@ -1434,12 +1435,13 @@ PySwigObject_dealloc(PyObject *v) res = ((*meth)(mself, v)); } Py_XDECREF(res); - } else { - const char *name = SWIG_TypePrettyName(ty); + } #if !defined(SWIG_PYTHON_SILENT_MEMLEAK) - printf("swig/python detected a memory leak of type '%s', no destructor found.\n", name); -#endif + else { + const char *name = SWIG_TypePrettyName(ty); + printf("swig/python detected a memory leak of type '%s', no destructor found.\n", (name ? name : "unknown")); } +#endif } Py_XDECREF(next); PyObject_DEL(v); @@ -1944,7 +1946,7 @@ SWIG_Python_GetSwigThis(PyObject *pyobj) SWIGRUNTIME int SWIG_Python_AcquirePtr(PyObject *obj, int own) { - if (own) { + if (own == SWIG_POINTER_OWN) { PySwigObject *sobj = SWIG_Python_GetSwigThis(obj); if (sobj) { int oldown = sobj->own; @@ -1965,6 +1967,8 @@ SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int return SWIG_OK; } else { PySwigObject *sobj = SWIG_Python_GetSwigThis(obj); + if (own) + *own = 0; while (sobj) { void *vptr = sobj->ptr; if (ty) { @@ -1978,7 +1982,15 @@ SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int if (!tc) { sobj = (PySwigObject *)sobj->next; } else { - if (ptr) *ptr = SWIG_TypeCast(tc,vptr); + if (ptr) { + int newmemory = 0; + *ptr = SWIG_TypeCast(tc,vptr,&newmemory); + if (newmemory == SWIG_CAST_NEW_MEMORY) { + assert(own); + if (own) + *own = *own | SWIG_CAST_NEW_MEMORY; + } + } break; } } @@ -1988,7 +2000,8 @@ SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int } } if (sobj) { - if (own) *own = sobj->own; + if (own) + *own = *own | sobj->own; if (flags & SWIG_POINTER_DISOWN) { sobj->own = 0; } @@ -2053,8 +2066,13 @@ SWIG_Python_ConvertFunctionPtr(PyObject *obj, void **ptr, swig_type_info *ty) { } if (ty) { swig_cast_info *tc = SWIG_TypeCheck(desc,ty); - if (!tc) return SWIG_ERROR; - *ptr = SWIG_TypeCast(tc,vptr); + if (tc) { + int newmemory = 0; + *ptr = SWIG_TypeCast(tc,vptr,&newmemory); + assert(!newmemory); /* newmemory handling not yet implemented */ + } else { + return SWIG_ERROR; + } } else { *ptr = vptr; } @@ -2506,7 +2524,7 @@ static swig_module_info swig_module = {swig_types, 17, 0, 0, 0, 0}; #define SWIG_name "_credentials" -#define SWIGVERSION 0x010333 +#define SWIGVERSION 0x010335 #define SWIG_VERSION SWIGVERSION @@ -2863,7 +2881,7 @@ SWIGINTERN PyObject *_wrap_Credentials_set_username(PyObject *SWIGUNUSEDPARM(sel PyObject * obj1 = 0 ; PyObject * obj2 = 0 ; char * kwnames[] = { - (char *) "self",(char *) "value",(char *)"arg3", NULL + (char *) "self",(char *) "value",(char *) "obtained", NULL }; arg1 = NULL; @@ -2944,7 +2962,7 @@ SWIGINTERN PyObject *_wrap_Credentials_set_password(PyObject *SWIGUNUSEDPARM(sel PyObject * obj1 = 0 ; PyObject * obj2 = 0 ; char * kwnames[] = { - (char *) "self",(char *) "val",(char *)"arg3", NULL + (char *) "self",(char *) "val",(char *) "obtained", NULL }; arg1 = NULL; @@ -3025,7 +3043,7 @@ SWIGINTERN PyObject *_wrap_Credentials_set_domain(PyObject *SWIGUNUSEDPARM(self) PyObject * obj1 = 0 ; PyObject * obj2 = 0 ; char * kwnames[] = { - (char *) "self",(char *) "val",(char *)"arg3", NULL + (char *) "self",(char *) "val",(char *) "obtained", NULL }; arg1 = NULL; @@ -3106,7 +3124,7 @@ SWIGINTERN PyObject *_wrap_Credentials_set_realm(PyObject *SWIGUNUSEDPARM(self), PyObject * obj1 = 0 ; PyObject * obj2 = 0 ; char * kwnames[] = { - (char *) "self",(char *) "val",(char *)"arg3", NULL + (char *) "self",(char *) "val",(char *) "obtained", NULL }; arg1 = NULL; @@ -3196,7 +3214,7 @@ SWIGINTERN PyObject *_wrap_Credentials_parse_string(PyObject *SWIGUNUSEDPARM(sel PyObject * obj1 = 0 ; PyObject * obj2 = 0 ; char * kwnames[] = { - (char *) "self",(char *) "text",(char *)"arg3", NULL + (char *) "self",(char *) "text",(char *) "obtained", NULL }; arg1 = NULL; @@ -3672,19 +3690,52 @@ SWIGINTERN PyObject *Credentials_swiginit(PyObject *SWIGUNUSEDPARM(self), PyObje static PyMethodDef SwigMethods[] = { { (char *)"new_Credentials", (PyCFunction)_wrap_new_Credentials, METH_NOARGS, NULL}, - { (char *)"Credentials_get_username", (PyCFunction) _wrap_Credentials_get_username, METH_VARARGS | METH_KEYWORDS, NULL}, - { (char *)"Credentials_set_username", (PyCFunction) _wrap_Credentials_set_username, METH_VARARGS | METH_KEYWORDS, NULL}, - { (char *)"Credentials_get_password", (PyCFunction) _wrap_Credentials_get_password, METH_VARARGS | METH_KEYWORDS, NULL}, - { (char *)"Credentials_set_password", (PyCFunction) _wrap_Credentials_set_password, METH_VARARGS | METH_KEYWORDS, NULL}, + { (char *)"Credentials_get_username", (PyCFunction) _wrap_Credentials_get_username, METH_VARARGS | METH_KEYWORDS, (char *)"\n" + "S.get_username() -> username\n" + "Obtain username.\n" + ""}, + { (char *)"Credentials_set_username", (PyCFunction) _wrap_Credentials_set_username, METH_VARARGS | METH_KEYWORDS, (char *)"\n" + "S.set_username(name, obtained=CRED_SPECIFIED) -> None\n" + "Change username.\n" + ""}, + { (char *)"Credentials_get_password", (PyCFunction) _wrap_Credentials_get_password, METH_VARARGS | METH_KEYWORDS, (char *)"\n" + "S.get_password() -> password\n" + "Obtain password.\n" + ""}, + { (char *)"Credentials_set_password", (PyCFunction) _wrap_Credentials_set_password, METH_VARARGS | METH_KEYWORDS, (char *)"\n" + "S.set_password(password, obtained=CRED_SPECIFIED) -> None\n" + "Change password.\n" + ""}, { (char *)"Credentials_get_domain", (PyCFunction) _wrap_Credentials_get_domain, METH_VARARGS | METH_KEYWORDS, NULL}, - { (char *)"Credentials_set_domain", (PyCFunction) _wrap_Credentials_set_domain, METH_VARARGS | METH_KEYWORDS, NULL}, - { (char *)"Credentials_get_realm", (PyCFunction) _wrap_Credentials_get_realm, METH_VARARGS | METH_KEYWORDS, NULL}, - { (char *)"Credentials_set_realm", (PyCFunction) _wrap_Credentials_set_realm, METH_VARARGS | METH_KEYWORDS, NULL}, + { (char *)"Credentials_set_domain", (PyCFunction) _wrap_Credentials_set_domain, METH_VARARGS | METH_KEYWORDS, (char *)"\n" + "S.set_domain(domain, obtained=CRED_SPECIFIED) -> None\n" + "Change domain name.\n" + ""}, + { (char *)"Credentials_get_realm", (PyCFunction) _wrap_Credentials_get_realm, METH_VARARGS | METH_KEYWORDS, (char *)"\n" + "S.get_realm() -> realm\n" + "Obtain realm name.\n" + ""}, + { (char *)"Credentials_set_realm", (PyCFunction) _wrap_Credentials_set_realm, METH_VARARGS | METH_KEYWORDS, (char *)"\n" + "S.set_realm(realm, obtained=CRED_SPECIFIED) -> None\n" + "Change realm name.\n" + ""}, { (char *)"Credentials_set_kerberos_state", (PyCFunction) _wrap_Credentials_set_kerberos_state, METH_VARARGS | METH_KEYWORDS, NULL}, - { (char *)"Credentials_parse_string", (PyCFunction) _wrap_Credentials_parse_string, METH_VARARGS | METH_KEYWORDS, NULL}, - { (char *)"Credentials_get_bind_dn", (PyCFunction) _wrap_Credentials_get_bind_dn, METH_VARARGS | METH_KEYWORDS, NULL}, - { (char *)"Credentials_set_bind_dn", (PyCFunction) _wrap_Credentials_set_bind_dn, METH_VARARGS | METH_KEYWORDS, NULL}, - { (char *)"Credentials_set_anonymous", (PyCFunction) _wrap_Credentials_set_anonymous, METH_VARARGS | METH_KEYWORDS, NULL}, + { (char *)"Credentials_parse_string", (PyCFunction) _wrap_Credentials_parse_string, METH_VARARGS | METH_KEYWORDS, (char *)"\n" + "S.parse_string(text, obtained=CRED_SPECIFIED) -> None\n" + "Parse credentials string.\n" + ""}, + { (char *)"Credentials_get_bind_dn", (PyCFunction) _wrap_Credentials_get_bind_dn, METH_VARARGS | METH_KEYWORDS, (char *)"\n" + "S.get_bind_dn() -> bind dn\n" + "Obtain bind DN.\n" + ""}, + { (char *)"Credentials_set_bind_dn", (PyCFunction) _wrap_Credentials_set_bind_dn, METH_VARARGS | METH_KEYWORDS, (char *)"\n" + "S.set_bind_dn(bind_dn) -> None\n" + "Change bind DN.\n" + ""}, + { (char *)"Credentials_set_anonymous", (PyCFunction) _wrap_Credentials_set_anonymous, METH_VARARGS | METH_KEYWORDS, (char *)"\n" + "S.set_anonymous() -> None\n" + "Use anonymous credentials.\n" + ""}, { (char *)"Credentials_get_workstation", (PyCFunction) _wrap_Credentials_get_workstation, METH_VARARGS | METH_KEYWORDS, NULL}, { (char *)"Credentials_set_workstation", (PyCFunction) _wrap_Credentials_set_workstation, METH_VARARGS | METH_KEYWORDS, NULL}, { (char *)"Credentials_set_machine_account", (PyCFunction) _wrap_Credentials_set_machine_account, METH_VARARGS | METH_KEYWORDS, NULL}, @@ -3692,8 +3743,14 @@ static PyMethodDef SwigMethods[] = { { (char *)"Credentials_is_anonymous", (PyCFunction) _wrap_Credentials_is_anonymous, METH_VARARGS | METH_KEYWORDS, NULL}, { (char *)"Credentials_get_nt_hash", (PyCFunction) _wrap_Credentials_get_nt_hash, METH_VARARGS | METH_KEYWORDS, NULL}, { (char *)"Credentials_authentication_requested", (PyCFunction) _wrap_Credentials_authentication_requested, METH_VARARGS | METH_KEYWORDS, NULL}, - { (char *)"Credentials_wrong_password", (PyCFunction) _wrap_Credentials_wrong_password, METH_VARARGS | METH_KEYWORDS, NULL}, - { (char *)"Credentials_set_cmdline_callbacks", (PyCFunction) _wrap_Credentials_set_cmdline_callbacks, METH_VARARGS | METH_KEYWORDS, NULL}, + { (char *)"Credentials_wrong_password", (PyCFunction) _wrap_Credentials_wrong_password, METH_VARARGS | METH_KEYWORDS, (char *)"\n" + "S.wrong_password() -> bool\n" + "Indicate the returned password was incorrect.\n" + ""}, + { (char *)"Credentials_set_cmdline_callbacks", (PyCFunction) _wrap_Credentials_set_cmdline_callbacks, METH_VARARGS | METH_KEYWORDS, (char *)"\n" + "S.set_cmdline_callbacks() -> bool\n" + "Use command-line to obtain credentials not explicitly set.\n" + ""}, { (char *)"delete_Credentials", (PyCFunction) _wrap_delete_Credentials, METH_VARARGS | METH_KEYWORDS, NULL}, { (char *)"Credentials_swigregister", Credentials_swigregister, METH_VARARGS, NULL}, { (char *)"Credentials_swiginit", Credentials_swiginit, METH_VARARGS, NULL}, @@ -3845,7 +3902,7 @@ SWIGRUNTIME void SWIG_InitializeModule(void *clientdata) { size_t i; swig_module_info *module_head, *iter; - int found; + int found, init; clientdata = clientdata; @@ -3855,6 +3912,9 @@ SWIG_InitializeModule(void *clientdata) { swig_module.type_initial = swig_type_initial; swig_module.cast_initial = swig_cast_initial; swig_module.next = &swig_module; + init = 1; + } else { + init = 0; } /* Try and load any already created modules */ @@ -3883,6 +3943,12 @@ SWIG_InitializeModule(void *clientdata) { module_head->next = &swig_module; } + /* When multiple interpeters are used, a module could have already been initialized in + a different interpreter, but not yet have a pointer in this interpreter. + In this case, we do not want to continue adding types... everything should be + set up already */ + if (init == 0) return; + /* Now work on filling in swig_module.types */ #ifdef SWIGRUNTIME_DEBUG printf("SWIG_InitializeModule: size %d\n", swig_module.size); diff --git a/source4/auth/credentials/tests/bindings.py b/source4/auth/credentials/tests/bindings.py index d0a99502c1..30120b3a60 100644 --- a/source4/auth/credentials/tests/bindings.py +++ b/source4/auth/credentials/tests/bindings.py @@ -24,7 +24,7 @@ the functionality, that's already done in other tests. """ import unittest -import credentials +from samba import credentials class CredentialsTests(unittest.TestCase): def setUp(self): |