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
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
char *cp;
const char *realm = NULL;
BOOL tried_closest_dc = False;
- BOOL closest_dc = False;
- BOOL site_matches = False;
/* lp_realm() should be handled by a command line param,
However, the join requires that realm be set in smb.conf
return status;
}
- if (!need_password && !second_time) {
+ if (!need_password && !second_time && !(auth_flags & ADS_AUTH_NO_BIND)) {
need_password = True;
second_time = True;
goto retry;
* This is done by reconnecting to ADS because only the first call to
* ads_connect will give us our own sitename */
- closest_dc = (ads->config.flags & ADS_CLOSEST);
- site_matches = ads_sitename_match(ads);
-
- DEBUG(10,("ads_startup_int: DC %s closest DC\n", closest_dc ? "is":"is *NOT*"));
- DEBUG(10,("ads_startup_int: sitenames %s match\n", site_matches ? "do":"do *NOT*"));
-
if ((only_own_domain || !opt_host) && !tried_closest_dc) {
tried_closest_dc = True; /* avoid loop */
- if (!closest_dc || !site_matches) {
+ if (!ads->config.tried_closest_dc) {
namecache_delete(ads->server.realm, 0x1C);
namecache_delete(ads->server.workgroup, 0x1C);
struct cli_state *cli = NULL;
TALLOC_CTX *ctx;
DOM_SID *dom_sid = NULL;
+ char *short_domain_name = NULL;
if (!secrets_init()) {
DEBUG(1,("Failed to initialise secrets database\n"));
goto done;
}
- saf_store( cli->server_domain, cli->desthost );
-
- if ( !NT_STATUS_IS_OK(netdom_get_domain_sid( ctx, cli, &dom_sid )) ) {
+ if ( !NT_STATUS_IS_OK(netdom_get_domain_sid( ctx, cli, &short_domain_name, &dom_sid )) ) {
goto done;
}
+ saf_delete( short_domain_name );
+
status = netdom_leave_domain(ctx, cli, dom_sid);
- /* Ty and delete it via LDAP - the old way we used to. */
+ /* Try and delete it via LDAP - the old way we used to. */
adsret = ads_leave_realm(ads, global_myname());
if (ADS_ERR_OK(adsret)) {
}
if ( lp_security() == SEC_ADS && !*lp_realm()) {
- d_fprintf(stderr, "realm must be set in in smb.conf for ADS "
- "join to succeed.\n");
+ d_fprintf(stderr, "realm must be set in in %s for ADS "
+ "join to succeed.\n", dyn_CONFIGFILE);
return NT_STATUS_INVALID_PARAMETER;
}
********************************************************************/
static NTSTATUS net_join_domain(TALLOC_CTX *ctx, const char *servername,
- struct in_addr *ip, DOM_SID **dom_sid,
+ struct in_addr *ip, char **domain,
+ DOM_SID **dom_sid,
const char *password)
{
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
goto done;
}
- saf_store( cli->server_domain, cli->desthost );
-
- ret = netdom_get_domain_sid( ctx, cli, dom_sid );
+ ret = netdom_get_domain_sid( ctx, cli, domain, dom_sid );
if ( !NT_STATUS_IS_OK(ret) ) {
goto done;
}
+ /* cli->server_domain is not filled in when using krb5
+ session setups */
+
+ saf_store( *domain, cli->desthost );
+
ret = netdom_join_domain( ctx, cli, *dom_sid, password, ND_TYPE_AD );
done:
return status;
}
+/*******************************************************************
+ Set a machines dNSHostName and servicePrincipalName attributes
+ ********************************************************************/
+
+static ADS_STATUS net_set_os_attributes(TALLOC_CTX *ctx, ADS_STRUCT *ads_s,
+ const char *os_name, const char *os_version )
+{
+ ADS_STATUS status = ADS_ERROR(LDAP_SERVER_DOWN);
+ char *new_dn;
+ ADS_MODLIST mods;
+ LDAPMessage *res = NULL;
+ char *dn_string = NULL;
+ const char *machine_name = global_myname();
+ int count;
+ char *os_sp = NULL;
+
+ if ( !os_name || !os_version ) {
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ /* Find our DN */
+
+ status = ads_find_machine_acct(ads_s, &res, machine_name);
+ if (!ADS_ERR_OK(status))
+ return status;
+
+ if ( (count = ads_count_replies(ads_s, res)) != 1 ) {
+ DEBUG(1,("net_set_machine_spn: %d entries returned!\n", count));
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ if ( (dn_string = ads_get_dn(ads_s, res)) == NULL ) {
+ DEBUG(1, ("ads_add_machine_acct: ads_get_dn returned NULL (malloc failure?)\n"));
+ goto done;
+ }
+
+ new_dn = talloc_strdup(ctx, dn_string);
+ ads_memfree(ads_s, dn_string);
+ if (!new_dn) {
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ /* now do the mods */
+
+ if (!(mods = ads_init_mods(ctx))) {
+ goto done;
+ }
+
+ os_sp = talloc_asprintf( ctx, "Samba %s", SAMBA_VERSION_STRING );
+
+ /* fields of primary importance */
+
+ ads_mod_str(ctx, &mods, "operatingSystem", os_name);
+ ads_mod_str(ctx, &mods, "operatingSystemVersion", os_version);
+ if ( os_sp )
+ ads_mod_str(ctx, &mods, "operatingSystemServicePack", os_sp);
+
+ status = ads_gen_mod(ads_s, new_dn, mods);
+
+done:
+ ads_msgfree(ads_s, res);
+ TALLOC_FREE( os_sp );
+
+ return status;
+}
+
/*******************************************************************
join a domain using ADS (LDAP mods)
********************************************************************/
static ADS_STATUS net_precreate_machine_acct( ADS_STRUCT *ads, const char *ou )
{
ADS_STATUS rc = ADS_ERROR(LDAP_SERVER_DOWN);
- char *dn, *ou_str;
+ char *ou_str = NULL;
+ char *dn = NULL;
LDAPMessage *res = NULL;
+ BOOL moved;
ou_str = ads_ou_string(ads, ou);
- if ((asprintf(&dn, "%s,%s", ou_str, ads->config.bind_path)) == -1) {
- SAFE_FREE(ou_str);
- return ADS_ERROR(LDAP_NO_MEMORY);
+ if (asprintf(&dn, "%s,%s", ou_str, ads->config.bind_path) == -1) {
+ rc = ADS_ERROR(LDAP_NO_MEMORY);
+ goto done;
}
rc = ads_search_dn(ads, &res, dn, NULL);
- ads_msgfree(ads, res);
+ if (!ADS_ERR_OK(rc)) {
+ d_fprintf(stderr, "The specified OU does not exist.\n");
+ goto done;
+ }
- if (ADS_ERR_OK(rc)) {
/* Attempt to create the machine account and bail if this fails.
Assume that the admin wants exactly what they requested */
rc = ads_create_machine_acct( ads, global_myname(), dn );
- if ( rc.error_type == ENUM_ADS_ERROR_LDAP && rc.err.rc == LDAP_ALREADY_EXISTS ) {
- rc = ADS_SUCCESS;
+ if (ADS_ERR_OK(rc)) {
+ DEBUG(1, ("machine account created\n"));
+ goto done;
}
+ if ( !(rc.error_type == ENUM_ADS_ERROR_LDAP && rc.err.rc == LDAP_ALREADY_EXISTS) ) {
+ DEBUG(1, ("machine account creation failed\n"));
+ goto done;
+ }
+
+ rc = ads_move_machine_acct(ads, global_myname(), dn, &moved);
+ if (!ADS_ERR_OK(rc)) {
+ DEBUG(1, ("failure to locate/move pre-existing machine account\n"));
+ goto done;
+ }
+
+ if (moved) {
+ d_printf("The machine account was moved into the specified OU.\n");
+ } else {
+ d_printf("The machine account already exists in the specified OU.\n");
}
+done:
+ ads_msgfree(ads, res);
SAFE_FREE( ou_str );
SAFE_FREE( dn );
*******************************************************************/
#if defined(WITH_DNS_UPDATES)
-static BOOL net_update_dns( TALLOC_CTX *ctx, ADS_STRUCT *ads )
+#include "dns.h"
+DNS_ERROR DoDNSUpdate(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 );
+ 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);
+ 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;
- }
+ 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) */
- /* Get our ip address (not the 127.0.0.x address but a real ip address) */
+ const char *rootname_attrs[] = { "rootDomainNamingContext", NULL };
+ LDAPMessage *msg = NULL;
+ char *root_dn;
+ ADS_STATUS ads_status;
+
+ if ( !ads->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;
+ }
- 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;
- }
+ root_dn = ads_pull_string(ads, ctx, msg, "rootDomainNamingContext");
+ if ( !root_dn ) {
+ ads_msgfree( ads, msg );
+ goto done;
+ }
- /* Drop the user creds */
+ root_domain = ads_build_domain( root_dn );
- ads_kdestroy( NULL );
+ /* cleanup */
+ ads_msgfree( ads, msg );
- 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;
- }
+ /* try again for NS servers */
- /* kinit with the machine password */
+ status = ads_dns_lookup_ns( ctx, root_domain, &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;
+ }
- 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 );
+ dnsdomain = root_domain;
+
+ }
- /* Now perform the dns update - we'll try non-secure and if we fail, we'll
- follow it up with a secure update */
+ /* 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"));
+ dns_err = DoDNSUpdate(dns_server, dnsdomain, machine_name, addrs, num_addrs);
+ if (!ERR_DNS_IS_OK(dns_err)) {
+ status = NT_STATUS_UNSUCCESSFUL;
}
done:
+
+ SAFE_FREE( root_domain );
+
+ return status;
+}
+
+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;
+
+ 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_ads_join: Failed to find my non-loopback IP "
+ "addresses!\n"));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ 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
d_printf(" createcomputer=OU Precreate the computer account in a specific OU.\n");
d_printf(" The OU string read from top to bottom without RDNs and delimited by a '/'.\n");
d_printf(" E.g. \"createcomputer=Computers/Servers/Unix\"\n");
+ d_printf(" NB: A backslash '\\' is used as escape at multiple levels and may\n");
+ d_printf(" need to be doubled or even quadrupled. It is not used as a separator.\n");
+ d_printf(" osName=string Set the operatingSystem attribute during the join.\n");
+ d_printf(" osVer=string Set the operatingSystemVersion attribute during the join.\n");
+ d_printf(" NB: osName and osVer must be specified together for either to take effect.\n");
+ d_printf(" Also, the operatingSystemService attribute is also set when along with\n");
+ d_printf(" the two other attributes.\n");
return -1;
}
ADS_STATUS status;
NTSTATUS nt_status;
char *machine_account = NULL;
- const char *short_domain_name = NULL;
+ char *short_domain_name = NULL;
char *tmp_password, *password;
- struct cldap_netlogon_reply cldap_reply;
TALLOC_CTX *ctx = NULL;
DOM_SID *domain_sid = NULL;
BOOL createupn = False;
const char *machineupn = NULL;
const char *create_in_ou = NULL;
int i;
+ fstring dc_name;
+ struct in_addr dcip;
+ const char *os_name = NULL;
+ const char *os_version = NULL;
nt_status = check_ads_config();
if (!NT_STATUS_IS_OK(nt_status)) {
goto fail;
}
+ /* find a DC to initialize the server affinity cache */
+
+ get_dc_name( lp_workgroup(), lp_realm(), dc_name, &dcip );
+
status = ads_startup(True, &ads);
if (!ADS_ERR_OK(status)) {
DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
}
if (strcmp(ads->config.realm, lp_realm()) != 0) {
- d_fprintf(stderr, "realm of remote server (%s) and realm in smb.conf "
+ d_fprintf(stderr, "realm of remote server (%s) and realm in %s "
"(%s) DO NOT match. Aborting join\n", ads->config.realm,
- lp_realm());
+ dyn_CONFIGFILE, lp_realm());
nt_status = NT_STATUS_INVALID_PARAMETER;
goto fail;
}
}
else if ( !StrnCaseCmp(argv[i], "createcomputer", strlen("createcomputer")) ) {
if ( (create_in_ou = get_string_param(argv[i])) == NULL ) {
- d_fprintf(stderr, "Please supply a valid OU path\n");
+ d_fprintf(stderr, "Please supply a valid OU path.\n");
+ nt_status = NT_STATUS_INVALID_PARAMETER;
+ goto fail;
+ }
+ }
+ else if ( !StrnCaseCmp(argv[i], "osName", strlen("osName")) ) {
+ if ( (os_name = get_string_param(argv[i])) == NULL ) {
+ d_fprintf(stderr, "Please supply a operating system name.\n");
+ nt_status = NT_STATUS_INVALID_PARAMETER;
+ goto fail;
+ }
+ }
+ else if ( !StrnCaseCmp(argv[i], "osVer", strlen("osVer")) ) {
+ if ( (os_version = get_string_param(argv[i])) == NULL ) {
+ d_fprintf(stderr, "Please supply a valid operating system version.\n");
nt_status = NT_STATUS_INVALID_PARAMETER;
goto fail;
}
status = net_precreate_machine_acct( ads, create_in_ou );
if ( !ADS_ERR_OK(status) ) {
d_fprintf( stderr, "Failed to pre-create the machine object "
- "in OU %s.\n", argv[0]);
+ "in OU %s.\n", create_in_ou);
DEBUG(1, ("error calling net_precreate_machine_acct: %s\n",
ads_errstr(status)));
nt_status = ads_ntstatus(status);
password = talloc_strdup(ctx, tmp_password);
nt_status = net_join_domain(ctx, ads->config.ldap_server_name,
- &ads->ldap_ip, &domain_sid, password);
+ &ads->ldap_ip, &short_domain_name, &domain_sid, password);
if ( !NT_STATUS_IS_OK(nt_status) ) {
DEBUG(1, ("call of net_join_domain failed: %s\n",
get_friendly_nt_error_msg(nt_status)));
goto fail;
}
-
+
/* Check the short name of the domain */
- ZERO_STRUCT( cldap_reply );
-
- if ( ads_cldap_netlogon( ads->config.ldap_server_name,
- ads->server.realm, &cldap_reply ) )
- {
- short_domain_name = talloc_strdup( ctx, cldap_reply.netbios_domain );
- if ( !strequal(lp_workgroup(), short_domain_name) ) {
- d_printf("The workgroup in smb.conf does not match the short\n");
- d_printf("domain name obtained from the server.\n");
- d_printf("Using the name [%s] from the server.\n", short_domain_name);
- d_printf("You should set \"workgroup = %s\" in smb.conf.\n", short_domain_name);
- }
- } else {
- short_domain_name = lp_workgroup();
+ if ( !strequal(lp_workgroup(), short_domain_name) ) {
+ d_printf("The workgroup in %s does not match the short\n", dyn_CONFIGFILE);
+ d_printf("domain name obtained from the server.\n");
+ d_printf("Using the name [%s] from the server.\n", short_domain_name);
+ d_printf("You should set \"workgroup = %s\" in %s.\n",
+ short_domain_name, dyn_CONFIGFILE);
}
d_printf("Using short domain name -- %s\n", short_domain_name);
}
}
+ /* Try to set the operatingSystem attributes if asked */
+
+ if ( os_name && os_version ) {
+ status = net_set_os_attributes( ctx, ads, os_name, os_version );
+ if ( !ADS_ERR_OK(status) ) {
+ d_fprintf(stderr, "Failed to set operatingSystem attributes. "
+ "Are you a Domain Admin?\n");
+ }
+ }
+
/* Now build the keytab, using the same ADS connection */
+
if (lp_use_kerberos_keytab() && ads_keytab_create_default(ads)) {
DEBUG(1,("Error creating host keytab!\n"));
}
#if defined(WITH_DNS_UPDATES)
/* We enter this block with user creds */
+ ads_kdestroy( NULL );
+ ads_destroy(&ads);
+ ads = NULL;
- if ( !net_update_dns( ctx, ads ) ) {
+ 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 ( !ads || !NT_STATUS_IS_OK(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);
+ d_printf("Joined '%s' to realm '%s'\n", global_myname(), ads->server.realm);
SAFE_FREE(machine_account);
TALLOC_FREE( ctx );
/*******************************************************************
********************************************************************/
-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;
- 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 > 0) {
+ 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 */
-
- 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;
- }
+ status = ads_startup(True, &ads);
+ if ( !ADS_ERR_OK(status) ) {
+ DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
+ TALLOC_FREE(ctx);
+ return -1;
}
-
- if ( !net_update_dns( ctx, ads ) ) {
+
+ if ( !NT_STATUS_IS_OK(net_update_dns(ctx, ads)) ) {
d_fprintf( stderr, "DNS update failed!\n" );
ads_destroy( &ads );
TALLOC_FREE( ctx );
#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);
+}
+
/*******************************************************************
********************************************************************/
return 0;
}
-void do_drv_upgrade_printer(int msg_type, struct process_id src,
- void *buf, size_t len)
-{
- return;
-}
-
static int net_ads_printer_publish(int argc, const char **argv)
{
ADS_STRUCT *ads;
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;
LDAPMessage *res = NULL;
if (!ADS_ERR_OK(ads_startup(True, &ads))) {
+ talloc_destroy(mem_ctx);
return -1;
}
if (argc < 1) {
+ talloc_destroy(mem_ctx);
return net_ads_printer_usage(argc, argv);
}
d_fprintf(stderr, "Unable to open a connnection to %s to obtain data "
"for %s\n", servername, printername);
ads_destroy(&ads);
+ talloc_destroy(mem_ctx);
return -1;
}
d_fprintf(stderr, "Could not find machine account for server %s\n",
servername);
ads_destroy(&ads);
+ talloc_destroy(mem_ctx);
return -1;
}
srv_dn = ldap_get_dn((LDAP *)ads->ld, (LDAPMessage *)res);
srv_cn = ldap_explode_dn(srv_dn, 1);
- asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn[0], printername, srv_dn);
+ srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn[0]);
+ printername_escaped = escape_rdn_val_string_alloc(printername);
+ if (!srv_cn_escaped || !printername_escaped) {
+ 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;
+ }
+
+ asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_escaped, printername_escaped, srv_dn);
+
+ SAFE_FREE(srv_cn_escaped);
+ SAFE_FREE(printername_escaped);
pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SPOOLSS, &nt_status);
if (!pipe_hnd) {
d_fprintf(stderr, "Unable to open a connnection to the spoolss pipe on %s\n",
servername);
+ SAFE_FREE(prt_dn);
ads_destroy(&ads);
+ talloc_destroy(mem_ctx);
return -1;
}
if (!W_ERROR_IS_OK(get_remote_printer_publishing_data(pipe_hnd, mem_ctx, &mods,
printername))) {
+ SAFE_FREE(prt_dn);
ads_destroy(&ads);
+ talloc_destroy(mem_ctx);
return -1;
}
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;
}
d_printf("published printer\n");
+ SAFE_FREE(prt_dn);
ads_destroy(&ads);
+ talloc_destroy(mem_ctx);
return 0;
}
"The DN standard LDAP DN, and the attributes are a list of LDAP fields \n"\
"to show in the results\n\n"\
"Example: net ads dn 'CN=administrator,CN=Users,DC=my,DC=domain' sAMAccountName\n\n"
+ "Note: the DN must be provided properly escaped. See RFC 4514 for details\n\n"
);
net_common_flags_usage(argc, argv);
return -1;
d_printf(
"net ads keytab <COMMAND>\n"\
"<COMMAND> can be either:\n"\
-" CREATE Creates a fresh keytab\n"\
" ADD Adds new service principal\n"\
+" CREATE Creates a fresh keytab\n"\
" FLUSH Flushes out all keytab entries\n"\
" HELP Prints this help message\n"\
-"The ADD command will take arguments, the other commands\n"\
+" LIST List the keytab\n"\
+"The ADD and LIST command will take arguments, the other commands\n"\
"will not take any arguments. The arguments given to ADD\n"\
"should be a list of principals to add. For example, \n"\
" net ads keytab add srv1 srv2\n"\
"will add principals for the services srv1 and srv2 to the\n"\
"system's keytab.\n"\
+"The LIST command takes a keytabname.\n"\
"\n"
);
return -1;
return ret;
}
+static int net_ads_keytab_list(int argc, const char **argv)
+{
+ const char *keytab = NULL;
+
+ if (argc >= 1) {
+ keytab = argv[0];
+ }
+
+ return ads_keytab_list(keytab);
+}
+
+
int net_ads_keytab(int argc, const char **argv)
{
struct functable func[] = {
- {"CREATE", net_ads_keytab_create},
{"ADD", net_ads_keytab_add},
+ {"CREATE", net_ads_keytab_create},
{"FLUSH", net_ads_keytab_flush},
{"HELP", net_ads_keytab_usage},
+ {"LIST", net_ads_keytab_list},
{NULL, NULL}
};