#include "includes.h"
#include "librpc/gen_ndr/samr.h" /* for struct samrPassword */
#include "auth/credentials/credentials.h"
-#include "auth/credentials/credentials_proto.h"
+#include "auth/credentials/credentials_internal.h"
#include "libcli/auth/libcli_auth.h"
-#include "lib/events/events.h"
+#include "tevent.h"
#include "param/param.h"
#include "system/filesys.h"
cred->machine_account = false;
- cred->tries = 3;
+ cred->password_tries = 0;
cred->callback_running = false;
cli_credentials_set_gensec_features(cred, 0);
cli_credentials_set_krb_forwardable(cred, CRED_AUTO_KRB_FORWARDABLE);
+ cred->forced_sasl_mech = NULL;
+
return cred;
}
+_PUBLIC_ void cli_credentials_set_callback_data(struct cli_credentials *cred,
+ void *callback_data)
+{
+ cred->priv_data = callback_data;
+}
+
+_PUBLIC_ void *_cli_credentials_callback_data(struct cli_credentials *cred)
+{
+ return cred->priv_data;
+}
+
+_PUBLIC_ struct cli_credentials *cli_credentials_shallow_copy(TALLOC_CTX *mem_ctx,
+ struct cli_credentials *src)
+{
+ struct cli_credentials *dst;
+
+ dst = talloc(mem_ctx, struct cli_credentials);
+ if (dst == NULL) {
+ return NULL;
+ }
+
+ *dst = *src;
+
+ return dst;
+}
+
/**
* Create a new anonymous credential
* @param mem_ctx TALLOC_CTX parent for credentials structure
creds->use_kerberos = use_kerberos;
}
+_PUBLIC_ void cli_credentials_set_forced_sasl_mech(struct cli_credentials *creds,
+ const char *sasl_mech)
+{
+ TALLOC_FREE(creds->forced_sasl_mech);
+ creds->forced_sasl_mech = talloc_strdup(creds, sasl_mech);
+}
+
_PUBLIC_ void cli_credentials_set_krb_forwardable(struct cli_credentials *creds,
enum credentials_krb_forwardable krb_forwardable)
{
return creds->use_kerberos;
}
+_PUBLIC_ const char *cli_credentials_get_forced_sasl_mech(struct cli_credentials *creds)
+{
+ return creds->forced_sasl_mech;
+}
+
_PUBLIC_ enum credentials_krb_forwardable cli_credentials_get_krb_forwardable(struct cli_credentials *creds)
{
return creds->krb_forwardable;
cred->callback_running = true;
cred->username = cred->username_cb(cred);
cred->callback_running = false;
- cred->username_obtained = CRED_SPECIFIED;
- cli_credentials_invalidate_ccache(cred, cred->username_obtained);
+ if (cred->username_obtained == CRED_CALLBACK) {
+ cred->username_obtained = CRED_CALLBACK_RESULT;
+ cli_credentials_invalidate_ccache(cred, cred->username_obtained);
+ }
}
return cred->username;
return false;
}
-bool cli_credentials_set_username_callback(struct cli_credentials *cred,
+_PUBLIC_ bool cli_credentials_set_username_callback(struct cli_credentials *cred,
const char *(*username_cb) (struct cli_credentials *))
{
if (cred->username_obtained < CRED_CALLBACK) {
* @retval The username set on this context.
* @note Return value will never be NULL except by programmer error.
*/
-const char *cli_credentials_get_principal_and_obtained(struct cli_credentials *cred, TALLOC_CTX *mem_ctx, enum credentials_obtained *obtained)
+_PUBLIC_ const char *cli_credentials_get_principal_and_obtained(struct cli_credentials *cred, TALLOC_CTX *mem_ctx, enum credentials_obtained *obtained)
{
if (cred->machine_account_pending) {
cli_credentials_set_machine_account(cred,
cred->callback_running = true;
cred->principal = cred->principal_cb(cred);
cred->callback_running = false;
- cred->principal_obtained = CRED_SPECIFIED;
- cli_credentials_invalidate_ccache(cred, cred->principal_obtained);
+ if (cred->principal_obtained == CRED_CALLBACK) {
+ cred->principal_obtained = CRED_CALLBACK_RESULT;
+ cli_credentials_invalidate_ccache(cred, cred->principal_obtained);
+ }
}
if (cred->principal_obtained < cred->username_obtained
}
}
*obtained = cred->principal_obtained;
- return talloc_reference(mem_ctx, cred->principal);
+ return talloc_strdup(mem_ctx, cred->principal);
}
/**
return cli_credentials_get_principal_and_obtained(cred, mem_ctx, &obtained);
}
-bool cli_credentials_set_principal(struct cli_credentials *cred,
+_PUBLIC_ bool cli_credentials_set_principal(struct cli_credentials *cred,
const char *val,
enum credentials_obtained obtained)
{
/* Set a callback to get the principal. This could be a popup dialog,
* a terminal prompt or similar. */
-bool cli_credentials_set_principal_callback(struct cli_credentials *cred,
+_PUBLIC_ bool cli_credentials_set_principal_callback(struct cli_credentials *cred,
const char *(*principal_cb) (struct cli_credentials *))
{
if (cred->principal_obtained < CRED_CALLBACK) {
return true;
}
+ /*
+ * If we forced the mech we clearly want authentication. E.g. to use
+ * SASL/EXTERNAL which has no credentials.
+ */
+ if (cred->forced_sasl_mech) {
+ return true;
+ }
+
if (cli_credentials_is_anonymous(cred)){
return false;
}
if (cred->password_obtained == CRED_CALLBACK &&
!cred->callback_running) {
- cred->callback_running = true;
+ cred->callback_running = true;
cred->password = cred->password_cb(cred);
- cred->callback_running = false;
- cred->password_obtained = CRED_CALLBACK_RESULT;
- cli_credentials_invalidate_ccache(cred, cred->password_obtained);
+ cred->callback_running = false;
+ if (cred->password_obtained == CRED_CALLBACK) {
+ cred->password_obtained = CRED_CALLBACK_RESULT;
+ cli_credentials_invalidate_ccache(cred, cred->password_obtained);
+ }
}
return cred->password;
enum credentials_obtained obtained)
{
if (obtained >= cred->password_obtained) {
+ cred->password_tries = 0;
cred->password = talloc_strdup(cred, val);
+ if (cred->password) {
+ /* Don't print the actual password in talloc memory dumps */
+ talloc_set_name_const(cred->password, "password set via cli_credentials_set_password");
+ }
cred->password_obtained = obtained;
cli_credentials_invalidate_ccache(cred, cred->password_obtained);
const char *(*password_cb) (struct cli_credentials *))
{
if (cred->password_obtained < CRED_CALLBACK) {
+ cred->password_tries = 3;
cred->password_cb = password_cb;
cred->password_obtained = CRED_CALLBACK;
cli_credentials_invalidate_ccache(cred, cred->password_obtained);
* @param cred credentials context
* @retval If set, the cleartext password, otherwise NULL
*/
-const char *cli_credentials_get_old_password(struct cli_credentials *cred)
+_PUBLIC_ const char *cli_credentials_get_old_password(struct cli_credentials *cred)
{
if (cred->machine_account_pending) {
cli_credentials_set_machine_account(cred,
return cred->old_password;
}
-bool cli_credentials_set_old_password(struct cli_credentials *cred,
+_PUBLIC_ bool cli_credentials_set_old_password(struct cli_credentials *cred,
const char *val,
enum credentials_obtained obtained)
{
cred->old_password = talloc_strdup(cred, val);
+ if (cred->old_password) {
+ /* Don't print the actual password in talloc memory dumps */
+ talloc_set_name_const(cred->old_password, "password set via cli_credentials_set_old_password");
+ }
return true;
}
* @param cred credentials context
* @retval If set, the cleartext password, otherwise NULL
*/
-_PUBLIC_ const struct samr_Password *cli_credentials_get_nt_hash(struct cli_credentials *cred,
- TALLOC_CTX *mem_ctx)
+_PUBLIC_ struct samr_Password *cli_credentials_get_nt_hash(struct cli_credentials *cred,
+ TALLOC_CTX *mem_ctx)
{
- const char *password = cli_credentials_get_password(cred);
+ const char *password = NULL;
+ if (cred->nt_hash != NULL) {
+ struct samr_Password *nt_hash = talloc(mem_ctx, struct samr_Password);
+ if (!nt_hash) {
+ return NULL;
+ }
+
+ *nt_hash = *cred->nt_hash;
+
+ return nt_hash;
+ }
+
+ password = cli_credentials_get_password(cred);
if (password) {
struct samr_Password *nt_hash = talloc(mem_ctx, struct samr_Password);
if (!nt_hash) {
return NULL;
}
-
- E_md4hash(password, nt_hash->hash);
+
+ E_md4hash(password, nt_hash->hash);
return nt_hash;
- } else {
- return cred->nt_hash;
}
+
+ return NULL;
}
/**
cred->callback_running = true;
cred->domain = cred->domain_cb(cred);
cred->callback_running = false;
- cred->domain_obtained = CRED_SPECIFIED;
- cli_credentials_invalidate_ccache(cred, cred->domain_obtained);
+ if (cred->domain_obtained == CRED_CALLBACK) {
+ cred->domain_obtained = CRED_CALLBACK_RESULT;
+ cli_credentials_invalidate_ccache(cred, cred->domain_obtained);
+ }
}
return cred->domain;
* calculations */
cred->domain = strupper_talloc(cred, val);
cred->domain_obtained = obtained;
- cli_credentials_invalidate_ccache(cred, cred->domain_obtained);
+ /* setting domain does not mean we have to invalidate ccache
+ * because domain in not used for Kerberos operations.
+ * If ccache invalidation is required, one will anyway specify
+ * a password to kinit, and that will force invalidation of the ccache
+ */
return true;
}
cred->callback_running = true;
cred->realm = cred->realm_cb(cred);
cred->callback_running = false;
- cred->realm_obtained = CRED_SPECIFIED;
- cli_credentials_invalidate_ccache(cred, cred->realm_obtained);
+ if (cred->realm_obtained == CRED_CALLBACK) {
+ cred->realm_obtained = CRED_CALLBACK_RESULT;
+ cli_credentials_invalidate_ccache(cred, cred->realm_obtained);
+ }
}
return cred->realm;
cred->callback_running = true;
cred->workstation = cred->workstation_cb(cred);
cred->callback_running = false;
- cred->workstation_obtained = CRED_SPECIFIED;
+ if (cred->workstation_obtained == CRED_CALLBACK) {
+ cred->workstation_obtained = CRED_CALLBACK_RESULT;
+ }
}
return cred->workstation;
const char *name;
if (bind_dn) {
- name = talloc_reference(mem_ctx, bind_dn);
+ name = talloc_strdup(mem_ctx, bind_dn);
} else {
cli_credentials_get_ntlm_username_domain(credentials, mem_ctx, &username, &domain);
if (domain && domain[0]) {
struct loadparm_context *lp_ctx)
{
cli_credentials_set_username(cred, "", CRED_UNINITIALISED);
- cli_credentials_set_domain(cred, lpcfg_workgroup(lp_ctx), CRED_UNINITIALISED);
- cli_credentials_set_workstation(cred, lpcfg_netbios_name(lp_ctx), CRED_UNINITIALISED);
- cli_credentials_set_realm(cred, lpcfg_realm(lp_ctx), CRED_UNINITIALISED);
+ if (lpcfg_parm_is_cmdline(lp_ctx, "workgroup")) {
+ cli_credentials_set_domain(cred, lpcfg_workgroup(lp_ctx), CRED_SPECIFIED);
+ } else {
+ cli_credentials_set_domain(cred, lpcfg_workgroup(lp_ctx), CRED_UNINITIALISED);
+ }
+ if (lpcfg_parm_is_cmdline(lp_ctx, "netbios name")) {
+ cli_credentials_set_workstation(cred, lpcfg_netbios_name(lp_ctx), CRED_SPECIFIED);
+ } else {
+ cli_credentials_set_workstation(cred, lpcfg_netbios_name(lp_ctx), CRED_UNINITIALISED);
+ }
+ if (lpcfg_parm_is_cmdline(lp_ctx, "realm")) {
+ cli_credentials_set_realm(cred, lpcfg_realm(lp_ctx), CRED_SPECIFIED);
+ } else {
+ cli_credentials_set_realm(cred, lpcfg_realm(lp_ctx), CRED_UNINITIALISED);
+ }
}
/**
_PUBLIC_ void cli_credentials_set_netlogon_creds(struct cli_credentials *cred,
struct netlogon_creds_CredentialState *netlogon_creds)
{
- cred->netlogon_creds = talloc_reference(cred, netlogon_creds);
+ TALLOC_FREE(cred->netlogon_creds);
+ if (netlogon_creds == NULL) {
+ return;
+ }
+ cred->netlogon_creds = netlogon_creds_copy(cred, netlogon_creds);
}
/**
* Return attached NETLOGON credentials
*/
-struct netlogon_creds_CredentialState *cli_credentials_get_netlogon_creds(struct cli_credentials *cred)
+_PUBLIC_ struct netlogon_creds_CredentialState *cli_credentials_get_netlogon_creds(struct cli_credentials *cred)
{
return cred->netlogon_creds;
}
if (cred->password_obtained != CRED_CALLBACK_RESULT) {
return false;
}
-
- cred->password_obtained = CRED_CALLBACK;
- cred->tries--;
+ if (cred->password_tries == 0) {
+ return false;
+ }
+
+ cred->password_tries--;
+
+ if (cred->password_tries == 0) {
+ return false;
+ }
- return (cred->tries > 0);
+ cred->password_obtained = CRED_CALLBACK;
+ return true;
}
_PUBLIC_ void cli_credentials_get_ntlm_username_domain(struct cli_credentials *cred, TALLOC_CTX *mem_ctx,