diff options
author | Gerald Carter <jerry@samba.org> | 2006-08-24 15:43:32 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 11:38:48 -0500 |
commit | 5693e6c599a586b1bb19eea375c6b1e22526031c (patch) | |
tree | 9190fcd83791a892aaca33debd400fd0b4124fc2 /source3/utils | |
parent | 6717e0d467bea50cb7712e6b5278ddb403fdf828 (diff) | |
download | samba-5693e6c599a586b1bb19eea375c6b1e22526031c.tar.gz samba-5693e6c599a586b1bb19eea375c6b1e22526031c.tar.bz2 samba-5693e6c599a586b1bb19eea375c6b1e22526031c.zip |
r17798: Beginnings of a standalone libaddns library released under
the LGPL. Original code by Krishna Ganugapati <krishnag@centeris.com>.
Additional work by me.
It's still got some warts, but non-secure updates do
currently work. There are at least four things left to
really clean up.
1. Change the memory management to use talloc() rather than
malloc() and cleanup the leaks.
2. Fix the error code reporting (see initial changes to
dnserr.h)
3. Fix the secure updates
4. Define a public interface in addns.h
5. Move the code in libads/dns.c into the libaddns/ directory
(and under the LGPL).
A few notes:
* Enable the new code by compiling with --with-dnsupdate
* Also adds the command 'net ads dns register'
* Requires -luuid (included in the e2fsprogs-devel package).
* Has only been tested on Linux platforms so there may be portability
issues.
(This used to be commit 36f04674aeefd93c5a0408b8967dcd48b86fdbc1)
Diffstat (limited to 'source3/utils')
-rw-r--r-- | source3/utils/net_ads.c | 179 | ||||
-rw-r--r-- | source3/utils/net_dns.c | 99 |
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) */ |