#include "includes.h"
#include "utils/net.h"
+#include "rpc_client/cli_pipe.h"
#include "librpc/gen_ndr/ndr_krb5pac.h"
-#include "../librpc/gen_ndr/cli_spoolss.h"
+#include "../librpc/gen_ndr/ndr_spoolss.h"
#include "nsswitch/libwbclient/wbclient.h"
+#include "ads.h"
+#include "libads/cldap.h"
+#include "libads/dns.h"
+#include "../libds/common/flags.h"
+#include "librpc/gen_ndr/libnet_join.h"
+#include "libnet/libnet_join.h"
+#include "smb_krb5.h"
+#include "secrets.h"
+#include "krb5_env.h"
+#include "../libcli/security/security.h"
#ifdef HAVE_ADS
printf(_("Domain:\t\t\t%s\n"), reply.dns_domain);
printf(_("Domain Controller:\t%s\n"), reply.pdc_dns_name);
- printf(_("Pre-Win2k Domain:\t%s\n"), reply.domain);
+ printf(_("Pre-Win2k Domain:\t%s\n"), reply.domain_name);
printf(_("Pre-Win2k Hostname:\t%s\n"), reply.pdc_name);
if (*reply.user_name) printf(_("User name:\t%s\n"), reply.user_name);
int ret;
if (c->display_usage) {
- d_printf(_("Usage:\n"),
- "net ads lookup\n"
- " ",_("Find the ADS DC using CLDAP lookup.\n"));
+ d_printf("%s\n"
+ "net ads lookup\n"
+ " %s",
+ _("Usage:"),
+ _("Find the ADS DC using CLDAP lookup.\n"));
return 0;
}
char addr[INET6_ADDRSTRLEN];
if (c->display_usage) {
- d_printf(_("Usage:\n"),
- "net ads info\n",
- " ",
- _("Display information about an Active Directory "
+ d_printf("%s\n"
+ "net ads info\n"
+ " %s",
+ _("Usage:"),
+ _("Display information about an Active Directory "
"server.\n"));
return 0;
}
struct NETLOGON_SAM_LOGON_RESPONSE_EX reply;
if (c->display_usage) {
- d_printf(_("Usage:\n"),
+ d_printf ("%s\n"
"net ads workgroup\n"
- " ",_("Print the workgroup name\n"));
+ " %s\n",
+ _("Usage:"),
+ _("Print the workgroup name"));
return 0;
}
return -1;
}
- d_printf(_("Workgroup: %s\n"), reply.domain);
+ d_printf(_("Workgroup: %s\n"), reply.domain_name);
ads_destroy(&ads);
if (c->opt_container) {
ou_str = SMB_STRDUP(c->opt_container);
} else {
- ou_str = ads_default_ou_string(ads, WELL_KNOWN_GUID_USERS);
+ ou_str = ads_default_ou_string(ads, DS_GUID_USERS_CONTAINER);
}
status = ads_add_user_acct(ads, argv[0], ou_str, c->opt_comment);
char **grouplist;
char *primary_group;
char *escaped_user;
- DOM_SID primary_group_sid;
+ struct dom_sid primary_group_sid;
uint32_t group_rid;
- enum SID_NAME_USE type;
+ enum wbcSidType type;
if (argc < 1 || c->display_usage) {
return net_ads_user_usage(c, argc, argv);
wbc_status = wbcLookupSid((struct wbcDomainSid *)&primary_group_sid,
NULL, /* don't look up domain */
&primary_group,
- (enum wbcSidType *) &type);
+ &type);
if (!WBC_ERROR_IS_OK(wbc_status)) {
d_fprintf(stderr, "wbcLookupSid: %s\n",
wbcErrorString(wbc_status));
if (argc == 0) {
if (c->display_usage) {
- d_printf(_("Usage:\n"),
+ d_printf( "%s\n"
"net ads user\n"
- " ",_("List AD users\n"));
+ " %s\n",
+ _("Usage:"),
+ _("List AD users"));
net_display_usage_from_functable(func);
return 0;
}
if (c->opt_container) {
ou_str = SMB_STRDUP(c->opt_container);
} else {
- ou_str = ads_default_ou_string(ads, WELL_KNOWN_GUID_USERS);
+ ou_str = ads_default_ou_string(ads, DS_GUID_USERS_CONTAINER);
}
status = ads_add_group_acct(ads, argv[0], ou_str, c->opt_comment);
if (argc == 0) {
if (c->display_usage) {
- d_printf(_("Usage:\n"),
+ d_printf( "%s\n"
"net ads group\n"
- " ", _("List AD groups\n"));
+ " %s\n",
+ _("Usage:"),
+ _("List AD groups"));
net_display_usage_from_functable(func);
return 0;
}
LDAPMessage *res;
if (c->display_usage) {
- d_printf(_("Usage:\n"),
+ d_printf( "%s\n"
"net ads status\n"
- " ",_("Display machine account details\n"));
+ " %s\n",
+ _("Usage:"),
+ _("Display machine account details"));
return 0;
}
WERROR werr;
if (c->display_usage) {
- d_printf(_("Usage:\n"),
+ d_printf( "%s\n"
"net ads leave\n"
- " ", _("Leave an AD domain\n"));
+ " %s\n",
+ _("Usage:"),
+ _("Leave an AD domain"));
return 0;
}
use_in_memory_ccache();
}
+ if (!c->msg_ctx) {
+ d_fprintf(stderr, _("Could not initialise message context. "
+ "Try running as root\n"));
+ return -1;
+ }
+
werr = libnet_init_UnjoinCtx(ctx, &r);
if (!W_ERROR_IS_OK(werr)) {
d_fprintf(stderr, _("Could not initialise unjoin context.\n"));
r->in.unjoin_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE;
r->in.delete_machine_account = true;
+ r->in.msg_ctx = c->msg_ctx;
werr = libnet_Unjoin(ctx, r);
if (!W_ERROR_IS_OK(werr)) {
use_in_memory_ccache();
if (c->display_usage) {
- d_printf(_("Usage:\n"),
+ d_printf( "%s\n"
"net ads testjoin\n"
- " ", _("Test if the existing join is ok\n"));
+ " %s\n",
+ _("Usage:"),
+ _("Test if the existing join is ok"));
return 0;
}
int num_addrs)
{
struct dns_rr_ns *nameservers = NULL;
- int ns_count = 0;
+ int ns_count = 0, i;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
DNS_ERROR dns_err;
fstring dns_server;
}
- /* Now perform the dns update - we'll try non-secure and if we fail,
- we'll follow it up with a secure update */
+ for (i=0; i < ns_count; i++) {
+
+ /* 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[0].hostname );
+ fstrcpy( dns_server, nameservers[i].hostname );
+
+ dns_err = DoDNSUpdate(dns_server, dnsdomain, machine_name, addrs, num_addrs);
+ if (ERR_DNS_IS_OK(dns_err)) {
+ status = NT_STATUS_OK;
+ goto done;
+ }
- dns_err = DoDNSUpdate(dns_server, dnsdomain, machine_name, addrs, num_addrs);
- if (!ERR_DNS_IS_OK(dns_err)) {
+ 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:
return status;
}
-static NTSTATUS net_update_dns(TALLOC_CTX *mem_ctx, ADS_STRUCT *ads)
+static NTSTATUS net_update_dns_ext(TALLOC_CTX *mem_ctx, ADS_STRUCT *ads,
+ const char *hostname,
+ struct sockaddr_storage *iplist,
+ int num_addrs)
{
- int num_addrs;
- struct sockaddr_storage *iplist = NULL;
+ struct sockaddr_storage *iplist_alloc = NULL;
fstring machine_name;
NTSTATUS status;
- name_to_fqdn( machine_name, global_myname() );
+ if (hostname) {
+ fstrcpy(machine_name, hostname);
+ } else {
+ name_to_fqdn( machine_name, global_myname() );
+ }
strlower_m( machine_name );
- /* Get our ip address (not the 127.0.0.x address but a real ip
- * address) */
-
- num_addrs = get_my_ip_address( &iplist );
- if ( num_addrs <= 0 ) {
- DEBUG(4,("net_update_dns: Failed to find my non-loopback IP "
- "addresses!\n"));
- return NT_STATUS_INVALID_PARAMETER;
+ if (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;
}
status = net_update_dns_internal(mem_ctx, ads, machine_name,
iplist, num_addrs);
- SAFE_FREE( iplist );
+
+ SAFE_FREE(iplist_alloc);
+ return status;
+}
+
+static NTSTATUS net_update_dns(TALLOC_CTX *mem_ctx, ADS_STRUCT *ads, const char *hostname)
+{
+ NTSTATUS status;
+
+ status = net_update_dns_ext(mem_ctx, ads, hostname, NULL, 0);
return status;
}
#endif
goto fail;
}
+ if (!c->msg_ctx) {
+ d_fprintf(stderr, _("Could not initialise message context. "
+ "Try running as root\n"));
+ werr = WERR_ACCESS_DENIED;
+ goto fail;
+ }
+
/* Do the domain join here */
r->in.domain_name = domain;
r->in.join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE |
WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED;
+ r->in.msg_ctx = c->msg_ctx;
werr = libnet_Join(ctx, r);
if (!W_ERROR_IS_OK(werr)) {
}
#if defined(WITH_DNS_UPDATES)
+ /*
+ * 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"));
+ goto done;
+ }
+
if (r->out.domain_is_ad) {
/* We enter this block with user creds */
ADS_STRUCT *ads_dns = NULL;
ads_kinit_password( ads_dns );
}
- if ( !ads_dns || !NT_STATUS_IS_OK(net_update_dns( ctx, ads_dns )) ) {
+ if ( !ads_dns || !NT_STATUS_IS_OK(net_update_dns( ctx, ads_dns, NULL)) ) {
d_fprintf( stderr, _("DNS update failed!\n") );
}
/* exit from this block using machine creds */
ads_destroy(&ads_dns);
}
+
+done:
#endif
+
TALLOC_FREE(r);
TALLOC_FREE( ctx );
#if defined(WITH_DNS_UPDATES)
ADS_STRUCT *ads;
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;
#ifdef DEVELOPER
talloc_enable_leak_report();
#endif
- if (argc > 0 || c->display_usage) {
- d_printf(_("Usage:\n"),
- "net ads dns register\n"
- " ", _("Register hostname with DNS\n"));
+ if (argc <= 1 && lp_clustering() && lp_cluster_addresses() == NULL) {
+ d_fprintf(stderr, _("Refusing DNS updates with automatic "
+ "detection of addresses in a clustered "
+ "setup.\n"));
+ c->display_usage = true;
+ }
+
+ if (c->display_usage) {
+ d_printf( "%s\n"
+ "net ads dns register [hostname [IP [IP...]]]\n"
+ " %s\n",
+ _("Usage:"),
+ _("Register hostname with DNS\n"));
return -1;
}
return -1;
}
+ if (argc >= 1) {
+ hostname = argv[0];
+ }
+
+ if (argc > 1) {
+ num_addrs = argc - 1;
+ addrs_list = &argv[1];
+ } else if (lp_clustering()) {
+ addrs_list = lp_cluster_addresses();
+ num_addrs = str_list_length(addrs_list);
+ }
+
+ if (num_addrs > 0) {
+ addrs = talloc_zero_array(ctx, struct sockaddr_storage, num_addrs);
+ if (addrs == NULL) {
+ d_fprintf(stderr, _("Error allocating memory!\n"));
+ talloc_free(ctx);
+ return -1;
+ }
+ }
+
+ for (count = 0; count < num_addrs; count++) {
+ if (!interpret_string_addr(&addrs[count], addrs_list[count], 0)) {
+ d_fprintf(stderr, "%s '%s'.\n",
+ _("Cannot interpret address"),
+ addrs_list[count]);
+ talloc_free(ctx);
+ return -1;
+ }
+ }
+
status = ads_startup(c, true, &ads);
if ( !ADS_ERR_OK(status) ) {
DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
return -1;
}
- if ( !NT_STATUS_IS_OK(net_update_dns(ctx, ads)) ) {
+ ntstatus = net_update_dns_ext(ctx, ads, hostname, addrs, num_addrs);
+ if (!NT_STATUS_IS_OK(ntstatus)) {
d_fprintf( stderr, _("DNS update failed!\n") );
ads_destroy( &ads );
TALLOC_FREE( ctx );
#endif
if (argc != 2 || c->display_usage) {
- d_printf(_("Usage:\n"),
+ 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"
err = do_gethostbyname(argv[0], argv[1]);
- d_printf(_("do_gethostbyname returned %d\n"), ERROR_DNS_V(err));
+ d_printf(_("do_gethostbyname returned %s (%d)\n"),
+ dns_errstr(err), ERROR_DNS_V(err));
#endif
return 0;
}
LDAPMessage *res = NULL;
if (c->display_usage) {
- d_printf(_("Usage:\n"),
+ d_printf( "%s\n"
"net ads printer search\n"
- " ", _("List printers in the AD\n"));
+ " %s\n",
+ _("Usage:"),
+ _("List printers in the AD"));
return 0;
}
LDAPMessage *res = NULL;
if (c->display_usage) {
- d_printf(_("Usage:\n"),
- _("net ads printer info [printername [servername]]\n"
+ d_printf("%s\n%s",
+ _("Usage:"),
+ _("net ads printer info [printername [servername]]\n"
" Display printer info from AD\n"
" printername\tPrinter name or wildcard\n"
" servername\tName of the print server\n"));
LDAPMessage *res = NULL;
if (argc < 1 || c->display_usage) {
- d_printf(_("Usage:\n"),
- _("net ads printer publish <printername> [servername]\n"
+ d_printf("%s\n%s",
+ _("Usage:"),
+ _("net ads printer publish <printername> [servername]\n"
" Publish printer in AD\n"
" printername\tName of the printer\n"
" servername\tName of the print server\n"));
c->opt_user_name, c->opt_workgroup,
c->opt_password ? c->opt_password : "",
CLI_FULL_CONNECTION_USE_KERBEROS,
- Undefined, NULL);
+ Undefined);
if (NT_STATUS_IS_ERR(nt_status)) {
d_fprintf(stderr, _("Unable to open a connnection to %s to "
LDAPMessage *res = NULL;
if (argc < 1 || c->display_usage) {
- d_printf(_("Usage:\n"),
- _("net ads printer remove <printername> [servername]\n"
+ d_printf("%s\n%s",
+ _("Usage:"),
+ _("net ads printer remove <printername> [servername]\n"
" Remove a printer from the AD\n"
" printername\tName of the printer\n"
" servername\tName of the print server\n"));
ADS_STATUS ret;
if (c->display_usage) {
- d_printf(_("Usage:\n"),
- _("net ads password <username>\n"
+ d_printf("%s\n%s",
+ _("Usage:"),
+ _("net ads password <username>\n"
" Change password for user\n"
" username\tName of user to change password for\n"));
return 0;
ADS_STATUS ret;
if (c->display_usage) {
- d_printf(_("Usage:\n"),
+ d_printf( "%s\n"
"net ads changetrustpw\n"
- " ", _("Change the machine account's trust password\n"));
+ " %s\n",
+ _("Usage:"),
+ _("Change the machine account's trust password"));
return 0;
}
const char *sid_string;
const char **attrs;
LDAPMessage *res = NULL;
- DOM_SID sid;
+ struct dom_sid sid;
if (argc < 1 || c->display_usage) {
return net_ads_sid_usage(c, argc, argv);
ADS_STRUCT *ads;
if (c->display_usage) {
- d_printf(_("Usage:\n"),
+ d_printf( "%s\n"
"net ads keytab flush\n"
- " ", _("Delete the whole keytab\n"));
+ " %s\n",
+ _("Usage:"),
+ _("Delete the whole keytab"));
return 0;
}
ADS_STRUCT *ads;
if (c->display_usage) {
- d_printf(_("Usage:\n"),
- _("net ads keytab add <principal> [principal ...]\n"
+ d_printf("%s\n%s",
+ _("Usage:"),
+ _("net ads keytab add <principal> [principal ...]\n"
" Add principals to local keytab\n"
" principal\tKerberos principal to add to "
"keytab\n"));
int ret;
if (c->display_usage) {
- d_printf(_("Usage:\n"),
+ d_printf( "%s\n"
"net ads keytab create\n"
- " ", _("Create new default keytab\n"));
+ " %s\n",
+ _("Usage:"),
+ _("Create new default keytab"));
return 0;
}
const char *keytab = NULL;
if (c->display_usage) {
- d_printf(_("Usage:\n"),
- _("net ads keytab list [keytab]\n"
+ d_printf("%s\n%s",
+ _("Usage:"),
+ _("net ads keytab list [keytab]\n"
" List a local keytab\n"
" keytab\tKeytab to list\n"));
return 0;
int ret = -1;
if (c->display_usage) {
- d_printf(_("Usage:\n"),
+ d_printf( "%s\n"
"net ads kerberos renew\n"
- " ", _("Renew TGT from existing credential cache\n"));
+ " %s\n",
+ _("Usage:"),
+ _("Renew TGT from existing credential cache"));
return 0;
}
static int net_ads_kerberos_pac(struct net_context *c, int argc, const char **argv)
{
- struct PAC_DATA *pac = NULL;
struct PAC_LOGON_INFO *info = NULL;
TALLOC_CTX *mem_ctx = NULL;
NTSTATUS status;
const char *impersonate_princ_s = NULL;
if (c->display_usage) {
- d_printf(_("Usage:\n"),
+ d_printf( "%s\n"
"net ads kerberos pac\n"
- " ", _("Dump the Kerberos PAC\n"));
+ " %s\n",
+ _("Usage:"),
+ _("Dump the Kerberos PAC"));
return 0;
}
status = kerberos_return_pac(mem_ctx,
c->opt_user_name,
c->opt_password,
- 0,
+ 0,
NULL,
NULL,
NULL,
true,
2592000, /* one month */
impersonate_princ_s,
- &pac);
+ &info);
if (!NT_STATUS_IS_OK(status)) {
d_printf(_("failed to query kerberos PAC: %s\n"),
nt_errstr(status));
goto out;
}
- info = get_logon_info_from_pac(pac);
if (info) {
const char *s;
s = NDR_PRINT_STRUCT_STRING(mem_ctx, PAC_LOGON_INFO, info);
NTSTATUS status;
if (c->display_usage) {
- d_printf(_("Usage:\n"),
+ d_printf( "%s\n"
"net ads kerberos kinit\n"
- " ", _("Get Ticket Granting Ticket (TGT) for the user\n"));
+ " %s\n",
+ _("Usage:"),
+ _("Get Ticket Granting Ticket (TGT) for the user"));
return 0;
}
return net_ads_noads();
}
+int net_ads_gpo(struct net_context *c, int argc, const char **argv)
+{
+ return net_ads_noads();
+}
+
/* this one shouldn't display a message */
int net_ads_check(struct net_context *c)
{