diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-05 17:47:29 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-05 17:47:29 +0000 |
commit | 4f5791ebd03eaec1c7da0865a383175b05102712 (patch) | |
tree | 8ce7b00f7a76baa386372422adebbe64510812d4 /source3/lib/netapi/netapi.c | |
parent | Initial commit. (diff) | |
download | samba-4f5791ebd03eaec1c7da0865a383175b05102712.tar.xz samba-4f5791ebd03eaec1c7da0865a383175b05102712.zip |
Adding upstream version 2:4.17.12+dfsg.upstream/2%4.17.12+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'source3/lib/netapi/netapi.c')
-rw-r--r-- | source3/lib/netapi/netapi.c | 507 |
1 files changed, 507 insertions, 0 deletions
diff --git a/source3/lib/netapi/netapi.c b/source3/lib/netapi/netapi.c new file mode 100644 index 0000000..fe98216 --- /dev/null +++ b/source3/lib/netapi/netapi.c @@ -0,0 +1,507 @@ +/* + * Unix SMB/CIFS implementation. + * NetApi Support + * Copyright (C) Guenther Deschner 2007-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "includes.h" +#include "../libcli/auth/netlogon_creds_cli.h" +#include "lib/netapi/netapi.h" +#include "lib/netapi/netapi_private.h" +#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; +static bool libnetapi_initialized = false; + +/**************************************************************** +****************************************************************/ + +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_PARAMETER); + } + + priv = talloc_zero(ctx, struct libnetapi_private_ctx); + if (!priv) { + return W_ERROR_V(WERR_NOT_ENOUGH_MEMORY); + } + + ctx->private_data = priv; + + return NET_API_STATUS_SUCCESS; +} + +/**************************************************************** +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 ret; + TALLOC_CTX *frame; + if (stat_ctx && libnetapi_initialized) { + *context = stat_ctx; + return NET_API_STATUS_SUCCESS; + } + +#if 0 + talloc_enable_leak_report(); +#endif + frame = talloc_stackframe(); + + /* 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); + + if (!lp_load_global(get_dyn_CONFIGFILE())) { + TALLOC_FREE(frame); + fprintf(stderr, "error loading %s\n", get_dyn_CONFIGFILE() ); + return W_ERROR_V(WERR_GEN_FAILURE); + } + + load_interfaces(); + reopen_logs(); + + BlockSignals(True, SIGPIPE); + + 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); + } + + ctx->creds = cli_credentials_init(ctx); + if (ctx->creds == NULL) { + TALLOC_FREE(frame); + return W_ERROR_V(WERR_NOT_ENOUGH_MEMORY); + } + + lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers()); + if (lp_ctx == NULL) { + TALLOC_FREE(frame); + return W_ERROR_V(WERR_NOT_ENOUGH_MEMORY); + } + + BlockSignals(True, SIGPIPE); + + /* Ignore return code, as we might not have a smb.conf */ + (void)cli_credentials_guess(ctx->creds, lp_ctx); + + status = libnetapi_init_private_context(ctx); + if (status != 0) { + TALLOC_FREE(frame); + return status; + } + + 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) +{ + if (stat_ctx) { + *ctx = stat_ctx; + return NET_API_STATUS_SUCCESS; + } + + return libnetapi_init(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); + + gfree_loadparm(); + gfree_charcnv(); + gfree_interfaces(); + + secrets_shutdown(); + + netlogon_creds_cli_close_global_db(); + + if (ctx == stat_ctx) { + stat_ctx = NULL; + } + TALLOC_FREE(ctx); + + 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) +{ + TALLOC_CTX *frame = talloc_stackframe(); + ctx->debuglevel = talloc_strdup(ctx, debuglevel); + + 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; +} + +/**************************************************************** +****************************************************************/ + +NET_API_STATUS libnetapi_set_logfile(struct libnetapi_ctx *ctx, + const char *logfile) +{ + TALLOC_CTX *frame = talloc_stackframe(); + ctx->logfile = talloc_strdup(ctx, logfile); + + if (!lp_set_cmdline("log file", logfile)) { + TALLOC_FREE(frame); + return W_ERROR_V(WERR_GEN_FAILURE); + } + debug_set_logfile(logfile); + setup_logging("libnetapi", DEBUG_FILE); + TALLOC_FREE(frame); + return NET_API_STATUS_SUCCESS; +} + +/**************************************************************** +****************************************************************/ + +NET_API_STATUS libnetapi_get_debuglevel(struct libnetapi_ctx *ctx, + char **debuglevel) +{ + *debuglevel = ctx->debuglevel; + return NET_API_STATUS_SUCCESS; +} + +/**************************************************************** +****************************************************************/ + +/** + * @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) +{ + 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) +{ + 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) +{ + 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; +} + +/** + * @brief Set the cli_credentials to be used in the netapi context + * + * @param[in] ctx The netapi context + * + * @param[in] creds The cli_credentials which should be used by netapi. + * + * @return 0 on success, an werror code otherwise. + */ +NET_API_STATUS libnetapi_set_creds(struct libnetapi_ctx *ctx, + struct cli_credentials *creds) +{ + if (ctx == NULL || creds == NULL) { + return W_ERROR_V(WERR_INVALID_PARAMETER); + } + + ctx->creds = creds; + + return NET_API_STATUS_SUCCESS; +} + +/**************************************************************** +****************************************************************/ + +NET_API_STATUS libnetapi_set_use_kerberos(struct libnetapi_ctx *ctx) +{ + cli_credentials_set_kerberos_state(ctx->creds, + CRED_USE_KERBEROS_REQUIRED, + CRED_SPECIFIED); + + return NET_API_STATUS_SUCCESS; +} + +/**************************************************************** +****************************************************************/ + +NET_API_STATUS libnetapi_get_use_kerberos(struct libnetapi_ctx *ctx, + int *use_kerberos) +{ + enum credentials_use_kerberos creds_use_kerberos; + + *use_kerberos = 0; + + creds_use_kerberos = cli_credentials_get_kerberos_state(ctx->creds); + if (creds_use_kerberos > CRED_USE_KERBEROS_DESIRED) { + *use_kerberos = 1; + } + + 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, + CRED_SPECIFIED); + + return NET_API_STATUS_SUCCESS; +} + +/**************************************************************** +Return a libnetapi error as a string, caller must free with NetApiBufferFree +****************************************************************/ + +char *libnetapi_errstr(NET_API_STATUS status) +{ + TALLOC_CTX *frame = talloc_stackframe(); + char *ret; + if (status & 0xc0000000) { + ret = talloc_strdup(NULL, + get_friendly_nt_error_msg(NT_STATUS(status))); + } else { + ret = talloc_strdup(NULL, + get_friendly_werror_msg(W_ERROR(status))); + } + TALLOC_FREE(frame); + return ret; +} + +/**************************************************************** +****************************************************************/ + +NET_API_STATUS libnetapi_set_error_string(struct libnetapi_ctx *ctx, + const char *format, ...) +{ + va_list args; + + TALLOC_FREE(ctx->error_string); + + va_start(args, format); + ctx->error_string = talloc_vasprintf(ctx, format, args); + va_end(args); + + if (!ctx->error_string) { + return W_ERROR_V(WERR_NOT_ENOUGH_MEMORY); + } + return NET_API_STATUS_SUCCESS; +} + +/**************************************************************** +Return a libnetapi_errstr(), caller must free with NetApiBufferFree +****************************************************************/ + +char *libnetapi_get_error_string(struct libnetapi_ctx *ctx, + NET_API_STATUS status_in) +{ + NET_API_STATUS status; + struct libnetapi_ctx *tmp_ctx = ctx; + + if (!tmp_ctx) { + status = libnetapi_getctx(&tmp_ctx); + if (status != 0) { + return NULL; + } + } + + if (tmp_ctx->error_string) { + return talloc_strdup(NULL, tmp_ctx->error_string); + } + + return libnetapi_errstr(status_in); +} + +/**************************************************************** +****************************************************************/ + +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) { + return W_ERROR_V(WERR_INSUFFICIENT_BUFFER); + } + + talloc_free(buffer); + + return NET_API_STATUS_SUCCESS; +} |