]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s3:libads: let ads_krb5_set_password() require an explicit krb5 ccache to operate on
authorStefan Metzmacher <metze@samba.org>
Mon, 11 Mar 2024 16:45:43 +0000 (17:45 +0100)
committerStefan Metzmacher <metze@samba.org>
Tue, 14 May 2024 10:18:31 +0000 (10:18 +0000)
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
source3/libads/kerberos_proto.h
source3/libads/krb5_setpw.c
source3/utils/net_ads.c

index b86feda3b7a673c04ed1b2ee3d50488bcf0f72bf..d3eea0f1544f1ae52b7b5e68fbf631e071aaba36 100644 (file)
@@ -85,7 +85,8 @@ NTSTATUS kerberos_return_pac(TALLOC_CTX *mem_ctx,
 /* The following definitions come from libads/krb5_setpw.c  */
 
 ADS_STATUS ads_krb5_set_password(const char *princ,
-                                const char *newpw);
+                                const char *newpw,
+                                const char *ccname);
 ADS_STATUS kerberos_set_password(const char *auth_principal,
                                 const char *auth_password,
                                 const char *target_principal,
index 11aff8131fbde4bb2bc66d74c4cd8ac1a809b113..787de96f7765032a1c569efb994c53f65f18900a 100644 (file)
@@ -57,7 +57,8 @@ static krb5_error_code kpasswd_err_to_krb5_err(krb5_error_code res_code)
 }
 
 ADS_STATUS ads_krb5_set_password(const char *principal,
-                                const char *newpw)
+                                const char *newpw,
+                                const char *ccname)
 {
 
        ADS_STATUS aret;
@@ -69,6 +70,12 @@ ADS_STATUS ads_krb5_set_password(const char *principal,
        krb5_data result_code_string = { 0 };
        krb5_data result_string = { 0 };
 
+       if (ccname == NULL) {
+               DBG_ERR("Missing ccache for [%s] and config [%s]\n",
+                       principal, getenv("KRB5_CONFIG"));
+               return ADS_ERROR_NT(NT_STATUS_WRONG_CREDENTIAL_HANDLE);
+       }
+
        ret = smb_krb5_init_context_common(&context);
        if (ret) {
                DBG_ERR("kerberos init context failed (%s)\n",
@@ -86,11 +93,12 @@ ADS_STATUS ads_krb5_set_password(const char *principal,
                }
        }
 
-       ret = krb5_cc_default(context, &ccache);
+       ret = krb5_cc_resolve(context, ccname, &ccache);
        if (ret) {
                krb5_free_principal(context, princ);
                krb5_free_context(context);
-               DEBUG(1,("Failed to get default creds (%s)\n", error_message(ret)));
+               DBG_WARNING("Failed to get creds from [%s] (%s)\n",
+                           ccname, error_message(ret));
                return ADS_ERROR_KRB5(ret);
        }
 
@@ -302,7 +310,11 @@ ADS_STATUS kerberos_set_password(const char *auth_principal,
                                 const char *target_principal,
                                 const char *new_password)
 {
-       const int time_offset = 0;
+       TALLOC_CTX *frame = NULL;
+       krb5_context ctx = NULL;
+       krb5_ccache ccid = NULL;
+       char *ccname = NULL;
+       ADS_STATUS status;
        int ret;
 
        if (strcmp(auth_principal, target_principal) == 0) {
@@ -315,13 +327,56 @@ ADS_STATUS kerberos_set_password(const char *auth_principal,
                                             new_password);
        }
 
-       if ((ret = kerberos_kinit_password(auth_principal, auth_password, time_offset, NULL))) {
-               DEBUG(1,("Failed kinit for principal %s (%s)\n", auth_principal, error_message(ret)));
-               return ADS_ERROR_KRB5(ret);
+       frame = talloc_stackframe();
+
+       ret = smb_krb5_init_context_common(&ctx);
+       if (ret != 0) {
+               status = ADS_ERROR_KRB5(ret);
+               goto done;
+       }
+
+       ret = smb_krb5_cc_new_unique_memory(ctx,
+                                           frame,
+                                           &ccname,
+                                           &ccid);
+       if (ret != 0) {
+               status = ADS_ERROR_KRB5(ret);
+               goto done;
        }
 
-       return ads_krb5_set_password(target_principal,
-                                    new_password);
+       ret = kerberos_kinit_password(auth_principal,
+                                     auth_password,
+                                     0, /* timeoutset */
+                                     ccname);
+       if (ret != 0) {
+               DBG_ERR("Failed kinit for principal %s (%s)\n",
+                       auth_principal, error_message(ret));
+               status = ADS_ERROR_KRB5(ret);
+               goto done;
+       }
+
+       status = ads_krb5_set_password(target_principal,
+                                      new_password,
+                                      ccname);
+       if (!ADS_ERR_OK(status)) {
+               DBG_ERR("Failed to set password for %s as %s: %s\n",
+                       target_principal,
+                       auth_principal,
+                       ads_errstr(status));
+               goto done;
+       }
+
+done:
+       if (ccid != NULL) {
+               krb5_cc_destroy(ctx, ccid);
+               ccid = NULL;
+       }
+       if (ctx != NULL) {
+               krb5_free_context(ctx);
+               ctx = NULL;
+       }
+       TALLOC_FREE(frame);
+       return status;
 }
 
 #endif
index 1144a31de7aab41c70c824641358e55572122949..0555ecaad0a090ce49466eafb7b175139c11752c 100644 (file)
@@ -969,6 +969,7 @@ static int ads_user_add(struct net_context *c, int argc, const char **argv)
        ADS_STATUS status;
        char *upn, *userdn;
        LDAPMessage *res=NULL;
+       const char *creds_ccname = NULL;
        int rc = -1;
        char *ou_str = NULL;
 
@@ -1037,7 +1038,13 @@ static int ads_user_add(struct net_context *c, int argc, const char **argv)
                goto done;
        }
 
-       status = ads_krb5_set_password(upn, argv[1]);
+       /*
+        * For this commit we still rely on use_in_memory_ccache()
+        * being used, but that will change in the next one...
+        */
+       creds_ccname = "MEMORY:net_ads";
+
+       status = ads_krb5_set_password(upn, argv[1], creds_ccname);
        if (ADS_ERR_OK(status)) {
                d_printf(_("User %s added\n"), argv[0]);
                rc = 0;