2 Unix SMB/CIFS implementation.
4 User credentials handling
6 Copyright (C) Jelmer Vernooij 2005
7 Copyright (C) Tim Potter 2001
8 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "lib/util/util_file.h"
26 #include "librpc/gen_ndr/samr.h" /* for struct samrPassword */
27 #include "auth/credentials/credentials.h"
28 #include "auth/credentials/credentials_internal.h"
29 #include "auth/gensec/gensec.h"
30 #include "libcli/auth/libcli_auth.h"
32 #include "param/param.h"
33 #include "system/filesys.h"
34 #include "system/passwd.h"
36 static bool str_is_ascii(const char *s) {
38 for (; s[0] != '\0'; s++) {
49 * Create a new credentials structure
50 * @param mem_ctx TALLOC_CTX parent for credentials structure
52 _PUBLIC_ struct cli_credentials *cli_credentials_init(TALLOC_CTX *mem_ctx)
54 struct cli_credentials *cred = talloc_zero(mem_ctx, struct cli_credentials);
59 cred->winbind_separator = '\\';
61 cred->kerberos_state = CRED_USE_KERBEROS_DESIRED;
63 cred->signing_state = SMB_SIGNING_DEFAULT;
66 * The default value of lpcfg_client_ipc_signing() is REQUIRED, so use
67 * the same value here.
69 cred->ipc_signing_state = SMB_SIGNING_REQUIRED;
70 cred->encryption_state = SMB_ENCRYPTION_DEFAULT;
76 struct cli_credentials *cli_credentials_init_server(TALLOC_CTX *mem_ctx,
77 struct loadparm_context *lp_ctx)
79 struct cli_credentials *server_creds = NULL;
83 server_creds = cli_credentials_init(mem_ctx);
84 if (server_creds == NULL) {
88 ok = cli_credentials_set_conf(server_creds, lp_ctx);
90 TALLOC_FREE(server_creds);
94 status = cli_credentials_set_machine_account(server_creds, lp_ctx);
95 if (!NT_STATUS_IS_OK(status)) {
96 DEBUG(1, ("Failed to obtain server credentials: %s\n",
98 TALLOC_FREE(server_creds);
105 _PUBLIC_ void cli_credentials_set_callback_data(struct cli_credentials *cred,
108 cred->priv_data = callback_data;
111 _PUBLIC_ void *_cli_credentials_callback_data(struct cli_credentials *cred)
113 return cred->priv_data;
117 * Create a new anonymous credential
118 * @param mem_ctx TALLOC_CTX parent for credentials structure
120 _PUBLIC_ struct cli_credentials *cli_credentials_init_anon(TALLOC_CTX *mem_ctx)
122 struct cli_credentials *anon_credentials;
124 anon_credentials = cli_credentials_init(mem_ctx);
125 cli_credentials_set_anonymous(anon_credentials);
127 return anon_credentials;
130 _PUBLIC_ bool cli_credentials_set_kerberos_state(struct cli_credentials *creds,
131 enum credentials_use_kerberos kerberos_state,
132 enum credentials_obtained obtained)
134 if (obtained >= creds->kerberos_state_obtained) {
135 creds->kerberos_state = kerberos_state;
136 creds->kerberos_state_obtained = obtained;
144 _PUBLIC_ void cli_credentials_set_forced_sasl_mech(struct cli_credentials *creds,
145 const char *sasl_mech)
147 TALLOC_FREE(creds->forced_sasl_mech);
148 creds->forced_sasl_mech = talloc_strdup(creds, sasl_mech);
151 _PUBLIC_ void cli_credentials_set_krb_forwardable(struct cli_credentials *creds,
152 enum credentials_krb_forwardable krb_forwardable)
154 creds->krb_forwardable = krb_forwardable;
157 _PUBLIC_ enum credentials_use_kerberos cli_credentials_get_kerberos_state(struct cli_credentials *creds)
159 return creds->kerberos_state;
162 _PUBLIC_ enum credentials_obtained cli_credentials_get_kerberos_state_obtained(struct cli_credentials *creds)
164 return creds->kerberos_state_obtained;
167 _PUBLIC_ const char *cli_credentials_get_forced_sasl_mech(struct cli_credentials *creds)
169 return creds->forced_sasl_mech;
172 _PUBLIC_ enum credentials_krb_forwardable cli_credentials_get_krb_forwardable(struct cli_credentials *creds)
174 return creds->krb_forwardable;
177 _PUBLIC_ bool cli_credentials_set_gensec_features(struct cli_credentials *creds,
178 uint32_t gensec_features,
179 enum credentials_obtained obtained)
181 if (obtained >= creds->gensec_features_obtained) {
182 creds->gensec_features_obtained = obtained;
183 creds->gensec_features = gensec_features;
191 _PUBLIC_ bool cli_credentials_add_gensec_features(
192 struct cli_credentials *creds,
193 uint32_t gensec_features,
194 enum credentials_obtained obtained)
196 return cli_credentials_set_gensec_features(
197 creds, creds->gensec_features | gensec_features, obtained);
200 _PUBLIC_ uint32_t cli_credentials_get_gensec_features(struct cli_credentials *creds)
202 return creds->gensec_features;
206 * @brief Find out how the username was obtained.
208 * @param cred A credentials context.
210 * @return The obtained information for the username.
212 _PUBLIC_ enum credentials_obtained
213 cli_credentials_get_username_obtained(struct cli_credentials *cred)
215 return cred->username_obtained;
219 * Obtain the username for this credentials context.
220 * @param cred credentials context
221 * @retval The username set on this context.
222 * @note Return value will never be NULL except by programmer error.
224 _PUBLIC_ const char *cli_credentials_get_username(struct cli_credentials *cred)
226 if (cred->machine_account_pending) {
227 cli_credentials_set_machine_account(cred,
228 cred->machine_account_pending_lp_ctx);
231 if (cred->username_obtained == CRED_CALLBACK &&
232 !cred->callback_running) {
233 cred->callback_running = true;
234 cred->username = cred->username_cb(cred);
235 cred->callback_running = false;
236 if (cred->username_obtained == CRED_CALLBACK) {
237 cred->username_obtained = CRED_CALLBACK_RESULT;
238 cli_credentials_invalidate_ccache(cred, cred->username_obtained);
242 return cred->username;
246 * @brief Obtain the username for this credentials context.
248 * @param[in] cred The credential context.
250 * @param[in] obtained A pointer to store the obtained information.
252 * return The user name or NULL if an error occurred.
254 _PUBLIC_ const char *
255 cli_credentials_get_username_and_obtained(struct cli_credentials *cred,
256 enum credentials_obtained *obtained)
258 if (obtained != NULL) {
259 *obtained = cred->username_obtained;
262 return cli_credentials_get_username(cred);
265 _PUBLIC_ bool cli_credentials_set_username(struct cli_credentials *cred,
266 const char *val, enum credentials_obtained obtained)
268 if (obtained >= cred->username_obtained) {
269 cred->username = talloc_strdup(cred, val);
270 cred->username_obtained = obtained;
271 cli_credentials_invalidate_ccache(cred, cred->username_obtained);
278 _PUBLIC_ bool cli_credentials_set_username_callback(struct cli_credentials *cred,
279 const char *(*username_cb) (struct cli_credentials *))
281 if (cred->username_obtained < CRED_CALLBACK) {
282 cred->username_cb = username_cb;
283 cred->username_obtained = CRED_CALLBACK;
290 _PUBLIC_ bool cli_credentials_set_bind_dn(struct cli_credentials *cred,
293 cred->bind_dn = talloc_strdup(cred, bind_dn);
298 * Obtain the BIND DN for this credentials context.
299 * @param cred credentials context
300 * @retval The username set on this context.
301 * @note Return value will be NULL if not specified explicitly
303 _PUBLIC_ const char *cli_credentials_get_bind_dn(struct cli_credentials *cred)
305 return cred->bind_dn;
310 * @brief Find out how the principal was obtained.
312 * @param cred A credentials context.
314 * @return The obtained information for the principal.
316 _PUBLIC_ enum credentials_obtained
317 cli_credentials_get_principal_obtained(struct cli_credentials *cred)
319 if (cred->machine_account_pending) {
320 cli_credentials_set_machine_account(cred,
321 cred->machine_account_pending_lp_ctx);
324 if (cred->principal_obtained < cred->username_obtained
325 || cred->principal_obtained < MAX(cred->domain_obtained, cred->realm_obtained)) {
326 const char *effective_username = NULL;
327 const char *effective_realm = NULL;
328 enum credentials_obtained effective_obtained;
331 * We don't want to trigger a callbacks in
332 * cli_credentials_get_username()
333 * cli_credentials_get_domain()
335 * cli_credentials_get_realm()
338 effective_username = cred->username;
339 if (effective_username == NULL || strlen(effective_username) == 0) {
340 return cred->username_obtained;
343 if (cred->domain_obtained > cred->realm_obtained) {
344 effective_realm = cred->domain;
345 effective_obtained = MIN(cred->domain_obtained,
346 cred->username_obtained);
348 effective_realm = cred->realm;
349 effective_obtained = MIN(cred->realm_obtained,
350 cred->username_obtained);
353 if (effective_realm == NULL || strlen(effective_realm) == 0) {
354 effective_realm = cred->domain;
355 effective_obtained = MIN(cred->domain_obtained,
356 cred->username_obtained);
359 if (effective_realm != NULL && strlen(effective_realm) != 0) {
360 return effective_obtained;
364 return cred->principal_obtained;
368 * Obtain the client principal for this credentials context.
369 * @param cred credentials context
370 * @retval The username set on this context.
371 * @note Return value will never be NULL except by programmer error.
373 _PUBLIC_ char *cli_credentials_get_principal_and_obtained(struct cli_credentials *cred, TALLOC_CTX *mem_ctx, enum credentials_obtained *obtained)
375 if (cred->machine_account_pending) {
376 cli_credentials_set_machine_account(cred,
377 cred->machine_account_pending_lp_ctx);
380 if (cred->principal_obtained == CRED_CALLBACK &&
381 !cred->callback_running) {
382 const char *princ = NULL;
384 cred->callback_running = true;
385 princ = cred->principal_cb(cred);
386 cred->callback_running = false;
388 cred->principal = NULL;
392 cred->principal = talloc_strdup(cred, princ);
393 if (cred->principal == NULL) {
397 p = strchr(cred->principal, '@');
401 for (; p[0] != '\0'; p++) {
407 if (cred->principal_obtained == CRED_CALLBACK) {
408 cred->principal_obtained = CRED_CALLBACK_RESULT;
409 cli_credentials_invalidate_ccache(cred, cred->principal_obtained);
413 if (cred->principal_obtained < cred->username_obtained
414 || cred->principal_obtained < MAX(cred->domain_obtained, cred->realm_obtained)) {
415 const char *effective_username = NULL;
416 const char *effective_realm = NULL;
417 enum credentials_obtained effective_obtained;
419 effective_username = cli_credentials_get_username(cred);
420 if (effective_username == NULL || strlen(effective_username) == 0) {
421 *obtained = cred->username_obtained;
425 if (cred->domain_obtained > cred->realm_obtained) {
426 effective_realm = cli_credentials_get_domain(cred);
427 effective_obtained = MIN(cred->domain_obtained,
428 cred->username_obtained);
430 effective_realm = cli_credentials_get_realm(cred);
431 effective_obtained = MIN(cred->realm_obtained,
432 cred->username_obtained);
435 if (effective_realm == NULL || strlen(effective_realm) == 0) {
436 effective_realm = cli_credentials_get_domain(cred);
437 effective_obtained = MIN(cred->domain_obtained,
438 cred->username_obtained);
441 if (effective_realm != NULL && strlen(effective_realm) != 0) {
442 *obtained = effective_obtained;
443 return talloc_asprintf(mem_ctx, "%s@%s",
448 *obtained = cred->principal_obtained;
449 return talloc_strdup(mem_ctx, cred->principal);
453 * Obtain the client principal for this credentials context.
454 * @param cred credentials context
455 * @retval The username set on this context.
456 * @note Return value will never be NULL except by programmer error.
458 _PUBLIC_ char *cli_credentials_get_principal(struct cli_credentials *cred, TALLOC_CTX *mem_ctx)
460 enum credentials_obtained obtained;
461 return cli_credentials_get_principal_and_obtained(cred, mem_ctx, &obtained);
465 * @brief Set the principal for the credentials context.
467 * The realm of the principal will be checked if it is ASCII only and upper
468 * cased if it isn't yet.
470 * @param cred The credential context.
472 * @param val The principal to set or NULL to reset.
474 * @param obtained This way the described principal was specified.
476 * @return true on success, false if the realm is not ASCII or the allocation
479 _PUBLIC_ bool cli_credentials_set_principal(struct cli_credentials *cred,
481 enum credentials_obtained obtained)
483 if (obtained >= cred->principal_obtained) {
484 /* If `val = NULL` is passed, principal is reset */
485 cred->principal = NULL;
487 char *p = strchr(val, '@');
489 /* For realm names, only ASCII is allowed */
490 if (!str_is_ascii(p + 1)) {
495 cred->principal = talloc_strdup(cred, val);
496 if (cred->principal == NULL) {
500 p = strchr(cred->principal, '@');
504 for (; p[0] != '\0'; p++) {
509 cred->principal_obtained = obtained;
510 cli_credentials_invalidate_ccache(cred, cred->principal_obtained);
517 /* Set a callback to get the principal. This could be a popup dialog,
518 * a terminal prompt or similar. */
519 _PUBLIC_ bool cli_credentials_set_principal_callback(struct cli_credentials *cred,
520 const char *(*principal_cb) (struct cli_credentials *))
522 if (cred->principal_obtained < CRED_CALLBACK) {
523 cred->principal_cb = principal_cb;
524 cred->principal_obtained = CRED_CALLBACK;
531 /* Some of our tools are 'anonymous by default'. This is a single
532 * function to determine if authentication has been explicitly
535 _PUBLIC_ bool cli_credentials_authentication_requested(struct cli_credentials *cred)
537 uint32_t gensec_features = 0;
544 * If we forced the mech we clearly want authentication. E.g. to use
545 * SASL/EXTERNAL which has no credentials.
547 if (cred->forced_sasl_mech) {
551 if (cli_credentials_is_anonymous(cred)){
555 if (cred->principal_obtained >= CRED_SPECIFIED) {
558 if (cred->username_obtained >= CRED_SPECIFIED) {
562 if (cli_credentials_get_kerberos_state(cred) == CRED_USE_KERBEROS_REQUIRED) {
566 gensec_features = cli_credentials_get_gensec_features(cred);
567 if (gensec_features & GENSEC_FEATURE_NTLM_CCACHE) {
571 if (gensec_features & GENSEC_FEATURE_SIGN) {
575 if (gensec_features & GENSEC_FEATURE_SEAL) {
583 * Obtain the password for this credentials context.
584 * @param cred credentials context
585 * @retval If set, the cleartext password, otherwise NULL
587 _PUBLIC_ const char *cli_credentials_get_password(struct cli_credentials *cred)
589 if (cred->machine_account_pending) {
590 cli_credentials_set_machine_account(cred,
591 cred->machine_account_pending_lp_ctx);
594 if (cred->password_obtained == CRED_CALLBACK &&
595 !cred->callback_running &&
596 !cred->password_will_be_nt_hash) {
597 cred->callback_running = true;
598 cred->password = cred->password_cb(cred);
599 cred->callback_running = false;
600 if (cred->password_obtained == CRED_CALLBACK) {
601 cred->password_obtained = CRED_CALLBACK_RESULT;
602 cli_credentials_invalidate_ccache(cred, cred->password_obtained);
606 return cred->password;
610 * @brief Find out how the password was obtained.
612 * @param cred A credentials context.
614 * @return The obtained information for the password.
616 _PUBLIC_ enum credentials_obtained
617 cli_credentials_get_password_obtained(struct cli_credentials *cred)
619 return cred->password_obtained;
623 * @brief Obtain the password for this credentials context.
625 * @param[in] cred The credential context.
627 * @param[in] obtained A pointer to store the obtained information.
629 * return The password if there is one.
631 _PUBLIC_ const char *
632 cli_credentials_get_password_and_obtained(struct cli_credentials *cred,
633 enum credentials_obtained *obtained)
635 const char *password = cli_credentials_get_password(cred);
637 if (obtained != NULL) {
638 *obtained = cred->password_obtained;
644 /* Set a password on the credentials context, including an indication
645 * of 'how' the password was obtained */
647 _PUBLIC_ bool cli_credentials_set_password(struct cli_credentials *cred,
649 enum credentials_obtained obtained)
651 if (obtained >= cred->password_obtained) {
653 cred->lm_response = data_blob_null;
654 cred->nt_response = data_blob_null;
655 cred->nt_hash = NULL;
656 cred->password = NULL;
658 cli_credentials_invalidate_ccache(cred, obtained);
660 cred->password_tries = 0;
663 cred->password_obtained = obtained;
667 if (cred->password_will_be_nt_hash) {
668 struct samr_Password *nt_hash = NULL;
669 size_t val_len = strlen(val);
672 nt_hash = talloc(cred, struct samr_Password);
673 if (nt_hash == NULL) {
676 talloc_keep_secret(nt_hash);
678 converted = strhex_to_str((char *)nt_hash->hash,
679 sizeof(nt_hash->hash),
681 if (converted != sizeof(nt_hash->hash)) {
682 TALLOC_FREE(nt_hash);
686 cred->nt_hash = nt_hash;
687 cred->password_obtained = obtained;
691 cred->password = talloc_strdup(cred, val);
692 if (cred->password == NULL) {
695 talloc_keep_secret(discard_const(cred->password));
697 /* Don't print the actual password in talloc memory dumps */
698 talloc_set_name_const(cred->password,
699 "password set via cli_credentials_set_password");
700 cred->password_obtained = obtained;
708 _PUBLIC_ bool cli_credentials_set_password_callback(struct cli_credentials *cred,
709 const char *(*password_cb) (struct cli_credentials *))
711 if (cred->password_obtained < CRED_CALLBACK) {
712 cred->password_tries = 3;
713 cred->password_cb = password_cb;
714 cred->password_obtained = CRED_CALLBACK;
715 cli_credentials_invalidate_ccache(cred, cred->password_obtained);
723 * Obtain the 'old' password for this credentials context (used for join accounts).
724 * @param cred credentials context
725 * @retval If set, the cleartext password, otherwise NULL
727 _PUBLIC_ const char *cli_credentials_get_old_password(struct cli_credentials *cred)
729 if (cred->machine_account_pending) {
730 cli_credentials_set_machine_account(cred,
731 cred->machine_account_pending_lp_ctx);
734 return cred->old_password;
737 _PUBLIC_ bool cli_credentials_set_old_password(struct cli_credentials *cred,
739 enum credentials_obtained obtained)
741 cred->old_password = talloc_strdup(cred, val);
742 if (cred->old_password) {
743 /* Don't print the actual password in talloc memory dumps */
744 talloc_set_name_const(cred->old_password, "password set via cli_credentials_set_old_password");
746 cred->old_nt_hash = NULL;
751 * Obtain the password, in the form MD4(unicode(password)) for this credentials context.
753 * Sometimes we only have this much of the password, while the rest of
754 * the time this call avoids calling E_md4hash themselves.
756 * @param cred credentials context
757 * @retval If set, the cleartext password, otherwise NULL
759 _PUBLIC_ struct samr_Password *cli_credentials_get_nt_hash(struct cli_credentials *cred,
762 enum credentials_obtained password_obtained;
763 enum credentials_obtained ccache_threshold;
764 enum credentials_obtained client_gss_creds_threshold;
765 bool password_is_nt_hash;
766 const char *password = NULL;
767 struct samr_Password *nt_hash = NULL;
769 if (cred->nt_hash != NULL) {
771 * If we already have a hash it's easy.
777 * This is a bit tricky, with password_will_be_nt_hash
778 * we still need to get the value via the password_callback
779 * but if we did that we should not remember it's state
780 * in the long run so we need to undo it.
783 password_obtained = cred->password_obtained;
784 ccache_threshold = cred->ccache_threshold;
785 client_gss_creds_threshold = cred->client_gss_creds_threshold;
786 password_is_nt_hash = cred->password_will_be_nt_hash;
788 cred->password_will_be_nt_hash = false;
789 password = cli_credentials_get_password(cred);
791 cred->password_will_be_nt_hash = password_is_nt_hash;
792 if (password_is_nt_hash && password_obtained == CRED_CALLBACK) {
794 * We got the nt_hash as string via the callback,
795 * so we need to undo the state change.
797 * And also don't remember it as plaintext password.
799 cred->client_gss_creds_threshold = client_gss_creds_threshold;
800 cred->ccache_threshold = ccache_threshold;
801 cred->password_obtained = password_obtained;
802 cred->password = NULL;
805 if (password == NULL) {
809 nt_hash = talloc(cred, struct samr_Password);
810 if (nt_hash == NULL) {
813 talloc_keep_secret(nt_hash);
815 if (password_is_nt_hash) {
816 size_t password_len = strlen(password);
819 converted = strhex_to_str((char *)nt_hash->hash,
820 sizeof(nt_hash->hash),
821 password, password_len);
822 if (converted != sizeof(nt_hash->hash)) {
823 TALLOC_FREE(nt_hash);
827 E_md4hash(password, nt_hash->hash);
830 cred->nt_hash = nt_hash;
834 nt_hash = talloc(mem_ctx, struct samr_Password);
835 if (nt_hash == NULL) {
838 talloc_keep_secret(nt_hash);
840 *nt_hash = *cred->nt_hash;
846 * Obtain the old password, in the form MD4(unicode(password)) for this credentials context.
848 * Sometimes we only have this much of the password, while the rest of
849 * the time this call avoids calling E_md4hash themselves.
851 * @param cred credentials context
852 * @retval If set, the cleartext password, otherwise NULL
854 _PUBLIC_ struct samr_Password *cli_credentials_get_old_nt_hash(struct cli_credentials *cred,
857 const char *old_password = NULL;
859 if (cred->old_nt_hash != NULL) {
860 struct samr_Password *nt_hash = talloc(mem_ctx, struct samr_Password);
864 talloc_keep_secret(nt_hash);
866 *nt_hash = *cred->old_nt_hash;
871 old_password = cli_credentials_get_old_password(cred);
873 struct samr_Password *nt_hash = talloc(mem_ctx, struct samr_Password);
877 talloc_keep_secret(nt_hash);
879 E_md4hash(old_password, nt_hash->hash);
888 * Obtain the 'short' or 'NetBIOS' domain for this credentials context.
889 * @param cred credentials context
890 * @retval The domain set on this context.
891 * @note Return value will never be NULL except by programmer error.
893 _PUBLIC_ const char *cli_credentials_get_domain(struct cli_credentials *cred)
895 if (cred->machine_account_pending) {
896 cli_credentials_set_machine_account(cred,
897 cred->machine_account_pending_lp_ctx);
900 if (cred->domain_obtained == CRED_CALLBACK &&
901 !cred->callback_running) {
902 cred->callback_running = true;
903 cred->domain = cred->domain_cb(cred);
904 cred->callback_running = false;
905 if (cred->domain_obtained == CRED_CALLBACK) {
906 cred->domain_obtained = CRED_CALLBACK_RESULT;
907 cli_credentials_invalidate_ccache(cred, cred->domain_obtained);
915 * @brief Obtain the domain for this credential context.
917 * @param[in] cred The credential context.
919 * @param[out] obtained A pointer to store the obtained information.
921 * @return The domain name or NULL if an error occurred.
923 _PUBLIC_ const char *cli_credentials_get_domain_and_obtained(
924 struct cli_credentials *cred,
925 enum credentials_obtained *obtained)
927 const char *domain = cli_credentials_get_domain(cred);
929 if (obtained != NULL) {
930 *obtained = cred->domain_obtained;
937 _PUBLIC_ bool cli_credentials_set_domain(struct cli_credentials *cred,
939 enum credentials_obtained obtained)
941 if (obtained >= cred->domain_obtained) {
942 /* it is important that the domain be in upper case,
943 * particularly for the sensitive NTLMv2
945 cred->domain = strupper_talloc(cred, val);
946 cred->domain_obtained = obtained;
947 /* setting domain does not mean we have to invalidate ccache
948 * because domain in not used for Kerberos operations.
949 * If ccache invalidation is required, one will anyway specify
950 * a password to kinit, and that will force invalidation of the ccache
958 bool cli_credentials_set_domain_callback(struct cli_credentials *cred,
959 const char *(*domain_cb) (struct cli_credentials *))
961 if (cred->domain_obtained < CRED_CALLBACK) {
962 cred->domain_cb = domain_cb;
963 cred->domain_obtained = CRED_CALLBACK;
971 * Obtain the Kerberos realm for this credentials context.
972 * @param cred credentials context
973 * @retval The realm set on this context.
974 * @note Return value will never be NULL except by programmer error.
976 _PUBLIC_ const char *cli_credentials_get_realm(struct cli_credentials *cred)
978 if (cred->machine_account_pending) {
979 cli_credentials_set_machine_account(cred,
980 cred->machine_account_pending_lp_ctx);
983 if (cred->realm_obtained == CRED_CALLBACK &&
984 !cred->callback_running) {
985 const char *realm = NULL;
987 cred->callback_running = true;
988 realm = cred->realm_cb(cred);
989 cred->callback_running = false;
993 cred->realm = strupper_talloc(cred, realm);
994 if (cred->realm == NULL) {
999 if (cred->realm_obtained == CRED_CALLBACK) {
1000 cred->realm_obtained = CRED_CALLBACK_RESULT;
1001 cli_credentials_invalidate_ccache(cred, cred->realm_obtained);
1009 * @brief Set the realm for this credentials context.
1011 * The realm be checked if it is ASCII only and upper cased if it isn't yet.
1013 * @param cred The credential context.
1015 * @param val The realm to set or NULL to reset.
1017 * @param obtained This way the described realm was specified.
1019 * @return true on success, false if the realm is not ASCII or the allocation
1022 _PUBLIC_ bool cli_credentials_set_realm(struct cli_credentials *cred,
1024 enum credentials_obtained obtained)
1026 if (obtained >= cred->realm_obtained) {
1027 /* If `val = NULL` is passed, realm is reset */
1030 /* For realm names, only ASCII is allowed */
1031 if (!str_is_ascii(val)) {
1035 cred->realm = strupper_talloc(cred, val);
1036 if (cred->realm == NULL) {
1040 cred->realm_obtained = obtained;
1041 cli_credentials_invalidate_ccache(cred, cred->realm_obtained);
1048 bool cli_credentials_set_realm_callback(struct cli_credentials *cred,
1049 const char *(*realm_cb) (struct cli_credentials *))
1051 if (cred->realm_obtained < CRED_CALLBACK) {
1052 cred->realm_cb = realm_cb;
1053 cred->realm_obtained = CRED_CALLBACK;
1061 * Obtain the 'short' or 'NetBIOS' workstation name for this credentials context.
1063 * @param cred credentials context
1064 * @retval The workstation name set on this context.
1065 * @note Return value will never be NULL except by programmer error.
1067 _PUBLIC_ const char *cli_credentials_get_workstation(struct cli_credentials *cred)
1069 if (cred->workstation_obtained == CRED_CALLBACK &&
1070 !cred->callback_running) {
1071 cred->callback_running = true;
1072 cred->workstation = cred->workstation_cb(cred);
1073 cred->callback_running = false;
1074 if (cred->workstation_obtained == CRED_CALLBACK) {
1075 cred->workstation_obtained = CRED_CALLBACK_RESULT;
1079 return cred->workstation;
1082 _PUBLIC_ bool cli_credentials_set_workstation(struct cli_credentials *cred,
1084 enum credentials_obtained obtained)
1086 if (obtained >= cred->workstation_obtained) {
1087 cred->workstation = talloc_strdup(cred, val);
1088 cred->workstation_obtained = obtained;
1095 bool cli_credentials_set_workstation_callback(struct cli_credentials *cred,
1096 const char *(*workstation_cb) (struct cli_credentials *))
1098 if (cred->workstation_obtained < CRED_CALLBACK) {
1099 cred->workstation_cb = workstation_cb;
1100 cred->workstation_obtained = CRED_CALLBACK;
1108 * Given a string, typically obtained from a -U argument, parse it into domain, username, realm and password fields
1110 * The format accepted is [domain\\]user[%password] or user[@realm][%password]
1112 * @param credentials Credentials structure on which to set the password
1113 * @param data the string containing the username, password etc
1114 * @param obtained This enum describes how 'specified' this password is
1117 _PUBLIC_ void cli_credentials_parse_string(struct cli_credentials *credentials, const char *data, enum credentials_obtained obtained)
1120 char *uname_free = NULL;
1122 if (strcmp("%",data) == 0) {
1123 cli_credentials_set_anonymous(credentials);
1127 uname = talloc_strdup(credentials, data);
1130 if ((p = strchr_m(uname,'%'))) {
1132 cli_credentials_set_password(credentials, p+1, obtained);
1135 if ((p = strchr_m(uname,'@'))) {
1137 * We also need to set username and domain
1138 * in order to undo the effect of
1139 * cli_credentials_guess().
1141 cli_credentials_set_username(credentials, uname, obtained);
1142 cli_credentials_set_domain(credentials, "", obtained);
1144 cli_credentials_set_principal(credentials, uname, obtained);
1146 cli_credentials_set_realm(credentials, p+1, obtained);
1147 TALLOC_FREE(uname_free);
1149 } else if ((p = strchr_m(uname,'\\'))
1150 || (p = strchr_m(uname, '/'))
1151 || (p = strchr_m(uname, credentials->winbind_separator)))
1153 const char *domain = NULL;
1159 if (obtained == credentials->realm_obtained &&
1160 !strequal_m(credentials->domain, domain))
1163 * We need to undo a former set with the same level
1164 * in order to get the expected result from
1165 * cli_credentials_get_principal().
1167 * But we only need to do that if the domain
1170 cli_credentials_set_realm(credentials, domain, obtained);
1172 cli_credentials_set_domain(credentials, domain, obtained);
1174 if (obtained == credentials->principal_obtained &&
1175 !strequal_m(credentials->username, uname))
1178 * We need to undo a former set with the same level
1179 * in order to get the expected result from
1180 * cli_credentials_get_principal().
1182 * But we only need to do that if the username
1185 credentials->principal_obtained = CRED_UNINITIALISED;
1186 credentials->principal = NULL;
1188 cli_credentials_set_username(credentials, uname, obtained);
1190 TALLOC_FREE(uname_free);
1194 * Given a a credentials structure, print it as a string
1196 * The format output is [domain\\]user[%password] or user[@realm][%password]
1198 * @param credentials Credentials structure on which to set the password
1199 * @param mem_ctx The memory context to place the result on
1202 _PUBLIC_ char *cli_credentials_get_unparsed_name(struct cli_credentials *credentials, TALLOC_CTX *mem_ctx)
1204 const char *bind_dn = cli_credentials_get_bind_dn(credentials);
1205 const char *domain = NULL;
1206 const char *username = NULL;
1210 name = talloc_strdup(mem_ctx, bind_dn);
1212 cli_credentials_get_ntlm_username_domain(credentials, mem_ctx, &username, &domain);
1213 if (domain && domain[0]) {
1214 name = talloc_asprintf(mem_ctx, "%s\\%s",
1217 name = talloc_asprintf(mem_ctx, "%s",
1226 * Specifies default values for domain, workstation and realm
1227 * from the smb.conf configuration file
1229 * @param cred Credentials structure to fill in
1231 * @return true on success, false on error.
1233 _PUBLIC_ bool cli_credentials_set_conf(struct cli_credentials *cred,
1234 struct loadparm_context *lp_ctx)
1236 const char *sep = NULL;
1237 const char *realm = lpcfg_realm(lp_ctx);
1238 enum credentials_client_protection protection =
1239 lpcfg_client_protection(lp_ctx);
1240 const char *workgroup = lpcfg_workgroup(lp_ctx);
1241 const char *netbios_name = lpcfg_netbios_name(lp_ctx);
1244 (void)cli_credentials_set_username(cred, "", CRED_UNINITIALISED);
1246 if (workgroup != NULL && strlen(workgroup) == 0) {
1250 if (workgroup != NULL) {
1251 if (lpcfg_parm_is_cmdline(lp_ctx, "workgroup")) {
1252 ok = cli_credentials_set_domain(cred,
1256 DBG_ERR("Failed to set domain!\n");
1260 (void)cli_credentials_set_domain(cred,
1266 if (netbios_name != NULL && strlen(netbios_name) == 0) {
1267 netbios_name = NULL;
1270 if (netbios_name != NULL) {
1271 if (lpcfg_parm_is_cmdline(lp_ctx, "netbios name")) {
1272 ok = cli_credentials_set_workstation(cred,
1276 DBG_ERR("Failed to set workstation!\n");
1280 (void)cli_credentials_set_workstation(cred,
1286 if (realm != NULL && strlen(realm) == 0) {
1290 if (realm != NULL) {
1291 if (lpcfg_parm_is_cmdline(lp_ctx, "realm")) {
1292 ok = cli_credentials_set_realm(cred,
1296 DBG_ERR("Failed to set realm!\n");
1300 (void)cli_credentials_set_realm(cred,
1306 sep = lpcfg_winbind_separator(lp_ctx);
1307 if (sep != NULL && sep[0] != '\0') {
1308 cred->winbind_separator = *lpcfg_winbind_separator(lp_ctx);
1311 if (cred->signing_state_obtained <= CRED_SMB_CONF) {
1312 /* Will be set to default for invalid smb.conf values */
1313 cred->signing_state = lpcfg_client_signing(lp_ctx);
1314 if (cred->signing_state == SMB_SIGNING_DEFAULT) {
1315 switch (protection) {
1316 case CRED_CLIENT_PROTECTION_DEFAULT:
1318 case CRED_CLIENT_PROTECTION_PLAIN:
1319 cred->signing_state = SMB_SIGNING_OFF;
1321 case CRED_CLIENT_PROTECTION_SIGN:
1322 case CRED_CLIENT_PROTECTION_ENCRYPT:
1323 cred->signing_state = SMB_SIGNING_REQUIRED;
1328 cred->signing_state_obtained = CRED_SMB_CONF;
1331 if (cred->ipc_signing_state_obtained <= CRED_SMB_CONF) {
1332 /* Will be set to required for invalid smb.conf values */
1333 cred->ipc_signing_state = lpcfg_client_ipc_signing(lp_ctx);
1334 cred->ipc_signing_state_obtained = CRED_SMB_CONF;
1337 if (cred->encryption_state_obtained <= CRED_SMB_CONF) {
1338 /* Will be set to default for invalid smb.conf values */
1339 cred->encryption_state = lpcfg_client_smb_encrypt(lp_ctx);
1340 if (cred->encryption_state == SMB_ENCRYPTION_DEFAULT) {
1341 switch (protection) {
1342 case CRED_CLIENT_PROTECTION_DEFAULT:
1344 case CRED_CLIENT_PROTECTION_PLAIN:
1345 case CRED_CLIENT_PROTECTION_SIGN:
1346 cred->encryption_state = SMB_ENCRYPTION_OFF;
1348 case CRED_CLIENT_PROTECTION_ENCRYPT:
1349 cred->encryption_state = SMB_ENCRYPTION_REQUIRED;
1355 if (cred->kerberos_state_obtained <= CRED_SMB_CONF) {
1356 /* Will be set to default for invalid smb.conf values */
1357 cred->kerberos_state = lpcfg_client_use_kerberos(lp_ctx);
1358 cred->kerberos_state_obtained = CRED_SMB_CONF;
1361 if (cred->gensec_features_obtained <= CRED_SMB_CONF) {
1362 switch (protection) {
1363 case CRED_CLIENT_PROTECTION_DEFAULT:
1365 case CRED_CLIENT_PROTECTION_PLAIN:
1366 cred->gensec_features = 0;
1368 case CRED_CLIENT_PROTECTION_SIGN:
1369 cred->gensec_features = GENSEC_FEATURE_SIGN;
1371 case CRED_CLIENT_PROTECTION_ENCRYPT:
1372 cred->gensec_features =
1373 GENSEC_FEATURE_SIGN|GENSEC_FEATURE_SEAL;
1376 cred->gensec_features_obtained = CRED_SMB_CONF;
1383 * Guess defaults for credentials from environment variables,
1384 * and from the configuration file
1386 * @param cred Credentials structure to fill in
1388 _PUBLIC_ bool cli_credentials_guess(struct cli_credentials *cred,
1389 struct loadparm_context *lp_ctx)
1391 const char *error_string;
1392 const char *env = NULL;
1393 struct passwd *pwd = NULL;
1396 if (lp_ctx != NULL) {
1397 ok = cli_credentials_set_conf(cred, lp_ctx);
1403 pwd = getpwuid(getuid());
1405 size_t len = strlen(pwd->pw_name);
1407 if (len > 0 && len <= 1024) {
1408 (void)cli_credentials_parse_string(cred,
1414 env = getenv("LOGNAME");
1416 size_t len = strlen(env);
1418 if (len > 0 && len <= 1024) {
1419 (void)cli_credentials_set_username(cred,
1425 env = getenv("USER");
1427 size_t len = strlen(env);
1429 if (len > 0 && len <= 1024) {
1432 (void)cli_credentials_parse_string(cred,
1435 if ((p = strchr_m(env, '%'))) {
1436 memset(p, '\0', strlen(cred->password));
1441 env = getenv("PASSWD");
1443 size_t len = strlen(env);
1445 if (len > 0 && len <= 1024) {
1446 (void)cli_credentials_set_password(cred,
1452 env = getenv("PASSWD_FD");
1454 size_t len = strlen(env);
1456 if (len > 0 && len <= 1024) {
1459 (void)cli_credentials_parse_password_fd(cred,
1465 env = getenv("PASSWD_FILE");
1467 size_t len = strlen(env);
1469 if (len > 0 && len <= 4096) {
1470 (void)cli_credentials_parse_password_file(cred,
1476 if (lp_ctx != NULL &&
1477 cli_credentials_get_kerberos_state(cred) != CRED_USE_KERBEROS_DISABLED) {
1478 (void)cli_credentials_set_ccache(cred,
1489 * Attach NETLOGON credentials for use with SCHANNEL
1492 _PUBLIC_ void cli_credentials_set_netlogon_creds(
1493 struct cli_credentials *cred,
1494 const struct netlogon_creds_CredentialState *netlogon_creds)
1496 TALLOC_FREE(cred->netlogon_creds);
1497 if (netlogon_creds == NULL) {
1500 cred->netlogon_creds = netlogon_creds_copy(cred, netlogon_creds);
1504 * Return attached NETLOGON credentials
1507 _PUBLIC_ struct netlogon_creds_CredentialState *cli_credentials_get_netlogon_creds(struct cli_credentials *cred)
1509 return cred->netlogon_creds;
1513 * Set NETLOGON secure channel type
1516 _PUBLIC_ void cli_credentials_set_secure_channel_type(struct cli_credentials *cred,
1517 enum netr_SchannelType secure_channel_type)
1519 cred->secure_channel_type = secure_channel_type;
1523 * Return NETLOGON secure channel type
1526 _PUBLIC_ time_t cli_credentials_get_password_last_changed_time(struct cli_credentials *cred)
1528 return cred->password_last_changed_time;
1532 * Set NETLOGON secure channel type
1535 _PUBLIC_ void cli_credentials_set_password_last_changed_time(struct cli_credentials *cred,
1536 time_t last_changed_time)
1538 cred->password_last_changed_time = last_changed_time;
1542 * Return NETLOGON secure channel type
1545 _PUBLIC_ enum netr_SchannelType cli_credentials_get_secure_channel_type(struct cli_credentials *cred)
1547 return cred->secure_channel_type;
1551 * Fill in a credentials structure as the anonymous user
1553 _PUBLIC_ void cli_credentials_set_anonymous(struct cli_credentials *cred)
1555 cli_credentials_set_username(cred, "", CRED_SPECIFIED);
1556 cli_credentials_set_domain(cred, "", CRED_SPECIFIED);
1557 cli_credentials_set_password(cred, NULL, CRED_SPECIFIED);
1558 cli_credentials_set_principal(cred, NULL, CRED_SPECIFIED);
1559 cli_credentials_set_realm(cred, NULL, CRED_SPECIFIED);
1560 cli_credentials_set_workstation(cred, "", CRED_UNINITIALISED);
1561 cli_credentials_set_kerberos_state(cred,
1562 CRED_USE_KERBEROS_DISABLED,
1567 * Describe a credentials context as anonymous or authenticated
1568 * @retval true if anonymous, false if a username is specified
1571 _PUBLIC_ bool cli_credentials_is_anonymous(struct cli_credentials *cred)
1573 const char *username;
1575 /* if bind dn is set it's not anonymous */
1576 if (cred->bind_dn) {
1580 if (cred->machine_account_pending) {
1581 cli_credentials_set_machine_account(cred,
1582 cred->machine_account_pending_lp_ctx);
1585 /* if principal is set, it's not anonymous */
1586 if ((cred->principal != NULL) && cred->principal_obtained >= cred->username_obtained) {
1590 username = cli_credentials_get_username(cred);
1592 /* Yes, it is deliberate that we die if we have a NULL pointer
1593 * here - anonymous is "", not NULL, which is 'never specified,
1594 * never guessed', ie programmer bug */
1603 * Mark the current password for a credentials struct as wrong. This will
1604 * cause the password to be prompted again (if a callback is set).
1606 * This will decrement the number of times the password can be tried.
1608 * @retval whether the credentials struct is finished
1610 _PUBLIC_ bool cli_credentials_wrong_password(struct cli_credentials *cred)
1612 if (cred->password_obtained != CRED_CALLBACK_RESULT) {
1616 if (cred->password_tries == 0) {
1620 cred->password_tries--;
1622 if (cred->password_tries == 0) {
1626 cred->password_obtained = CRED_CALLBACK;
1630 _PUBLIC_ void cli_credentials_get_ntlm_username_domain(struct cli_credentials *cred, TALLOC_CTX *mem_ctx,
1631 const char **username,
1632 const char **domain)
1634 if (!cli_credentials_is_anonymous(cred) &&
1635 cred->principal_obtained >= cred->username_obtained)
1637 *domain = talloc_strdup(mem_ctx, "");
1638 *username = cli_credentials_get_principal(cred, mem_ctx);
1640 *domain = cli_credentials_get_domain(cred);
1641 *username = cli_credentials_get_username(cred);
1646 * Read a named file, and parse it for username, domain, realm and password
1648 * @param credentials Credentials structure on which to set the password
1649 * @param file a named file to read the details from
1650 * @param obtained This enum describes how 'specified' this password is
1653 _PUBLIC_ bool cli_credentials_parse_file(struct cli_credentials *cred, const char *file, enum credentials_obtained obtained)
1656 char *ptr, *val, *param;
1659 const char *realm = NULL;
1660 const char *domain = NULL;
1661 const char *password = NULL;
1662 const char *username = NULL;
1664 lines = file_lines_load(file, &numlines, 0, NULL);
1668 /* fail if we can't open the credentials file */
1669 d_printf("ERROR: Unable to open credentials file!\n");
1673 for (i = 0; i < numlines; i++) {
1674 len = strlen(lines[i]);
1679 /* break up the line into parameter & value.
1680 * will need to eat a little whitespace possibly */
1682 if (!(ptr = strchr_m (lines[i], '=')))
1688 /* eat leading white space */
1689 while ((*val!='\0') && ((*val==' ') || (*val=='\t')))
1692 if (strwicmp("password", param) == 0) {
1694 } else if (strwicmp("username", param) == 0) {
1696 } else if (strwicmp("domain", param) == 0) {
1698 } else if (strwicmp("realm", param) == 0) {
1703 * We need to readd '=' in order to let
1704 * the strlen() work in the last loop
1705 * that clears the memory.
1710 if (realm != NULL && strlen(realm) != 0) {
1712 * only overwrite with a valid string
1714 cli_credentials_set_realm(cred, realm, obtained);
1717 if (domain != NULL && strlen(domain) != 0) {
1719 * only overwrite with a valid string
1721 cli_credentials_set_domain(cred, domain, obtained);
1724 if (password != NULL) {
1728 cli_credentials_set_password(cred, password, obtained);
1731 if (username != NULL) {
1733 * The last "username" line takes preference
1734 * if the string also contains domain, realm or
1737 cli_credentials_parse_string(cred, username, obtained);
1740 for (i = 0; i < numlines; i++) {
1741 len = strlen(lines[i]);
1742 memset(lines[i], 0, len);
1750 * Read a named file, and parse it for a password
1752 * @param credentials Credentials structure on which to set the password
1753 * @param file a named file to read the password from
1754 * @param obtained This enum describes how 'specified' this password is
1757 _PUBLIC_ bool cli_credentials_parse_password_file(struct cli_credentials *credentials, const char *file, enum credentials_obtained obtained)
1759 int fd = open(file, O_RDONLY, 0);
1763 fprintf(stderr, "Error opening password file %s: %s\n",
1764 file, strerror(errno));
1768 ret = cli_credentials_parse_password_fd(credentials, fd, obtained);
1777 * Read a file descriptor, and parse it for a password (eg from a file or stdin)
1779 * @param credentials Credentials structure on which to set the password
1780 * @param fd open file descriptor to read the password from
1781 * @param obtained This enum describes how 'specified' this password is
1784 _PUBLIC_ bool cli_credentials_parse_password_fd(struct cli_credentials *credentials,
1785 int fd, enum credentials_obtained obtained)
1790 if (credentials->password_obtained >= obtained) {
1794 for(p = pass, *p = '\0'; /* ensure that pass is null-terminated */
1795 p && p - pass < sizeof(pass) - 1;) {
1796 switch (read(fd, p, 1)) {
1798 if (*p != '\n' && *p != '\0') {
1799 *++p = '\0'; /* advance p, and null-terminate pass */
1806 *p = '\0'; /* null-terminate it, just in case... */
1807 p = NULL; /* then force the loop condition to become false */
1812 "Error reading password from file descriptor "
1813 "%d: empty password\n",
1818 fprintf(stderr, "Error reading password from file descriptor %d: %s\n",
1819 fd, strerror(errno));
1824 cli_credentials_set_password(credentials, pass, obtained);
1829 * @brief Set the SMB signing state to request for a SMB connection.
1831 * @param[in] creds The credentials structure to update.
1833 * @param[in] signing_state The signing state to set.
1835 * @param obtained This way the described signing state was specified.
1837 * @return true if we could set the signing state, false otherwise.
1839 _PUBLIC_ bool cli_credentials_set_smb_signing(struct cli_credentials *creds,
1840 enum smb_signing_setting signing_state,
1841 enum credentials_obtained obtained)
1843 if (obtained >= creds->signing_state_obtained) {
1844 creds->signing_state_obtained = obtained;
1845 creds->signing_state = signing_state;
1853 * @brief Obtain the SMB signing state from a credentials structure.
1855 * @param[in] creds The credential structure to obtain the SMB signing state
1858 * @return The SMB signing state.
1860 _PUBLIC_ enum smb_signing_setting
1861 cli_credentials_get_smb_signing(struct cli_credentials *creds)
1863 return creds->signing_state;
1867 * @brief Set the SMB IPC signing state to request for a SMB connection.
1869 * @param[in] creds The credentials structure to update.
1871 * @param[in] signing_state The signing state to set.
1873 * @param obtained This way the described signing state was specified.
1875 * @return true if we could set the signing state, false otherwise.
1878 cli_credentials_set_smb_ipc_signing(struct cli_credentials *creds,
1879 enum smb_signing_setting ipc_signing_state,
1880 enum credentials_obtained obtained)
1882 if (obtained >= creds->ipc_signing_state_obtained) {
1883 creds->ipc_signing_state_obtained = obtained;
1884 creds->ipc_signing_state = ipc_signing_state;
1892 * @brief Obtain the SMB IPC signing state from a credentials structure.
1894 * @param[in] creds The credential structure to obtain the SMB IPC signing
1897 * @return The SMB signing state.
1899 _PUBLIC_ enum smb_signing_setting
1900 cli_credentials_get_smb_ipc_signing(struct cli_credentials *creds)
1902 return creds->ipc_signing_state;
1906 * @brief Set the SMB encryption state to request for a SMB connection.
1908 * @param[in] creds The credentials structure to update.
1910 * @param[in] encryption_state The encryption state to set.
1912 * @param obtained This way the described encryption state was specified.
1914 * @return true if we could set the encryption state, false otherwise.
1916 _PUBLIC_ bool cli_credentials_set_smb_encryption(struct cli_credentials *creds,
1917 enum smb_encryption_setting encryption_state,
1918 enum credentials_obtained obtained)
1920 if (obtained >= creds->encryption_state_obtained) {
1921 creds->encryption_state_obtained = obtained;
1922 creds->encryption_state = encryption_state;
1929 static const char *obtained_to_str(enum credentials_obtained obtained)
1932 case CRED_UNINITIALISED:
1933 return "CRED_UNINITIALISED";
1935 return "CRED_SMB_CONF";
1937 return "CRED_CALLBACK";
1938 case CRED_GUESS_ENV:
1939 return "CRED_GUESS_ENV";
1940 case CRED_GUESS_FILE:
1941 return "CRED_GUESS_FILE";
1942 case CRED_CALLBACK_RESULT:
1943 return "CRED_CALLBACK_RESULT";
1944 case CRED_SPECIFIED:
1945 return "CRED_SPECIFIED";
1952 static const char *krb5_state_to_str(enum credentials_use_kerberos krb5_state)
1954 switch (krb5_state) {
1955 case CRED_USE_KERBEROS_DISABLED:
1956 return "CRED_USE_KERBEROS_DISABLED";
1957 case CRED_USE_KERBEROS_DESIRED:
1958 return "CRED_USE_KERBEROS_DESIRED";
1959 case CRED_USE_KERBEROS_REQUIRED:
1960 return "CRED_USE_KERBEROS_REQUIRED";
1967 static const char *krb5_fwd_to_str(enum credentials_krb_forwardable krb5_fwd)
1970 case CRED_AUTO_KRB_FORWARDABLE:
1971 return "CRED_AUTO_KRB_FORWARDABLE";
1972 case CRED_NO_KRB_FORWARDABLE:
1973 return "CRED_NO_KRB_FORWARDABLE";
1974 case CRED_FORCE_KRB_FORWARDABLE:
1975 return "CRED_FORCE_KRB_FORWARDABLE";
1982 static const char *signing_state_to_str(enum smb_signing_setting signing_state)
1984 switch(signing_state) {
1985 case SMB_SIGNING_IPC_DEFAULT:
1986 return "SMB_SIGNING_IPC_DEFAULT";
1987 case SMB_SIGNING_DEFAULT:
1988 return "SMB_SIGNING_DEFAULT";
1989 case SMB_SIGNING_OFF:
1990 return "SMB_SIGNING_OFF";
1991 case SMB_SIGNING_IF_REQUIRED:
1992 return "SMB_SIGNING_IF_REQUIRED";
1993 case SMB_SIGNING_DESIRED:
1994 return "SMB_SIGNING_DESIRED";
1995 case SMB_SIGNING_REQUIRED:
1996 return "SMB_SIGNING_REQUIRED";
2003 static const char *encryption_state_to_str(enum smb_encryption_setting encryption_state)
2005 switch(encryption_state) {
2006 case SMB_ENCRYPTION_DEFAULT:
2007 return "SMB_ENCRYPTION_DEFAULT";
2008 case SMB_ENCRYPTION_OFF:
2009 return "SMB_ENCRYPTION_OFF";
2010 case SMB_ENCRYPTION_IF_REQUIRED:
2011 return "SMB_ENCRYPTION_IF_REQUIRED";
2012 case SMB_ENCRYPTION_DESIRED:
2013 return "SMB_ENCRYPTION_DESIRED";
2014 case SMB_ENCRYPTION_REQUIRED:
2015 return "SMB_ENCRYPTION_REQUIRED";
2022 _PUBLIC_ void cli_credentials_dump(struct cli_credentials *creds)
2024 DBG_ERR("CLI_CREDENTIALS:\n");
2026 DBG_ERR(" Username: %s - %s\n",
2028 obtained_to_str(creds->username_obtained));
2029 DBG_ERR(" Workstation: %s - %s\n",
2031 obtained_to_str(creds->workstation_obtained));
2032 DBG_ERR(" Domain: %s - %s\n",
2034 obtained_to_str(creds->domain_obtained));
2035 DBG_ERR(" Password: %s - %s\n",
2036 creds->password != NULL ? "*SECRET*" : "NULL",
2037 obtained_to_str(creds->password_obtained));
2038 DBG_ERR(" Old password: %s\n",
2039 creds->old_password != NULL ? "*SECRET*" : "NULL");
2040 DBG_ERR(" Password tries: %u\n",
2041 creds->password_tries);
2042 DBG_ERR(" Realm: %s - %s\n",
2044 obtained_to_str(creds->realm_obtained));
2045 DBG_ERR(" Principal: %s - %s\n",
2047 obtained_to_str(creds->principal_obtained));
2048 DBG_ERR(" Salt principal: %s\n",
2049 creds->salt_principal);
2050 DBG_ERR(" Impersonate principal: %s\n",
2051 creds->impersonate_principal);
2052 DBG_ERR(" Self service: %s\n",
2053 creds->self_service);
2054 DBG_ERR(" Target service: %s\n",
2055 creds->target_service);
2056 DBG_ERR(" Kerberos state: %s - %s\n",
2057 krb5_state_to_str(creds->kerberos_state),
2058 obtained_to_str(creds->kerberos_state_obtained));
2059 DBG_ERR(" Kerberos forwardable ticket: %s\n",
2060 krb5_fwd_to_str(creds->krb_forwardable));
2061 DBG_ERR(" Signing state: %s - %s\n",
2062 signing_state_to_str(creds->signing_state),
2063 obtained_to_str(creds->signing_state_obtained));
2064 DBG_ERR(" IPC signing state: %s - %s\n",
2065 signing_state_to_str(creds->ipc_signing_state),
2066 obtained_to_str(creds->ipc_signing_state_obtained));
2067 DBG_ERR(" Encryption state: %s - %s\n",
2068 encryption_state_to_str(creds->encryption_state),
2069 obtained_to_str(creds->encryption_state_obtained));
2070 DBG_ERR(" Gensec features: %#X\n",
2071 creds->gensec_features);
2072 DBG_ERR(" Forced sasl mech: %s\n",
2073 creds->forced_sasl_mech);
2074 DBG_ERR(" CCACHE: %p - %s\n",
2076 obtained_to_str(creds->ccache_obtained));
2077 DBG_ERR(" CLIENT_GSS_CREDS: %p - %s\n",
2078 creds->client_gss_creds,
2079 obtained_to_str(creds->client_gss_creds_obtained));
2080 DBG_ERR(" SERVER_GSS_CREDS: %p - %s\n",
2081 creds->server_gss_creds,
2082 obtained_to_str(creds->server_gss_creds_obtained));
2083 DBG_ERR(" KEYTAB: %p - %s\n",
2085 obtained_to_str(creds->keytab_obtained));
2086 DBG_ERR(" KVNO: %u\n",
2092 * @brief Obtain the SMB encryption state from a credentials structure.
2094 * @param[in] creds The credential structure to obtain the SMB encryption state
2097 * @return The SMB signing state.
2099 _PUBLIC_ enum smb_encryption_setting
2100 cli_credentials_get_smb_encryption(struct cli_credentials *creds)
2102 return creds->encryption_state;