summaryrefslogtreecommitdiff
path: root/source3/utils
diff options
context:
space:
mode:
Diffstat (limited to 'source3/utils')
-rw-r--r--source3/utils/net_ads.c179
-rw-r--r--source3/utils/net_dns.c99
2 files changed, 275 insertions, 3 deletions
diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c
index 2fbe088653..e6ad7c21b3 100644
--- a/source3/utils/net_ads.c
+++ b/source3/utils/net_ads.c
@@ -55,6 +55,9 @@ int net_ads_usage(int argc, const char **argv)
d_printf(" Issue LDAP search queries using a general filter, by DN, or by SID\n");
d_printf("keytab\n");
d_printf(" Manage a local keytab file based on the machine account in AD\n");
+ d_printf("dns\n");
+ d_printf(" Issue a dynamic DNS update request the server's hostname\n");
+ d_printf(" (using the machine credentials)\n");
return -1;
}
@@ -1136,7 +1139,89 @@ static BOOL net_derive_salting_principal( TALLOC_CTX *ctx, ADS_STRUCT *ads )
return kerberos_secrets_store_des_salt( salt );
}
-/*********************************************************
+/*******************************************************************
+ Send a DNS update request
+*******************************************************************/
+
+#if defined(WITH_DNS_UPDATES)
+static BOOL net_update_dns( TALLOC_CTX *ctx, ADS_STRUCT *ads )
+{
+ int num_addrs;
+ struct in_addr *iplist = NULL;
+ struct dns_rr_ns *nameservers = NULL;
+ int ns_count = 0;
+ int ret = 0;
+ NTSTATUS dns_status;
+ fstring machine_name;
+ fstring dns_server;
+ const char *dnsdomain;
+ ADS_STRUCT *ads_s = NULL;
+
+ name_to_fqdn( machine_name, global_myname() );
+ strlower_m( machine_name );
+
+ if ( (dnsdomain = strchr_m( machine_name, '.')) == NULL ) {
+ d_printf("No DNS domain configured for %s. Unable to perform DNS Update.\n",
+ machine_name);
+ goto done;
+ }
+ dnsdomain++;
+
+ dns_status = ads_dns_lookup_ns( ctx, dnsdomain, &nameservers, &ns_count );
+ if ( !NT_STATUS_IS_OK(dns_status) || (ns_count == 0)) {
+ DEBUG(3,("net_ads_join: Failed to find name server for the %s realm\n",
+ ads->config.realm));
+ goto done;
+ }
+
+ /* 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_ads_join: Failed to find my non-loopback IP addresses!\n"));
+ ret = -1;
+ goto done;
+ }
+
+ /* Drop the user creds */
+
+ ads_kdestroy( NULL );
+
+ ads_s = ads_init( ads->server.realm, ads->server.workgroup, ads->server.ldap_server );
+ if ( !ads_s ) {
+ DEBUG(1,("net_ads_join: ads_init() failed!\n"));
+ ret = -1;
+ goto done;
+ }
+
+ /* kinit with the machine password */
+
+ asprintf( &ads_s->auth.user_name, "%s$", global_myname() );
+ ads_s->auth.password = secrets_fetch_machine_password( lp_workgroup(), NULL, NULL );
+ ads_s->auth.realm = SMB_STRDUP( lp_realm() );
+ ads_kinit_password( ads_s );
+
+ /* 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 );
+
+ ret = DoDNSUpdate(dns_server, dnsdomain, machine_name, iplist, num_addrs );
+ if ( ret ) {
+ DEBUG(1, ("Error creating dns update!\n"));
+ }
+
+done:
+ SAFE_FREE( iplist );
+ if ( ads_s )
+ ads_destroy( &ads_s );
+
+ return (ret == 0);
+}
+#endif
+
+
+/*******************************************************************
utility function to parse an integer parameter from
"parameter = value"
**********************************************************/
@@ -1174,6 +1259,7 @@ int net_ads_join(int argc, const char **argv)
ADS_STRUCT *ads = NULL;
ADS_STATUS status;
NTSTATUS nt_status;
+ char *machine_account = NULL;
const char *short_domain_name = NULL;
char *tmp_password, *password;
struct cldap_netlogon_reply cldap_reply;
@@ -1352,8 +1438,19 @@ int net_ads_join(int argc, const char **argv)
DEBUG(1,("Error creating host keytab!\n"));
}
+#if defined(WITH_DNS_UPDATES)
+ /* We enter this block with user creds */
+
+ if ( !net_update_dns( ctx, ads ) ) {
+ d_fprintf( stderr, "DNS update failed!\n" );
+ }
+
+ /* exit from this block using machine creds */
+#endif
+
d_printf("Joined '%s' to realm '%s'\n", global_myname(), ads->config.realm);
+ SAFE_FREE(machine_account);
TALLOC_FREE( ctx );
ads_destroy(&ads);
@@ -1361,11 +1458,85 @@ int net_ads_join(int argc, const char **argv)
fail:
/* issue an overall failure message at the end. */
- d_printf("Failed to join domain: %s\n",
- get_friendly_nt_error_msg(nt_status));
+ d_printf("Failed to join domain: %s\n", get_friendly_nt_error_msg(nt_status));
+
+ SAFE_FREE(machine_account);
+ TALLOC_FREE( ctx );
+ ads_destroy(&ads);
+
+ return -1;
+
+}
+
+/*******************************************************************
+ ********************************************************************/
+
+static int net_ads_dns_usage(int argc, const char **argv)
+{
+#if defined(WITH_DNS_UPDATES)
+ d_printf("net ads dns <command>\n");
+ d_printf("Valid commands:\n");
+ d_printf(" register Issue a dynamic DNS update request for our hostname\n");
+
+ return 0;
+#else
+ d_fprintf(stderr, "DNS update support not enabled at compile time!\n");
+ return -1;
+#endif
+}
+
+/*******************************************************************
+ ********************************************************************/
+
+static int net_ads_dns(int argc, const char **argv)
+{
+#if defined(WITH_DNS_UPDATES)
+ ADS_STRUCT *ads;
+ ADS_STATUS status;
+ TALLOC_CTX *ctx;
+ BOOL register_dns = False;
+ int i;
+
+ status = ads_startup(True, &ads);
+ if ( !ADS_ERR_OK(status) ) {
+ DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
+ return -1;
+ }
+
+ if (!(ctx = talloc_init("net_ads_dns"))) {
+ DEBUG(0, ("Could not initialise talloc context\n"));
+ return -1;
+ }
+
+ /* process additional command line args */
+
+ for ( i=0; i<argc; i++ ) {
+ if ( strequal(argv[i], "register") ) {
+ register_dns = True;
+ }
+ else {
+ d_fprintf(stderr, "Bad option: %s\n", argv[i]);
+ return -1;
+ }
+ }
+
+ if ( !net_update_dns( ctx, ads ) ) {
+ d_fprintf( stderr, "DNS update failed!\n" );
+ ads_destroy( &ads );
+ TALLOC_FREE( ctx );
+ return -1;
+ }
+
+ d_fprintf( stderr, "Successfully registered hostname with DNS\n" );
+
ads_destroy(&ads);
TALLOC_FREE( ctx );
+
+ return 0;
+#else
+ d_fprintf(stderr, "DNS update support not enabled at compile time!\n");
return -1;
+#endif
}
/*******************************************************************
@@ -2026,6 +2197,7 @@ int net_ads_help(int argc, const char **argv)
{"SEARCH", net_ads_search_usage},
{"INFO", net_ads_info},
{"JOIN", net_ads_join_usage},
+ {"DNS", net_ads_dns_usage},
{"LEAVE", net_ads_leave},
{"STATUS", net_ads_status},
{"PASSWORD", net_ads_password},
@@ -2046,6 +2218,7 @@ int net_ads(int argc, const char **argv)
{"STATUS", net_ads_status},
{"USER", net_ads_user},
{"GROUP", net_ads_group},
+ {"DNS", net_ads_dns},
{"PASSWORD", net_ads_password},
{"CHANGETRUSTPW", net_ads_changetrustpw},
{"PRINTER", net_ads_printer},
diff --git a/source3/utils/net_dns.c b/source3/utils/net_dns.c
new file mode 100644
index 0000000000..873eda377e
--- /dev/null
+++ b/source3/utils/net_dns.c
@@ -0,0 +1,99 @@
+
+/*
+ Samba Unix/Linux Dynamic DNS Update
+ net ads commands
+
+ Copyright (C) Krishna Ganugapati (krishnag@centeris.com) 2006
+ Copyright (C) Gerald Carter 2006
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "utils/net.h"
+#include "dns.h"
+
+#if defined(WITH_DNS_UPDATES)
+
+/*********************************************************************
+*********************************************************************/
+
+int DoDNSUpdate( char *pszServerName, char *pszDomainName,
+ char *pszHostName, struct in_addr *iplist, int num_addrs )
+{
+ int32 dwError = 0;
+ DNS_ERROR dns_status;
+ HANDLE hDNSServer = ( HANDLE ) NULL;
+ int32 dwResponseCode = 0;
+ DNS_UPDATE_RESPONSE *pDNSUpdateResponse = NULL;
+#if 0
+ DNS_UPDATE_RESPONSE *pDNSSecureUpdateResponse = NULL;
+#endif
+
+ if ( (num_addrs <= 0) || !iplist ) {
+ return -1;
+ }
+
+ dns_status = DNSOpen( pszServerName, DNS_TCP, &hDNSServer );
+ BAIL_ON_DNS_ERROR( dns_status );
+
+ dwError = DNSSendUpdate( hDNSServer, pszDomainName, pszHostName,
+ iplist, num_addrs, &pDNSUpdateResponse );
+ BAIL_ON_ERROR( dwError );
+
+ dwError = DNSUpdateGetResponseCode( pDNSUpdateResponse,
+ &dwResponseCode );
+ if ( dwResponseCode == DNS_REFUSED ) {
+ dwError = -1;
+ }
+ BAIL_ON_ERROR( dwError );
+
+cleanup:
+ return dwError;
+
+error:
+ goto cleanup;
+}
+
+/*********************************************************************
+*********************************************************************/
+
+int get_my_ip_address( struct in_addr **ips )
+{
+ struct iface_struct nics[MAX_INTERFACES];
+ int i, n;
+ struct in_addr loopback_ip = *interpret_addr2("127.0.0.1");
+ struct in_addr *list;
+ int count = 0;
+
+ /* find the first non-loopback address from our list of interfaces */
+
+ n = get_interfaces(nics, MAX_INTERFACES);
+
+ if ( (list = SMB_MALLOC_ARRAY( struct in_addr, n )) == NULL ) {
+ return -1;
+ }
+
+ for ( i=0; i<n; i++ ) {
+ if ( nics[i].ip.s_addr != loopback_ip.s_addr ) {
+ memcpy( &list[count++], &nics[i].ip, sizeof( struct in_addr ) );
+ }
+ }
+ *ips = list;
+
+ return count;
+}
+
+#endif /* defined(WITH_DNS_UPDATES) */