s3:netapi: Remove use_ccache from 'struct libnetapi_ctx'
[metze/samba-autobuild/.git] / source3 / lib / netapi / netapi.c
index 7d78aa8120ab6e854931d2242f83f1669d63aa6b..dfb11fdc9513723f67bc136c507636737e54f2ae 100644 (file)
  */
 
 #include "includes.h"
+#include "../libcli/auth/netlogon_creds_cli.h"
 #include "lib/netapi/netapi.h"
 #include "lib/netapi/netapi_private.h"
-
-extern bool AllowDebugChange;
+#include "secrets.h"
+#include "krb5_env.h"
+#include "source3/param/loadparm.h"
+#include "lib/param/param.h"
+#include "auth/gensec/gensec.h"
 
 struct libnetapi_ctx *stat_ctx = NULL;
-TALLOC_CTX *frame = NULL;
 static bool libnetapi_initialized = false;
 
 /****************************************************************
@@ -35,12 +38,12 @@ static NET_API_STATUS libnetapi_init_private_context(struct libnetapi_ctx *ctx)
        struct libnetapi_private_ctx *priv;
 
        if (!ctx) {
-               return W_ERROR_V(WERR_INVALID_PARAM);
+               return W_ERROR_V(WERR_INVALID_PARAMETER);
        }
 
-       priv = TALLOC_ZERO_P(ctx, struct libnetapi_private_ctx);
+       priv = talloc_zero(ctx, struct libnetapi_private_ctx);
        if (!priv) {
-               return W_ERROR_V(WERR_NOMEM);
+               return W_ERROR_V(WERR_NOT_ENOUGH_MEMORY);
        }
 
        ctx->private_data = priv;
@@ -49,14 +52,16 @@ static NET_API_STATUS libnetapi_init_private_context(struct libnetapi_ctx *ctx)
 }
 
 /****************************************************************
+Create a libnetapi context, for use in non-Samba applications.  This
+loads the smb.conf file and sets the debug level to 0, so that
+applications are not flooded with debug logs at level 10, when they
+were not expecting it.
 ****************************************************************/
 
 NET_API_STATUS libnetapi_init(struct libnetapi_ctx **context)
 {
-       NET_API_STATUS status;
-       struct libnetapi_ctx *ctx = NULL;
-       char *krb5_cc_env = NULL;
-
+       NET_API_STATUS ret;
+       TALLOC_CTX *frame;
        if (stat_ctx && libnetapi_initialized) {
                *context = stat_ctx;
                return NET_API_STATUS_SUCCESS;
@@ -67,57 +72,65 @@ NET_API_STATUS libnetapi_init(struct libnetapi_ctx **context)
 #endif
        frame = talloc_stackframe();
 
-       ctx = talloc_zero(frame, struct libnetapi_ctx);
-       if (!ctx) {
-               TALLOC_FREE(frame);
-               return W_ERROR_V(WERR_NOMEM);
-       }
-
-       if (!DEBUGLEVEL) {
-               DEBUGLEVEL = 0;
-       }
-
-       /* prevent setup_logging() from closing x_stderr... */
-       dbf = 0;
-       setup_logging("libnetapi", true);
+       /* When libnetapi is invoked from an application, it does not
+        * want to be swamped with level 10 debug messages, even if
+        * this has been set for the server in smb.conf */
+       lp_set_cmdline("log level", "0");
+       setup_logging("libnetapi", DEBUG_STDERR);
 
-       dbf = x_stderr;
-       x_setbuf(x_stderr, NULL);
-       AllowDebugChange = false;
-
-       load_case_tables();
-
-       if (!lp_load(get_dyn_CONFIGFILE(), true, false, false, false)) {
+       if (!lp_load_global(get_dyn_CONFIGFILE())) {
                TALLOC_FREE(frame);
-               fprintf(stderr, "lp_load failed\n");
-               return W_ERROR_V(WERR_GENERAL_FAILURE);
+               fprintf(stderr, "error loading %s\n", get_dyn_CONFIGFILE() );
+               return W_ERROR_V(WERR_GEN_FAILURE);
        }
 
-       AllowDebugChange = true;
-
-       init_names();
        load_interfaces();
        reopen_logs();
 
        BlockSignals(True, SIGPIPE);
 
-       krb5_cc_env = getenv(KRB5_ENV_CCNAME);
-       if (!krb5_cc_env || (strlen(krb5_cc_env) == 0)) {
-               ctx->krb5_cc_env = talloc_strdup(frame, "MEMORY:libnetapi");
-               setenv(KRB5_ENV_CCNAME, ctx->krb5_cc_env, 1);
+       ret = libnetapi_net_init(context);
+       TALLOC_FREE(frame);
+       return ret;
+}
+
+/****************************************************************
+Create a libnetapi context, for use inside the 'net' binary.
+
+As we know net has already loaded the smb.conf file, and set the debug
+level etc, this avoids doing so again (which causes trouble with -d on
+the command line).
+****************************************************************/
+
+NET_API_STATUS libnetapi_net_init(struct libnetapi_ctx **context)
+{
+       NET_API_STATUS status;
+       struct libnetapi_ctx *ctx = NULL;
+       TALLOC_CTX *frame = talloc_stackframe();
+       struct loadparm_context *lp_ctx = NULL;
+
+       ctx = talloc_zero(frame, struct libnetapi_ctx);
+       if (!ctx) {
+               TALLOC_FREE(frame);
+               return W_ERROR_V(WERR_NOT_ENOUGH_MEMORY);
        }
 
-       if (getenv("USER")) {
-               ctx->username = talloc_strdup(frame, getenv("USER"));
-       } else {
-               ctx->username = talloc_strdup(frame, "");
+       ctx->creds = cli_credentials_init(ctx);
+       if (ctx->creds == NULL) {
+               TALLOC_FREE(frame);
+               return W_ERROR_V(WERR_NOT_ENOUGH_MEMORY);
        }
-       if (!ctx->username) {
+
+       lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
+       if (lp_ctx == NULL) {
                TALLOC_FREE(frame);
-               fprintf(stderr, "libnetapi_init: out of memory\n");
-               return W_ERROR_V(WERR_NOMEM);
+               return W_ERROR_V(WERR_NOT_ENOUGH_MEMORY);
        }
 
+       BlockSignals(True, SIGPIPE);
+
+       cli_credentials_guess(ctx->creds, lp_ctx);
+
        status = libnetapi_init_private_context(ctx);
        if (status != 0) {
                TALLOC_FREE(frame);
@@ -126,12 +139,15 @@ NET_API_STATUS libnetapi_init(struct libnetapi_ctx **context)
 
        libnetapi_initialized = true;
 
+       talloc_steal(NULL, ctx);
        *context = stat_ctx = ctx;
-
+       
+       TALLOC_FREE(frame);
        return NET_API_STATUS_SUCCESS;
 }
 
 /****************************************************************
+ Return the static libnetapi context
 ****************************************************************/
 
 NET_API_STATUS libnetapi_getctx(struct libnetapi_ctx **ctx)
@@ -145,53 +161,56 @@ NET_API_STATUS libnetapi_getctx(struct libnetapi_ctx **ctx)
 }
 
 /****************************************************************
+ Free the static libnetapi context
 ****************************************************************/
 
 NET_API_STATUS libnetapi_free(struct libnetapi_ctx *ctx)
 {
+       TALLOC_CTX *frame;
+
        if (!ctx) {
                return NET_API_STATUS_SUCCESS;
        }
 
+       frame = talloc_stackframe();
        libnetapi_samr_free(ctx);
 
        libnetapi_shutdown_cm(ctx);
 
-       if (ctx->krb5_cc_env) {
-               char *env = getenv(KRB5_ENV_CCNAME);
-               if (env && (strequal(ctx->krb5_cc_env, env))) {
-                       unsetenv(KRB5_ENV_CCNAME);
-               }
-       }
-
-       gfree_names();
        gfree_loadparm();
-       gfree_case_tables();
        gfree_charcnv();
        gfree_interfaces();
 
-       gencache_shutdown();
        secrets_shutdown();
 
+       netlogon_creds_cli_close_global_db();
+
+       if (ctx == stat_ctx) {
+               stat_ctx = NULL;
+       }
        TALLOC_FREE(ctx);
-       TALLOC_FREE(frame);
 
        gfree_debugsyms();
+       talloc_free(frame);
 
        return NET_API_STATUS_SUCCESS;
 }
 
 /****************************************************************
+ Override the current log level for libnetapi
 ****************************************************************/
 
 NET_API_STATUS libnetapi_set_debuglevel(struct libnetapi_ctx *ctx,
                                        const char *debuglevel)
 {
-       AllowDebugChange = true;
+       TALLOC_CTX *frame = talloc_stackframe();
        ctx->debuglevel = talloc_strdup(ctx, debuglevel);
-       if (!debug_parse_levels(debuglevel)) {
-               return W_ERROR_V(WERR_GENERAL_FAILURE);
+       
+       if (!lp_set_cmdline("log level", debuglevel)) {
+               TALLOC_FREE(frame);
+               return W_ERROR_V(WERR_GEN_FAILURE);
        }
+       TALLOC_FREE(frame);
        return NET_API_STATUS_SUCCESS;
 }
 
@@ -208,37 +227,91 @@ NET_API_STATUS libnetapi_get_debuglevel(struct libnetapi_ctx *ctx,
 /****************************************************************
 ****************************************************************/
 
+/**
+ * @brief Get the username of the libnet context
+ *
+ * @param[in]  ctx      The netapi context
+ *
+ * @param[in]  username A pointer to hold the username.
+ *
+ * @return 0 on success, an werror code otherwise.
+ */
+NET_API_STATUS libnetapi_get_username(struct libnetapi_ctx *ctx,
+                                     const char **username)
+{
+       if (ctx == NULL) {
+               return W_ERROR_V(WERR_INVALID_PARAMETER);
+       }
+
+       if (username != NULL) {
+               *username = cli_credentials_get_username(ctx->creds);
+       }
+
+       return NET_API_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Get the password of the libnet context
+ *
+ * @param[in]  ctx      The netapi context
+ *
+ * @param[in]  password A pointer to hold the password.
+ *
+ * @return 0 on success, an werror code otherwise.
+ */
+NET_API_STATUS libnetapi_get_password(struct libnetapi_ctx *ctx,
+                                     const char **password)
+{
+       if (ctx == NULL) {
+               return W_ERROR_V(WERR_INVALID_PARAMETER);
+       }
+
+       if (password != NULL) {
+               *password = cli_credentials_get_password(ctx->creds);
+       }
+
+       return NET_API_STATUS_SUCCESS;
+}
+
 NET_API_STATUS libnetapi_set_username(struct libnetapi_ctx *ctx,
                                      const char *username)
 {
-       TALLOC_FREE(ctx->username);
-       ctx->username = talloc_strdup(ctx, username ? username : "");
-
-       if (!ctx->username) {
-               return W_ERROR_V(WERR_NOMEM);
+       if (ctx == NULL || username == NULL) {
+               return W_ERROR_V(WERR_INVALID_PARAMETER);
        }
+
+       cli_credentials_parse_string(ctx->creds, username, CRED_SPECIFIED);
+
        return NET_API_STATUS_SUCCESS;
 }
 
 NET_API_STATUS libnetapi_set_password(struct libnetapi_ctx *ctx,
                                      const char *password)
 {
-       TALLOC_FREE(ctx->password);
-       ctx->password = talloc_strdup(ctx, password);
-       if (!ctx->password) {
-               return W_ERROR_V(WERR_NOMEM);
+       bool ok;
+
+       if (ctx == NULL || password == NULL) {
+               return W_ERROR_V(WERR_INVALID_PARAMETER);
+       }
+
+       ok = cli_credentials_set_password(ctx->creds, password, CRED_SPECIFIED);
+       if (!ok) {
+               return W_ERROR_V(WERR_INTERNAL_ERROR);
        }
+
        return NET_API_STATUS_SUCCESS;
 }
 
 NET_API_STATUS libnetapi_set_workgroup(struct libnetapi_ctx *ctx,
                                       const char *workgroup)
 {
-       TALLOC_FREE(ctx->workgroup);
-       ctx->workgroup = talloc_strdup(ctx, workgroup);
-       if (!ctx->workgroup) {
-               return W_ERROR_V(WERR_NOMEM);
+       bool ok;
+
+       ok = cli_credentials_set_domain(ctx->creds, workgroup, CRED_SPECIFIED);
+       if (!ok) {
+               return W_ERROR_V(WERR_INTERNAL_ERROR);
        }
+
        return NET_API_STATUS_SUCCESS;
 }
 
@@ -247,20 +320,43 @@ NET_API_STATUS libnetapi_set_workgroup(struct libnetapi_ctx *ctx,
 
 NET_API_STATUS libnetapi_set_use_kerberos(struct libnetapi_ctx *ctx)
 {
-       ctx->use_kerberos = true;
+       cli_credentials_set_kerberos_state(ctx->creds,
+                                          CRED_USE_KERBEROS_REQUIRED);
+
+       return NET_API_STATUS_SUCCESS;
+}
+
+/****************************************************************
+****************************************************************/
+
+NET_API_STATUS libnetapi_set_use_ccache(struct libnetapi_ctx *ctx)
+{
+       uint32_t gensec_features;
+
+       gensec_features = cli_credentials_get_gensec_features(ctx->creds);
+       gensec_features |= GENSEC_FEATURE_NTLM_CCACHE;
+       cli_credentials_set_gensec_features(ctx->creds, gensec_features);
+
        return NET_API_STATUS_SUCCESS;
 }
 
 /****************************************************************
+Return a libnetapi error as a string, caller must free with NetApiBufferFree
 ****************************************************************/
 
-const char *libnetapi_errstr(NET_API_STATUS status)
+char *libnetapi_errstr(NET_API_STATUS status)
 {
+       TALLOC_CTX *frame = talloc_stackframe();
+       char *ret;
        if (status & 0xc0000000) {
-               return get_friendly_nt_error_msg(NT_STATUS(status));
+               ret = talloc_strdup(NULL, 
+                                    get_friendly_nt_error_msg(NT_STATUS(status)));
+       } else {
+               ret = talloc_strdup(NULL,
+                                   get_friendly_werror_msg(W_ERROR(status)));
        }
-
-       return get_friendly_werror_msg(W_ERROR(status));
+       TALLOC_FREE(frame);
+       return ret;
 }
 
 /****************************************************************
@@ -278,15 +374,16 @@ NET_API_STATUS libnetapi_set_error_string(struct libnetapi_ctx *ctx,
        va_end(args);
 
        if (!ctx->error_string) {
-               return W_ERROR_V(WERR_NOMEM);
+               return W_ERROR_V(WERR_NOT_ENOUGH_MEMORY);
        }
        return NET_API_STATUS_SUCCESS;
 }
 
 /****************************************************************
+Return a libnetapi_errstr(), caller must free with NetApiBufferFree
 ****************************************************************/
 
-const char *libnetapi_get_error_string(struct libnetapi_ctx *ctx,
+char *libnetapi_get_error_string(struct libnetapi_ctx *ctx,
                                       NET_API_STATUS status_in)
 {
        NET_API_STATUS status;
@@ -300,7 +397,7 @@ const char *libnetapi_get_error_string(struct libnetapi_ctx *ctx,
        }
 
        if (tmp_ctx->error_string) {
-               return tmp_ctx->error_string;
+               return talloc_strdup(NULL, tmp_ctx->error_string);
        }
 
        return libnetapi_errstr(status_in);
@@ -309,6 +406,33 @@ const char *libnetapi_get_error_string(struct libnetapi_ctx *ctx,
 /****************************************************************
 ****************************************************************/
 
+NET_API_STATUS NetApiBufferAllocate(uint32_t byte_count,
+                                   void **buffer)
+{
+       void *buf = NULL;
+
+       if (!buffer) {
+               return W_ERROR_V(WERR_INSUFFICIENT_BUFFER);
+       }
+
+       if (byte_count == 0) {
+               goto done;
+       }
+
+       buf = talloc_size(NULL, byte_count);
+       if (!buf) {
+               return W_ERROR_V(WERR_NOT_ENOUGH_MEMORY);
+       }
+
+ done:
+       *buffer = buf;
+
+       return NET_API_STATUS_SUCCESS;
+}
+
+/****************************************************************
+****************************************************************/
+
 NET_API_STATUS NetApiBufferFree(void *buffer)
 {
        if (!buffer) {