s3-kerberos: fix some build warnings when building against heimdal.
[gd/samba-autobuild/.git] / source3 / libads / kerberos.c
index b37b9a500fb97d12b91097649e54c2a4ea96023f..89357b01fbd801f47bda155fc0db5f01d98caa04 100644 (file)
@@ -46,9 +46,9 @@ kerb_prompter(krb5_context ctx, void *data,
        memset(prompts[0].reply->data, '\0', prompts[0].reply->length);
        if (prompts[0].reply->length > 0) {
                if (data) {
-                       strncpy(prompts[0].reply->data, (const char *)data,
+                       strncpy((char *)prompts[0].reply->data, (const char *)data,
                                prompts[0].reply->length-1);
-                       prompts[0].reply->length = strlen(prompts[0].reply->data);
+                       prompts[0].reply->length = strlen((const char *)prompts[0].reply->data);
                } else {
                        prompts[0].reply->length = 0;
                }
@@ -56,47 +56,14 @@ kerb_prompter(krb5_context ctx, void *data,
        return 0;
 }
 
-static bool smb_krb5_err_io_nstatus(TALLOC_CTX *mem_ctx, 
-                                   DATA_BLOB *edata_blob, 
-                                   KRB5_EDATA_NTSTATUS *edata)
-{
-       bool ret = False;
-       prs_struct ps;
-
-       if (!mem_ctx || !edata_blob || !edata) 
-               return False;
-
-       if (!prs_init(&ps, edata_blob->length, mem_ctx, UNMARSHALL))
-               return False;
-
-       if (!prs_copy_data_in(&ps, (char *)edata_blob->data, edata_blob->length))
-               goto out;
-
-       prs_set_offset(&ps, 0);
-
-       if (!prs_ntstatus("ntstatus", &ps, 1, &edata->ntstatus))
-               goto out;
-
-       if (!prs_uint32("unknown1", &ps, 1, &edata->unknown1))
-               goto out;
-
-       if (!prs_uint32("unknown2", &ps, 1, &edata->unknown2)) /* only seen 00000001 here */
-               goto out;
-
-       ret = True;
- out:
-       prs_mem_free(&ps);
-
-       return ret;
-}
-
  static bool smb_krb5_get_ntstatus_from_krb5_error(krb5_error *error,
                                                   NTSTATUS *nt_status)
 {
        DATA_BLOB edata;
        DATA_BLOB unwrapped_edata;
        TALLOC_CTX *mem_ctx;
-       KRB5_EDATA_NTSTATUS parsed_edata;
+       struct KRB5_EDATA_NTSTATUS parsed_edata;
+       enum ndr_err_code ndr_err;
 
 #ifdef HAVE_E_DATA_POINTER_IN_KRB5_ERROR
        edata = data_blob(error->e_data->data, error->e_data->length);
@@ -122,7 +89,10 @@ static bool smb_krb5_err_io_nstatus(TALLOC_CTX *mem_ctx,
 
        data_blob_free(&edata);
 
-       if (!smb_krb5_err_io_nstatus(mem_ctx, &unwrapped_edata, &parsed_edata)) {
+       ndr_err = ndr_pull_struct_blob_all(&unwrapped_edata, mem_ctx, NULL,
+                       &parsed_edata,
+                       (ndr_pull_flags_fn_t)ndr_pull_KRB5_EDATA_NTSTATUS);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                data_blob_free(&unwrapped_edata);
                TALLOC_FREE(mem_ctx);
                return False;
@@ -323,6 +293,11 @@ int ads_kinit_password(ADS_STRUCT *ads)
        const char *account_name;
        fstring acct_name;
 
+       if (ads->auth.flags & ADS_AUTH_USER_CREDS) {
+               account_name = ads->auth.user_name;
+               goto got_accountname;
+       }
+
        if ( IS_DC ) {
                /* this will end up getting a ticket for DOMAIN@RUSTED.REA.LM */
                account_name = lp_workgroup();
@@ -338,6 +313,7 @@ int ads_kinit_password(ADS_STRUCT *ads)
                        account_name = ads->auth.user_name;
        }
 
+ got_accountname:
        if (asprintf(&s, "%s@%s", account_name, ads->auth.realm) == -1) {
                return KRB5_CC_NOMEM;
        }
@@ -535,13 +511,13 @@ char *kerberos_get_default_realm_from_ccache( void )
 
   out:
 
-       if (princ) {
-               krb5_free_principal(ctx, princ);
-       }
-       if (cc) {
-               krb5_cc_close(ctx, cc);
-       }
        if (ctx) {
+               if (princ) {
+                       krb5_free_principal(ctx, princ);
+               }
+               if (cc) {
+                       krb5_cc_close(ctx, cc);
+               }
                krb5_free_context(ctx);
        }
 
@@ -569,7 +545,7 @@ krb5_principal kerberos_fetch_salt_princ_for_host_princ(krb5_context context,
        
                /* look under the old key.  If this fails, just use the standard key */
 
-               if (smb_krb5_unparse_name(context, host_princ, &unparsed_name) != 0) {
+               if (smb_krb5_unparse_name(talloc_tos(), context, host_princ, &unparsed_name) != 0) {
                        return (krb5_principal)NULL;
                }
                if ((salt_princ_s = kerberos_secrets_fetch_salting_principal(unparsed_name, enctype)) == NULL) {
@@ -582,7 +558,7 @@ krb5_principal kerberos_fetch_salt_princ_for_host_princ(krb5_context context,
                ret_princ = NULL;
        }
        
-       SAFE_FREE(unparsed_name);
+       TALLOC_FREE(unparsed_name);
        SAFE_FREE(salt_princ_s);
        
        return ret_princ;
@@ -606,9 +582,11 @@ bool kerberos_secrets_store_salting_principal(const char *service,
        krb5_principal princ = NULL;
        char *princ_s = NULL;
        char *unparsed_name = NULL;
+       krb5_error_code code;
 
-       krb5_init_context(&context);
-       if (!context) {
+       if (((code = krb5_init_context(&context)) != 0) || (context == NULL)) {
+               DEBUG(5, ("kerberos_secrets_store_salting_pricipal: kdb5_init_context failed: %s\n",
+                         error_message(code)));
                return False;
        }
        if (strchr_m(service, '@')) {
@@ -625,7 +603,7 @@ bool kerberos_secrets_store_salting_principal(const char *service,
                goto out;
                
        }
-       if (smb_krb5_unparse_name(context, princ, &unparsed_name) != 0) {
+       if (smb_krb5_unparse_name(talloc_tos(), context, princ, &unparsed_name) != 0) {
                goto out;
        }
 
@@ -645,7 +623,11 @@ bool kerberos_secrets_store_salting_principal(const char *service,
 
        SAFE_FREE(key);
        SAFE_FREE(princ_s);
-       SAFE_FREE(unparsed_name);
+       TALLOC_FREE(unparsed_name);
+
+       if (princ) {
+               krb5_free_principal(context, princ);
+       }
 
        if (context) {
                krb5_free_context(context);
@@ -729,6 +711,9 @@ static char *print_kdc_line(char *mem_ctx,
 /************************************************************************
  Create a string list of available kdc's, possibly searching by sitename.
  Does DNS queries.
+
+ If "sitename" is given, the DC's in that site are listed first.
+
 ************************************************************************/
 
 static char *get_kdc_ip_string(char *mem_ctx,
@@ -747,14 +732,18 @@ static char *get_kdc_ip_string(char *mem_ctx,
                return NULL;
        }
 
-       /* Get the KDC's only in this site. */
+       /*
+        * First get the KDC's only in this site, the rest will be
+        * appended later
+        */
 
        if (sitename) {
 
                get_kdc_list(realm, sitename, &ip_srv_site, &count_site);
 
                for (i = 0; i < count_site; i++) {
-                       if (addr_equal(&ip_srv_site[i].ss, pss)) {
+                       if (sockaddr_equal((struct sockaddr *)&ip_srv_site[i].ss,
+                                                  (struct sockaddr *)pss)) {
                                continue;
                        }
                        /* Append to the string - inefficient
@@ -776,14 +765,14 @@ static char *get_kdc_ip_string(char *mem_ctx,
        for (i = 0; i < count_nonsite; i++) {
                int j;
 
-               if (addr_equal(&ip_srv_nonsite[i].ss, pss)) {
+               if (sockaddr_equal((struct sockaddr *)&ip_srv_nonsite[i].ss, (struct sockaddr *)pss)) {
                        continue;
                }
 
                /* Ensure this isn't an IP already seen (YUK! this is n*n....) */
                for (j = 0; j < count_site; j++) {
-                       if (addr_equal(&ip_srv_nonsite[i].ss,
-                                               &ip_srv_site[j].ss)) {
+                       if (sockaddr_equal((struct sockaddr *)&ip_srv_nonsite[i].ss,
+                                               (struct sockaddr *)&ip_srv_site[j].ss)) {
                                break;
                        }
                        /* As the lists are sorted we can break early if nonsite > site. */
@@ -828,7 +817,7 @@ bool create_local_private_krb5_conf_for_domain(const char *realm,
                                                const char *sitename,
                                                struct sockaddr_storage *pss)
 {
-       char *dname = talloc_asprintf(NULL, "%s/smb_krb5", lp_lockdir());
+       char *dname;
        char *tmpname = NULL;
        char *fname = NULL;
        char *file_contents = NULL;
@@ -837,28 +826,31 @@ bool create_local_private_krb5_conf_for_domain(const char *realm,
        ssize_t ret;
        int fd;
        char *realm_upper = NULL;
+       bool result = false;
+
+       if (!lp_create_krb5_conf()) {
+               return false;
+       }
 
+       dname = lock_path("smb_krb5");
        if (!dname) {
-               return False;
+               return false;
        }
        if ((mkdir(dname, 0755)==-1) && (errno != EEXIST)) {
                DEBUG(0,("create_local_private_krb5_conf_for_domain: "
                        "failed to create directory %s. Error was %s\n",
                        dname, strerror(errno) ));
-               TALLOC_FREE(dname);
-               return False;
+               goto done;
        }
 
-       tmpname = talloc_asprintf(dname, "%s/smb_tmp_krb5.XXXXXX", lp_lockdir());
+       tmpname = lock_path("smb_tmp_krb5.XXXXXX");
        if (!tmpname) {
-               TALLOC_FREE(dname);
-               return False;
+               goto done;
        }
 
        fname = talloc_asprintf(dname, "%s/krb5.conf.%s", dname, domain);
        if (!fname) {
-               TALLOC_FREE(dname);
-               return False;
+               goto done;
        }
 
        DEBUG(10,("create_local_private_krb5_conf_for_domain: fname = %s, realm = %s, domain = %s\n",
@@ -869,31 +861,30 @@ bool create_local_private_krb5_conf_for_domain(const char *realm,
 
        kdc_ip_string = get_kdc_ip_string(dname, realm, sitename, pss);
        if (!kdc_ip_string) {
-               TALLOC_FREE(dname);
-               return False;
+               goto done;
        }
 
        file_contents = talloc_asprintf(fname,
                                        "[libdefaults]\n\tdefault_realm = %s\n"
-                                       "default_tgs_enctypes = RC4-HMAC DES-CBC-CRC DES-CBC-MD5\n"
-                                       "default_tkt_enctypes = RC4-HMAC DES-CBC-CRC DES-CBC-MD5\n"
-                                       "preferred_enctypes = RC4-HMAC DES-CBC-CRC DES-CBC-MD5\n\n"
+                                       "\tdefault_tgs_enctypes = RC4-HMAC DES-CBC-CRC DES-CBC-MD5\n"
+                                       "\tdefault_tkt_enctypes = RC4-HMAC DES-CBC-CRC DES-CBC-MD5\n"
+                                       "\tpreferred_enctypes = RC4-HMAC DES-CBC-CRC DES-CBC-MD5\n\n"
                                        "[realms]\n\t%s = {\n"
                                        "\t%s\t}\n",
                                        realm_upper, realm_upper, kdc_ip_string);
 
        if (!file_contents) {
-               TALLOC_FREE(dname);
-               return False;
+               goto done;
        }
 
        flen = strlen(file_contents);
 
-       fd = smb_mkstemp(tmpname);
+       fd = mkstemp(tmpname);
        if (fd == -1) {
                DEBUG(0,("create_local_private_krb5_conf_for_domain: smb_mkstemp failed,"
                        " for file %s. Errno %s\n",
                        tmpname, strerror(errno) ));
+               goto done;
        }
 
        if (fchmod(fd, 0644)==-1) {
@@ -902,8 +893,7 @@ bool create_local_private_krb5_conf_for_domain(const char *realm,
                        tmpname, strerror(errno) ));
                unlink(tmpname);
                close(fd);
-               TALLOC_FREE(dname);
-               return False;
+               goto done;
        }
 
        ret = write(fd, file_contents, flen);
@@ -913,15 +903,13 @@ bool create_local_private_krb5_conf_for_domain(const char *realm,
                        (int)ret, (unsigned int)flen, strerror(errno) ));
                unlink(tmpname);
                close(fd);
-               TALLOC_FREE(dname);
-               return False;
+               goto done;
        }
        if (close(fd)==-1) {
                DEBUG(0,("create_local_private_krb5_conf_for_domain: close failed."
                        " Errno %s\n", strerror(errno) ));
                unlink(tmpname);
-               TALLOC_FREE(dname);
-               return False;
+               goto done;
        }
 
        if (rename(tmpname, fname) == -1) {
@@ -929,8 +917,7 @@ bool create_local_private_krb5_conf_for_domain(const char *realm,
                        "of %s to %s failed. Errno %s\n",
                        tmpname, fname, strerror(errno) ));
                unlink(tmpname);
-               TALLOC_FREE(dname);
-               return False;
+               goto done;
        }
 
        DEBUG(5,("create_local_private_krb5_conf_for_domain: wrote "
@@ -940,6 +927,8 @@ bool create_local_private_krb5_conf_for_domain(const char *realm,
        /* Set the environment variable to this file. */
        setenv("KRB5_CONFIG", fname, 1);
 
+       result = true;
+
 #if defined(OVERWRITE_SYSTEM_KRB5_CONF)
 
 #define SYSTEM_KRB5_CONF_PATH "/etc/krb5.conf"
@@ -956,8 +945,7 @@ bool create_local_private_krb5_conf_for_domain(const char *realm,
 
                if (lret != -1 || strcmp(linkpath, fname) == 0) {
                        /* Symlink already exists. */
-                       TALLOC_FREE(dname);
-                       return True;
+                       goto done;
                }
 
                /* Try and replace with a symlink. */
@@ -967,8 +955,7 @@ bool create_local_private_krb5_conf_for_domain(const char *realm,
                                DEBUG(0,("create_local_private_krb5_conf_for_domain: symlink "
                                        "of %s to %s failed. Errno %s\n",
                                        fname, SYSTEM_KRB5_CONF_PATH, strerror(errno) ));
-                               TALLOC_FREE(dname);
-                               return True; /* Not a fatal error. */
+                               goto done; /* Not a fatal error. */
                        }
 
                        /* Yes, this is a race conditon... too bad. */
@@ -977,23 +964,23 @@ bool create_local_private_krb5_conf_for_domain(const char *realm,
                                        "of %s to %s failed. Errno %s\n",
                                        SYSTEM_KRB5_CONF_PATH, newpath,
                                        strerror(errno) ));
-                               TALLOC_FREE(dname);
-                               return True; /* Not a fatal error. */
+                               goto done; /* Not a fatal error. */
                        }
 
                        if (symlink(fname, SYSTEM_KRB5_CONF_PATH) == -1) {
                                DEBUG(0,("create_local_private_krb5_conf_for_domain: "
                                        "forced symlink of %s to /etc/krb5.conf failed. Errno %s\n",
                                        fname, strerror(errno) ));
-                               TALLOC_FREE(dname);
-                               return True; /* Not a fatal error. */
+                               goto done; /* Not a fatal error. */
                        }
                }
        }
 #endif
 
+done:
+       TALLOC_FREE(tmpname);
        TALLOC_FREE(dname);
 
-       return True;
+       return result;
 }
 #endif