summaryrefslogtreecommitdiff
path: root/source3/utils
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2006-11-17 21:46:26 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:15:53 -0500
commitc2aae726ea3f697c50f8d2304e2a9e69c56ab90f (patch)
tree0c05a34d585fa27282a3a106863c99e24237957f /source3/utils
parent9a88644bb5834b526085fad7536a02e333bf8c3c (diff)
downloadsamba-c2aae726ea3f697c50f8d2304e2a9e69c56ab90f.tar.gz
samba-c2aae726ea3f697c50f8d2304e2a9e69c56ab90f.tar.bz2
samba-c2aae726ea3f697c50f8d2304e2a9e69c56ab90f.zip
r19762: libaddns/*[ch] code fixes donated by Centeris Corporation
(http://www.centeris.com/) under my copyright. * Rework error reporting to use DNS_ERROR instead of int32 * Convert memory allocation to use talloc() * Generalize the DNS request/response packet marshalling * Fix the secure update requests (This used to be commit c78798333616c3f823514df0f58da2eb3a30a988)
Diffstat (limited to 'source3/utils')
-rw-r--r--source3/utils/net_ads.c206
-rw-r--r--source3/utils/net_dns.c141
2 files changed, 261 insertions, 86 deletions
diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c
index 0f189f9c6f..76b6b043ba 100644
--- a/source3/utils/net_ads.c
+++ b/source3/utils/net_ads.c
@@ -1220,79 +1220,79 @@ static BOOL net_derive_salting_principal( TALLOC_CTX *ctx, ADS_STRUCT *ads )
*******************************************************************/
#if defined(WITH_DNS_UPDATES)
-static BOOL net_update_dns( TALLOC_CTX *ctx, ADS_STRUCT *ads )
+#include "dns.h"
+DNS_ERROR DoDNSUpdate(ADS_STRUCT *ads, char *pszServerName,
+ const char *pszDomainName,
+ const char *pszHostName,
+ const struct in_addr *iplist, int num_addrs );
+
+
+static NTSTATUS net_update_dns_internal(TALLOC_CTX *ctx, ADS_STRUCT *ads,
+ const char *machine_name,
+ const struct in_addr *addrs,
+ int num_addrs)
{
- 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;
+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+ DNS_ERROR dns_err;
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);
+ d_printf("No DNS domain configured for %s. "
+ "Unable to perform DNS Update.\n", machine_name);
+ status = NT_STATUS_INVALID_PARAMETER;
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;
+ status = ads_dns_lookup_ns( ctx, dnsdomain, &nameservers, &ns_count );
+ if ( !NT_STATUS_IS_OK(status) || (ns_count == 0)) {
+ DEBUG(3,("net_ads_join: Failed to find name server for the %s "
+ "realm\n", ads->config.realm));
goto done;
}
- /* Drop the user creds */
+ /* Now perform the dns update - we'll try non-secure and if we fail,
+ we'll follow it up with a secure update */
- ads_kdestroy( NULL );
+ fstrcpy( dns_server, nameservers[0].hostname );
- 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;
+ dns_err = DoDNSUpdate(ads, dns_server, dnsdomain, machine_name, addrs, num_addrs);
+ if (!ERR_DNS_IS_OK(dns_err)) {
+ status = NT_STATUS_UNSUCCESSFUL;
}
- /* kinit with the machine password */
+done:
+ return status;
+ }
- 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 );
+static NTSTATUS net_update_dns(TALLOC_CTX *mem_ctx, ADS_STRUCT *ads)
+{
+ int num_addrs;
+ struct in_addr *iplist = NULL;
+ fstring machine_name;
+ NTSTATUS status;
- /* Now perform the dns update - we'll try non-secure and if we fail, we'll
- follow it up with a secure update */
+ name_to_fqdn( machine_name, global_myname() );
+ strlower_m( machine_name );
- fstrcpy( dns_server, nameservers[0].hostname );
+ /* Get our ip address (not the 127.0.0.x address but a real ip
+ * address) */
- ret = DoDNSUpdate(dns_server, dnsdomain, machine_name, iplist, num_addrs );
- if ( ret ) {
- DEBUG(1, ("Error creating dns update!\n"));
+ 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"));
+ return NT_STATUS_INVALID_PARAMETER;
}
-done:
+ status = net_update_dns_internal(mem_ctx, ads, machine_name,
+ iplist, num_addrs);
SAFE_FREE( iplist );
- if ( ads_s )
- ads_destroy( &ads_s );
-
- return (ret == 0);
+ return status;
}
#endif
@@ -1506,8 +1506,22 @@ int net_ads_join(int argc, const char **argv)
#if defined(WITH_DNS_UPDATES)
/* We enter this block with user creds */
+ ads_kdestroy( NULL );
+ ads_destroy(&ads);
+ ads = NULL;
+
+ if ( (ads = ads_init( lp_realm(), NULL, NULL )) != NULL ) {
+ /* kinit with the machine password */
+
+ use_in_memory_ccache();
+ asprintf( &ads->auth.user_name, "%s$", global_myname() );
+ ads->auth.password = secrets_fetch_machine_password(
+ lp_workgroup(), NULL, NULL );
+ ads->auth.realm = SMB_STRDUP( lp_realm() );
+ ads_kinit_password( ads );
+ }
- if ( !net_update_dns( ctx, ads ) ) {
+ if ( !ads || !NT_STATUS_IS_OK(net_update_dns( ctx, ads )) ) {
d_fprintf( stderr, "DNS update failed!\n" );
}
@@ -1554,42 +1568,72 @@ static int net_ads_dns_usage(int argc, const char **argv)
/*******************************************************************
********************************************************************/
-static int net_ads_dns(int argc, const char **argv)
+static int net_ads_dns_register(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;
+ fstring name;
+ int num_addrs;
+ struct in_addr *iplist = NULL;
- status = ads_startup(True, &ads);
- if ( !ADS_ERR_OK(status) ) {
- DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
+#ifdef DEVELOPER
+ talloc_enable_leak_report();
+#endif
+
+ if (argc > 2) {
+ d_fprintf(stderr, "net ads dns register <name> <ip>\n");
return -1;
}
if (!(ctx = talloc_init("net_ads_dns"))) {
- DEBUG(0, ("Could not initialise talloc context\n"));
+ d_fprintf(stderr, "Could not initialise talloc context\n");
return -1;
}
- /* process additional command line args */
+ if (argc > 0) {
+ fstrcpy(name, argv[0]);
+ } else {
+ name_to_fqdn(name, global_myname());
+ }
+ strlower_m(name);
- for ( i=0; i<argc; i++ ) {
- if ( strequal(argv[i], "register") ) {
- register_dns = True;
+ if (argc > 1) {
+ if (!(iplist = SMB_MALLOC_ARRAY(struct in_addr, 1))) {
+ d_fprintf(stderr, "net_ads_dns_register: malloc "
+ "failed\n");
+ return -1;
}
- else {
- d_fprintf(stderr, "Bad option: %s\n", argv[i]);
+ if (inet_aton(argv[1], iplist) == 0) {
+ d_fprintf(stderr, "net_ads_dns_register: %s is not "
+ "a valid IP address\n", argv[1]);
+ SAFE_FREE(iplist);
+ return -1;
+ }
+ num_addrs = 1;
+ } else {
+ num_addrs = get_my_ip_address( &iplist );
+ if ( num_addrs <= 0 ) {
+ d_fprintf(stderr, "net_ads_dns_regiser: Failed to "
+ "find my non-loopback IP addresses!\n");
return -1;
}
}
- if ( !net_update_dns( ctx, ads ) ) {
+ status = ads_startup_nobind(True, &ads);
+ if ( !ADS_ERR_OK(status) ) {
+ DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
+ TALLOC_FREE(ctx);
+ return -1;
+ }
+
+ if ( !NT_STATUS_IS_OK(net_update_dns_internal(ctx, ads, name,
+ iplist, num_addrs)) ) {
d_fprintf( stderr, "DNS update failed!\n" );
ads_destroy( &ads );
TALLOC_FREE( ctx );
+ SAFE_FREE(iplist);
return -1;
}
@@ -1597,6 +1641,7 @@ static int net_ads_dns(int argc, const char **argv)
ads_destroy(&ads);
TALLOC_FREE( ctx );
+ SAFE_FREE(iplist);
return 0;
#else
@@ -1605,6 +1650,43 @@ static int net_ads_dns(int argc, const char **argv)
#endif
}
+#if defined(WITH_DNS_UPDATES)
+DNS_ERROR do_gethostbyname(const char *server, const char *host);
+#endif
+
+static int net_ads_dns_gethostbyname(int argc, const char **argv)
+{
+#if defined(WITH_DNS_UPDATES)
+ DNS_ERROR err;
+
+#ifdef DEVELOPER
+ talloc_enable_leak_report();
+#endif
+
+ if (argc != 2) {
+ d_fprintf(stderr, "net ads dns gethostbyname <server> "
+ "<name>\n");
+ return -1;
+ }
+
+ err = do_gethostbyname(argv[0], argv[1]);
+
+ d_printf("do_gethostbyname returned %d\n", ERROR_DNS_V(err));
+#endif
+ return 0;
+}
+
+static int net_ads_dns(int argc, const char *argv[])
+{
+ struct functable func[] = {
+ {"REGISTER", net_ads_dns_register},
+ {"GETHOSTBYNAME", net_ads_dns_gethostbyname},
+ {NULL, NULL}
+ };
+
+ return net_run_function(argc, argv, func, net_ads_dns_usage);
+}
+
/*******************************************************************
********************************************************************/
diff --git a/source3/utils/net_dns.c b/source3/utils/net_dns.c
index cb83b000ca..d372211a5f 100644
--- a/source3/utils/net_dns.c
+++ b/source3/utils/net_dns.c
@@ -30,41 +30,115 @@
/*********************************************************************
*********************************************************************/
-int DoDNSUpdate( char *pszServerName, const char *pszDomainName,
- char *pszHostName, struct in_addr *iplist, int num_addrs )
+DNS_ERROR DoDNSUpdate(ADS_STRUCT *ads, char *pszServerName,
+ const char *pszDomainName, const char *pszHostName,
+ const 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
+ DNS_ERROR err;
+ struct dns_connection *conn;
+ TALLOC_CTX *mem_ctx;
+ OM_uint32 minor;
+ struct dns_update_request *req, *resp;
if ( (num_addrs <= 0) || !iplist ) {
- return -1;
+ return ERROR_DNS_INVALID_PARAMETER;
+ }
+
+ if (!(mem_ctx = talloc_init("DoDNSUpdate"))) {
+ return ERROR_DNS_NO_MEMORY;
}
- dns_status = DNSOpen( pszServerName, DNS_TCP, &hDNSServer );
- BAIL_ON_DNS_ERROR( dns_status );
+ err = dns_open( pszServerName, DNS_TCP, mem_ctx, &conn );
+ if (!ERR_DNS_IS_OK(err)) {
+ goto error;
+ }
+
+ /*
+ * Probe if everything's fine
+ */
+
+ err = dns_create_probe(mem_ctx, pszDomainName, pszHostName,
+ num_addrs, iplist, &req);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ err = dns_update_transaction(mem_ctx, conn, req, &resp);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ if (dns_response_code(resp->flags) == DNS_NO_ERROR) {
+ TALLOC_FREE(mem_ctx);
+ return ERROR_DNS_SUCCESS;
+ }
+
+ /*
+ * First try without signing
+ */
- dwError = DNSSendUpdate( hDNSServer, pszDomainName, pszHostName,
- iplist, num_addrs, &pDNSUpdateResponse );
- BAIL_ON_ERROR( dwError );
+ err = dns_create_update_request(mem_ctx, pszDomainName, pszHostName,
+ iplist[0].s_addr, &req);
+ if (!ERR_DNS_IS_OK(err)) goto error;
- dwError = DNSUpdateGetResponseCode( pDNSUpdateResponse,
- &dwResponseCode );
- if ( dwResponseCode == DNS_REFUSED ) {
- dwError = -1;
+ err = dns_update_transaction(mem_ctx, conn, req, &resp);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ if (dns_response_code(resp->flags) == DNS_NO_ERROR) {
+ TALLOC_FREE(mem_ctx);
+ return ERROR_DNS_SUCCESS;
+ }
+
+ /*
+ * Okay, we have to try with signing
+ */
+ {
+ ADS_STRUCT *ads_s;
+ gss_ctx_id_t gss_context;
+ int res;
+ char *keyname;
+
+ if (!(keyname = dns_generate_keyname( mem_ctx ))) {
+ err = ERROR_DNS_NO_MEMORY;
+ goto error;
+ }
+
+ if (!(ads_s = ads_init(ads->server.realm, ads->server.workgroup,
+ ads->server.ldap_server))) {
+ return ERROR_DNS_NO_MEMORY;
+ }
+
+ /* kinit with the machine password */
+ setenv(KRB5_ENV_CCNAME, "MEMORY:net_ads", 1);
+ 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() );
+ res = ads_kinit_password( ads_s );
+ ads_destroy(&ads_s);
+ if (res) {
+ err = ERROR_DNS_GSS_ERROR;
+ goto error;
+ }
+
+ err = dns_negotiate_sec_ctx( pszDomainName, pszServerName,
+ keyname, &gss_context );
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ err = dns_sign_update(req, gss_context, keyname,
+ "gss.microsoft.com", time(NULL), 3600);
+
+ gss_delete_sec_context(&minor, &gss_context, GSS_C_NO_BUFFER);
+
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ err = dns_update_transaction(mem_ctx, conn, req, &resp);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ err = (dns_response_code(resp->flags) == DNS_NO_ERROR) ?
+ ERROR_DNS_SUCCESS : ERROR_DNS_UPDATE_FAILED;
}
- BAIL_ON_ERROR( dwError );
-cleanup:
- return dwError;
error:
- goto cleanup;
+ TALLOC_FREE(mem_ctx);
+ return err;
}
/*********************************************************************
@@ -96,4 +170,23 @@ int get_my_ip_address( struct in_addr **ips )
return count;
}
+DNS_ERROR do_gethostbyname(const char *server, const char *host)
+{
+ struct dns_connection *conn;
+ struct dns_request *req, *resp;
+ DNS_ERROR err;
+
+ err = dns_open(server, DNS_UDP, NULL, &conn);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ err = dns_create_query(conn, host, QTYPE_A, DNS_CLASS_IN, &req);
+ if (!ERR_DNS_IS_OK(err)) goto error;
+
+ err = dns_transaction(conn, conn, req, &resp);
+
+ error:
+ TALLOC_FREE(conn);
+ return err;
+}
+
#endif /* defined(WITH_DNS_UPDATES) */