#include "includes.h"
#include "utils/net.h"
+#include "libsmb/namequery.h"
#include "rpc_client/cli_pipe.h"
#include "librpc/gen_ndr/ndr_krb5pac.h"
#include "../librpc/gen_ndr/ndr_spoolss.h"
#include "libsmb/libsmb.h"
#include "lib/param/loadparm.h"
#include "utils/net_dns.h"
+#include "auth/kerberos/pac_utils.h"
+#include "lib/util/string_wrappers.h"
+
+#ifdef HAVE_JANSSON
+#include <jansson.h>
+#include "audit_logging.h" /* various JSON helpers */
+#include "auth/common_auth.h"
+#endif /* [HAVE_JANSSON] */
#ifdef HAVE_ADS
return NULL;
}
+#ifdef HAVE_JANSSON
+
+/*
+ * note: JSON output deliberately bypasses gettext so as to provide the same
+ * output irrespective of the locale.
+ */
+
+static int output_json(const struct json_object *jsobj)
+{
+ TALLOC_CTX *ctx = NULL;
+ char *json = NULL;
+
+ if (json_is_invalid(jsobj)) {
+ return -1;
+ }
+
+ ctx = talloc_new(NULL);
+ if (ctx == NULL) {
+ d_fprintf(stderr, _("Out of memory\n"));
+ return -1;
+ }
+
+ json = json_to_string(ctx, jsobj);
+ if (!json) {
+ d_fprintf(stderr, _("error encoding to JSON\n"));
+ return -1;
+ }
+
+ d_printf("%s\n", json);
+ TALLOC_FREE(ctx);
+
+ return 0;
+}
+
+static int net_ads_cldap_netlogon_json
+ (ADS_STRUCT *ads,
+ const char *addr,
+ const struct NETLOGON_SAM_LOGON_RESPONSE_EX *reply)
+{
+ struct json_object jsobj = json_new_object();
+ struct json_object flagsobj = json_new_object();
+ char response_type [32] = { '\0' };
+ int ret = 0;
+
+ if (json_is_invalid(&jsobj) || json_is_invalid(&flagsobj)) {
+ d_fprintf(stderr, _("error setting up JSON value\n"));
+
+ goto failure;
+ }
+
+ switch (reply->command) {
+ case LOGON_SAM_LOGON_USER_UNKNOWN_EX:
+ strncpy(response_type,
+ "LOGON_SAM_LOGON_USER_UNKNOWN_EX",
+ sizeof(response_type));
+ break;
+ case LOGON_SAM_LOGON_RESPONSE_EX:
+ strncpy(response_type, "LOGON_SAM_LOGON_RESPONSE_EX",
+ sizeof(response_type));
+ break;
+ default:
+ snprintf(response_type, sizeof(response_type), "0x%x",
+ reply->command);
+ break;
+ }
+
+ ret = json_add_string(&jsobj, "Information for Domain Controller",
+ addr);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ ret = json_add_string(&jsobj, "Response Type", response_type);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ ret = json_add_guid(&jsobj, "GUID", &reply->domain_uuid);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ ret = json_add_bool(&flagsobj, "Is a PDC",
+ reply->server_type & NBT_SERVER_PDC);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ ret = json_add_bool(&flagsobj, "Is a GC of the forest",
+ reply->server_type & NBT_SERVER_GC);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ ret = json_add_bool(&flagsobj, "Is an LDAP server",
+ reply->server_type & NBT_SERVER_LDAP);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ ret = json_add_bool(&flagsobj, "Supports DS",
+ reply->server_type & NBT_SERVER_DS);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ ret = json_add_bool(&flagsobj, "Is running a KDC",
+ reply->server_type & NBT_SERVER_KDC);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ ret = json_add_bool(&flagsobj, "Is running time services",
+ reply->server_type & NBT_SERVER_TIMESERV);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ ret = json_add_bool(&flagsobj, "Is the closest DC",
+ reply->server_type & NBT_SERVER_CLOSEST);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ ret = json_add_bool(&flagsobj, "Is writable",
+ reply->server_type & NBT_SERVER_WRITABLE);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ ret = json_add_bool(&flagsobj, "Has a hardware clock",
+ reply->server_type & NBT_SERVER_GOOD_TIMESERV);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ ret = json_add_bool(&flagsobj,
+ "Is a non-domain NC serviced by LDAP server",
+ reply->server_type & NBT_SERVER_NDNC);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ ret = json_add_bool
+ (&flagsobj, "Is NT6 DC that has some secrets",
+ reply->server_type & NBT_SERVER_SELECT_SECRET_DOMAIN_6);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ ret = json_add_bool
+ (&flagsobj, "Is NT6 DC that has all secrets",
+ reply->server_type & NBT_SERVER_FULL_SECRET_DOMAIN_6);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ ret = json_add_bool(&flagsobj, "Runs Active Directory Web Services",
+ reply->server_type & NBT_SERVER_ADS_WEB_SERVICE);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ ret = json_add_bool(&flagsobj, "Runs on Windows 2012 or later",
+ reply->server_type & NBT_SERVER_DS_8);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ ret = json_add_bool(&flagsobj, "Runs on Windows 2012R2 or later",
+ reply->server_type & NBT_SERVER_DS_9);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ ret = json_add_bool(&flagsobj, "Runs on Windows 2016 or later",
+ reply->server_type & NBT_SERVER_DS_10);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ ret = json_add_bool(&flagsobj, "Has a DNS name",
+ reply->server_type & NBT_SERVER_HAS_DNS_NAME);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ ret = json_add_bool(&flagsobj, "Is a default NC",
+ reply->server_type & NBT_SERVER_IS_DEFAULT_NC);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ ret = json_add_bool(&flagsobj, "Is the forest root",
+ reply->server_type & NBT_SERVER_FOREST_ROOT);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ ret = json_add_string(&jsobj, "Forest", reply->forest);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ ret = json_add_string(&jsobj, "Domain", reply->dns_domain);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ ret = json_add_string(&jsobj, "Domain Controller", reply->pdc_dns_name);
+ if (ret != 0) {
+ goto failure;
+ }
+
+
+ ret = json_add_string(&jsobj, "Pre-Win2k Domain", reply->domain_name);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ ret = json_add_string(&jsobj, "Pre-Win2k Hostname", reply->pdc_name);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ if (*reply->user_name) {
+ ret = json_add_string(&jsobj, "User name", reply->user_name);
+ if (ret != 0) {
+ goto failure;
+ }
+ }
+
+ ret = json_add_string(&jsobj, "Server Site Name", reply->server_site);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ ret = json_add_string(&jsobj, "Client Site Name", reply->client_site);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ ret = json_add_int(&jsobj, "NT Version", reply->nt_version);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ ret = json_add_int(&jsobj, "LMNT Token", reply->lmnt_token);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ ret = json_add_int(&jsobj, "LM20 Token", reply->lm20_token);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ ret = json_add_object(&jsobj, "Flags", &flagsobj);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ ret = output_json(&jsobj);
+ json_free(&jsobj); /* frees flagsobj recursively */
+
+ return ret;
+
+failure:
+ json_free(&flagsobj);
+ json_free(&jsobj);
+
+ return ret;
+}
+
+#else /* [HAVE_JANSSON] */
+
+static int net_ads_cldap_netlogon_json
+ (ADS_STRUCT *ads,
+ const char *addr,
+ const struct NETLOGON_SAM_LOGON_RESPONSE_EX * reply)
+{
+ d_fprintf(stderr, _("JSON support not available\n"));
+
+ return -1;
+}
+
+#endif /* [HAVE_JANSSON] */
+
/*
do a cldap netlogon query
*/
return -1;
}
+ if (c->opt_json) {
+ return net_ads_cldap_netlogon_json(ads, addr, &reply);
+ }
+
d_printf(_("Information for Domain Controller: %s\n\n"),
addr);
"\tIs NT6 DC that has some secrets: %s\n"
"\tIs NT6 DC that has all secrets: %s\n"
"\tRuns Active Directory Web Services: %s\n"
- "\tRuns on Windows 2012 or later: %s\n"),
+ "\tRuns on Windows 2012 or later: %s\n"
+ "\tRuns on Windows 2012R2 or later: %s\n"
+ "\tRuns on Windows 2016 or later: %s\n"
+ "\tHas a DNS name: %s\n"
+ "\tIs a default NC: %s\n"
+ "\tIs the forest root: %s\n"),
(reply.server_type & NBT_SERVER_PDC) ? _("yes") : _("no"),
(reply.server_type & NBT_SERVER_GC) ? _("yes") : _("no"),
(reply.server_type & NBT_SERVER_LDAP) ? _("yes") : _("no"),
(reply.server_type & NBT_SERVER_SELECT_SECRET_DOMAIN_6) ? _("yes") : _("no"),
(reply.server_type & NBT_SERVER_FULL_SECRET_DOMAIN_6) ? _("yes") : _("no"),
(reply.server_type & NBT_SERVER_ADS_WEB_SERVICE) ? _("yes") : _("no"),
- (reply.server_type & NBT_SERVER_DS_8) ? _("yes") : _("no"));
+ (reply.server_type & NBT_SERVER_DS_8) ? _("yes") : _("no"),
+ (reply.server_type & NBT_SERVER_DS_9) ? _("yes") : _("no"),
+ (reply.server_type & NBT_SERVER_DS_10) ? _("yes") : _("no"),
+ (reply.server_type & NBT_SERVER_HAS_DNS_NAME) ? _("yes") : _("no"),
+ (reply.server_type & NBT_SERVER_IS_DEFAULT_NC) ? _("yes") : _("no"),
+ (reply.server_type & NBT_SERVER_FOREST_ROOT) ? _("yes") : _("no"));
- printf(_("Forest:\t\t\t%s\n"), reply.forest);
- printf(_("Domain:\t\t\t%s\n"), reply.dns_domain);
- printf(_("Domain Controller:\t%s\n"), reply.pdc_dns_name);
+ printf(_("Forest: %s\n"), reply.forest);
+ printf(_("Domain: %s\n"), reply.dns_domain);
+ printf(_("Domain Controller: %s\n"), reply.pdc_dns_name);
- printf(_("Pre-Win2k Domain:\t%s\n"), reply.domain_name);
- printf(_("Pre-Win2k Hostname:\t%s\n"), reply.pdc_name);
+ printf(_("Pre-Win2k Domain: %s\n"), reply.domain_name);
+ printf(_("Pre-Win2k Hostname: %s\n"), reply.pdc_name);
- if (*reply.user_name) printf(_("User name:\t%s\n"), reply.user_name);
+ if (*reply.user_name) printf(_("User name: %s\n"), reply.user_name);
- printf(_("Server Site Name :\t\t%s\n"), reply.server_site);
- printf(_("Client Site Name :\t\t%s\n"), reply.client_site);
+ printf(_("Server Site Name: %s\n"), reply.server_site);
+ printf(_("Client Site Name: %s\n"), reply.client_site);
d_printf(_("NT Version: %d\n"), reply.nt_version);
d_printf(_("LMNT Token: %.2x\n"), reply.lmnt_token);
*/
static int net_ads_lookup(struct net_context *c, int argc, const char **argv)
{
- ADS_STRUCT *ads;
- int ret;
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
+ ADS_STRUCT *ads = NULL;
+ ADS_STATUS status;
+ int ret = -1;
if (c->display_usage) {
d_printf("%s\n"
" %s",
_("Usage:"),
_("Find the ADS DC using CLDAP lookup.\n"));
- return 0;
+ TALLOC_FREE(tmp_ctx);
+ return -1;
}
- if (!ADS_ERR_OK(ads_startup_nobind(c, false, &ads))) {
+ status = ads_startup_nobind(c, false, tmp_ctx, &ads);
+ if (!ADS_ERR_OK(status)) {
d_fprintf(stderr, _("Didn't find the cldap server!\n"));
- ads_destroy(&ads);
- return -1;
+ goto out;
}
if (!ads->config.realm) {
- ads->config.realm = discard_const_p(char, c->opt_target_workgroup);
+ ads->config.realm = talloc_strdup(ads, c->opt_target_workgroup);
+ if (ads->config.realm == NULL) {
+ d_fprintf(stderr, _("Out of memory\n"));
+ goto out;
+ }
ads->ldap.port = 389;
}
ret = net_ads_cldap_netlogon(c, ads);
- ads_destroy(&ads);
+out:
+ TALLOC_FREE(tmp_ctx);
return ret;
}
+#ifdef HAVE_JANSSON
+
+static int net_ads_info_json(ADS_STRUCT *ads)
+{
+ int ret = 0;
+ char addr[INET6_ADDRSTRLEN];
+ time_t pass_time;
+ struct json_object jsobj = json_new_object();
+
+ if (json_is_invalid(&jsobj)) {
+ d_fprintf(stderr, _("error setting up JSON value\n"));
+
+ goto failure;
+ }
+
+ pass_time = secrets_fetch_pass_last_set_time(ads->server.workgroup);
+
+ print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
+
+ ret = json_add_string (&jsobj, "LDAP server", addr);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ ret = json_add_string (&jsobj, "LDAP server name",
+ ads->config.ldap_server_name);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ ret = json_add_string (&jsobj, "Realm", ads->config.realm);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ ret = json_add_string (&jsobj, "Bind Path", ads->config.bind_path);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ ret = json_add_int (&jsobj, "LDAP port", ads->ldap.port);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ ret = json_add_int (&jsobj, "Server time", ads->config.current_time);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ ret = json_add_string (&jsobj, "KDC server", ads->auth.kdc_server);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ ret = json_add_int (&jsobj, "Server time offset",
+ ads->auth.time_offset);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ ret = json_add_int (&jsobj, "Last machine account password change",
+ pass_time);
+ if (ret != 0) {
+ goto failure;
+ }
+
+ ret = output_json(&jsobj);
+failure:
+ json_free(&jsobj);
+
+ return ret;
+}
+
+#else /* [HAVE_JANSSON] */
+
+static int net_ads_info_json(ADS_STRUCT *ads)
+{
+ d_fprintf(stderr, _("JSON support not available\n"));
+
+ return -1;
+}
+
+#endif /* [HAVE_JANSSON] */
+
+
static int net_ads_info(struct net_context *c, int argc, const char **argv)
{
- ADS_STRUCT *ads;
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
+ ADS_STRUCT *ads = NULL;
+ ADS_STATUS status;
char addr[INET6_ADDRSTRLEN];
time_t pass_time;
+ int ret = -1;
if (c->display_usage) {
d_printf("%s\n"
_("Usage:"),
_("Display information about an Active Directory "
"server.\n"));
- return 0;
+ TALLOC_FREE(tmp_ctx);
+ return -1;
}
- if (!ADS_ERR_OK(ads_startup_nobind(c, false, &ads))) {
+ status = ads_startup_nobind(c, false, tmp_ctx, &ads);
+ if (!ADS_ERR_OK(status)) {
d_fprintf(stderr, _("Didn't find the ldap server!\n"));
- return -1;
+ goto out;
}
if (!ads || !ads->config.realm) {
d_fprintf(stderr, _("Didn't find the ldap server!\n"));
- ads_destroy(&ads);
- return -1;
+ goto out;
}
/* Try to set the server's current time since we didn't do a full
d_fprintf( stderr, _("Failed to get server's current time!\n"));
}
+ if (c->opt_json) {
+ ret = net_ads_info_json(ads);
+ goto out;
+ }
+
pass_time = secrets_fetch_pass_last_set_time(ads->server.workgroup);
print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
d_printf(_("Bind Path: %s\n"), ads->config.bind_path);
d_printf(_("LDAP port: %d\n"), ads->ldap.port);
d_printf(_("Server time: %s\n"),
- http_timestring(talloc_tos(), ads->config.current_time));
+ http_timestring(tmp_ctx, ads->config.current_time));
d_printf(_("KDC server: %s\n"), ads->auth.kdc_server );
d_printf(_("Server time offset: %d\n"), ads->auth.time_offset );
d_printf(_("Last machine account password change: %s\n"),
- http_timestring(talloc_tos(), pass_time));
-
- ads_destroy(&ads);
- return 0;
-}
+ http_timestring(tmp_ctx, pass_time));
-static void use_in_memory_ccache(void) {
- /* Use in-memory credentials cache so we do not interfere with
- * existing credentials */
- setenv(KRB5_ENV_CCNAME, "MEMORY:net_ads", 1);
+ ret = 0;
+out:
+ TALLOC_FREE(tmp_ctx);
+ return ret;
}
-static ADS_STATUS ads_startup_int(struct net_context *c, bool only_own_domain,
- uint32_t auth_flags, ADS_STRUCT **ads_ret)
+static ADS_STATUS ads_startup_int(struct net_context *c,
+ bool only_own_domain,
+ uint32_t auth_flags,
+ TALLOC_CTX *mem_ctx,
+ ADS_STRUCT **ads_ret)
{
ADS_STRUCT *ads = NULL;
ADS_STATUS status;
char *cp;
const char *realm = NULL;
bool tried_closest_dc = false;
+ enum credentials_use_kerberos krb5_state =
+ CRED_USE_KERBEROS_DISABLED;
/* lp_realm() should be handled by a command line param,
However, the join requires that realm be set in smb.conf
realm = assume_own_realm(c);
}
- ads = ads_init(realm, c->opt_target_workgroup, c->opt_host);
+ ads = ads_init(mem_ctx,
+ realm,
+ c->opt_target_workgroup,
+ c->opt_host,
+ ADS_SASL_PLAIN);
+ if (ads == NULL) {
+ return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
+ }
if (!c->opt_user_name) {
c->opt_user_name = "administrator";
if (!c->opt_password && need_password && !c->opt_machine_pass) {
c->opt_password = net_prompt_pass(c, c->opt_user_name);
if (!c->opt_password) {
- ads_destroy(&ads);
+ TALLOC_FREE(ads);
return ADS_ERROR(LDAP_NO_MEMORY);
}
}
if (c->opt_password) {
use_in_memory_ccache();
- SAFE_FREE(ads->auth.password);
- ads->auth.password = smb_xstrdup(c->opt_password);
+ ADS_TALLOC_CONST_FREE(ads->auth.password);
+ ads->auth.password = talloc_strdup(ads, c->opt_password);
+ if (ads->auth.password == NULL) {
+ TALLOC_FREE(ads);
+ return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
+ }
+ }
+
+ ADS_TALLOC_CONST_FREE(ads->auth.user_name);
+ ads->auth.user_name = talloc_strdup(ads, c->opt_user_name);
+ if (ads->auth.user_name == NULL) {
+ TALLOC_FREE(ads);
+ return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
}
ads->auth.flags |= auth_flags;
- SAFE_FREE(ads->auth.user_name);
- ads->auth.user_name = smb_xstrdup(c->opt_user_name);
+
+ /* The ADS code will handle FIPS mode */
+ krb5_state = cli_credentials_get_kerberos_state(c->creds);
+ switch (krb5_state) {
+ case CRED_USE_KERBEROS_REQUIRED:
+ ads->auth.flags &= ~ADS_AUTH_DISABLE_KERBEROS;
+ ads->auth.flags &= ~ADS_AUTH_ALLOW_NTLMSSP;
+ break;
+ case CRED_USE_KERBEROS_DESIRED:
+ ads->auth.flags &= ~ADS_AUTH_DISABLE_KERBEROS;
+ ads->auth.flags |= ADS_AUTH_ALLOW_NTLMSSP;
+ break;
+ case CRED_USE_KERBEROS_DISABLED:
+ ads->auth.flags |= ADS_AUTH_DISABLE_KERBEROS;
+ ads->auth.flags |= ADS_AUTH_ALLOW_NTLMSSP;
+ break;
+ }
/*
* If the username is of the form "name@realm",
*/
if ((cp = strchr_m(ads->auth.user_name, '@'))!=0) {
*cp++ = '\0';
- SAFE_FREE(ads->auth.realm);
- ads->auth.realm = smb_xstrdup(cp);
- if (!strupper_m(ads->auth.realm)) {
- ads_destroy(&ads);
+ ADS_TALLOC_CONST_FREE(ads->auth.realm);
+ ads->auth.realm = talloc_asprintf_strupper_m(ads, "%s", cp);
+ if (ads->auth.realm == NULL) {
+ TALLOC_FREE(ads);
return ADS_ERROR(LDAP_NO_MEMORY);
}
- }
+ } else if (ads->auth.realm == NULL) {
+ const char *c_realm = cli_credentials_get_realm(c->creds);
+
+ if (c_realm != NULL) {
+ ads->auth.realm = talloc_strdup(ads, c_realm);
+ if (ads->auth.realm == NULL) {
+ TALLOC_FREE(ads);
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+ }
+ }
status = ads_connect(ads);
if (NT_STATUS_EQUAL(ads_ntstatus(status),
NT_STATUS_NO_LOGON_SERVERS)) {
DEBUG(0,("ads_connect: %s\n", ads_errstr(status)));
- ads_destroy(&ads);
+ TALLOC_FREE(ads);
return status;
}
second_time = true;
goto retry;
} else {
- ads_destroy(&ads);
+ TALLOC_FREE(ads);
return status;
}
}
namecache_delete(ads->server.realm, 0x1C);
namecache_delete(ads->server.workgroup, 0x1C);
- ads_destroy(&ads);
- ads = NULL;
+ TALLOC_FREE(ads);
goto retry_connect;
}
}
- *ads_ret = ads;
+ *ads_ret = talloc_move(mem_ctx, &ads);
return status;
}
-ADS_STATUS ads_startup(struct net_context *c, bool only_own_domain, ADS_STRUCT **ads)
+ADS_STATUS ads_startup(struct net_context *c,
+ bool only_own_domain,
+ TALLOC_CTX *mem_ctx,
+ ADS_STRUCT **ads)
{
- return ads_startup_int(c, only_own_domain, 0, ads);
+ return ads_startup_int(c, only_own_domain, 0, mem_ctx, ads);
}
-ADS_STATUS ads_startup_nobind(struct net_context *c, bool only_own_domain, ADS_STRUCT **ads)
+ADS_STATUS ads_startup_nobind(struct net_context *c,
+ bool only_own_domain,
+ TALLOC_CTX *mem_ctx,
+ ADS_STRUCT **ads)
{
- return ads_startup_int(c, only_own_domain, ADS_AUTH_NO_BIND, ads);
+ return ads_startup_int(c,
+ only_own_domain,
+ ADS_AUTH_NO_BIND,
+ mem_ctx,
+ ads);
}
/*
ads_startup() stores the password in opt_password if it needs to so
that rpc or rap can use it without re-prompting.
*/
-static int net_ads_check_int(const char *realm, const char *workgroup, const char *host)
+static int net_ads_check_int(struct net_context *c,
+ const char *realm,
+ const char *workgroup,
+ const char *host)
{
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
ADS_STRUCT *ads;
ADS_STATUS status;
+ int ret = -1;
- if ( (ads = ads_init( realm, workgroup, host )) == NULL ) {
- return -1;
+ ads = ads_init(tmp_ctx, realm, workgroup, host, ADS_SASL_PLAIN);
+ if (ads == NULL) {
+ goto out;
}
ads->auth.flags |= ADS_AUTH_NO_BIND;
status = ads_connect(ads);
if ( !ADS_ERR_OK(status) ) {
- return -1;
+ goto out;
}
- ads_destroy(&ads);
- return 0;
+ ret = 0;
+out:
+ TALLOC_FREE(tmp_ctx);
+ return ret;
}
int net_ads_check_our_domain(struct net_context *c)
{
- return net_ads_check_int(lp_realm(), lp_workgroup(), NULL);
+ return net_ads_check_int(c, lp_realm(), lp_workgroup(), NULL);
}
int net_ads_check(struct net_context *c)
{
- return net_ads_check_int(NULL, c->opt_workgroup, c->opt_host);
+ return net_ads_check_int(c, NULL, c->opt_workgroup, c->opt_host);
}
/*
*/
static int net_ads_workgroup(struct net_context *c, int argc, const char **argv)
{
- ADS_STRUCT *ads;
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
+ ADS_STRUCT *ads = NULL;
+ ADS_STATUS status;
struct NETLOGON_SAM_LOGON_RESPONSE_EX reply;
+ bool ok = false;
+ int ret = -1;
if (c->display_usage) {
d_printf ("%s\n"
" %s\n",
_("Usage:"),
_("Print the workgroup name"));
- return 0;
+ TALLOC_FREE(tmp_ctx);
+ return -1;
}
- if (!ADS_ERR_OK(ads_startup_nobind(c, false, &ads))) {
+ status = ads_startup_nobind(c, false, tmp_ctx, &ads);
+ if (!ADS_ERR_OK(status)) {
d_fprintf(stderr, _("Didn't find the cldap server!\n"));
- return -1;
+ goto out;
}
if (!ads->config.realm) {
- ads->config.realm = discard_const_p(char, c->opt_target_workgroup);
+ ads->config.realm = talloc_strdup(ads, c->opt_target_workgroup);
+ if (ads->config.realm == NULL) {
+ d_fprintf(stderr, _("Out of memory\n"));
+ goto out;
+ }
ads->ldap.port = 389;
}
- if ( !ads_cldap_netlogon_5(talloc_tos(), &ads->ldap.ss, ads->server.realm, &reply ) ) {
+ ok = ads_cldap_netlogon_5(tmp_ctx,
+ &ads->ldap.ss, ads->server.realm, &reply);
+ if (!ok) {
d_fprintf(stderr, _("CLDAP query failed!\n"));
- ads_destroy(&ads);
- return -1;
+ goto out;
}
d_printf(_("Workgroup: %s\n"), reply.domain_name);
- ads_destroy(&ads);
+ ret = 0;
+out:
+ TALLOC_FREE(tmp_ctx);
- return 0;
+ return ret;
}
static int ads_user_add(struct net_context *c, int argc, const char **argv)
{
- ADS_STRUCT *ads;
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
+ ADS_STRUCT *ads = NULL;
ADS_STATUS status;
char *upn, *userdn;
LDAPMessage *res=NULL;
int rc = -1;
char *ou_str = NULL;
- if (argc < 1 || c->display_usage)
+ if (argc < 1 || c->display_usage) {
+ TALLOC_FREE(tmp_ctx);
return net_ads_user_usage(c, argc, argv);
+ }
- if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
- return -1;
+ status = ads_startup(c, false, tmp_ctx, &ads);
+ if (!ADS_ERR_OK(status)) {
+ goto done;
}
status = ads_find_user_acct(ads, &res, argv[0]);
-
if (!ADS_ERR_OK(status)) {
d_fprintf(stderr, _("ads_user_add: %s\n"), ads_errstr(status));
goto done;
}
status = ads_add_user_acct(ads, argv[0], ou_str, c->opt_comment);
-
if (!ADS_ERR_OK(status)) {
d_fprintf(stderr, _("Could not add user %s: %s\n"), argv[0],
ads_errstr(status));
}
/* try setting the password */
- if (asprintf(&upn, "%s@%s", argv[0], ads->config.realm) == -1) {
+ upn = talloc_asprintf(tmp_ctx,
+ "%s@%s",
+ argv[0],
+ ads->config.realm);
+ if (upn == NULL) {
goto done;
}
+
status = ads_krb5_set_password(ads->auth.kdc_server, upn, argv[1],
ads->auth.time_offset);
- SAFE_FREE(upn);
if (ADS_ERR_OK(status)) {
d_printf(_("User %s added\n"), argv[0]);
rc = 0;
goto done;
}
+ TALLOC_FREE(upn);
/* password didn't set, delete account */
d_fprintf(stderr, _("Could not add user %s. "
"Error setting password %s\n"),
argv[0], ads_errstr(status));
+
ads_msgfree(ads, res);
+ res = NULL;
+
status=ads_find_user_acct(ads, &res, argv[0]);
if (ADS_ERR_OK(status)) {
- userdn = ads_get_dn(ads, talloc_tos(), res);
+ userdn = ads_get_dn(ads, tmp_ctx, res);
ads_del_dn(ads, userdn);
TALLOC_FREE(userdn);
}
done:
- if (res)
- ads_msgfree(ads, res);
- ads_destroy(&ads);
+ ads_msgfree(ads, res);
SAFE_FREE(ou_str);
+ TALLOC_FREE(tmp_ctx);
return rc;
}
static int ads_user_info(struct net_context *c, int argc, const char **argv)
{
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
ADS_STRUCT *ads = NULL;
- ADS_STATUS rc;
+ ADS_STATUS status;
LDAPMessage *res = NULL;
- TALLOC_CTX *frame;
- int ret = 0;
+ int ret = -1;
wbcErr wbc_status;
const char *attrs[] = {"memberOf", "primaryGroupID", NULL};
- char *searchstring=NULL;
- char **grouplist;
- char *primary_group;
- char *escaped_user;
+ char *searchstring = NULL;
+ char **grouplist = NULL;
+ char *primary_group = NULL;
+ char *escaped_user = NULL;
struct dom_sid primary_group_sid;
uint32_t group_rid;
enum wbcSidType type;
if (argc < 1 || c->display_usage) {
+ TALLOC_FREE(tmp_ctx);
return net_ads_user_usage(c, argc, argv);
}
- frame = talloc_new(talloc_tos());
- if (frame == NULL) {
- return -1;
- }
-
- escaped_user = escape_ldap_string(frame, argv[0]);
+ escaped_user = escape_ldap_string(tmp_ctx, argv[0]);
if (!escaped_user) {
d_fprintf(stderr,
_("ads_user_info: failed to escape user %s\n"),
argv[0]);
- return -1;
+ goto out;
}
- if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
- ret = -1;
- goto error;
+ status = ads_startup(c, false, tmp_ctx, &ads);
+ if (!ADS_ERR_OK(status)) {
+ goto out;
}
- if (asprintf(&searchstring, "(sAMAccountName=%s)", escaped_user) == -1) {
- ret =-1;
- goto error;
+ searchstring = talloc_asprintf(tmp_ctx,
+ "(sAMAccountName=%s)",
+ escaped_user);
+ if (searchstring == NULL) {
+ goto out;
}
- rc = ads_search(ads, &res, searchstring, attrs);
- SAFE_FREE(searchstring);
- if (!ADS_ERR_OK(rc)) {
- d_fprintf(stderr, _("ads_search: %s\n"), ads_errstr(rc));
- ret = -1;
- goto error;
+ status = ads_search(ads, &res, searchstring, attrs);
+ if (!ADS_ERR_OK(status)) {
+ d_fprintf(stderr, _("ads_search: %s\n"), ads_errstr(status));
+ goto out;
}
if (!ads_pull_uint32(ads, res, "primaryGroupID", &group_rid)) {
d_fprintf(stderr, _("ads_pull_uint32 failed\n"));
- ret = -1;
- goto error;
+ goto out;
}
- rc = ads_domain_sid(ads, &primary_group_sid);
- if (!ADS_ERR_OK(rc)) {
- d_fprintf(stderr, _("ads_domain_sid: %s\n"), ads_errstr(rc));
- ret = -1;
- goto error;
+ status = ads_domain_sid(ads, &primary_group_sid);
+ if (!ADS_ERR_OK(status)) {
+ d_fprintf(stderr, _("ads_domain_sid: %s\n"), ads_errstr(status));
+ goto out;
}
sid_append_rid(&primary_group_sid, group_rid);
if (!WBC_ERROR_IS_OK(wbc_status)) {
d_fprintf(stderr, "wbcLookupSid: %s\n",
wbcErrorString(wbc_status));
- ret = -1;
- goto error;
+ goto out;
}
d_printf("%s\n", primary_group);
ldap_value_free(grouplist);
}
-error:
- if (res) ads_msgfree(ads, res);
- if (ads) ads_destroy(&ads);
- TALLOC_FREE(frame);
+ ret = 0;
+out:
+ ads_msgfree(ads, res);
+ TALLOC_FREE(tmp_ctx);
return ret;
}
static int ads_user_delete(struct net_context *c, int argc, const char **argv)
{
- ADS_STRUCT *ads;
- ADS_STATUS rc;
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
+ ADS_STRUCT *ads = NULL;
+ ADS_STATUS status;
LDAPMessage *res = NULL;
- char *userdn;
+ char *userdn = NULL;
+ int ret = -1;
if (argc < 1) {
+ TALLOC_FREE(tmp_ctx);
return net_ads_user_usage(c, argc, argv);
}
- if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
- return -1;
+ status = ads_startup(c, false, tmp_ctx, &ads);
+ if (!ADS_ERR_OK(status)) {
+ goto out;
}
- rc = ads_find_user_acct(ads, &res, argv[0]);
- if (!ADS_ERR_OK(rc) || ads_count_replies(ads, res) != 1) {
+ status = ads_find_user_acct(ads, &res, argv[0]);
+ if (!ADS_ERR_OK(status) || ads_count_replies(ads, res) != 1) {
d_printf(_("User %s does not exist.\n"), argv[0]);
- ads_msgfree(ads, res);
- ads_destroy(&ads);
- return -1;
+ goto out;
}
- userdn = ads_get_dn(ads, talloc_tos(), res);
- ads_msgfree(ads, res);
- rc = ads_del_dn(ads, userdn);
- TALLOC_FREE(userdn);
- if (ADS_ERR_OK(rc)) {
- d_printf(_("User %s deleted\n"), argv[0]);
- ads_destroy(&ads);
- return 0;
+
+ userdn = ads_get_dn(ads, tmp_ctx, res);
+ if (userdn == NULL) {
+ goto out;
}
- d_fprintf(stderr, _("Error deleting user %s: %s\n"), argv[0],
- ads_errstr(rc));
- ads_destroy(&ads);
- return -1;
+
+ status = ads_del_dn(ads, userdn);
+ if (!ADS_ERR_OK(status)) {
+ d_fprintf(stderr, _("Error deleting user %s: %s\n"), argv[0],
+ ads_errstr(status));
+ goto out;
+ }
+
+ d_printf(_("User %s deleted\n"), argv[0]);
+
+ ret = 0;
+out:
+ ads_msgfree(ads, res);
+ TALLOC_FREE(tmp_ctx);
+ return ret;
}
int net_ads_user(struct net_context *c, int argc, const char **argv)
},
{NULL, NULL, 0, NULL, NULL}
};
- ADS_STRUCT *ads;
- ADS_STATUS rc;
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
+ ADS_STRUCT *ads = NULL;
+ ADS_STATUS status;
const char *shortattrs[] = {"sAMAccountName", NULL};
const char *longattrs[] = {"sAMAccountName", "description", NULL};
char *disp_fields[2] = {NULL, NULL};
+ int ret = -1;
- if (argc == 0) {
- if (c->display_usage) {
- d_printf( "%s\n"
- "net ads user\n"
- " %s\n",
- _("Usage:"),
- _("List AD users"));
- net_display_usage_from_functable(func);
- return 0;
- }
+ if (argc > 0) {
+ TALLOC_FREE(tmp_ctx);
+ return net_run_function(c, argc, argv, "net ads user", func);
+ }
- if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
- return -1;
- }
+ if (c->display_usage) {
+ d_printf( "%s\n"
+ "net ads user\n"
+ " %s\n",
+ _("Usage:"),
+ _("List AD users"));
+ net_display_usage_from_functable(func);
+ TALLOC_FREE(tmp_ctx);
+ return -1;
+ }
+
+ status = ads_startup(c, false, tmp_ctx, &ads);
+ if (!ADS_ERR_OK(status)) {
+ goto out;
+ }
- if (c->opt_long_list_entries)
- d_printf(_("\nUser name Comment"
- "\n-----------------------------\n"));
+ if (c->opt_long_list_entries)
+ d_printf(_("\nUser name Comment"
+ "\n-----------------------------\n"));
- rc = ads_do_search_all_fn(ads, ads->config.bind_path,
- LDAP_SCOPE_SUBTREE,
- "(objectCategory=user)",
- c->opt_long_list_entries ? longattrs :
- shortattrs, usergrp_display,
- disp_fields);
- ads_destroy(&ads);
- return ADS_ERR_OK(rc) ? 0 : -1;
+ status = ads_do_search_all_fn(ads,
+ ads->config.bind_path,
+ LDAP_SCOPE_SUBTREE,
+ "(objectCategory=user)",
+ c->opt_long_list_entries ?
+ longattrs : shortattrs,
+ usergrp_display,
+ disp_fields);
+ if (!ADS_ERR_OK(status)) {
+ goto out;
}
- return net_run_function(c, argc, argv, "net ads user", func);
+ ret = 0;
+out:
+ TALLOC_FREE(tmp_ctx);
+ return ret;
}
static int net_ads_group_usage(struct net_context *c, int argc, const char **argv)
static int ads_group_add(struct net_context *c, int argc, const char **argv)
{
- ADS_STRUCT *ads;
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
+ ADS_STRUCT *ads = NULL;
ADS_STATUS status;
- LDAPMessage *res=NULL;
- int rc = -1;
+ LDAPMessage *res = NULL;
+ int ret = -1;
char *ou_str = NULL;
if (argc < 1 || c->display_usage) {
+ TALLOC_FREE(tmp_ctx);
return net_ads_group_usage(c, argc, argv);
}
- if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
- return -1;
+ status = ads_startup(c, false, tmp_ctx, &ads);
+ if (!ADS_ERR_OK(status)) {
+ goto out;
}
status = ads_find_user_acct(ads, &res, argv[0]);
-
if (!ADS_ERR_OK(status)) {
d_fprintf(stderr, _("ads_group_add: %s\n"), ads_errstr(status));
- goto done;
+ goto out;
}
if (ads_count_replies(ads, res)) {
d_fprintf(stderr, _("ads_group_add: Group %s already exists\n"), argv[0]);
- goto done;
+ goto out;
}
if (c->opt_container) {
}
status = ads_add_group_acct(ads, argv[0], ou_str, c->opt_comment);
-
- if (ADS_ERR_OK(status)) {
- d_printf(_("Group %s added\n"), argv[0]);
- rc = 0;
- } else {
+ if (!ADS_ERR_OK(status)) {
d_fprintf(stderr, _("Could not add group %s: %s\n"), argv[0],
- ads_errstr(status));
+ ads_errstr(status));
+ goto out;
}
- done:
- if (res)
- ads_msgfree(ads, res);
- ads_destroy(&ads);
+ d_printf(_("Group %s added\n"), argv[0]);
+
+ ret = 0;
+ out:
+ ads_msgfree(ads, res);
SAFE_FREE(ou_str);
- return rc;
+ TALLOC_FREE(tmp_ctx);
+ return ret;
}
static int ads_group_delete(struct net_context *c, int argc, const char **argv)
{
- ADS_STRUCT *ads;
- ADS_STATUS rc;
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
+ ADS_STRUCT *ads = NULL;
+ ADS_STATUS status;
LDAPMessage *res = NULL;
- char *groupdn;
+ char *groupdn = NULL;
+ int ret = -1;
if (argc < 1 || c->display_usage) {
+ TALLOC_FREE(tmp_ctx);
return net_ads_group_usage(c, argc, argv);
}
- if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
- return -1;
+ status = ads_startup(c, false, tmp_ctx, &ads);
+ if (!ADS_ERR_OK(status)) {
+ goto out;
}
- rc = ads_find_user_acct(ads, &res, argv[0]);
- if (!ADS_ERR_OK(rc) || ads_count_replies(ads, res) != 1) {
+ status = ads_find_user_acct(ads, &res, argv[0]);
+ if (!ADS_ERR_OK(status) || ads_count_replies(ads, res) != 1) {
d_printf(_("Group %s does not exist.\n"), argv[0]);
- ads_msgfree(ads, res);
- ads_destroy(&ads);
- return -1;
+ goto out;
}
- groupdn = ads_get_dn(ads, talloc_tos(), res);
- ads_msgfree(ads, res);
- rc = ads_del_dn(ads, groupdn);
- TALLOC_FREE(groupdn);
- if (ADS_ERR_OK(rc)) {
- d_printf(_("Group %s deleted\n"), argv[0]);
- ads_destroy(&ads);
- return 0;
+
+ groupdn = ads_get_dn(ads, tmp_ctx, res);
+ if (groupdn == NULL) {
+ goto out;
}
- d_fprintf(stderr, _("Error deleting group %s: %s\n"), argv[0],
- ads_errstr(rc));
- ads_destroy(&ads);
- return -1;
+
+ status = ads_del_dn(ads, groupdn);
+ if (!ADS_ERR_OK(status)) {
+ d_fprintf(stderr, _("Error deleting group %s: %s\n"), argv[0],
+ ads_errstr(status));
+ goto out;
+ }
+ d_printf(_("Group %s deleted\n"), argv[0]);
+
+ ret = 0;
+out:
+ ads_msgfree(ads, res);
+ TALLOC_FREE(tmp_ctx);
+ return ret;
}
int net_ads_group(struct net_context *c, int argc, const char **argv)
},
{NULL, NULL, 0, NULL, NULL}
};
- ADS_STRUCT *ads;
- ADS_STATUS rc;
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
+ ADS_STRUCT *ads = NULL;
+ ADS_STATUS status;
const char *shortattrs[] = {"sAMAccountName", NULL};
const char *longattrs[] = {"sAMAccountName", "description", NULL};
char *disp_fields[2] = {NULL, NULL};
+ int ret = -1;
- if (argc == 0) {
- if (c->display_usage) {
- d_printf( "%s\n"
- "net ads group\n"
- " %s\n",
- _("Usage:"),
- _("List AD groups"));
- net_display_usage_from_functable(func);
- return 0;
- }
+ if (argc >= 0) {
+ TALLOC_FREE(tmp_ctx);
+ return net_run_function(c, argc, argv, "net ads group", func);
+ }
- if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
- return -1;
- }
+ if (c->display_usage) {
+ d_printf( "%s\n"
+ "net ads group\n"
+ " %s\n",
+ _("Usage:"),
+ _("List AD groups"));
+ net_display_usage_from_functable(func);
+ TALLOC_FREE(tmp_ctx);
+ return -1;
+ }
+
+ status = ads_startup(c, false, tmp_ctx, &ads);
+ if (!ADS_ERR_OK(status)) {
+ goto out;
+ }
- if (c->opt_long_list_entries)
- d_printf(_("\nGroup name Comment"
- "\n-----------------------------\n"));
- rc = ads_do_search_all_fn(ads, ads->config.bind_path,
- LDAP_SCOPE_SUBTREE,
- "(objectCategory=group)",
- c->opt_long_list_entries ? longattrs :
- shortattrs, usergrp_display,
- disp_fields);
+ if (c->opt_long_list_entries)
+ d_printf(_("\nGroup name Comment"
+ "\n-----------------------------\n"));
- ads_destroy(&ads);
- return ADS_ERR_OK(rc) ? 0 : -1;
+ status = ads_do_search_all_fn(ads,
+ ads->config.bind_path,
+ LDAP_SCOPE_SUBTREE,
+ "(objectCategory=group)",
+ c->opt_long_list_entries ?
+ longattrs : shortattrs,
+ usergrp_display,
+ disp_fields);
+ if (!ADS_ERR_OK(status)) {
+ goto out;
}
- return net_run_function(c, argc, argv, "net ads group", func);
+
+ ret = 0;
+out:
+ TALLOC_FREE(tmp_ctx);
+ return ret;
}
static int net_ads_status(struct net_context *c, int argc, const char **argv)
{
- ADS_STRUCT *ads;
- ADS_STATUS rc;
- LDAPMessage *res;
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
+ ADS_STRUCT *ads = NULL;
+ ADS_STATUS status;
+ LDAPMessage *res = NULL;
+ int ret = -1;
if (c->display_usage) {
d_printf( "%s\n"
" %s\n",
_("Usage:"),
_("Display machine account details"));
- return 0;
+ TALLOC_FREE(tmp_ctx);
+ return -1;
}
- if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
- return -1;
+ net_warn_member_options();
+
+ status = ads_startup(c, true, tmp_ctx, &ads);
+ if (!ADS_ERR_OK(status)) {
+ goto out;
}
- rc = ads_find_machine_acct(ads, &res, lp_netbios_name());
- if (!ADS_ERR_OK(rc)) {
- d_fprintf(stderr, _("ads_find_machine_acct: %s\n"), ads_errstr(rc));
- ads_destroy(&ads);
- return -1;
+ status = ads_find_machine_acct(ads, &res, lp_netbios_name());
+ if (!ADS_ERR_OK(status)) {
+ d_fprintf(stderr, _("ads_find_machine_acct: %s\n"),
+ ads_errstr(status));
+ goto out;
}
if (ads_count_replies(ads, res) == 0) {
- d_fprintf(stderr, _("No machine account for '%s' found\n"), lp_netbios_name());
- ads_destroy(&ads);
- return -1;
+ d_fprintf(stderr, _("No machine account for '%s' found\n"),
+ lp_netbios_name());
+ goto out;
}
ads_dump(ads, res);
- ads_destroy(&ads);
- return 0;
+
+ ret = 0;
+out:
+ ads_msgfree(ads, res);
+ TALLOC_FREE(tmp_ctx);
+ return ret;
}
/*******************************************************************
static int net_ads_leave(struct net_context *c, int argc, const char **argv)
{
- TALLOC_CTX *ctx;
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
struct libnet_UnjoinCtx *r = NULL;
WERROR werr;
+ int ret = -1;
if (c->display_usage) {
d_printf( "%s\n"
- "net ads leave\n"
+ "net ads leave [--keep-account]\n"
" %s\n",
_("Usage:"),
_("Leave an AD domain"));
- return 0;
+ TALLOC_FREE(tmp_ctx);
+ return -1;
}
if (!*lp_realm()) {
d_fprintf(stderr, _("No realm set, are we joined ?\n"));
- return -1;
- }
-
- if (!(ctx = talloc_init("net_ads_leave"))) {
- d_fprintf(stderr, _("Could not initialise talloc context.\n"));
+ TALLOC_FREE(tmp_ctx);
return -1;
}
if (!c->msg_ctx) {
d_fprintf(stderr, _("Could not initialise message context. "
"Try running as root\n"));
- return -1;
+ goto done;
}
- werr = libnet_init_UnjoinCtx(ctx, &r);
+ werr = libnet_init_UnjoinCtx(tmp_ctx, &r);
if (!W_ERROR_IS_OK(werr)) {
d_fprintf(stderr, _("Could not initialise unjoin context.\n"));
- return -1;
+ goto done;
}
r->in.debug = true;
WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE really means "disable */
r->in.unjoin_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE;
- r->in.delete_machine_account = true;
+ if (c->opt_keep_account) {
+ r->in.delete_machine_account = false;
+ } else {
+ r->in.delete_machine_account = true;
+ }
+
r->in.msg_ctx = c->msg_ctx;
- werr = libnet_Unjoin(ctx, r);
+ werr = libnet_Unjoin(tmp_ctx, r);
if (!W_ERROR_IS_OK(werr)) {
d_printf(_("Failed to leave domain: %s\n"),
r->out.error_string ? r->out.error_string :
if (r->out.deleted_machine_account) {
d_printf(_("Deleted account for '%s' in realm '%s'\n"),
r->in.machine_name, r->out.dns_domain_name);
+ ret = 0;
goto done;
}
if (r->out.disabled_machine_account) {
d_printf(_("Disabled account for '%s' in realm '%s'\n"),
r->in.machine_name, r->out.dns_domain_name);
- werr = WERR_OK;
+ ret = 0;
goto done;
}
d_fprintf(stderr, _("Machine '%s' Left domain '%s'\n"),
r->in.machine_name, r->out.dns_domain_name);
+ ret = 0;
done:
- TALLOC_FREE(r);
- TALLOC_FREE(ctx);
-
- if (W_ERROR_IS_OK(werr)) {
- return 0;
- }
-
- return -1;
+ TALLOC_FREE(tmp_ctx);
+ return ret;
}
-static NTSTATUS net_ads_join_ok(struct net_context *c)
+static ADS_STATUS net_ads_join_ok(struct net_context *c)
{
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
ADS_STRUCT *ads = NULL;
ADS_STATUS status;
fstring dc_name;
if (!secrets_init()) {
DEBUG(1,("Failed to initialise secrets database\n"));
- return NT_STATUS_ACCESS_DENIED;
+ TALLOC_FREE(tmp_ctx);
+ return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED);
}
+ net_warn_member_options();
+
net_use_krb_machine_account(c);
get_dc_name(lp_workgroup(), lp_realm(), dc_name, &dcip);
- status = ads_startup(c, true, &ads);
+ status = ads_startup(c, true, tmp_ctx, &ads);
if (!ADS_ERR_OK(status)) {
- return ads_ntstatus(status);
+ goto out;
}
- ads_destroy(&ads);
- return NT_STATUS_OK;
+ status = ADS_ERROR_NT(NT_STATUS_OK);
+out:
+ TALLOC_FREE(tmp_ctx);
+ return status;
}
/*
*/
int net_ads_testjoin(struct net_context *c, int argc, const char **argv)
{
- NTSTATUS status;
+ ADS_STATUS status;
use_in_memory_ccache();
if (c->display_usage) {
" %s\n",
_("Usage:"),
_("Test if the existing join is ok"));
- return 0;
- }
-
- /* Display success or failure */
- status = net_ads_join_ok(c);
- if (!NT_STATUS_IS_OK(status)) {
- fprintf(stderr, _("Join to domain is not valid: %s\n"),
- get_friendly_nt_error_msg(status));
return -1;
}
- printf(_("Join is OK\n"));
- return 0;
-}
-
-/*******************************************************************
- Simple configu checks before beginning the join
- ********************************************************************/
-
-static WERROR check_ads_config( void )
-{
- if (lp_server_role() != ROLE_DOMAIN_MEMBER ) {
- d_printf(_("Host is not configured as a member server.\n"));
- return WERR_INVALID_DOMAIN_ROLE;
- }
-
- if (strlen(lp_netbios_name()) > 15) {
- d_printf(_("Our netbios name can be at most 15 chars long, "
- "\"%s\" is %u chars long\n"), lp_netbios_name(),
- (unsigned int)strlen(lp_netbios_name()));
- return WERR_INVALID_COMPUTERNAME;
- }
-
- if ( lp_security() == SEC_ADS && !*lp_realm()) {
- d_fprintf(stderr, _("realm must be set in in %s for ADS "
- "join to succeed.\n"), get_dyn_CONFIGFILE());
- return WERR_INVALID_PARAMETER;
- }
-
- return WERR_OK;
-}
-
-/*******************************************************************
- Send a DNS update request
-*******************************************************************/
-
-#if defined(WITH_DNS_UPDATES)
-#include "../lib/addns/dns.h"
-
-static NTSTATUS net_update_dns_internal(struct net_context *c,
- TALLOC_CTX *ctx, ADS_STRUCT *ads,
- const char *machine_name,
- const struct sockaddr_storage *addrs,
- int num_addrs, bool remove_host)
-{
- struct dns_rr_ns *nameservers = NULL;
- int ns_count = 0, i;
- NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
- DNS_ERROR dns_err;
- fstring dns_server;
- const char *dnsdomain = NULL;
- char *root_domain = NULL;
-
- if ( (dnsdomain = strchr_m( machine_name, '.')) == NULL ) {
- d_printf(_("No DNS domain configured for %s. "
- "Unable to perform DNS Update.\n"), machine_name);
- status = NT_STATUS_INVALID_PARAMETER;
- goto done;
- }
- dnsdomain++;
-
- status = ads_dns_lookup_ns(ctx,
- dnsdomain,
- &nameservers,
- &ns_count);
- if ( !NT_STATUS_IS_OK(status) || (ns_count == 0)) {
- /* Child domains often do not have NS records. Look
- for the NS record for the forest root domain
- (rootDomainNamingContext in therootDSE) */
-
- const char *rootname_attrs[] = { "rootDomainNamingContext", NULL };
- LDAPMessage *msg = NULL;
- char *root_dn;
- ADS_STATUS ads_status;
-
- if ( !ads->ldap.ld ) {
- ads_status = ads_connect( ads );
- if ( !ADS_ERR_OK(ads_status) ) {
- DEBUG(0,("net_update_dns_internal: Failed to connect to our DC!\n"));
- goto done;
- }
- }
-
- ads_status = ads_do_search(ads, "", LDAP_SCOPE_BASE,
- "(objectclass=*)", rootname_attrs, &msg);
- if (!ADS_ERR_OK(ads_status)) {
- goto done;
- }
-
- root_dn = ads_pull_string(ads, ctx, msg, "rootDomainNamingContext");
- if ( !root_dn ) {
- ads_msgfree( ads, msg );
- goto done;
- }
-
- root_domain = ads_build_domain( root_dn );
-
- /* cleanup */
- ads_msgfree( ads, msg );
-
- /* try again for NS servers */
-
- status = ads_dns_lookup_ns(ctx,
- root_domain,
- &nameservers,
- &ns_count);
-
- if ( !NT_STATUS_IS_OK(status) || (ns_count == 0)) {
- DEBUG(3,("net_update_dns_internal: Failed to find name server for the %s "
- "realm\n", ads->config.realm));
- if (ns_count == 0) {
- status = NT_STATUS_UNSUCCESSFUL;
- }
- goto done;
- }
-
- dnsdomain = root_domain;
-
- }
-
- for (i=0; i < ns_count; i++) {
-
- uint32_t flags = DNS_UPDATE_SIGNED |
- DNS_UPDATE_UNSIGNED |
- DNS_UPDATE_UNSIGNED_SUFFICIENT |
- DNS_UPDATE_PROBE |
- DNS_UPDATE_PROBE_SUFFICIENT;
-
- if (c->opt_force) {
- flags &= ~DNS_UPDATE_PROBE_SUFFICIENT;
- flags &= ~DNS_UPDATE_UNSIGNED_SUFFICIENT;
- }
-
- /*
- * Do not return after PROBE completion if this function
- * is called for DNS removal.
- */
- if (remove_host) {
- flags &= ~DNS_UPDATE_PROBE_SUFFICIENT;
- }
-
- status = NT_STATUS_UNSUCCESSFUL;
-
- /* Now perform the dns update - we'll try non-secure and if we fail,
- we'll follow it up with a secure update */
-
- fstrcpy( dns_server, nameservers[i].hostname );
-
- dns_err = DoDNSUpdate(dns_server,
- dnsdomain,
- machine_name,
- addrs,
- num_addrs,
- flags,
- remove_host);
- if (ERR_DNS_IS_OK(dns_err)) {
- status = NT_STATUS_OK;
- goto done;
- }
-
- if (ERR_DNS_EQUAL(dns_err, ERROR_DNS_INVALID_NAME_SERVER) ||
- ERR_DNS_EQUAL(dns_err, ERROR_DNS_CONNECTION_FAILED) ||
- ERR_DNS_EQUAL(dns_err, ERROR_DNS_SOCKET_ERROR)) {
- DEBUG(1,("retrying DNS update with next nameserver after receiving %s\n",
- dns_errstr(dns_err)));
- continue;
- }
-
- d_printf(_("DNS Update for %s failed: %s\n"),
- machine_name, dns_errstr(dns_err));
- status = NT_STATUS_UNSUCCESSFUL;
- goto done;
- }
-
-done:
+ net_warn_member_options();
- SAFE_FREE( root_domain );
+ /* Display success or failure */
+ status = net_ads_join_ok(c);
+ if (!ADS_ERR_OK(status)) {
+ fprintf(stderr, _("Join to domain is not valid: %s\n"),
+ get_friendly_nt_error_msg(ads_ntstatus(status)));
+ return -1;
+ }
- return status;
+ printf(_("Join is OK\n"));
+ return 0;
}
-static NTSTATUS net_update_dns_ext(struct net_context *c,
- TALLOC_CTX *mem_ctx, ADS_STRUCT *ads,
- const char *hostname,
- struct sockaddr_storage *iplist,
- int num_addrs, bool remove_host)
-{
- struct sockaddr_storage *iplist_alloc = NULL;
- fstring machine_name;
- NTSTATUS status;
+/*******************************************************************
+ Simple config checks before beginning the join
+ ********************************************************************/
- if (hostname) {
- fstrcpy(machine_name, hostname);
- } else {
- name_to_fqdn( machine_name, lp_netbios_name() );
- }
- if (!strlower_m( machine_name )) {
- return NT_STATUS_INVALID_PARAMETER;
+static WERROR check_ads_config( void )
+{
+ if (lp_server_role() != ROLE_DOMAIN_MEMBER ) {
+ d_printf(_("Host is not configured as a member server.\n"));
+ return WERR_INVALID_DOMAIN_ROLE;
}
- /*
- * If remove_host is true, then remove all IP addresses associated with
- * this hostname from the AD server.
- */
- if (!remove_host && (num_addrs == 0 || iplist == NULL)) {
- /*
- * Get our ip address
- * (not the 127.0.0.x address but a real ip address)
- */
- num_addrs = get_my_ip_address(&iplist_alloc);
- if ( num_addrs <= 0 ) {
- DEBUG(4, ("net_update_dns_ext: Failed to find my "
- "non-loopback IP addresses!\n"));
- return NT_STATUS_INVALID_PARAMETER;
- }
- iplist = iplist_alloc;
+ if (strlen(lp_netbios_name()) > 15) {
+ d_printf(_("Our netbios name can be at most 15 chars long, "
+ "\"%s\" is %u chars long\n"), lp_netbios_name(),
+ (unsigned int)strlen(lp_netbios_name()));
+ return WERR_INVALID_COMPUTERNAME;
}
- status = net_update_dns_internal(c, mem_ctx, ads, machine_name,
- iplist, num_addrs, remove_host);
-
- SAFE_FREE(iplist_alloc);
- return status;
-}
-
-static NTSTATUS net_update_dns(struct net_context *c, TALLOC_CTX *mem_ctx, ADS_STRUCT *ads, const char *hostname)
-{
- NTSTATUS status;
+ if ( lp_security() == SEC_ADS && !*lp_realm()) {
+ d_fprintf(stderr, _("realm must be set in in %s for ADS "
+ "join to succeed.\n"), get_dyn_CONFIGFILE());
+ return WERR_INVALID_PARAMETER;
+ }
- status = net_update_dns_ext(c, mem_ctx, ads, hostname, NULL, 0, false);
- return status;
+ return WERR_OK;
}
-#endif
-
/*******************************************************************
********************************************************************/
{
d_printf(_("net ads join [--no-dns-updates] [options]\n"
"Valid options:\n"));
+ d_printf(_(" dnshostname=FQDN Set the dnsHostName attribute during the join.\n"
+ " The default is in the form netbiosname.dnsdomain\n"));
d_printf(_(" createupn[=UPN] Set the userPrincipalName attribute during the join.\n"
" The default UPN is in the form host/netbiosname@REALM.\n"));
d_printf(_(" createcomputer=OU Precreate the computer account in a specific OU.\n"
}
-static void _net_ads_join_dns_updates(struct net_context *c, TALLOC_CTX *ctx, struct libnet_JoinCtx *r)
-{
-#if defined(WITH_DNS_UPDATES)
- ADS_STRUCT *ads_dns = NULL;
- int ret;
- NTSTATUS status;
-
- /*
- * In a clustered environment, don't do dynamic dns updates:
- * Registering the set of ip addresses that are assigned to
- * the interfaces of the node that performs the join does usually
- * not have the desired effect, since the local interfaces do not
- * carry the complete set of the cluster's public IP addresses.
- * And it can also contain internal addresses that should not
- * be visible to the outside at all.
- * In order to do dns updates in a clustererd setup, use
- * net ads dns register.
- */
- if (lp_clustering()) {
- d_fprintf(stderr, _("Not doing automatic DNS update in a "
- "clustered setup.\n"));
- return;
- }
-
- if (!r->out.domain_is_ad) {
- return;
- }
-
- /*
- * We enter this block with user creds.
- * kinit with the machine password to do dns update.
- */
-
- ads_dns = ads_init(lp_realm(), NULL, r->in.dc_name);
-
- if (ads_dns == NULL) {
- d_fprintf(stderr, _("DNS update failed: out of memory!\n"));
- goto done;
- }
-
- use_in_memory_ccache();
-
- ret = asprintf(&ads_dns->auth.user_name, "%s$", lp_netbios_name());
- if (ret == -1) {
- d_fprintf(stderr, _("DNS update failed: out of memory\n"));
- goto done;
- }
-
- ads_dns->auth.password = secrets_fetch_machine_password(
- r->out.netbios_domain_name, NULL, NULL);
- if (ads_dns->auth.password == NULL) {
- d_fprintf(stderr, _("DNS update failed: out of memory\n"));
- goto done;
- }
-
- ads_dns->auth.realm = SMB_STRDUP(r->out.dns_domain_name);
- if (ads_dns->auth.realm == NULL) {
- d_fprintf(stderr, _("DNS update failed: out of memory\n"));
- goto done;
- }
-
- if (!strupper_m(ads_dns->auth.realm)) {
- d_fprintf(stderr, _("strupper_m %s failed\n"), ads_dns->auth.realm);
- goto done;
- }
-
- ret = ads_kinit_password(ads_dns);
- if (ret != 0) {
- d_fprintf(stderr,
- _("DNS update failed: kinit failed: %s\n"),
- error_message(ret));
- goto done;
- }
-
- status = net_update_dns(c, ctx, ads_dns, NULL);
- if (!NT_STATUS_IS_OK(status)) {
- d_fprintf( stderr, _("DNS update failed: %s\n"),
- nt_errstr(status));
- }
-
-done:
- ads_destroy(&ads_dns);
-#endif
-
- return;
-}
-
-
int net_ads_join(struct net_context *c, int argc, const char **argv)
{
- TALLOC_CTX *ctx = NULL;
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
struct libnet_JoinCtx *r = NULL;
const char *domain = lp_realm();
WERROR werr = WERR_NERR_SETUPNOTJOINED;
bool createupn = false;
+ const char *dnshostname = NULL;
const char *machineupn = NULL;
const char *machine_password = NULL;
const char *create_in_ou = NULL;
const char *os_servicepack = NULL;
bool modify_config = lp_config_backend_is_registry();
enum libnetjoin_JoinDomNameType domain_name_type = JoinDomNameTypeDNS;
+ int ret = -1;
- if (c->display_usage)
+ if (c->display_usage) {
+ TALLOC_FREE(tmp_ctx);
return net_ads_join_usage(c, argc, argv);
+ }
- if (!modify_config) {
+ net_warn_member_options();
+ if (!modify_config) {
werr = check_ads_config();
if (!W_ERROR_IS_OK(werr)) {
d_fprintf(stderr, _("Invalid configuration. Exiting....\n"));
}
}
- if (!(ctx = talloc_init("net_ads_join"))) {
- d_fprintf(stderr, _("Could not initialise talloc context.\n"));
- werr = WERR_NOT_ENOUGH_MEMORY;
- goto fail;
- }
-
if (!c->opt_kerberos) {
use_in_memory_ccache();
}
- werr = libnet_init_JoinCtx(ctx, &r);
+ werr = libnet_init_JoinCtx(tmp_ctx, &r);
if (!W_ERROR_IS_OK(werr)) {
goto fail;
}
/* process additional command line args */
for ( i=0; i<argc; i++ ) {
- if ( !strncasecmp_m(argv[i], "createupn", strlen("createupn")) ) {
+ if ( !strncasecmp_m(argv[i], "dnshostname", strlen("dnshostname")) ) {
+ dnshostname = get_string_param(argv[i]);
+ }
+ else if ( !strncasecmp_m(argv[i], "createupn", strlen("createupn")) ) {
createupn = true;
machineupn = get_string_param(argv[i]);
}
werr = WERR_INVALID_PARAMETER;
goto fail;
}
- }
- else {
+ } else {
domain = argv[i];
if (strchr(domain, '.') == NULL) {
domain_name_type = JoinDomNameTypeUnknown;
r->in.domain_name_type = domain_name_type;
r->in.create_upn = createupn;
r->in.upn = machineupn;
+ r->in.dnshostname = dnshostname;
r->in.account_ou = create_in_ou;
r->in.os_name = os_name;
r->in.os_version = os_version;
WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED;
r->in.msg_ctx = c->msg_ctx;
- werr = libnet_Join(ctx, r);
+ werr = libnet_Join(tmp_ctx, r);
if (W_ERROR_EQUAL(werr, WERR_NERR_DCNOTFOUND) &&
strequal(domain, lp_realm())) {
r->in.domain_name = lp_workgroup();
r->in.domain_name_type = JoinDomNameTypeNBT;
- werr = libnet_Join(ctx, r);
+ werr = libnet_Join(tmp_ctx, r);
}
if (!W_ERROR_IS_OK(werr)) {
goto fail;
* operation as succeeded if we came this far.
*/
if (!c->opt_no_dns_updates) {
- _net_ads_join_dns_updates(c, ctx, r);
+ net_ads_join_dns_updates(c, tmp_ctx, r);
}
- TALLOC_FREE(r);
- TALLOC_FREE( ctx );
-
- return 0;
+ ret = 0;
fail:
- /* issue an overall failure message at the end. */
- d_printf(_("Failed to join domain: %s\n"),
- r && r->out.error_string ? r->out.error_string :
- get_friendly_werror_msg(werr));
- TALLOC_FREE( ctx );
+ if (ret != 0) {
+ /* issue an overall failure message at the end. */
+ d_printf(_("Failed to join domain: %s\n"),
+ r && r->out.error_string ? r->out.error_string :
+ get_friendly_werror_msg(werr));
+ }
+
+ TALLOC_FREE(tmp_ctx);
- return -1;
+ return ret;
}
/*******************************************************************
static int net_ads_dns_register(struct net_context *c, int argc, const char **argv)
{
-#if defined(WITH_DNS_UPDATES)
- ADS_STRUCT *ads;
+#if defined(HAVE_KRB5)
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
+ ADS_STRUCT *ads = NULL;
ADS_STATUS status;
NTSTATUS ntstatus;
- TALLOC_CTX *ctx;
const char *hostname = NULL;
const char **addrs_list = NULL;
struct sockaddr_storage *addrs = NULL;
int num_addrs = 0;
int count;
+ int ret = -1;
#ifdef DEVELOPER
talloc_enable_leak_report();
if (c->display_usage) {
d_printf( "%s\n"
- "net ads dns register [hostname [IP [IP...]]]\n"
+ "net ads dns register [hostname [IP [IP...]]] "
+ "[--force] [--dns-ttl TTL]\n"
" %s\n",
_("Usage:"),
_("Register hostname with DNS\n"));
- return -1;
- }
-
- if (!(ctx = talloc_init("net_ads_dns"))) {
- d_fprintf(stderr, _("Could not initialise talloc context\n"));
+ TALLOC_FREE(tmp_ctx);
return -1;
}
}
if (num_addrs > 0) {
- addrs = talloc_zero_array(ctx, struct sockaddr_storage, num_addrs);
+ addrs = talloc_zero_array(tmp_ctx,
+ struct sockaddr_storage,
+ num_addrs);
if (addrs == NULL) {
d_fprintf(stderr, _("Error allocating memory!\n"));
- talloc_free(ctx);
- return -1;
+ goto out;
}
}
d_fprintf(stderr, "%s '%s'.\n",
_("Cannot interpret address"),
addrs_list[count]);
- talloc_free(ctx);
- return -1;
+ goto out;
}
}
- status = ads_startup(c, true, &ads);
+ status = ads_startup(c, true, tmp_ctx, &ads);
if ( !ADS_ERR_OK(status) ) {
DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
- TALLOC_FREE(ctx);
- return -1;
+ goto out;
}
- ntstatus = net_update_dns_ext(c, ctx, ads, hostname, addrs, num_addrs, false);
+ ntstatus = net_update_dns_ext(c,
+ tmp_ctx,
+ ads,
+ hostname,
+ addrs,
+ num_addrs,
+ false);
if (!NT_STATUS_IS_OK(ntstatus)) {
d_fprintf( stderr, _("DNS update failed!\n") );
- ads_destroy( &ads );
- TALLOC_FREE( ctx );
- return -1;
+ goto out;
}
d_fprintf( stderr, _("Successfully registered hostname with DNS\n") );
- ads_destroy(&ads);
- TALLOC_FREE( ctx );
+ ret = 0;
+out:
+ TALLOC_FREE(tmp_ctx);
- return 0;
+ return ret;
#else
d_fprintf(stderr,
_("DNS update support not enabled at compile time!\n"));
int argc,
const char **argv)
{
-#if defined(WITH_DNS_UPDATES)
- ADS_STRUCT *ads;
+#if defined(HAVE_KRB5)
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
+ ADS_STRUCT *ads = NULL;
ADS_STATUS status;
NTSTATUS ntstatus;
- TALLOC_CTX *ctx;
const char *hostname = NULL;
+ int ret = -1;
#ifdef DEVELOPER
talloc_enable_leak_report();
"net ads dns unregister [hostname]\n"
" %s\n",
_("Usage:"),
- _("Register hostname with DNS\n"));
- return -1;
- }
-
- if (!(ctx = talloc_init("net_ads_dns"))) {
- d_fprintf(stderr, _("Could not initialise talloc context\n"));
+ _("Remove all IP Address entries for a given\n"
+ " hostname from the Active Directory server.\n"));
+ TALLOC_FREE(tmp_ctx);
return -1;
}
/* Get the hostname for un-registering */
hostname = argv[0];
- status = ads_startup(c, true, &ads);
+ status = ads_startup(c, true, tmp_ctx, &ads);
if ( !ADS_ERR_OK(status) ) {
DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
- TALLOC_FREE(ctx);
- return -1;
+ goto out;
}
- ntstatus = net_update_dns_ext(c, ctx, ads, hostname, NULL, 0, true);
+ ntstatus = net_update_dns_ext(c,
+ tmp_ctx,
+ ads,
+ hostname,
+ NULL,
+ 0,
+ true);
if (!NT_STATUS_IS_OK(ntstatus)) {
d_fprintf( stderr, _("DNS update failed!\n") );
- ads_destroy( &ads );
- TALLOC_FREE( ctx );
- return -1;
+ goto out;
}
d_fprintf( stderr, _("Successfully un-registered hostname from DNS\n"));
- ads_destroy(&ads);
- TALLOC_FREE( ctx );
+ ret = 0;
+out:
+ TALLOC_FREE(tmp_ctx);
- return 0;
+ return ret;
#else
d_fprintf(stderr,
_("DNS update support not enabled at compile time!\n"));
#endif
}
-static int net_ads_dns_gethostbyname(struct net_context *c, int argc, const char **argv)
-{
-#if defined(WITH_DNS_UPDATES)
- DNS_ERROR err;
-#ifdef DEVELOPER
- talloc_enable_leak_report();
-#endif
+static int net_ads_dns_async(struct net_context *c, int argc, const char **argv)
+{
+ size_t num_names = 0;
+ char **hostnames = NULL;
+ size_t i = 0;
+ struct samba_sockaddr *addrs = NULL;
+ NTSTATUS status;
- if (argc != 2 || c->display_usage) {
+ if (argc != 1 || c->display_usage) {
d_printf( "%s\n"
" %s\n"
" %s\n",
_("Usage:"),
- _("net ads dns gethostbyname <server> <name>\n"),
- _(" Look up hostname from the AD\n"
- " server\tName server to use\n"
- " name\tName to look up\n"));
+ _("net ads dns async <name>\n"),
+ _(" Async look up hostname from the DNS server\n"
+ " hostname\tName to look up\n"));
return -1;
}
- err = do_gethostbyname(argv[0], argv[1]);
- if (!ERR_DNS_IS_OK(err)) {
- d_printf(_("do_gethostbyname returned %s (%d)\n"),
- dns_errstr(err), ERROR_DNS_V(err));
+ status = ads_dns_lookup_a(talloc_tos(),
+ argv[0],
+ &num_names,
+ &hostnames,
+ &addrs);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("Looking up A record for %s got error %s\n",
+ argv[0],
+ nt_errstr(status));
+ return -1;
+ }
+ d_printf("Async A record lookup - got %u names for %s\n",
+ (unsigned int)num_names,
+ argv[0]);
+ for (i = 0; i < num_names; i++) {
+ char addr_buf[INET6_ADDRSTRLEN];
+ print_sockaddr(addr_buf,
+ sizeof(addr_buf),
+ &addrs[i].u.ss);
+ d_printf("hostname[%u] = %s, IPv4addr = %s\n",
+ (unsigned int)i,
+ hostnames[i],
+ addr_buf);
+ }
+
+#if defined(HAVE_IPV6)
+ status = ads_dns_lookup_aaaa(talloc_tos(),
+ argv[0],
+ &num_names,
+ &hostnames,
+ &addrs);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("Looking up AAAA record for %s got error %s\n",
+ argv[0],
+ nt_errstr(status));
+ return -1;
+ }
+ d_printf("Async AAAA record lookup - got %u names for %s\n",
+ (unsigned int)num_names,
+ argv[0]);
+ for (i = 0; i < num_names; i++) {
+ char addr_buf[INET6_ADDRSTRLEN];
+ print_sockaddr(addr_buf,
+ sizeof(addr_buf),
+ &addrs[i].u.ss);
+ d_printf("hostname[%u] = %s, IPv6addr = %s\n",
+ (unsigned int)i,
+ hostnames[i],
+ addr_buf);
}
#endif
return 0;
}
+
static int net_ads_dns(struct net_context *c, int argc, const char *argv[])
{
struct functable func[] = {
" Remove host dns entry from AD")
},
{
- "gethostbyname",
- net_ads_dns_gethostbyname,
+ "async",
+ net_ads_dns_async,
NET_TRANSPORT_ADS,
N_("Look up host"),
- N_("net ads dns gethostbyname\n"
- " Look up host")
+ N_("net ads dns async\n"
+ " Look up host using async DNS")
},
{NULL, NULL, 0, NULL, NULL}
};
/*******************************************************************
********************************************************************/
-static int net_ads_printer_search(struct net_context *c, int argc, const char **argv)
+static int net_ads_printer_search(struct net_context *c,
+ int argc,
+ const char **argv)
{
- ADS_STRUCT *ads;
- ADS_STATUS rc;
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
+ ADS_STRUCT *ads = NULL;
+ ADS_STATUS status;
LDAPMessage *res = NULL;
+ int ret = -1;
if (c->display_usage) {
d_printf( "%s\n"
" %s\n",
_("Usage:"),
_("List printers in the AD"));
- return 0;
- }
-
- if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
+ TALLOC_FREE(tmp_ctx);
return -1;
}
- rc = ads_find_printers(ads, &res);
+ status = ads_startup(c, false, tmp_ctx, &ads);
+ if (!ADS_ERR_OK(status)) {
+ goto out;
+ }
- if (!ADS_ERR_OK(rc)) {
- d_fprintf(stderr, _("ads_find_printer: %s\n"), ads_errstr(rc));
- ads_msgfree(ads, res);
- ads_destroy(&ads);
- return -1;
+ status = ads_find_printers(ads, &res);
+ if (!ADS_ERR_OK(status)) {
+ d_fprintf(stderr, _("ads_find_printer: %s\n"),
+ ads_errstr(status));
+ goto out;
}
if (ads_count_replies(ads, res) == 0) {
d_fprintf(stderr, _("No results found\n"));
- ads_msgfree(ads, res);
- ads_destroy(&ads);
- return -1;
+ goto out;
}
ads_dump(ads, res);
+
+ ret = 0;
+out:
ads_msgfree(ads, res);
- ads_destroy(&ads);
- return 0;
+ TALLOC_FREE(tmp_ctx);
+ return ret;
}
-static int net_ads_printer_info(struct net_context *c, int argc, const char **argv)
+static int net_ads_printer_info(struct net_context *c,
+ int argc,
+ const char **argv)
{
- ADS_STRUCT *ads;
- ADS_STATUS rc;
- const char *servername, *printername;
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
+ ADS_STRUCT *ads = NULL;
+ ADS_STATUS status;
+ const char *servername = NULL;
+ const char *printername = NULL;
LDAPMessage *res = NULL;
+ int ret = -1;
if (c->display_usage) {
d_printf("%s\n%s",
" Display printer info from AD\n"
" printername\tPrinter name or wildcard\n"
" servername\tName of the print server\n"));
- return 0;
+ TALLOC_FREE(tmp_ctx);
+ return -1;
}
- if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
- return -1;
+ status = ads_startup(c, false, tmp_ctx, &ads);
+ if (!ADS_ERR_OK(status)) {
+ goto out;
}
if (argc > 0) {
servername = lp_netbios_name();
}
- rc = ads_find_printer_on_server(ads, &res, printername, servername);
-
- if (!ADS_ERR_OK(rc)) {
+ status = ads_find_printer_on_server(ads, &res, printername, servername);
+ if (!ADS_ERR_OK(status)) {
d_fprintf(stderr, _("Server '%s' not found: %s\n"),
- servername, ads_errstr(rc));
- ads_msgfree(ads, res);
- ads_destroy(&ads);
- return -1;
+ servername, ads_errstr(status));
+ goto out;
}
if (ads_count_replies(ads, res) == 0) {
d_fprintf(stderr, _("Printer '%s' not found\n"), printername);
- ads_msgfree(ads, res);
- ads_destroy(&ads);
- return -1;
+ goto out;
}
ads_dump(ads, res);
- ads_msgfree(ads, res);
- ads_destroy(&ads);
- return 0;
+ ret = 0;
+out:
+ ads_msgfree(ads, res);
+ TALLOC_FREE(tmp_ctx);
+ return ret;
}
-static int net_ads_printer_publish(struct net_context *c, int argc, const char **argv)
+static int net_ads_printer_publish(struct net_context *c,
+ int argc,
+ const char **argv)
{
- ADS_STRUCT *ads;
- ADS_STATUS rc;
- const char *servername, *printername;
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
+ ADS_STRUCT *ads = NULL;
+ ADS_STATUS status;
+ const char *servername = NULL;
+ const char *printername = NULL;
struct cli_state *cli = NULL;
struct rpc_pipe_client *pipe_hnd = NULL;
- struct sockaddr_storage server_ss;
+ struct sockaddr_storage server_ss = { 0 };
NTSTATUS nt_status;
- TALLOC_CTX *mem_ctx = talloc_init("net_ads_printer_publish");
- ADS_MODLIST mods = ads_init_mods(mem_ctx);
- char *prt_dn, *srv_dn, **srv_cn;
- char *srv_cn_escaped = NULL, *printername_escaped = NULL;
+ ADS_MODLIST mods = NULL;
+ char *prt_dn = NULL;
+ char *srv_dn = NULL;
+ char **srv_cn = NULL;
+ char *srv_cn_escaped = NULL;
+ char *printername_escaped = NULL;
LDAPMessage *res = NULL;
bool ok;
+ int ret = -1;
if (argc < 1 || c->display_usage) {
d_printf("%s\n%s",
" Publish printer in AD\n"
" printername\tName of the printer\n"
" servername\tName of the print server\n"));
- talloc_destroy(mem_ctx);
+ TALLOC_FREE(tmp_ctx);
return -1;
}
- if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
- talloc_destroy(mem_ctx);
- return -1;
+ mods = ads_init_mods(tmp_ctx);
+ if (mods == NULL) {
+ d_fprintf(stderr, _("Out of memory\n"));
+ goto out;
+ }
+
+ status = ads_startup(c, true, tmp_ctx, &ads);
+ if (!ADS_ERR_OK(status)) {
+ goto out;
}
printername = argv[0];
if (!ok) {
d_fprintf(stderr, _("Could not find server %s\n"),
servername);
- ads_destroy(&ads);
- talloc_destroy(mem_ctx);
- return -1;
+ goto out;
}
- nt_status = cli_full_connection(&cli, lp_netbios_name(), servername,
+ cli_credentials_set_kerberos_state(c->creds,
+ CRED_USE_KERBEROS_REQUIRED,
+ CRED_SPECIFIED);
+
+ nt_status = cli_full_connection_creds(&cli, lp_netbios_name(), servername,
&server_ss, 0,
"IPC$", "IPC",
- c->opt_user_name, c->opt_workgroup,
- c->opt_password ? c->opt_password : "",
- CLI_FULL_CONNECTION_USE_KERBEROS,
- SMB_SIGNING_IPC_DEFAULT);
+ c->creds,
+ CLI_FULL_CONNECTION_IPC);
if (NT_STATUS_IS_ERR(nt_status)) {
d_fprintf(stderr, _("Unable to open a connection to %s to "
"obtain data for %s\n"),
servername, printername);
- ads_destroy(&ads);
- talloc_destroy(mem_ctx);
- return -1;
+ goto out;
}
/* Publish on AD server */
d_fprintf(stderr, _("Could not find machine account for server "
"%s\n"),
servername);
- ads_destroy(&ads);
- talloc_destroy(mem_ctx);
- return -1;
+ goto out;
}
srv_dn = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
SAFE_FREE(srv_cn_escaped);
SAFE_FREE(printername_escaped);
d_fprintf(stderr, _("Internal error, out of memory!"));
- ads_destroy(&ads);
- talloc_destroy(mem_ctx);
- return -1;
+ goto out;
}
- if (asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_escaped, printername_escaped, srv_dn) == -1) {
+ prt_dn = talloc_asprintf(tmp_ctx,
+ "cn=%s-%s,%s",
+ srv_cn_escaped,
+ printername_escaped,
+ srv_dn);
+ if (prt_dn == NULL) {
SAFE_FREE(srv_cn_escaped);
SAFE_FREE(printername_escaped);
d_fprintf(stderr, _("Internal error, out of memory!"));
- ads_destroy(&ads);
- talloc_destroy(mem_ctx);
- return -1;
+ goto out;
}
SAFE_FREE(srv_cn_escaped);
if (!NT_STATUS_IS_OK(nt_status)) {
d_fprintf(stderr, _("Unable to open a connection to the spoolss pipe on %s\n"),
servername);
- SAFE_FREE(prt_dn);
- ads_destroy(&ads);
- talloc_destroy(mem_ctx);
- return -1;
+ goto out;
}
- if (!W_ERROR_IS_OK(get_remote_printer_publishing_data(pipe_hnd, mem_ctx, &mods,
+ if (!W_ERROR_IS_OK(get_remote_printer_publishing_data(pipe_hnd,
+ tmp_ctx,
+ &mods,
printername))) {
- SAFE_FREE(prt_dn);
- ads_destroy(&ads);
- talloc_destroy(mem_ctx);
- return -1;
+ goto out;
}
- rc = ads_add_printer_entry(ads, prt_dn, mem_ctx, &mods);
- if (!ADS_ERR_OK(rc)) {
- d_fprintf(stderr, "ads_publish_printer: %s\n", ads_errstr(rc));
- SAFE_FREE(prt_dn);
- ads_destroy(&ads);
- talloc_destroy(mem_ctx);
- return -1;
+ status = ads_add_printer_entry(ads, prt_dn, tmp_ctx, &mods);
+ if (!ADS_ERR_OK(status)) {
+ d_fprintf(stderr, "ads_publish_printer: %s\n",
+ ads_errstr(status));
+ goto out;
}
d_printf("published printer\n");
- SAFE_FREE(prt_dn);
- ads_destroy(&ads);
- talloc_destroy(mem_ctx);
- return 0;
+ ret = 0;
+out:
+ talloc_destroy(tmp_ctx);
+
+ return ret;
}
-static int net_ads_printer_remove(struct net_context *c, int argc, const char **argv)
+static int net_ads_printer_remove(struct net_context *c,
+ int argc,
+ const char **argv)
{
- ADS_STRUCT *ads;
- ADS_STATUS rc;
- const char *servername;
- char *prt_dn;
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
+ ADS_STRUCT *ads = NULL;
+ ADS_STATUS status;
+ const char *servername = NULL;
+ char *prt_dn = NULL;
LDAPMessage *res = NULL;
+ int ret = -1;
if (argc < 1 || c->display_usage) {
d_printf("%s\n%s",
" Remove a printer from the AD\n"
" printername\tName of the printer\n"
" servername\tName of the print server\n"));
+ TALLOC_FREE(tmp_ctx);
return -1;
}
- if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
- return -1;
+ status = ads_startup(c, true, tmp_ctx, &ads);
+ if (!ADS_ERR_OK(status)) {
+ goto out;
}
if (argc > 1) {
servername = lp_netbios_name();
}
- rc = ads_find_printer_on_server(ads, &res, argv[0], servername);
-
- if (!ADS_ERR_OK(rc)) {
- d_fprintf(stderr, _("ads_find_printer_on_server: %s\n"), ads_errstr(rc));
- ads_msgfree(ads, res);
- ads_destroy(&ads);
- return -1;
+ status = ads_find_printer_on_server(ads, &res, argv[0], servername);
+ if (!ADS_ERR_OK(status)) {
+ d_fprintf(stderr, _("ads_find_printer_on_server: %s\n"),
+ ads_errstr(status));
+ goto out;
}
if (ads_count_replies(ads, res) == 0) {
d_fprintf(stderr, _("Printer '%s' not found\n"), argv[1]);
- ads_msgfree(ads, res);
- ads_destroy(&ads);
- return -1;
+ goto out;
}
- prt_dn = ads_get_dn(ads, talloc_tos(), res);
- ads_msgfree(ads, res);
- rc = ads_del_dn(ads, prt_dn);
- TALLOC_FREE(prt_dn);
+ prt_dn = ads_get_dn(ads, tmp_ctx, res);
+ if (prt_dn == NULL) {
+ d_fprintf(stderr, _("Out of memory\n"));
+ goto out;
+ }
- if (!ADS_ERR_OK(rc)) {
- d_fprintf(stderr, _("ads_del_dn: %s\n"), ads_errstr(rc));
- ads_destroy(&ads);
- return -1;
+ status = ads_del_dn(ads, prt_dn);
+ if (!ADS_ERR_OK(status)) {
+ d_fprintf(stderr, _("ads_del_dn: %s\n"), ads_errstr(status));
+ goto out;
}
- ads_destroy(&ads);
- return 0;
+ ret = 0;
+out:
+ ads_msgfree(ads, res);
+ TALLOC_FREE(tmp_ctx);
+ return ret;
}
static int net_ads_printer(struct net_context *c, int argc, const char **argv)
static int net_ads_password(struct net_context *c, int argc, const char **argv)
{
- ADS_STRUCT *ads;
- const char *auth_principal = c->opt_user_name;
- const char *auth_password = c->opt_password;
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
+ ADS_STRUCT *ads = NULL;
+ const char *auth_principal = cli_credentials_get_username(c->creds);
+ const char *auth_password = cli_credentials_get_password(c->creds);
const char *realm = NULL;
- const char *new_password = NULL;
- char *chr, *prompt;
- const char *user;
+ char *new_password = NULL;
+ char *chr = NULL;
+ char *prompt = NULL;
+ const char *user = NULL;
char pwd[256] = {0};
- ADS_STATUS ret;
+ ADS_STATUS status;
+ int ret = 0;
if (c->display_usage) {
d_printf("%s\n%s",
_("net ads password <username>\n"
" Change password for user\n"
" username\tName of user to change password for\n"));
- return 0;
+ TALLOC_FREE(tmp_ctx);
+ return -1;
}
- if (c->opt_user_name == NULL || c->opt_password == NULL) {
+ if (auth_principal == NULL || auth_password == NULL) {
d_fprintf(stderr, _("You must supply an administrator "
"username/password\n"));
+ TALLOC_FREE(tmp_ctx);
return -1;
}
if (argc < 1) {
d_fprintf(stderr, _("ERROR: You must say which username to "
"change password for\n"));
+ TALLOC_FREE(tmp_ctx);
return -1;
}
- user = argv[0];
- if (!strchr_m(user, '@')) {
- if (asprintf(&chr, "%s@%s", argv[0], lp_realm()) == -1) {
- return -1;
- }
- user = chr;
+ if (strchr_m(argv[0], '@')) {
+ user = talloc_strdup(tmp_ctx, argv[0]);
+ } else {
+ user = talloc_asprintf(tmp_ctx, "%s@%s", argv[0], lp_realm());
+ }
+ if (user == NULL) {
+ d_fprintf(stderr, _("Out of memory\n"));
+ goto out;
}
use_in_memory_ccache();
/* use the realm so we can eventually change passwords for users
in realms other than default */
- if (!(ads = ads_init(realm, c->opt_workgroup, c->opt_host))) {
- return -1;
+ ads = ads_init(tmp_ctx,
+ realm,
+ c->opt_workgroup,
+ c->opt_host,
+ ADS_SASL_PLAIN);
+ if (ads == NULL) {
+ goto out;
}
/* we don't actually need a full connect, but it's the easy way to
- fill in the KDC's addresss */
+ fill in the KDC's address */
ads_connect(ads);
if (!ads->config.realm) {
d_fprintf(stderr, _("Didn't find the kerberos server!\n"));
- ads_destroy(&ads);
- return -1;
+ goto out;
}
- if (argv[1]) {
- new_password = (const char *)argv[1];
+ if (argv[1] != NULL) {
+ new_password = talloc_strdup(tmp_ctx, argv[1]);
} else {
int rc;
- if (asprintf(&prompt, _("Enter new password for %s:"), user) == -1) {
- return -1;
+ prompt = talloc_asprintf(tmp_ctx, _("Enter new password for %s:"), user);
+ if (prompt == NULL) {
+ d_fprintf(stderr, _("Out of memory\n"));
+ goto out;
}
+
rc = samba_getpass(prompt, pwd, sizeof(pwd), false, true);
if (rc < 0) {
- return -1;
+ goto out;
}
- new_password = pwd;
- free(prompt);
+ new_password = talloc_strdup(tmp_ctx, pwd);
+ memset(pwd, '\0', sizeof(pwd));
}
- ret = kerberos_set_password(ads->auth.kdc_server, auth_principal,
- auth_password, user, new_password, ads->auth.time_offset);
- memset(pwd, '\0', sizeof(pwd));
- if (!ADS_ERR_OK(ret)) {
- d_fprintf(stderr, _("Password change failed: %s\n"), ads_errstr(ret));
- ads_destroy(&ads);
- return -1;
+ if (new_password == NULL) {
+ d_fprintf(stderr, _("Out of memory\n"));
+ goto out;
+ }
+
+ status = kerberos_set_password(ads->auth.kdc_server,
+ auth_principal,
+ auth_password,
+ user,
+ new_password,
+ ads->auth.time_offset);
+ memset(new_password, '\0', strlen(new_password));
+ if (!ADS_ERR_OK(status)) {
+ d_fprintf(stderr, _("Password change failed: %s\n"),
+ ads_errstr(status));
+ goto out;
}
d_printf(_("Password change for %s completed.\n"), user);
- ads_destroy(&ads);
- return 0;
+ ret = 0;
+out:
+ TALLOC_FREE(tmp_ctx);
+ return ret;
}
int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
{
- ADS_STRUCT *ads;
- char *host_principal;
- fstring my_name;
- ADS_STATUS ret;
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
+ ADS_STRUCT *ads = NULL;
+ char *host_principal = NULL;
+ char *my_name = NULL;
+ ADS_STATUS status;
+ int ret = -1;
if (c->display_usage) {
d_printf( "%s\n"
" %s\n",
_("Usage:"),
_("Change the machine account's trust password"));
- return 0;
+ TALLOC_FREE(tmp_ctx);
+ return -1;
}
if (!secrets_init()) {
DEBUG(1,("Failed to initialise secrets database\n"));
- return -1;
+ goto out;
}
+ net_warn_member_options();
+
net_use_krb_machine_account(c);
use_in_memory_ccache();
- if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
- return -1;
+ status = ads_startup(c, true, tmp_ctx, &ads);
+ if (!ADS_ERR_OK(status)) {
+ goto out;
}
- fstrcpy(my_name, lp_netbios_name());
- if (!strlower_m(my_name)) {
- ads_destroy(&ads);
- return -1;
+ my_name = talloc_asprintf_strlower_m(tmp_ctx, "%s", lp_netbios_name());
+ if (my_name == NULL) {
+ d_fprintf(stderr, _("Out of memory\n"));
+ goto out;
}
- if (asprintf(&host_principal, "%s$@%s", my_name, ads->config.realm) == -1) {
- ads_destroy(&ads);
- return -1;
+ host_principal = talloc_asprintf(tmp_ctx, "%s$@%s", my_name, ads->config.realm);
+ if (host_principal == NULL) {
+ d_fprintf(stderr, _("Out of memory\n"));
+ goto out;
}
- d_printf(_("Changing password for principal: %s\n"), host_principal);
- ret = ads_change_trust_account_password(ads, host_principal);
+ d_printf(_("Changing password for principal: %s\n"), host_principal);
- if (!ADS_ERR_OK(ret)) {
- d_fprintf(stderr, _("Password change failed: %s\n"), ads_errstr(ret));
- ads_destroy(&ads);
- SAFE_FREE(host_principal);
- return -1;
+ status = ads_change_trust_account_password(ads, host_principal);
+ if (!ADS_ERR_OK(status)) {
+ d_fprintf(stderr, _("Password change failed: %s\n"), ads_errstr(status));
+ goto out;
}
d_printf(_("Password change for principal %s succeeded.\n"), host_principal);
}
}
- ads_destroy(&ads);
- SAFE_FREE(host_principal);
+ ret = 0;
+out:
+ TALLOC_FREE(tmp_ctx);
- return 0;
+ return ret;
}
/*
*/
static int net_ads_search(struct net_context *c, int argc, const char **argv)
{
- ADS_STRUCT *ads;
- ADS_STATUS rc;
- const char *ldap_exp;
- const char **attrs;
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
+ ADS_STRUCT *ads = NULL;
+ ADS_STATUS status;
+ const char *ldap_exp = NULL;
+ const char **attrs = NULL;
LDAPMessage *res = NULL;
+ int ret = -1;
if (argc < 1 || c->display_usage) {
+ TALLOC_FREE(tmp_ctx);
return net_ads_search_usage(c, argc, argv);
}
- if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
- return -1;
+ status = ads_startup(c, false, tmp_ctx, &ads);
+ if (!ADS_ERR_OK(status)) {
+ goto out;
}
ldap_exp = argv[0];
attrs = (argv + 1);
- rc = ads_do_search_retry(ads, ads->config.bind_path,
- LDAP_SCOPE_SUBTREE,
- ldap_exp, attrs, &res);
- if (!ADS_ERR_OK(rc)) {
- d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(rc));
- ads_destroy(&ads);
- return -1;
+ status = ads_do_search_retry(ads,
+ ads->config.bind_path,
+ LDAP_SCOPE_SUBTREE,
+ ldap_exp,
+ attrs,
+ &res);
+ if (!ADS_ERR_OK(status)) {
+ d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(status));
+ goto out;
}
d_printf(_("Got %d replies\n\n"), ads_count_replies(ads, res));
/* dump the results */
ads_dump(ads, res);
+ ret = 0;
+out:
ads_msgfree(ads, res);
- ads_destroy(&ads);
-
- return 0;
+ TALLOC_FREE(tmp_ctx);
+ return ret;
}
*/
static int net_ads_dn(struct net_context *c, int argc, const char **argv)
{
- ADS_STRUCT *ads;
- ADS_STATUS rc;
- const char *dn;
- const char **attrs;
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
+ ADS_STRUCT *ads = NULL;
+ ADS_STATUS status;
+ const char *dn = NULL;
+ const char **attrs = NULL;
LDAPMessage *res = NULL;
+ int ret = -1;
if (argc < 1 || c->display_usage) {
+ TALLOC_FREE(tmp_ctx);
return net_ads_dn_usage(c, argc, argv);
}
- if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
- return -1;
+ status = ads_startup(c, false, tmp_ctx, &ads);
+ if (!ADS_ERR_OK(status)) {
+ goto out;
}
dn = argv[0];
attrs = (argv + 1);
- rc = ads_do_search_all(ads, dn,
- LDAP_SCOPE_BASE,
- "(objectclass=*)", attrs, &res);
- if (!ADS_ERR_OK(rc)) {
- d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(rc));
- ads_destroy(&ads);
- return -1;
+ status = ads_do_search_all(ads,
+ dn,
+ LDAP_SCOPE_BASE,
+ "(objectclass=*)",
+ attrs,
+ &res);
+ if (!ADS_ERR_OK(status)) {
+ d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(status));
+ goto out;
}
d_printf("Got %d replies\n\n", ads_count_replies(ads, res));
/* dump the results */
ads_dump(ads, res);
+ ret = 0;
+out:
ads_msgfree(ads, res);
- ads_destroy(&ads);
-
- return 0;
+ TALLOC_FREE(tmp_ctx);
+ return ret;
}
/*
*/
static int net_ads_sid(struct net_context *c, int argc, const char **argv)
{
- ADS_STRUCT *ads;
- ADS_STATUS rc;
- const char *sid_string;
- const char **attrs;
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
+ ADS_STRUCT *ads = NULL;
+ ADS_STATUS status;
+ const char *sid_string = NULL;
+ const char **attrs = NULL;
LDAPMessage *res = NULL;
- struct dom_sid sid;
+ struct dom_sid sid = { 0 };
+ int ret = -1;
if (argc < 1 || c->display_usage) {
+ TALLOC_FREE(tmp_ctx);
return net_ads_sid_usage(c, argc, argv);
}
- if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
- return -1;
+ status = ads_startup(c, false, tmp_ctx, &ads);
+ if (!ADS_ERR_OK(status)) {
+ goto out;
}
sid_string = argv[0];
if (!string_to_sid(&sid, sid_string)) {
d_fprintf(stderr, _("could not convert sid\n"));
- ads_destroy(&ads);
- return -1;
+ goto out;
}
- rc = ads_search_retry_sid(ads, &res, &sid, attrs);
- if (!ADS_ERR_OK(rc)) {
- d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(rc));
- ads_destroy(&ads);
- return -1;
+ status = ads_search_retry_sid(ads, &res, &sid, attrs);
+ if (!ADS_ERR_OK(status)) {
+ d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(status));
+ goto out;
}
d_printf(_("Got %d replies\n\n"), ads_count_replies(ads, res));
/* dump the results */
ads_dump(ads, res);
+ ret = 0;
+out:
ads_msgfree(ads, res);
- ads_destroy(&ads);
-
- return 0;
+ TALLOC_FREE(tmp_ctx);
+ return ret;
}
-static int net_ads_keytab_flush(struct net_context *c, int argc, const char **argv)
+static int net_ads_keytab_flush(struct net_context *c,
+ int argc,
+ const char **argv)
{
- int ret;
- ADS_STRUCT *ads;
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
+ ADS_STRUCT *ads = NULL;
+ ADS_STATUS status;
+ int ret = -1;
if (c->display_usage) {
d_printf( "%s\n"
" %s\n",
_("Usage:"),
_("Delete the whole keytab"));
- return 0;
+ TALLOC_FREE(tmp_ctx);
+ return -1;
}
- if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
- return -1;
+ if (!c->opt_user_specified && c->opt_password == NULL) {
+ net_use_krb_machine_account(c);
+ }
+
+ status = ads_startup(c, true, tmp_ctx, &ads);
+ if (!ADS_ERR_OK(status)) {
+ goto out;
}
+
ret = ads_keytab_flush(ads);
- ads_destroy(&ads);
+out:
+ TALLOC_FREE(tmp_ctx);
return ret;
}
-static int net_ads_keytab_add(struct net_context *c, int argc, const char **argv)
+static int net_ads_keytab_add(struct net_context *c,
+ int argc,
+ const char **argv,
+ bool update_ads)
{
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
+ ADS_STRUCT *ads = NULL;
+ ADS_STATUS status;
int i;
- int ret = 0;
- ADS_STRUCT *ads;
+ int ret = -1;
if (c->display_usage) {
d_printf("%s\n%s",
" Add principals to local keytab\n"
" principal\tKerberos principal to add to "
"keytab\n"));
- return 0;
+ TALLOC_FREE(tmp_ctx);
+ return -1;
}
+ net_warn_member_options();
+
d_printf(_("Processing principals to add...\n"));
- if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
+
+ if (!c->opt_user_specified && c->opt_password == NULL) {
+ net_use_krb_machine_account(c);
+ }
+
+ status = ads_startup(c, true, tmp_ctx, &ads);
+ if (!ADS_ERR_OK(status)) {
+ goto out;
+ }
+
+ for (ret = 0, i = 0; i < argc; i++) {
+ ret |= ads_keytab_add_entry(ads, argv[i], update_ads);
+ }
+out:
+ TALLOC_FREE(tmp_ctx);
+ return ret;
+}
+
+static int net_ads_keytab_add_default(struct net_context *c,
+ int argc,
+ const char **argv)
+{
+ return net_ads_keytab_add(c, argc, argv, false);
+}
+
+static int net_ads_keytab_add_update_ads(struct net_context *c,
+ int argc,
+ const char **argv)
+{
+ return net_ads_keytab_add(c, argc, argv, true);
+}
+
+static int net_ads_keytab_delete(struct net_context *c,
+ int argc,
+ const char **argv)
+{
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
+ ADS_STRUCT *ads = NULL;
+ ADS_STATUS status;
+ int i;
+ int ret = -1;
+
+ if (c->display_usage) {
+ d_printf("%s\n%s",
+ _("Usage:"),
+ _("net ads keytab delete <principal> [principal ...]\n"
+ " Remove entries for service principal, "
+ " from the keytab file only."
+ " Remove principals from local keytab\n"
+ " principal\tKerberos principal to remove from "
+ "keytab\n"));
+ TALLOC_FREE(tmp_ctx);
return -1;
}
- for (i = 0; i < argc; i++) {
- ret |= ads_keytab_add_entry(ads, argv[i]);
+
+ d_printf(_("Processing principals to delete...\n"));
+
+ if (!c->opt_user_specified && c->opt_password == NULL) {
+ net_use_krb_machine_account(c);
+ }
+
+ status = ads_startup(c, true, tmp_ctx, &ads);
+ if (!ADS_ERR_OK(status)) {
+ goto out;
+ }
+
+ for (ret = 0, i = 0; i < argc; i++) {
+ ret |= ads_keytab_delete_entry(ads, argv[i]);
}
- ads_destroy(&ads);
+out:
+ TALLOC_FREE(tmp_ctx);
return ret;
}
static int net_ads_keytab_create(struct net_context *c, int argc, const char **argv)
{
- ADS_STRUCT *ads;
- int ret;
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
+ ADS_STRUCT *ads = NULL;
+ ADS_STATUS status;
+ int ret = -1;
if (c->display_usage) {
d_printf( "%s\n"
" %s\n",
_("Usage:"),
_("Create new default keytab"));
- return 0;
+ TALLOC_FREE(tmp_ctx);
+ return -1;
}
- if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
- return -1;
+ net_warn_member_options();
+
+ if (!c->opt_user_specified && c->opt_password == NULL) {
+ net_use_krb_machine_account(c);
+ }
+
+ status = ads_startup(c, true, tmp_ctx, &ads);
+ if (!ADS_ERR_OK(status)) {
+ goto out;
}
+
ret = ads_keytab_create_default(ads);
- ads_destroy(&ads);
+out:
+ TALLOC_FREE(tmp_ctx);
return ret;
}
_("net ads keytab list [keytab]\n"
" List a local keytab\n"
" keytab\tKeytab to list\n"));
- return 0;
+ return -1;
}
if (argc >= 1) {
struct functable func[] = {
{
"add",
- net_ads_keytab_add,
+ net_ads_keytab_add_default,
NET_TRANSPORT_ADS,
N_("Add a service principal"),
N_("net ads keytab add\n"
- " Add a service principal")
+ " Add a service principal, updates keytab file only.")
+ },
+ {
+ "delete",
+ net_ads_keytab_delete,
+ NET_TRANSPORT_ADS,
+ N_("Delete a service principal"),
+ N_("net ads keytab delete\n"
+ " Remove entries for service principal, from the keytab file only.")
+ },
+ {
+ "add_update_ads",
+ net_ads_keytab_add_update_ads,
+ NET_TRANSPORT_ADS,
+ N_("Add a service principal"),
+ N_("net ads keytab add_update_ads\n"
+ " Add a service principal, depending on the param passed may update ADS computer object in addition to the keytab file.")
},
{
"create",
NET_TRANSPORT_ADS,
N_("Create a fresh keytab"),
N_("net ads keytab create\n"
- " Create a fresh keytab")
+ " Create a fresh keytab or update existing one.")
},
{
"flush",
" %s\n",
_("Usage:"),
_("Renew TGT from existing credential cache"));
- return 0;
+ return -1;
}
ret = smb_krb5_renew_ticket(NULL, NULL, NULL, NULL);
2592000, /* one month */
impersonate_princ_s,
local_service,
+ NULL,
+ NULL,
pac_data_ctr);
if (!NT_STATUS_IS_OK(status)) {
d_printf(_("failed to query kerberos PAC: %s\n"),
static int net_ads_kerberos_pac_dump(struct net_context *c, int argc, const char **argv)
{
struct PAC_DATA_CTR *pac_data_ctr = NULL;
- int i;
+ int i, num_buffers;
int ret = -1;
enum PAC_TYPE type = 0;
return 0;
}
- for (i=0; i < pac_data_ctr->pac_data->num_buffers; i++) {
+ num_buffers = pac_data_ctr->pac_data->num_buffers;
+
+ for (i=0; i<num_buffers; i++) {
char *s = NULL;
static int net_ads_kerberos_kinit(struct net_context *c, int argc, const char **argv)
{
- TALLOC_CTX *mem_ctx = NULL;
int ret = -1;
NTSTATUS status;
" %s\n",
_("Usage:"),
_("Get Ticket Granting Ticket (TGT) for the user"));
- return 0;
- }
-
- mem_ctx = talloc_init("net_ads_kerberos_kinit");
- if (!mem_ctx) {
- goto out;
+ return -1;
}
c->opt_password = net_prompt_pass(c, c->opt_user_name);
true,
true,
2592000, /* one month */
+ NULL,
+ NULL,
+ NULL,
&status);
if (ret) {
d_printf(_("failed to kinit password: %s\n"),
nt_errstr(status));
}
- out:
return ret;
}
return net_run_function(c, argc, argv, "net ads kerberos", func);
}
-static int net_ads_setspn_list(struct net_context *c, int argc, const char **argv)
+static int net_ads_setspn_list(struct net_context *c,
+ int argc,
+ const char **argv)
{
- int ret = 0;
- bool ok = false;
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
ADS_STRUCT *ads = NULL;
+ ADS_STATUS status;
+ bool ok = false;
+ int ret = -1;
+
if (c->display_usage) {
d_printf("%s\n%s",
_("Usage:"),
_("net ads setspn list <machinename>\n"));
- ret = 0;
- goto done;
+ TALLOC_FREE(tmp_ctx);
+ return -1;
}
- if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
- ret = -1;
- goto done;
+
+ status = ads_startup(c, true, tmp_ctx, &ads);
+ if (!ADS_ERR_OK(status)) {
+ goto out;
}
+
if (argc) {
ok = ads_setspn_list(ads, argv[0]);
} else {
ok = ads_setspn_list(ads, lp_netbios_name());
}
- if (!ok) {
- ret = -1;
- }
-done:
- if (ads) {
- ads_destroy(&ads);
- }
+
+ ret = ok ? 0 : -1;
+out:
+ TALLOC_FREE(tmp_ctx);
return ret;
}
static int net_ads_setspn_add(struct net_context *c, int argc, const char **argv)
{
- int ret = 0;
- bool ok = false;
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
ADS_STRUCT *ads = NULL;
+ ADS_STATUS status;
+ bool ok = false;
+ int ret = -1;
+
if (c->display_usage || argc < 1) {
d_printf("%s\n%s",
_("Usage:"),
_("net ads setspn add <machinename> SPN\n"));
- ret = 0;
- goto done;
+ TALLOC_FREE(tmp_ctx);
+ return -1;
}
- if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
- ret = -1;
- goto done;
+
+ status = ads_startup(c, true, tmp_ctx, &ads);
+ if (!ADS_ERR_OK(status)) {
+ goto out;
}
+
if (argc > 1) {
ok = ads_setspn_add(ads, argv[0], argv[1]);
} else {
ok = ads_setspn_add(ads, lp_netbios_name(), argv[0]);
}
- if (!ok) {
- ret = -1;
- }
-done:
- if (ads) {
- ads_destroy(&ads);
- }
+
+ ret = ok ? 0 : -1;
+out:
+ TALLOC_FREE(tmp_ctx);
return ret;
}
static int net_ads_setspn_delete(struct net_context *c, int argc, const char **argv)
{
- int ret = 0;
- bool ok = false;
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
ADS_STRUCT *ads = NULL;
+ ADS_STATUS status;
+ bool ok = false;
+ int ret = -1;
+
if (c->display_usage || argc < 1) {
d_printf("%s\n%s",
_("Usage:"),
_("net ads setspn delete <machinename> SPN\n"));
- ret = 0;
- goto done;
+ TALLOC_FREE(tmp_ctx);
+ return -1;
}
- if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
- ret = -1;
- goto done;
+
+ status = ads_startup(c, true, tmp_ctx, &ads);
+ if (!ADS_ERR_OK(status)) {
+ goto out;
}
+
if (argc > 1) {
ok = ads_setspn_delete(ads, argv[0], argv[1]);
} else {
ok = ads_setspn_delete(ads, lp_netbios_name(), argv[0]);
}
- if (!ok) {
- ret = -1;
- }
-done:
- if (ads) {
- ads_destroy(&ads);
- }
+
+ ret = ok ? 0 : -1;
+out:
+ TALLOC_FREE(tmp_ctx);
return ret;
}
printf("[%s] 0x%08x AES256-CTS-HMAC-SHA1-96\n",
enctypes & ENC_HMAC_SHA1_96_AES256 ? "X" : " ",
ENC_HMAC_SHA1_96_AES256);
+ printf("[%s] 0x%08x AES256-CTS-HMAC-SHA1-96-SK\n",
+ enctypes & ENC_HMAC_SHA1_96_AES256_SK ? "X" : " ",
+ ENC_HMAC_SHA1_96_AES256_SK);
+ printf("[%s] 0x%08x RESOURCE-SID-COMPRESSION-DISABLED\n",
+ enctypes & KERB_ENCTYPE_RESOURCE_SID_COMPRESSION_DISABLED ? "X" : " ",
+ KERB_ENCTYPE_RESOURCE_SID_COMPRESSION_DISABLED);
}
static int net_ads_enctypes_list(struct net_context *c, int argc, const char **argv)
{
- int ret = -1;
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
ADS_STATUS status;
ADS_STRUCT *ads = NULL;
LDAPMessage *res = NULL;
const char *str = NULL;
+ int ret = -1;
if (c->display_usage || (argc < 1)) {
d_printf( "%s\n"
" %s\n",
_("Usage:"),
_("List supported enctypes"));
- return 0;
+ TALLOC_FREE(tmp_ctx);
+ return -1;
}
- status = ads_startup(c, false, &ads);
+ status = ads_startup(c, false, tmp_ctx, &ads);
if (!ADS_ERR_OK(status)) {
- printf("startup failed\n");
- return ret;
+ goto out;
}
ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, &str);
if (ret) {
- goto done;
+ goto out;
}
net_ads_enctype_dump_enctypes(argv[0], str);
ret = 0;
- done:
+ out:
ads_msgfree(ads, res);
- ads_destroy(&ads);
-
+ TALLOC_FREE(tmp_ctx);
return ret;
}
static int net_ads_enctypes_set(struct net_context *c, int argc, const char **argv)
{
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
int ret = -1;
ADS_STATUS status;
- ADS_STRUCT *ads;
+ ADS_STRUCT *ads = NULL;
LDAPMessage *res = NULL;
- const char *etype_list_str;
- const char *dn;
- ADS_MODLIST mods;
+ const char *etype_list_str = NULL;
+ const char *dn = NULL;
+ ADS_MODLIST mods = NULL;
uint32_t etype_list;
- const char *str;
+ const char *str = NULL;
if (c->display_usage || argc < 1) {
d_printf( "%s\n"
" %s\n",
_("Usage:"),
_("Set supported enctypes"));
- return 0;
+ TALLOC_FREE(tmp_ctx);
+ return -1;
}
- status = ads_startup(c, false, &ads);
+ status = ads_startup(c, false, tmp_ctx, &ads);
if (!ADS_ERR_OK(status)) {
- printf("startup failed\n");
- return ret;
+ goto done;
}
ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, NULL);
goto done;
}
- dn = ads_get_dn(ads, c, res);
+ dn = ads_get_dn(ads, tmp_ctx, res);
if (dn == NULL) {
goto done;
}
- etype_list = ENC_CRC32 | ENC_RSA_MD5 | ENC_RC4_HMAC_MD5;
-#ifdef HAVE_ENCTYPE_AES128_CTS_HMAC_SHA1_96
+ etype_list = 0;
+ etype_list |= ENC_RC4_HMAC_MD5;
etype_list |= ENC_HMAC_SHA1_96_AES128;
-#endif
-#ifdef HAVE_ENCTYPE_AES256_CTS_HMAC_SHA1_96
etype_list |= ENC_HMAC_SHA1_96_AES256;
-#endif
if (argv[1] != NULL) {
sscanf(argv[1], "%i", &etype_list);
}
- etype_list_str = talloc_asprintf(c, "%d", etype_list);
+ etype_list_str = talloc_asprintf(tmp_ctx, "%d", etype_list);
if (!etype_list_str) {
goto done;
}
- mods = ads_init_mods(c);
+ mods = ads_init_mods(tmp_ctx);
if (!mods) {
goto done;
}
- status = ads_mod_str(c, &mods, "msDS-SupportedEncryptionTypes",
+ status = ads_mod_str(tmp_ctx, &mods, "msDS-SupportedEncryptionTypes",
etype_list_str);
if (!ADS_ERR_OK(status)) {
goto done;
}
ads_msgfree(ads, res);
+ res = NULL;
ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, &str);
if (ret) {
ret = 0;
done:
ads_msgfree(ads, res);
- ads_destroy(&ads);
-
+ TALLOC_FREE(tmp_ctx);
return ret;
}
static int net_ads_enctypes_delete(struct net_context *c, int argc, const char **argv)
{
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
int ret = -1;
ADS_STATUS status;
- ADS_STRUCT *ads;
+ ADS_STRUCT *ads = NULL;
LDAPMessage *res = NULL;
- const char *dn;
- ADS_MODLIST mods;
+ const char *dn = NULL;
+ ADS_MODLIST mods = NULL;
if (c->display_usage || argc < 1) {
d_printf( "%s\n"
" %s\n",
_("Usage:"),
_("Delete supported enctypes"));
- return 0;
+ TALLOC_FREE(tmp_ctx);
+ return -1;
}
- status = ads_startup(c, false, &ads);
+ status = ads_startup(c, false, tmp_ctx, &ads);
if (!ADS_ERR_OK(status)) {
- printf("startup failed\n");
- return ret;
+ goto done;
}
ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, NULL);
goto done;
}
- dn = ads_get_dn(ads, c, res);
+ dn = ads_get_dn(ads, tmp_ctx, res);
if (dn == NULL) {
goto done;
}
- mods = ads_init_mods(c);
+ mods = ads_init_mods(tmp_ctx);
if (!mods) {
goto done;
}
- status = ads_mod_str(c, &mods, "msDS-SupportedEncryptionTypes", NULL);
+ status = ads_mod_str(tmp_ctx, &mods, "msDS-SupportedEncryptionTypes", NULL);
if (!ADS_ERR_OK(status)) {
goto done;
}
done:
ads_msgfree(ads, res);
- ads_destroy(&ads);
+ TALLOC_FREE(tmp_ctx);
return ret;
}