X-Git-Url: http://git.samba.org/samba.git/?a=blobdiff_plain;f=source3%2Futils%2Fnet_ads.c;h=031a338835d6a4d065dba12a17a50219ef7cd578;hb=5363d6e62c2d4d3275e78d04c48835524c54f620;hp=9358a4f18404bb59e9286ed9da6fc606de350bae;hpb=c4fbe2846231a6b322c1094c6a1dbf93b7305768;p=ira%2Fwip.git diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c index 9358a4f1840..031a338835d 100644 --- a/source3/utils/net_ads.c +++ b/source3/utils/net_ads.c @@ -22,53 +22,17 @@ #include "includes.h" #include "utils/net.h" - -#include "libnet/libnet.h" +#include "librpc/gen_ndr/ndr_krb5pac.h" +#include "nsswitch/libwbclient/wbclient.h" #ifdef HAVE_ADS -int net_ads_usage(int argc, const char **argv) -{ - d_printf("join [createupn[=principal]] [createcomputer=]\n"); - d_printf(" Join the local machine to a ADS realm\n"); - d_printf("leave\n"); - d_printf(" Remove the local machine from a ADS realm\n"); - d_printf("testjoin\n"); - d_printf(" Validates the machine account in the domain\n"); - d_printf("user\n"); - d_printf(" List, add, or delete users in the realm\n"); - d_printf("group\n"); - d_printf(" List, add, or delete groups in the realm\n"); - d_printf("info\n"); - d_printf(" Displays details regarding a specific AD server\n"); - d_printf("status\n"); - d_printf(" Display details regarding the machine's account in AD\n"); - d_printf("lookup\n"); - d_printf(" Performs CLDAP query of AD domain controllers\n"); - d_printf("password -Uadmin_username@realm%%admin_pass\n"); - d_printf(" Change a user's password using an admin account\n"); - d_printf(" (note: use realm in UPPERCASE, prompts if password is obmitted)\n"); - d_printf("changetrustpw\n"); - d_printf(" Change the trust account password of this machine in the AD tree\n"); - d_printf("printer [info | publish | remove] \n"); - d_printf(" Lookup, add, or remove directory entry for a printer\n"); - d_printf("{search,dn,sid}\n"); - 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; -} - /* when we do not have sufficient input parameters to contact a remote domain * we always fall back to our own realm - Guenther*/ -static const char *assume_own_realm(void) +static const char *assume_own_realm(struct net_context *c) { - if (!opt_host && strequal(lp_workgroup(), opt_target_workgroup)) { + if (!c->opt_host && strequal(lp_workgroup(), c->opt_target_workgroup)) { return lp_realm(); } @@ -78,75 +42,77 @@ static const char *assume_own_realm(void) /* do a cldap netlogon query */ -static int net_ads_cldap_netlogon(ADS_STRUCT *ads) +static int net_ads_cldap_netlogon(struct net_context *c, ADS_STRUCT *ads) { char addr[INET6_ADDRSTRLEN]; - struct cldap_netlogon_reply reply; - struct GUID tmp_guid; + struct NETLOGON_SAM_LOGON_RESPONSE_EX reply; print_sockaddr(addr, sizeof(addr), &ads->ldap.ss); - if ( !ads_cldap_netlogon(addr, ads->server.realm, &reply ) ) { - d_fprintf(stderr, "CLDAP query failed!\n"); + if ( !ads_cldap_netlogon_5(talloc_tos(), addr, ads->server.realm, &reply ) ) { + d_fprintf(stderr, _("CLDAP query failed!\n")); return -1; } - d_printf("Information for Domain Controller: %s\n\n", + d_printf(_("Information for Domain Controller: %s\n\n"), addr); - d_printf("Response Type: "); - switch (reply.type) { - case SAMLOGON_AD_UNK_R: - d_printf("SAMLOGON\n"); + d_printf(_("Response Type: ")); + switch (reply.command) { + case LOGON_SAM_LOGON_USER_UNKNOWN_EX: + d_printf("LOGON_SAM_LOGON_USER_UNKNOWN_EX\n"); break; - case SAMLOGON_AD_R: - d_printf("SAMLOGON_USER\n"); + case LOGON_SAM_LOGON_RESPONSE_EX: + d_printf("LOGON_SAM_LOGON_RESPONSE_EX\n"); break; default: - d_printf("0x%x\n", reply.type); + d_printf("0x%x\n", reply.command); break; } - smb_uuid_unpack(reply.guid, &tmp_guid); - d_printf("GUID: %s\n", smb_uuid_string(talloc_tos(), tmp_guid)); - - d_printf("Flags:\n" - "\tIs a PDC: %s\n" - "\tIs a GC of the forest: %s\n" - "\tIs an LDAP server: %s\n" - "\tSupports DS: %s\n" - "\tIs running a KDC: %s\n" - "\tIs running time services: %s\n" - "\tIs the closest DC: %s\n" - "\tIs writable: %s\n" - "\tHas a hardware clock: %s\n" - "\tIs a non-domain NC serviced by LDAP server: %s\n", - (reply.flags & ADS_PDC) ? "yes" : "no", - (reply.flags & ADS_GC) ? "yes" : "no", - (reply.flags & ADS_LDAP) ? "yes" : "no", - (reply.flags & ADS_DS) ? "yes" : "no", - (reply.flags & ADS_KDC) ? "yes" : "no", - (reply.flags & ADS_TIMESERV) ? "yes" : "no", - (reply.flags & ADS_CLOSEST) ? "yes" : "no", - (reply.flags & ADS_WRITABLE) ? "yes" : "no", - (reply.flags & ADS_GOOD_TIMESERV) ? "yes" : "no", - (reply.flags & ADS_NDNC) ? "yes" : "no"); - - printf("Forest:\t\t\t%s\n", reply.forest); - printf("Domain:\t\t\t%s\n", reply.domain); - printf("Domain Controller:\t%s\n", reply.hostname); - - printf("Pre-Win2k Domain:\t%s\n", reply.netbios_domain); - printf("Pre-Win2k Hostname:\t%s\n", reply.netbios_hostname); - - if (*reply.unk) printf("Unk:\t\t\t%s\n", reply.unk); - if (*reply.user_name) printf("User name:\t%s\n", reply.user_name); - - printf("Server Site Name :\t\t%s\n", reply.server_site_name); - printf("Client Site Name :\t\t%s\n", reply.client_site_name); - - d_printf("NT Version: %d\n", reply.version); - d_printf("LMNT Token: %.2x\n", reply.lmnt_token); - d_printf("LM20 Token: %.2x\n", reply.lm20_token); + d_printf(_("GUID: %s\n"), GUID_string(talloc_tos(),&reply.domain_uuid)); + + d_printf(_("Flags:\n" + "\tIs a PDC: %s\n" + "\tIs a GC of the forest: %s\n" + "\tIs an LDAP server: %s\n" + "\tSupports DS: %s\n" + "\tIs running a KDC: %s\n" + "\tIs running time services: %s\n" + "\tIs the closest DC: %s\n" + "\tIs writable: %s\n" + "\tHas a hardware clock: %s\n" + "\tIs a non-domain NC serviced by LDAP server: %s\n" + "\tIs NT6 DC that has some secrets: %s\n" + "\tIs NT6 DC that has all secrets: %s\n"), + (reply.server_type & NBT_SERVER_PDC) ? _("yes") : _("no"), + (reply.server_type & NBT_SERVER_GC) ? _("yes") : _("no"), + (reply.server_type & NBT_SERVER_LDAP) ? _("yes") : _("no"), + (reply.server_type & NBT_SERVER_DS) ? _("yes") : _("no"), + (reply.server_type & NBT_SERVER_KDC) ? _("yes") : _("no"), + (reply.server_type & NBT_SERVER_TIMESERV) ? _("yes") : _("no"), + (reply.server_type & NBT_SERVER_CLOSEST) ? _("yes") : _("no"), + (reply.server_type & NBT_SERVER_WRITABLE) ? _("yes") : _("no"), + (reply.server_type & NBT_SERVER_GOOD_TIMESERV) ? _("yes") : _("no"), + (reply.server_type & NBT_SERVER_NDNC) ? _("yes") : _("no"), + (reply.server_type & NBT_SERVER_SELECT_SECRET_DOMAIN_6) ? _("yes") : _("no"), + (reply.server_type & NBT_SERVER_FULL_SECRET_DOMAIN_6) ? _("yes") : _("no")); + + + printf(_("Forest:\t\t\t%s\n"), reply.forest); + 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 Hostname:\t%s\n"), reply.pdc_name); + + if (*reply.user_name) printf(_("User name:\t%s\n"), reply.user_name); + + printf(_("Server Site Name :\t\t%s\n"), reply.server_site); + printf(_("Client Site Name :\t\t%s\n"), reply.client_site); + + d_printf(_("NT Version: %d\n"), reply.nt_version); + d_printf(_("LMNT Token: %.2x\n"), reply.lmnt_token); + d_printf(_("LM20 Token: %.2x\n"), reply.lm20_token); return 0; } @@ -155,37 +121,57 @@ static int net_ads_cldap_netlogon(ADS_STRUCT *ads) this implements the CLDAP based netlogon lookup requests for finding the domain controller of a ADS domain */ -static int net_ads_lookup(int argc, const char **argv) +static int net_ads_lookup(struct net_context *c, int argc, const char **argv) { ADS_STRUCT *ads; + int ret; - if (!ADS_ERR_OK(ads_startup_nobind(False, &ads))) { - d_fprintf(stderr, "Didn't find the cldap server!\n"); + if (c->display_usage) { + d_printf(_("Usage:\n" + "net ads lookup\n" + " Find the ADS DC using CLDAP lookup.\n")); + return 0; + } + + if (!ADS_ERR_OK(ads_startup_nobind(c, false, &ads))) { + d_fprintf(stderr, _("Didn't find the cldap server!\n")); + ads_destroy(&ads); return -1; } if (!ads->config.realm) { - ads->config.realm = CONST_DISCARD(char *, opt_target_workgroup); + ads->config.realm = CONST_DISCARD(char *, c->opt_target_workgroup); ads->ldap.port = 389; } - return net_ads_cldap_netlogon(ads); + ret = net_ads_cldap_netlogon(c, ads); + ads_destroy(&ads); + return ret; } -static int net_ads_info(int argc, const char **argv) +static int net_ads_info(struct net_context *c, int argc, const char **argv) { ADS_STRUCT *ads; char addr[INET6_ADDRSTRLEN]; - if (!ADS_ERR_OK(ads_startup_nobind(False, &ads))) { - d_fprintf(stderr, "Didn't find the ldap server!\n"); + if (c->display_usage) { + d_printf(_("Usage:\n" + "net ads info\n" + " Display information about an Active Directory " + "server.\n")); + return 0; + } + + if (!ADS_ERR_OK(ads_startup_nobind(c, false, &ads))) { + d_fprintf(stderr, _("Didn't find the ldap server!\n")); return -1; } if (!ads || !ads->config.realm) { - d_fprintf(stderr, "Didn't find the ldap server!\n"); + d_fprintf(stderr, _("Didn't find the ldap server!\n")); + ads_destroy(&ads); return -1; } @@ -193,21 +179,23 @@ static int net_ads_info(int argc, const char **argv) TCP LDAP session initially */ if ( !ADS_ERR_OK(ads_current_time( ads )) ) { - d_fprintf( stderr, "Failed to get server's current time!\n"); + d_fprintf( stderr, _("Failed to get server's current time!\n")); } print_sockaddr(addr, sizeof(addr), &ads->ldap.ss); - d_printf("LDAP server: %s\n", addr); - d_printf("LDAP server name: %s\n", ads->config.ldap_server_name); - d_printf("Realm: %s\n", ads->config.realm); - d_printf("Bind Path: %s\n", ads->config.bind_path); - d_printf("LDAP port: %d\n", ads->ldap.port); - d_printf("Server time: %s\n", http_timestring(ads->config.current_time)); + d_printf(_("LDAP server: %s\n"), addr); + d_printf(_("LDAP server name: %s\n"), ads->config.ldap_server_name); + d_printf(_("Realm: %s\n"), ads->config.realm); + d_printf(_("Bind Path: %s\n"), ads->config.bind_path); + d_printf(_("LDAP port: %d\n"), ads->ldap.port); + d_printf(_("Server time: %s\n"), + http_timestring(talloc_tos(), ads->config.current_time)); - d_printf("KDC server: %s\n", ads->auth.kdc_server ); - d_printf("Server time offset: %d\n", ads->auth.time_offset ); + d_printf(_("KDC server: %s\n"), ads->auth.kdc_server ); + d_printf(_("Server time offset: %d\n"), ads->auth.time_offset ); + ads_destroy(&ads); return 0; } @@ -217,15 +205,16 @@ static void use_in_memory_ccache(void) { setenv(KRB5_ENV_CCNAME, "MEMORY:net_ads", 1); } -static ADS_STATUS ads_startup_int(bool only_own_domain, uint32 auth_flags, ADS_STRUCT **ads_ret) +static ADS_STATUS ads_startup_int(struct net_context *c, bool only_own_domain, + uint32 auth_flags, ADS_STRUCT **ads_ret) { ADS_STRUCT *ads = NULL; ADS_STATUS status; - bool need_password = False; - bool second_time = False; + bool need_password = false; + bool second_time = false; char *cp; const char *realm = NULL; - bool tried_closest_dc = False; + bool tried_closest_dc = false; /* lp_realm() should be handled by a command line param, However, the join requires that realm be set in smb.conf @@ -238,37 +227,37 @@ retry_connect: if (only_own_domain) { realm = lp_realm(); } else { - realm = assume_own_realm(); + realm = assume_own_realm(c); } - ads = ads_init(realm, opt_target_workgroup, opt_host); + ads = ads_init(realm, c->opt_target_workgroup, c->opt_host); - if (!opt_user_name) { - opt_user_name = "administrator"; + if (!c->opt_user_name) { + c->opt_user_name = "administrator"; } - if (opt_user_specified) { - need_password = True; + if (c->opt_user_specified) { + need_password = true; } retry: - if (!opt_password && need_password && !opt_machine_pass) { - opt_password = net_prompt_pass(opt_user_name); - if (!opt_password) { + if (!c->opt_password && need_password && !c->opt_machine_pass) { + c->opt_password = net_prompt_pass(c, c->opt_user_name); + if (!c->opt_password) { ads_destroy(&ads); return ADS_ERROR(LDAP_NO_MEMORY); } } - if (opt_password) { + if (c->opt_password) { use_in_memory_ccache(); SAFE_FREE(ads->auth.password); - ads->auth.password = smb_xstrdup(opt_password); + ads->auth.password = smb_xstrdup(c->opt_password); } ads->auth.flags |= auth_flags; SAFE_FREE(ads->auth.user_name); - ads->auth.user_name = smb_xstrdup(opt_user_name); + ads->auth.user_name = smb_xstrdup(c->opt_user_name); /* * If the username is of the form "name@realm", @@ -294,8 +283,8 @@ retry: } if (!need_password && !second_time && !(auth_flags & ADS_AUTH_NO_BIND)) { - need_password = True; - second_time = True; + need_password = true; + second_time = true; goto retry; } else { ads_destroy(&ads); @@ -307,11 +296,11 @@ retry: * This is done by reconnecting to ADS because only the first call to * ads_connect will give us our own sitename */ - if ((only_own_domain || !opt_host) && !tried_closest_dc) { + if ((only_own_domain || !c->opt_host) && !tried_closest_dc) { - tried_closest_dc = True; /* avoid loop */ + tried_closest_dc = true; /* avoid loop */ - if (!ads->config.tried_closest_dc) { + if (!ads_closest_dc(ads)) { namecache_delete(ads->server.realm, 0x1C); namecache_delete(ads->server.workgroup, 0x1C); @@ -327,14 +316,14 @@ retry: return status; } -ADS_STATUS ads_startup(bool only_own_domain, ADS_STRUCT **ads) +ADS_STATUS ads_startup(struct net_context *c, bool only_own_domain, ADS_STRUCT **ads) { - return ads_startup_int(only_own_domain, 0, ads); + return ads_startup_int(c, only_own_domain, 0, ads); } -ADS_STATUS ads_startup_nobind(bool only_own_domain, ADS_STRUCT **ads) +ADS_STATUS ads_startup_nobind(struct net_context *c, bool only_own_domain, ADS_STRUCT **ads) { - return ads_startup_int(only_own_domain, ADS_AUTH_NO_BIND, ads); + return ads_startup_int(c, only_own_domain, ADS_AUTH_NO_BIND, ads); } /* @@ -362,42 +351,50 @@ static int net_ads_check_int(const char *realm, const char *workgroup, const cha return 0; } -int net_ads_check_our_domain(void) +int net_ads_check_our_domain(struct net_context *c) { return net_ads_check_int(lp_realm(), lp_workgroup(), NULL); } -int net_ads_check(void) +int net_ads_check(struct net_context *c) { - return net_ads_check_int(NULL, opt_workgroup, opt_host); + return net_ads_check_int(NULL, c->opt_workgroup, c->opt_host); } /* determine the netbios workgroup name for a domain */ -static int net_ads_workgroup(int argc, const char **argv) +static int net_ads_workgroup(struct net_context *c, int argc, const char **argv) { ADS_STRUCT *ads; char addr[INET6_ADDRSTRLEN]; - struct cldap_netlogon_reply reply; + struct NETLOGON_SAM_LOGON_RESPONSE_EX reply; + + if (c->display_usage) { + d_printf(_("Usage:\n" + "net ads workgroup\n" + " Print the workgroup name\n")); + return 0; + } - if (!ADS_ERR_OK(ads_startup_nobind(False, &ads))) { - d_fprintf(stderr, "Didn't find the cldap server!\n"); + if (!ADS_ERR_OK(ads_startup_nobind(c, false, &ads))) { + d_fprintf(stderr, _("Didn't find the cldap server!\n")); return -1; } if (!ads->config.realm) { - ads->config.realm = CONST_DISCARD(char *, opt_target_workgroup); + ads->config.realm = CONST_DISCARD(char *, c->opt_target_workgroup); ads->ldap.port = 389; } print_sockaddr(addr, sizeof(addr), &ads->ldap.ss); - if ( !ads_cldap_netlogon(addr, ads->server.realm, &reply ) ) { - d_fprintf(stderr, "CLDAP query failed!\n"); + if ( !ads_cldap_netlogon_5(talloc_tos(), addr, ads->server.realm, &reply ) ) { + d_fprintf(stderr, _("CLDAP query failed!\n")); + ads_destroy(&ads); return -1; } - d_printf("Workgroup: %s\n", reply.netbios_domain); + d_printf(_("Workgroup: %s\n"), reply.domain); ads_destroy(&ads); @@ -422,24 +419,24 @@ static bool usergrp_display(ADS_STRUCT *ads, char *field, void **values, void *d } SAFE_FREE(disp_fields[0]); SAFE_FREE(disp_fields[1]); - return True; + return true; } if (!values) /* must be new field, indicate string field */ - return True; + return true; if (StrCaseCmp(field, "sAMAccountName") == 0) { disp_fields[0] = SMB_STRDUP((char *) values[0]); } if (StrCaseCmp(field, "description") == 0) disp_fields[1] = SMB_STRDUP((char *) values[0]); - return True; + return true; } -static int net_ads_user_usage(int argc, const char **argv) +static int net_ads_user_usage(struct net_context *c, int argc, const char **argv) { - return net_help_user(argc, argv); + return net_user_usage(c, argc, argv); } -static int ads_user_add(int argc, const char **argv) +static int ads_user_add(struct net_context *c, int argc, const char **argv) { ADS_STRUCT *ads; ADS_STATUS status; @@ -448,65 +445,70 @@ static int ads_user_add(int argc, const char **argv) int rc = -1; char *ou_str = NULL; - if (argc < 1) return net_ads_user_usage(argc, argv); + if (argc < 1 || c->display_usage) + return net_ads_user_usage(c, argc, argv); - if (!ADS_ERR_OK(ads_startup(False, &ads))) { + if (!ADS_ERR_OK(ads_startup(c, false, &ads))) { return -1; } status = ads_find_user_acct(ads, &res, argv[0]); if (!ADS_ERR_OK(status)) { - d_fprintf(stderr, "ads_user_add: %s\n", ads_errstr(status)); + d_fprintf(stderr, _("ads_user_add: %s\n"), ads_errstr(status)); goto done; } if (ads_count_replies(ads, res)) { - d_fprintf(stderr, "ads_user_add: User %s already exists\n", argv[0]); + d_fprintf(stderr, _("ads_user_add: User %s already exists\n"), + argv[0]); goto done; } - if (opt_container) { - ou_str = SMB_STRDUP(opt_container); + if (c->opt_container) { + ou_str = SMB_STRDUP(c->opt_container); } else { ou_str = ads_default_ou_string(ads, WELL_KNOWN_GUID_USERS); } - status = ads_add_user_acct(ads, argv[0], ou_str, opt_comment); + status = ads_add_user_acct(ads, argv[0], ou_str, c->opt_comment); if (!ADS_ERR_OK(status)) { - d_fprintf(stderr, "Could not add user %s: %s\n", argv[0], + d_fprintf(stderr, _("Could not add user %s: %s\n"), argv[0], ads_errstr(status)); goto done; } /* if no password is to be set, we're done */ if (argc == 1) { - d_printf("User %s added\n", argv[0]); + d_printf(_("User %s added\n"), argv[0]); rc = 0; goto done; } /* try setting the password */ - asprintf(&upn, "%s@%s", argv[0], ads->config.realm); + if (asprintf(&upn, "%s@%s", argv[0], ads->config.realm) == -1) { + goto done; + } status = ads_krb5_set_password(ads->auth.kdc_server, upn, argv[1], ads->auth.time_offset); - safe_free(upn); + SAFE_FREE(upn); if (ADS_ERR_OK(status)) { - d_printf("User %s added\n", argv[0]); + d_printf(_("User %s added\n"), argv[0]); rc = 0; goto done; } /* password didn't set, delete account */ - d_fprintf(stderr, "Could not add user %s. Error setting password %s\n", + d_fprintf(stderr, _("Could not add user %s. " + "Error setting password %s\n"), argv[0], ads_errstr(status)); ads_msgfree(ads, res); status=ads_find_user_acct(ads, &res, argv[0]); if (ADS_ERR_OK(status)) { - userdn = ads_get_dn(ads, res); + userdn = ads_get_dn(ads, talloc_tos(), res); ads_del_dn(ads, userdn); - ads_memfree(ads, userdn); + TALLOC_FREE(userdn); } done: @@ -517,43 +519,88 @@ static int ads_user_add(int argc, const char **argv) return rc; } -static int ads_user_info(int argc, const char **argv) +static int ads_user_info(struct net_context *c, int argc, const char **argv) { - ADS_STRUCT *ads; + ADS_STRUCT *ads = NULL; ADS_STATUS rc; - LDAPMessage *res; - const char *attrs[] = {"memberOf", NULL}; + LDAPMessage *res = NULL; + TALLOC_CTX *frame; + int ret = 0; + wbcErr wbc_status; + const char *attrs[] = {"memberOf", "primaryGroupID", NULL}; char *searchstring=NULL; char **grouplist; + char *primary_group; char *escaped_user; + DOM_SID primary_group_sid; + uint32_t group_rid; + enum SID_NAME_USE type; - if (argc < 1) { - return net_ads_user_usage(argc, argv); + if (argc < 1 || c->display_usage) { + return net_ads_user_usage(c, argc, argv); } - escaped_user = escape_ldap_string_alloc(argv[0]); + frame = talloc_new(talloc_tos()); + if (frame == NULL) { + return -1; + } + escaped_user = escape_ldap_string(frame, argv[0]); if (!escaped_user) { - d_fprintf(stderr, "ads_user_info: failed to escape user %s\n", argv[0]); + d_fprintf(stderr, + _("ads_user_info: failed to escape user %s\n"), + argv[0]); return -1; } - if (!ADS_ERR_OK(ads_startup(False, &ads))) { - SAFE_FREE(escaped_user); - return -1; + if (!ADS_ERR_OK(ads_startup(c, false, &ads))) { + ret = -1; + goto error; } - asprintf(&searchstring, "(sAMAccountName=%s)", escaped_user); + if (asprintf(&searchstring, "(sAMAccountName=%s)", escaped_user) == -1) { + ret =-1; + goto error; + } rc = ads_search(ads, &res, searchstring, attrs); - safe_free(searchstring); + SAFE_FREE(searchstring); if (!ADS_ERR_OK(rc)) { - d_fprintf(stderr, "ads_search: %s\n", ads_errstr(rc)); - ads_destroy(&ads); - SAFE_FREE(escaped_user); - return -1; + d_fprintf(stderr, _("ads_search: %s\n"), ads_errstr(rc)); + ret = -1; + goto error; + } + + if (!ads_pull_uint32(ads, res, "primaryGroupID", &group_rid)) { + d_fprintf(stderr, _("ads_pull_uint32 failed\n")); + ret = -1; + goto error; } + rc = ads_domain_sid(ads, &primary_group_sid); + if (!ADS_ERR_OK(rc)) { + d_fprintf(stderr, _("ads_domain_sid: %s\n"), ads_errstr(rc)); + ret = -1; + goto error; + } + + sid_append_rid(&primary_group_sid, group_rid); + + wbc_status = wbcLookupSid((struct wbcDomainSid *)&primary_group_sid, + NULL, /* don't look up domain */ + &primary_group, + (enum wbcSidType *) &type); + if (!WBC_ERROR_IS_OK(wbc_status)) { + d_fprintf(stderr, "wbcLookupSid: %s\n", + wbcErrorString(wbc_status)); + ret = -1; + goto error; + } + + d_printf("%s\n", primary_group); + + wbcFreeMemory(primary_group); + grouplist = ldap_get_values((LDAP *)ads->ldap.ld, (LDAPMessage *)res, "memberOf"); @@ -568,13 +615,14 @@ static int ads_user_info(int argc, const char **argv) ldap_value_free(grouplist); } - ads_msgfree(ads, res); - ads_destroy(&ads); - SAFE_FREE(escaped_user); - return 0; +error: + if (res) ads_msgfree(ads, res); + if (ads) ads_destroy(&ads); + TALLOC_FREE(frame); + return ret; } -static int ads_user_delete(int argc, const char **argv) +static int ads_user_delete(struct net_context *c, int argc, const char **argv) { ADS_STRUCT *ads; ADS_STATUS rc; @@ -582,42 +630,63 @@ static int ads_user_delete(int argc, const char **argv) char *userdn; if (argc < 1) { - return net_ads_user_usage(argc, argv); + return net_ads_user_usage(c, argc, argv); } - if (!ADS_ERR_OK(ads_startup(False, &ads))) { + if (!ADS_ERR_OK(ads_startup(c, false, &ads))) { return -1; } rc = ads_find_user_acct(ads, &res, argv[0]); if (!ADS_ERR_OK(rc) || ads_count_replies(ads, res) != 1) { - d_printf("User %s does not exist.\n", argv[0]); + d_printf(_("User %s does not exist.\n"), argv[0]); ads_msgfree(ads, res); ads_destroy(&ads); return -1; } - userdn = ads_get_dn(ads, res); + userdn = ads_get_dn(ads, talloc_tos(), res); ads_msgfree(ads, res); rc = ads_del_dn(ads, userdn); - ads_memfree(ads, userdn); + TALLOC_FREE(userdn); if (ADS_ERR_OK(rc)) { - d_printf("User %s deleted\n", argv[0]); + d_printf(_("User %s deleted\n"), argv[0]); ads_destroy(&ads); return 0; } - d_fprintf(stderr, "Error deleting user %s: %s\n", argv[0], + d_fprintf(stderr, _("Error deleting user %s: %s\n"), argv[0], ads_errstr(rc)); ads_destroy(&ads); return -1; } -int net_ads_user(int argc, const char **argv) +int net_ads_user(struct net_context *c, int argc, const char **argv) { struct functable func[] = { - {"ADD", ads_user_add}, - {"INFO", ads_user_info}, - {"DELETE", ads_user_delete}, - {NULL, NULL} + { + "add", + ads_user_add, + NET_TRANSPORT_ADS, + N_("Add an AD user"), + N_("net ads user add\n" + " Add an AD user") + }, + { + "info", + ads_user_info, + NET_TRANSPORT_ADS, + N_("Display information about an AD user"), + N_("net ads user info\n" + " Display information about an AD user") + }, + { + "delete", + ads_user_delete, + NET_TRANSPORT_ADS, + N_("Delete an AD user"), + N_("net ads user delete\n" + " Delete an AD user") + }, + {NULL, NULL, 0, NULL, NULL} }; ADS_STRUCT *ads; ADS_STATUS rc; @@ -626,33 +695,41 @@ int net_ads_user(int argc, const char **argv) char *disp_fields[2] = {NULL, NULL}; if (argc == 0) { - if (!ADS_ERR_OK(ads_startup(False, &ads))) { + if (c->display_usage) { + d_printf(_("Usage:\n" + "net ads user\n" + " List AD users\n")); + net_display_usage_from_functable(func); + return 0; + } + + if (!ADS_ERR_OK(ads_startup(c, false, &ads))) { return -1; } - if (opt_long_list_entries) - d_printf("\nUser name Comment"\ - "\n-----------------------------\n"); + if (c->opt_long_list_entries) + d_printf(_("\nUser name Comment" + "\n-----------------------------\n")); rc = ads_do_search_all_fn(ads, ads->config.bind_path, LDAP_SCOPE_SUBTREE, "(objectCategory=user)", - opt_long_list_entries ? longattrs : + c->opt_long_list_entries ? longattrs : shortattrs, usergrp_display, disp_fields); ads_destroy(&ads); return ADS_ERR_OK(rc) ? 0 : -1; } - return net_run_function(argc, argv, func, net_ads_user_usage); + return net_run_function(c, argc, argv, "net ads user", func); } -static int net_ads_group_usage(int argc, const char **argv) +static int net_ads_group_usage(struct net_context *c, int argc, const char **argv) { - return net_help_group(argc, argv); + return net_group_usage(c, argc, argv); } -static int ads_group_add(int argc, const char **argv) +static int ads_group_add(struct net_context *c, int argc, const char **argv) { ADS_STRUCT *ads; ADS_STATUS status; @@ -660,39 +737,39 @@ static int ads_group_add(int argc, const char **argv) int rc = -1; char *ou_str = NULL; - if (argc < 1) { - return net_ads_group_usage(argc, argv); + if (argc < 1 || c->display_usage) { + return net_ads_group_usage(c, argc, argv); } - if (!ADS_ERR_OK(ads_startup(False, &ads))) { + if (!ADS_ERR_OK(ads_startup(c, false, &ads))) { return -1; } status = ads_find_user_acct(ads, &res, argv[0]); if (!ADS_ERR_OK(status)) { - d_fprintf(stderr, "ads_group_add: %s\n", ads_errstr(status)); + d_fprintf(stderr, _("ads_group_add: %s\n"), ads_errstr(status)); goto done; } if (ads_count_replies(ads, res)) { - d_fprintf(stderr, "ads_group_add: Group %s already exists\n", argv[0]); + d_fprintf(stderr, _("ads_group_add: Group %s already exists\n"), argv[0]); goto done; } - if (opt_container) { - ou_str = SMB_STRDUP(opt_container); + if (c->opt_container) { + ou_str = SMB_STRDUP(c->opt_container); } else { ou_str = ads_default_ou_string(ads, WELL_KNOWN_GUID_USERS); } - status = ads_add_group_acct(ads, argv[0], ou_str, opt_comment); + status = ads_add_group_acct(ads, argv[0], ou_str, c->opt_comment); if (ADS_ERR_OK(status)) { - d_printf("Group %s added\n", argv[0]); + d_printf(_("Group %s added\n"), argv[0]); rc = 0; } else { - d_fprintf(stderr, "Could not add group %s: %s\n", argv[0], + d_fprintf(stderr, _("Could not add group %s: %s\n"), argv[0], ads_errstr(status)); } @@ -704,49 +781,63 @@ static int ads_group_add(int argc, const char **argv) return rc; } -static int ads_group_delete(int argc, const char **argv) +static int ads_group_delete(struct net_context *c, int argc, const char **argv) { ADS_STRUCT *ads; ADS_STATUS rc; LDAPMessage *res = NULL; char *groupdn; - if (argc < 1) { - return net_ads_group_usage(argc, argv); + if (argc < 1 || c->display_usage) { + return net_ads_group_usage(c, argc, argv); } - if (!ADS_ERR_OK(ads_startup(False, &ads))) { + if (!ADS_ERR_OK(ads_startup(c, false, &ads))) { return -1; } rc = ads_find_user_acct(ads, &res, argv[0]); if (!ADS_ERR_OK(rc) || ads_count_replies(ads, res) != 1) { - d_printf("Group %s does not exist.\n", argv[0]); + d_printf(_("Group %s does not exist.\n"), argv[0]); ads_msgfree(ads, res); ads_destroy(&ads); return -1; } - groupdn = ads_get_dn(ads, res); + groupdn = ads_get_dn(ads, talloc_tos(), res); ads_msgfree(ads, res); rc = ads_del_dn(ads, groupdn); - ads_memfree(ads, groupdn); + TALLOC_FREE(groupdn); if (ADS_ERR_OK(rc)) { - d_printf("Group %s deleted\n", argv[0]); + d_printf(_("Group %s deleted\n"), argv[0]); ads_destroy(&ads); return 0; } - d_fprintf(stderr, "Error deleting group %s: %s\n", argv[0], + d_fprintf(stderr, _("Error deleting group %s: %s\n"), argv[0], ads_errstr(rc)); ads_destroy(&ads); return -1; } -int net_ads_group(int argc, const char **argv) +int net_ads_group(struct net_context *c, int argc, const char **argv) { struct functable func[] = { - {"ADD", ads_group_add}, - {"DELETE", ads_group_delete}, - {NULL, NULL} + { + "add", + ads_group_add, + NET_TRANSPORT_ADS, + N_("Add an AD group"), + N_("net ads group add\n" + " Add an AD group") + }, + { + "delete", + ads_group_delete, + NET_TRANSPORT_ADS, + N_("Delete an AD group"), + N_("net ads group delete\n" + " Delete an AD group") + }, + {NULL, NULL, 0, NULL, NULL} }; ADS_STRUCT *ads; ADS_STATUS rc; @@ -755,45 +846,60 @@ int net_ads_group(int argc, const char **argv) char *disp_fields[2] = {NULL, NULL}; if (argc == 0) { - if (!ADS_ERR_OK(ads_startup(False, &ads))) { + if (c->display_usage) { + d_printf(_("Usage:\n" + "net ads group\n" + " List AD groups\n")); + net_display_usage_from_functable(func); + return 0; + } + + if (!ADS_ERR_OK(ads_startup(c, false, &ads))) { return -1; } - if (opt_long_list_entries) - d_printf("\nGroup name Comment"\ - "\n-----------------------------\n"); + if (c->opt_long_list_entries) + d_printf(_("\nGroup name Comment" + "\n-----------------------------\n")); rc = ads_do_search_all_fn(ads, ads->config.bind_path, LDAP_SCOPE_SUBTREE, "(objectCategory=group)", - opt_long_list_entries ? longattrs : + c->opt_long_list_entries ? longattrs : shortattrs, usergrp_display, disp_fields); ads_destroy(&ads); return ADS_ERR_OK(rc) ? 0 : -1; } - return net_run_function(argc, argv, func, net_ads_group_usage); + return net_run_function(c, argc, argv, "net ads group", func); } -static int net_ads_status(int argc, const char **argv) +static int net_ads_status(struct net_context *c, int argc, const char **argv) { ADS_STRUCT *ads; ADS_STATUS rc; LDAPMessage *res; - if (!ADS_ERR_OK(ads_startup(True, &ads))) { + if (c->display_usage) { + d_printf(_("Usage:\n" + "net ads status\n" + " Display machine account details\n")); + return 0; + } + + if (!ADS_ERR_OK(ads_startup(c, true, &ads))) { return -1; } rc = ads_find_machine_acct(ads, &res, global_myname()); if (!ADS_ERR_OK(rc)) { - d_fprintf(stderr, "ads_find_machine_acct: %s\n", ads_errstr(rc)); + d_fprintf(stderr, _("ads_find_machine_acct: %s\n"), ads_errstr(rc)); ads_destroy(&ads); return -1; } if (ads_count_replies(ads, res) == 0) { - d_fprintf(stderr, "No machine account for '%s' found\n", global_myname()); + d_fprintf(stderr, _("No machine account for '%s' found\n"), global_myname()); ads_destroy(&ads); return -1; } @@ -810,56 +916,79 @@ static int net_ads_status(int argc, const char **argv) with full control to the computer object's ACL. *******************************************************************/ -static int net_ads_leave(int argc, const char **argv) +static int net_ads_leave(struct net_context *c, int argc, const char **argv) { TALLOC_CTX *ctx; struct libnet_UnjoinCtx *r = NULL; WERROR werr; + if (c->display_usage) { + d_printf(_("Usage:\n" + "net ads leave\n" + " Leave an AD domain\n")); + return 0; + } + + if (!*lp_realm()) { + d_fprintf(stderr, _("No realm set, are we joined ?\n")); + return -1; + } + if (!(ctx = talloc_init("net_ads_leave"))) { - d_fprintf(stderr, "Could not initialise talloc context.\n"); + d_fprintf(stderr, _("Could not initialise talloc context.\n")); return -1; } - use_in_memory_ccache(); + if (!c->opt_kerberos) { + use_in_memory_ccache(); + } werr = libnet_init_UnjoinCtx(ctx, &r); if (!W_ERROR_IS_OK(werr)) { - d_fprintf(stderr, "Could not initialise unjoin context.\n"); + d_fprintf(stderr, _("Could not initialise unjoin context.\n")); return -1; } - r->in.debug = opt_verbose; - r->in.dc_name = opt_host; + r->in.debug = true; + r->in.use_kerberos = c->opt_kerberos; + r->in.dc_name = c->opt_host; r->in.domain_name = lp_realm(); - r->in.admin_account = opt_user_name; - r->in.admin_password = net_prompt_pass(opt_user_name); + r->in.admin_account = c->opt_user_name; + r->in.admin_password = net_prompt_pass(c, c->opt_user_name); + r->in.modify_config = lp_config_backend_is_registry(); + + /* Try to delete it, but if that fails, disable it. The + WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE really means "disable */ r->in.unjoin_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE | WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE; + r->in.delete_machine_account = true; werr = libnet_Unjoin(ctx, r); if (!W_ERROR_IS_OK(werr)) { - d_printf("Failed to leave domain: %s\n", + d_printf(_("Failed to leave domain: %s\n"), r->out.error_string ? r->out.error_string : get_friendly_werror_msg(werr)); goto done; } - if (W_ERROR_IS_OK(werr)) { - d_printf("Deleted account for '%s' in realm '%s'\n", + if (r->out.deleted_machine_account) { + d_printf(_("Deleted account for '%s' in realm '%s'\n"), r->in.machine_name, r->out.dns_domain_name); goto done; } /* We couldn't delete it - see if the disable succeeded. */ if (r->out.disabled_machine_account) { - d_printf("Disabled account for '%s' in realm '%s'\n", + d_printf(_("Disabled account for '%s' in realm '%s'\n"), r->in.machine_name, r->out.dns_domain_name); werr = WERR_OK; goto done; } - d_fprintf(stderr, "Failed to disable machine account for '%s' in realm '%s'\n", + /* Based on what we requseted, we shouldn't get here, but if + we did, it means the secrets were removed, and therefore + we have left the domain */ + d_fprintf(stderr, _("Machine '%s' Left domain '%s'\n"), r->in.machine_name, r->out.dns_domain_name); done: @@ -873,7 +1002,7 @@ static int net_ads_leave(int argc, const char **argv) return -1; } -static NTSTATUS net_ads_join_ok(void) +static NTSTATUS net_ads_join_ok(struct net_context *c) { ADS_STRUCT *ads = NULL; ADS_STATUS status; @@ -883,9 +1012,9 @@ static NTSTATUS net_ads_join_ok(void) return NT_STATUS_ACCESS_DENIED; } - net_use_krb_machine_account(); + net_use_krb_machine_account(c); - status = ads_startup(True, &ads); + status = ads_startup(c, true, &ads); if (!ADS_ERR_OK(status)) { return ads_ntstatus(status); } @@ -897,20 +1026,27 @@ static NTSTATUS net_ads_join_ok(void) /* check that an existing join is OK */ -int net_ads_testjoin(int argc, const char **argv) +int net_ads_testjoin(struct net_context *c, int argc, const char **argv) { NTSTATUS status; use_in_memory_ccache(); + if (c->display_usage) { + d_printf(_("Usage:\n" + "net ads testjoin\n" + " Test if the existing join is ok\n")); + return 0; + } + /* Display success or failure */ - status = net_ads_join_ok(); + status = net_ads_join_ok(c); if (!NT_STATUS_IS_OK(status)) { - fprintf(stderr,"Join to domain is not valid: %s\n", + fprintf(stderr, _("Join to domain is not valid: %s\n"), get_friendly_nt_error_msg(status)); return -1; } - printf("Join is OK\n"); + printf(_("Join is OK\n")); return 0; } @@ -918,33 +1054,27 @@ int net_ads_testjoin(int argc, const char **argv) Simple configu checks before beginning the join ********************************************************************/ -static NTSTATUS check_ads_config( void ) +static WERROR check_ads_config( void ) { if (lp_server_role() != ROLE_DOMAIN_MEMBER ) { - d_printf("Host is not configured as a member server.\n"); - return NT_STATUS_INVALID_DOMAIN_ROLE; + d_printf(_("Host is not configured as a member server.\n")); + return WERR_INVALID_DOMAIN_ROLE; } if (strlen(global_myname()) > 15) { - d_printf("Our netbios name can be at most 15 chars long, " - "\"%s\" is %u chars long\n", global_myname(), + d_printf(_("Our netbios name can be at most 15 chars long, " + "\"%s\" is %u chars long\n"), global_myname(), (unsigned int)strlen(global_myname())); - return NT_STATUS_NAME_TOO_LONG; + return WERR_INVALID_COMPUTERNAME; } if ( lp_security() == SEC_ADS && !*lp_realm()) { - d_fprintf(stderr, "realm must be set in in %s for ADS " - "join to succeed.\n", get_dyn_CONFIGFILE()); - return NT_STATUS_INVALID_PARAMETER; - } - - if (!secrets_init()) { - DEBUG(1,("Failed to initialise secrets database\n")); - /* This is a good bet for failure of secrets_init ... */ - return NT_STATUS_ACCESS_DENIED; + d_fprintf(stderr, _("realm must be set in in %s for ADS " + "join to succeed.\n"), get_dyn_CONFIGFILE()); + return WERR_INVALID_PARAM; } - return NT_STATUS_OK; + return WERR_OK; } /******************************************************************* @@ -972,8 +1102,8 @@ static NTSTATUS net_update_dns_internal(TALLOC_CTX *ctx, ADS_STRUCT *ads, 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; } @@ -1077,22 +1207,22 @@ static NTSTATUS net_update_dns(TALLOC_CTX *mem_ctx, ADS_STRUCT *ads) /******************************************************************* ********************************************************************/ -static int net_ads_join_usage(int argc, const char **argv) -{ - d_printf("net ads join [options]\n"); - d_printf("Valid options:\n"); - d_printf(" createupn[=UPN] Set the userPrincipalName attribute during the join.\n"); - d_printf(" The deault UPN is in the form host/netbiosname@REALM.\n"); - 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"); +static int net_ads_join_usage(struct net_context *c, int argc, const char **argv) +{ + d_printf(_("net ads join [options]\n" + "Valid options:\n")); + d_printf(_(" createupn[=UPN] Set the userPrincipalName attribute during the join.\n" + " The deault UPN is in the form host/netbiosname@REALM.\n")); + d_printf(_(" createcomputer=OU Precreate the computer account in a specific OU.\n" + " The OU string read from top to bottom without RDNs and delimited by a '/'.\n" + " E.g. \"createcomputer=Computers/Servers/Unix\"\n" + " NB: A backslash '\\' is used as escape at multiple levels and may\n" + " 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" + " NB: osName and osVer must be specified together for either to take effect.\n" + " Also, the operatingSystemService attribute is also set when along with\n" + " the two other attributes.\n")); return -1; } @@ -1100,64 +1230,71 @@ static int net_ads_join_usage(int argc, const char **argv) /******************************************************************* ********************************************************************/ -int net_ads_join(int argc, const char **argv) +int net_ads_join(struct net_context *c, int argc, const char **argv) { - NTSTATUS nt_status; TALLOC_CTX *ctx = NULL; struct libnet_JoinCtx *r = NULL; const char *domain = lp_realm(); WERROR werr = WERR_SETUP_NOT_JOINED; - bool createupn = False; + bool createupn = false; const char *machineupn = NULL; const char *create_in_ou = NULL; int i; const char *os_name = NULL; const char *os_version = NULL; + bool modify_config = lp_config_backend_is_registry(); - nt_status = check_ads_config(); - if (!NT_STATUS_IS_OK(nt_status)) { - d_fprintf(stderr, "Invalid configuration. Exiting....\n"); - werr = ntstatus_to_werror(nt_status); - goto fail; - } + if (c->display_usage) + return net_ads_join_usage(c, argc, argv); - use_in_memory_ccache(); + if (!modify_config) { - werr = libnet_init_JoinCtx(ctx, &r); - if (!W_ERROR_IS_OK(werr)) { - goto fail; + werr = check_ads_config(); + if (!W_ERROR_IS_OK(werr)) { + d_fprintf(stderr, _("Invalid configuration. Exiting....\n")); + goto fail; + } } if (!(ctx = talloc_init("net_ads_join"))) { - d_fprintf(stderr, "Could not initialise talloc context.\n"); + d_fprintf(stderr, _("Could not initialise talloc context.\n")); werr = WERR_NOMEM; goto fail; } + if (!c->opt_kerberos) { + use_in_memory_ccache(); + } + + werr = libnet_init_JoinCtx(ctx, &r); + if (!W_ERROR_IS_OK(werr)) { + goto fail; + } + /* process additional command line args */ for ( i=0; iin.domain_name = domain; @@ -1175,10 +1318,12 @@ int net_ads_join(int argc, const char **argv) r->in.account_ou = create_in_ou; r->in.os_name = os_name; r->in.os_version = os_version; - r->in.dc_name = opt_host; - r->in.admin_account = opt_user_name; - r->in.admin_password = net_prompt_pass(opt_user_name); - r->in.debug = opt_verbose; + r->in.dc_name = c->opt_host; + r->in.admin_account = c->opt_user_name; + r->in.admin_password = net_prompt_pass(c, c->opt_user_name); + r->in.debug = true; + r->in.use_kerberos = c->opt_kerberos; + r->in.modify_config = modify_config; r->in.join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE | WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE | WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED; @@ -1190,21 +1335,27 @@ int net_ads_join(int argc, const char **argv) /* Check the short name of the domain */ - if (!strequal(lp_workgroup(), r->out.netbios_domain_name)) { - d_printf("The workgroup in %s does not match the short\n", get_dyn_CONFIGFILE()); - d_printf("domain name obtained from the server.\n"); - d_printf("Using the name [%s] from the server.\n", r->out.netbios_domain_name); - d_printf("You should set \"workgroup = %s\" in %s.\n", + if (!modify_config && !strequal(lp_workgroup(), r->out.netbios_domain_name)) { + d_printf(_("The workgroup in %s does not match the short\n" + "domain name obtained from the server.\n" + "Using the name [%s] from the server.\n" + "You should set \"workgroup = %s\" in %s.\n"), + get_dyn_CONFIGFILE(), r->out.netbios_domain_name, r->out.netbios_domain_name, get_dyn_CONFIGFILE()); } - d_printf("Using short domain name -- %s\n", r->out.netbios_domain_name); + d_printf(_("Using short domain name -- %s\n"), r->out.netbios_domain_name); - d_printf("Joined '%s' to realm '%s'\n", r->in.machine_name, - r->out.dns_domain_name); + if (r->out.dns_domain_name) { + d_printf(_("Joined '%s' to realm '%s'\n"), r->in.machine_name, + r->out.dns_domain_name); + } else { + d_printf(_("Joined '%s' to domain '%s'\n"), r->in.machine_name, + r->out.netbios_domain_name); + } #if defined(WITH_DNS_UPDATES) - { + if (r->out.domain_is_ad) { /* We enter this block with user creds */ ADS_STRUCT *ads_dns = NULL; @@ -1212,15 +1363,18 @@ int net_ads_join(int argc, const char **argv) /* kinit with the machine password */ use_in_memory_ccache(); - asprintf( &ads_dns->auth.user_name, "%s$", global_myname() ); + if (asprintf( &ads_dns->auth.user_name, "%s$", global_myname()) == -1) { + goto fail; + } ads_dns->auth.password = secrets_fetch_machine_password( - lp_workgroup(), NULL, NULL ); - ads_dns->auth.realm = SMB_STRDUP( lp_realm() ); + r->out.netbios_domain_name, NULL, NULL ); + ads_dns->auth.realm = SMB_STRDUP( r->out.dns_domain_name ); + strupper_m(ads_dns->auth.realm ); ads_kinit_password( ads_dns ); } if ( !ads_dns || !NT_STATUS_IS_OK(net_update_dns( ctx, ads_dns )) ) { - d_fprintf( stderr, "DNS update failed!\n" ); + d_fprintf( stderr, _("DNS update failed!\n") ); } /* exit from this block using machine creds */ @@ -1234,7 +1388,7 @@ 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", + d_printf(_("Failed to join domain: %s\n"), r && r->out.error_string ? r->out.error_string : get_friendly_werror_msg(werr)); TALLOC_FREE( ctx ); @@ -1245,24 +1399,7 @@ fail: /******************************************************************* ********************************************************************/ -static int net_ads_dns_usage(int argc, const char **argv) -{ -#if defined(WITH_DNS_UPDATES) - d_printf("net ads dns \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_register(int argc, const char **argv) +static int net_ads_dns_register(struct net_context *c, int argc, const char **argv) { #if defined(WITH_DNS_UPDATES) ADS_STRUCT *ads; @@ -1273,17 +1410,19 @@ static int net_ads_dns_register(int argc, const char **argv) talloc_enable_leak_report(); #endif - if (argc > 0) { - d_fprintf(stderr, "net ads dns register\n"); + if (argc > 0 || c->display_usage) { + d_printf(_("Usage:\n" + "net ads dns register\n" + " Register hostname with DNS\n")); return -1; } if (!(ctx = talloc_init("net_ads_dns"))) { - d_fprintf(stderr, "Could not initialise talloc context\n"); + d_fprintf(stderr, _("Could not initialise talloc context\n")); return -1; } - status = ads_startup(True, &ads); + status = ads_startup(c, true, &ads); if ( !ADS_ERR_OK(status) ) { DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status))); TALLOC_FREE(ctx); @@ -1291,20 +1430,21 @@ static int net_ads_dns_register(int argc, const char **argv) } if ( !NT_STATUS_IS_OK(net_update_dns(ctx, ads)) ) { - d_fprintf( stderr, "DNS update failed!\n" ); + d_fprintf( stderr, _("DNS update failed!\n") ); ads_destroy( &ads ); TALLOC_FREE( ctx ); return -1; } - d_fprintf( stderr, "Successfully registered hostname with DNS\n" ); + 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"); + d_fprintf(stderr, + _("DNS update support not enabled at compile time!\n")); return -1; #endif } @@ -1313,7 +1453,7 @@ static int net_ads_dns_register(int argc, const char **argv) DNS_ERROR do_gethostbyname(const char *server, const char *host); #endif -static int net_ads_dns_gethostbyname(int argc, const char **argv) +static int net_ads_dns_gethostbyname(struct net_context *c, int argc, const char **argv) { #if defined(WITH_DNS_UPDATES) DNS_ERROR err; @@ -1322,36 +1462,53 @@ static int net_ads_dns_gethostbyname(int argc, const char **argv) talloc_enable_leak_report(); #endif - if (argc != 2) { - d_fprintf(stderr, "net ads dns gethostbyname " - "\n"); + if (argc != 2 || c->display_usage) { + d_printf(_("Usage:\n" + "net ads dns gethostbyname \n" + " Look up hostname from the AD\n" + " server\tName server to use\n" + " name\tName to look up\n")); return -1; } err = do_gethostbyname(argv[0], argv[1]); - d_printf("do_gethostbyname returned %d\n", ERROR_DNS_V(err)); + d_printf(_("do_gethostbyname returned %d\n"), ERROR_DNS_V(err)); #endif return 0; } -static int net_ads_dns(int argc, const char *argv[]) +static int net_ads_dns(struct net_context *c, int argc, const char *argv[]) { struct functable func[] = { - {"REGISTER", net_ads_dns_register}, - {"GETHOSTBYNAME", net_ads_dns_gethostbyname}, - {NULL, NULL} + { + "register", + net_ads_dns_register, + NET_TRANSPORT_ADS, + N_("Add host dns entry to AD"), + N_("net ads dns register\n" + " Add host dns entry to AD") + }, + { + "gethostbyname", + net_ads_dns_gethostbyname, + NET_TRANSPORT_ADS, + N_("Look up host"), + N_("net ads dns gethostbyname\n" + " Look up host") + }, + {NULL, NULL, 0, NULL, NULL} }; - return net_run_function(argc, argv, func, net_ads_dns_usage); + return net_run_function(c, argc, argv, "net ads dns", func); } /******************************************************************* ********************************************************************/ -int net_ads_printer_usage(int argc, const char **argv) +int net_ads_printer_usage(struct net_context *c, int argc, const char **argv) { - d_printf( + d_printf(_( "\nnet ads printer search " "\n\tsearch for a printer in the directory\n" "\nnet ads printer info " @@ -1362,34 +1519,41 @@ int net_ads_printer_usage(int argc, const char **argv) "\n\t(note: printer name is required)\n" "\nnet ads printer remove " "\n\tremove printer from directory" -"\n\t(note: printer name is required)\n"); +"\n\t(note: printer name is required)\n")); return -1; } /******************************************************************* ********************************************************************/ -static int net_ads_printer_search(int argc, const char **argv) +static int net_ads_printer_search(struct net_context *c, int argc, const char **argv) { ADS_STRUCT *ads; ADS_STATUS rc; LDAPMessage *res = NULL; - if (!ADS_ERR_OK(ads_startup(False, &ads))) { + if (c->display_usage) { + d_printf(_("Usage:\n" + "net ads printer search\n" + " List printers in the AD\n")); + return 0; + } + + if (!ADS_ERR_OK(ads_startup(c, false, &ads))) { return -1; } rc = ads_find_printers(ads, &res); if (!ADS_ERR_OK(rc)) { - d_fprintf(stderr, "ads_find_printer: %s\n", ads_errstr(rc)); + d_fprintf(stderr, _("ads_find_printer: %s\n"), ads_errstr(rc)); ads_msgfree(ads, res); ads_destroy(&ads); return -1; } if (ads_count_replies(ads, res) == 0) { - d_fprintf(stderr, "No results found\n"); + d_fprintf(stderr, _("No results found\n")); ads_msgfree(ads, res); ads_destroy(&ads); return -1; @@ -1401,14 +1565,23 @@ static int net_ads_printer_search(int argc, const char **argv) return 0; } -static int net_ads_printer_info(int argc, const char **argv) +static int net_ads_printer_info(struct net_context *c, int argc, const char **argv) { ADS_STRUCT *ads; ADS_STATUS rc; const char *servername, *printername; LDAPMessage *res = NULL; - if (!ADS_ERR_OK(ads_startup(False, &ads))) { + if (c->display_usage) { + d_printf(_("Usage:\n" + "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")); + return 0; + } + + if (!ADS_ERR_OK(ads_startup(c, false, &ads))) { return -1; } @@ -1427,7 +1600,7 @@ static int net_ads_printer_info(int argc, const char **argv) rc = ads_find_printer_on_server(ads, &res, printername, servername); if (!ADS_ERR_OK(rc)) { - d_fprintf(stderr, "Server '%s' not found: %s\n", + d_fprintf(stderr, _("Server '%s' not found: %s\n"), servername, ads_errstr(rc)); ads_msgfree(ads, res); ads_destroy(&ads); @@ -1435,7 +1608,7 @@ static int net_ads_printer_info(int argc, const char **argv) } if (ads_count_replies(ads, res) == 0) { - d_fprintf(stderr, "Printer '%s' not found\n", printername); + d_fprintf(stderr, _("Printer '%s' not found\n"), printername); ads_msgfree(ads, res); ads_destroy(&ads); return -1; @@ -1448,13 +1621,13 @@ static int net_ads_printer_info(int argc, const char **argv) return 0; } -static int net_ads_printer_publish(int argc, const char **argv) +static int net_ads_printer_publish(struct net_context *c, int argc, const char **argv) { ADS_STRUCT *ads; ADS_STATUS rc; const char *servername, *printername; - struct cli_state *cli; - struct rpc_pipe_client *pipe_hnd; + struct cli_state *cli = NULL; + struct rpc_pipe_client *pipe_hnd = NULL; struct sockaddr_storage server_ss; NTSTATUS nt_status; TALLOC_CTX *mem_ctx = talloc_init("net_ads_printer_publish"); @@ -1463,14 +1636,19 @@ static int net_ads_printer_publish(int argc, const char **argv) char *srv_cn_escaped = NULL, *printername_escaped = NULL; LDAPMessage *res = NULL; - if (!ADS_ERR_OK(ads_startup(True, &ads))) { + if (argc < 1 || c->display_usage) { + d_printf(_("Usage:\n" + "net ads printer publish [servername]\n" + " Publish printer in AD\n" + " printername\tName of the printer\n" + " servername\tName of the print server\n")); talloc_destroy(mem_ctx); return -1; } - if (argc < 1) { + if (!ADS_ERR_OK(ads_startup(c, true, &ads))) { talloc_destroy(mem_ctx); - return net_ads_printer_usage(argc, argv); + return -1; } printername = argv[0]; @@ -1483,19 +1661,20 @@ static int net_ads_printer_publish(int argc, const char **argv) /* Get printer data from SPOOLSS */ - resolve_name(servername, &server_ss, 0x20); + resolve_name(servername, &server_ss, 0x20, false); nt_status = cli_full_connection(&cli, global_myname(), servername, &server_ss, 0, "IPC$", "IPC", - opt_user_name, opt_workgroup, - opt_password ? opt_password : "", + c->opt_user_name, c->opt_workgroup, + c->opt_password ? c->opt_password : "", CLI_FULL_CONNECTION_USE_KERBEROS, Undefined, NULL); if (NT_STATUS_IS_ERR(nt_status)) { - d_fprintf(stderr, "Unable to open a connnection to %s to obtain data " - "for %s\n", servername, printername); + 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; @@ -1506,7 +1685,8 @@ static int net_ads_printer_publish(int argc, const char **argv) ads_find_machine_acct(ads, &res, servername); if (ads_count_replies(ads, res) == 0) { - d_fprintf(stderr, "Could not find machine account for server %s\n", + d_fprintf(stderr, _("Could not find machine account for server " + "%s\n"), servername); ads_destroy(&ads); talloc_destroy(mem_ctx); @@ -1521,20 +1701,27 @@ static int net_ads_printer_publish(int argc, const char **argv) if (!srv_cn_escaped || !printername_escaped) { SAFE_FREE(srv_cn_escaped); SAFE_FREE(printername_escaped); - d_fprintf(stderr, "Internal error, out of memory!"); + 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); + if (asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_escaped, printername_escaped, srv_dn) == -1) { + 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; + } 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", + nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_spoolss.syntax_id, &pipe_hnd); + if (!NT_STATUS_IS_OK(nt_status)) { + d_fprintf(stderr, _("Unable to open a connnection to the spoolss pipe on %s\n"), servername); SAFE_FREE(prt_dn); ads_destroy(&ads); @@ -1567,7 +1754,7 @@ static int net_ads_printer_publish(int argc, const char **argv) return 0; } -static int net_ads_printer_remove(int argc, const char **argv) +static int net_ads_printer_remove(struct net_context *c, int argc, const char **argv) { ADS_STRUCT *ads; ADS_STATUS rc; @@ -1575,12 +1762,17 @@ static int net_ads_printer_remove(int argc, const char **argv) char *prt_dn; LDAPMessage *res = NULL; - if (!ADS_ERR_OK(ads_startup(True, &ads))) { + if (argc < 1 || c->display_usage) { + d_printf(_("Usage:\n" + "net ads printer remove [servername]\n" + " Remove a printer from the AD\n" + " printername\tName of the printer\n" + " servername\tName of the print server\n")); return -1; } - if (argc < 1) { - return net_ads_printer_usage(argc, argv); + if (!ADS_ERR_OK(ads_startup(c, true, &ads))) { + return -1; } if (argc > 1) { @@ -1592,26 +1784,26 @@ static int net_ads_printer_remove(int argc, const char **argv) rc = ads_find_printer_on_server(ads, &res, argv[0], servername); if (!ADS_ERR_OK(rc)) { - d_fprintf(stderr, "ads_find_printer_on_server: %s\n", ads_errstr(rc)); + d_fprintf(stderr, _("ads_find_printer_on_server: %s\n"), ads_errstr(rc)); ads_msgfree(ads, res); ads_destroy(&ads); return -1; } if (ads_count_replies(ads, res) == 0) { - d_fprintf(stderr, "Printer '%s' not found\n", argv[1]); + d_fprintf(stderr, _("Printer '%s' not found\n"), argv[1]); ads_msgfree(ads, res); ads_destroy(&ads); return -1; } - prt_dn = ads_get_dn(ads, res); + prt_dn = ads_get_dn(ads, talloc_tos(), res); ads_msgfree(ads, res); rc = ads_del_dn(ads, prt_dn); - ads_memfree(ads, prt_dn); + TALLOC_FREE(prt_dn); if (!ADS_ERR_OK(rc)) { - d_fprintf(stderr, "ads_del_dn: %s\n", ads_errstr(rc)); + d_fprintf(stderr, _("ads_del_dn: %s\n"), ads_errstr(rc)); ads_destroy(&ads); return -1; } @@ -1620,58 +1812,98 @@ static int net_ads_printer_remove(int argc, const char **argv) return 0; } -static int net_ads_printer(int argc, const char **argv) +static int net_ads_printer(struct net_context *c, int argc, const char **argv) { struct functable func[] = { - {"SEARCH", net_ads_printer_search}, - {"INFO", net_ads_printer_info}, - {"PUBLISH", net_ads_printer_publish}, - {"REMOVE", net_ads_printer_remove}, - {NULL, NULL} + { + "search", + net_ads_printer_search, + NET_TRANSPORT_ADS, + N_("Search for a printer"), + N_("net ads printer search\n" + " Search for a printer") + }, + { + "info", + net_ads_printer_info, + NET_TRANSPORT_ADS, + N_("Display printer information"), + N_("net ads printer info\n" + " Display printer information") + }, + { + "publish", + net_ads_printer_publish, + NET_TRANSPORT_ADS, + N_("Publish a printer"), + N_("net ads printer publish\n" + " Publish a printer") + }, + { + "remove", + net_ads_printer_remove, + NET_TRANSPORT_ADS, + N_("Delete a printer"), + N_("net ads printer remove\n" + " Delete a printer") + }, + {NULL, NULL, 0, NULL, NULL} }; - return net_run_function(argc, argv, func, net_ads_printer_usage); + return net_run_function(c, argc, argv, "net ads printer", func); } -static int net_ads_password(int argc, const char **argv) +static int net_ads_password(struct net_context *c, int argc, const char **argv) { ADS_STRUCT *ads; - const char *auth_principal = opt_user_name; - const char *auth_password = opt_password; + const char *auth_principal = c->opt_user_name; + const char *auth_password = c->opt_password; char *realm = NULL; char *new_password = NULL; - char *c, *prompt; + char *chr, *prompt; const char *user; ADS_STATUS ret; - if (opt_user_name == NULL || opt_password == NULL) { - d_fprintf(stderr, "You must supply an administrator username/password\n"); + if (c->display_usage) { + d_printf(_("Usage:\n" + "net ads password \n" + " Change password for user\n" + " username\tName of user to change password for\n")); + return 0; + } + + if (c->opt_user_name == NULL || c->opt_password == NULL) { + d_fprintf(stderr, _("You must supply an administrator " + "username/password\n")); return -1; } if (argc < 1) { - d_fprintf(stderr, "ERROR: You must say which username to change password for\n"); + d_fprintf(stderr, _("ERROR: You must say which username to " + "change password for\n")); return -1; } user = argv[0]; if (!strchr_m(user, '@')) { - asprintf(&c, "%s@%s", argv[0], lp_realm()); - user = c; + if (asprintf(&chr, "%s@%s", argv[0], lp_realm()) == -1) { + return -1; + } + user = chr; } use_in_memory_ccache(); - c = strchr_m(auth_principal, '@'); - if (c) { - realm = ++c; + chr = strchr_m(auth_principal, '@'); + if (chr) { + realm = ++chr; } else { realm = lp_realm(); } /* use the realm so we can eventually change passwords for users in realms other than default */ - if (!(ads = ads_init(realm, opt_workgroup, opt_host))) { + if (!(ads = ads_init(realm, c->opt_workgroup, c->opt_host))) { return -1; } @@ -1679,15 +1911,18 @@ static int net_ads_password(int argc, const char **argv) fill in the KDC's addresss */ ads_connect(ads); - if (!ads || !ads->config.realm) { - d_fprintf(stderr, "Didn't find the kerberos server!\n"); + if (!ads->config.realm) { + d_fprintf(stderr, _("Didn't find the kerberos server!\n")); + ads_destroy(&ads); return -1; } if (argv[1]) { new_password = (char *)argv[1]; } else { - asprintf(&prompt, "Enter new password for %s:", user); + if (asprintf(&prompt, _("Enter new password for %s:"), user) == -1) { + return -1; + } new_password = getpass(prompt); free(prompt); } @@ -1695,57 +1930,67 @@ static int net_ads_password(int argc, const char **argv) ret = kerberos_set_password(ads->auth.kdc_server, auth_principal, auth_password, user, new_password, ads->auth.time_offset); if (!ADS_ERR_OK(ret)) { - d_fprintf(stderr, "Password change failed: %s\n", ads_errstr(ret)); + d_fprintf(stderr, _("Password change failed: %s\n"), ads_errstr(ret)); ads_destroy(&ads); return -1; } - d_printf("Password change for %s completed.\n", user); + d_printf(_("Password change for %s completed.\n"), user); ads_destroy(&ads); return 0; } -int net_ads_changetrustpw(int argc, const char **argv) +int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv) { ADS_STRUCT *ads; char *host_principal; fstring my_name; ADS_STATUS ret; + if (c->display_usage) { + d_printf(_("Usage:\n" + "net ads changetrustpw\n" + " Change the machine account's trust password\n")); + return 0; + } + if (!secrets_init()) { DEBUG(1,("Failed to initialise secrets database\n")); return -1; } - net_use_krb_machine_account(); + net_use_krb_machine_account(c); use_in_memory_ccache(); - if (!ADS_ERR_OK(ads_startup(True, &ads))) { + if (!ADS_ERR_OK(ads_startup(c, true, &ads))) { return -1; } fstrcpy(my_name, global_myname()); strlower_m(my_name); - asprintf(&host_principal, "%s$@%s", my_name, ads->config.realm); - d_printf("Changing password for principal: %s\n", host_principal); + if (asprintf(&host_principal, "%s$@%s", my_name, ads->config.realm) == -1) { + ads_destroy(&ads); + return -1; + } + d_printf(_("Changing password for principal: %s\n"), host_principal); ret = ads_change_trust_account_password(ads, host_principal); if (!ADS_ERR_OK(ret)) { - d_fprintf(stderr, "Password change failed: %s\n", ads_errstr(ret)); + d_fprintf(stderr, _("Password change failed: %s\n"), ads_errstr(ret)); ads_destroy(&ads); SAFE_FREE(host_principal); return -1; } - d_printf("Password change for principal %s succeeded.\n", host_principal); + d_printf(_("Password change for principal %s succeeded.\n"), host_principal); - if (lp_use_kerberos_keytab()) { - d_printf("Attempting to update system keytab with new password.\n"); + if (USE_SYSTEM_KEYTAB) { + d_printf(_("Attempting to update system keytab with new password.\n")); if (ads_keytab_create_default(ads)) { - d_printf("Failed to update system keytab.\n"); + d_printf(_("Failed to update system keytab.\n")); } } @@ -1758,16 +2003,16 @@ int net_ads_changetrustpw(int argc, const char **argv) /* help for net ads search */ -static int net_ads_search_usage(int argc, const char **argv) +static int net_ads_search_usage(struct net_context *c, int argc, const char **argv) { - d_printf( - "\nnet ads search \n"\ - "\nperform a raw LDAP search on a ADS server and dump the results\n"\ - "The expression is a standard LDAP search expression, and the\n"\ - "attributes are a list of LDAP fields to show in the results\n\n"\ + d_printf(_( + "\nnet ads search \n" + "\nPerform a raw LDAP search on a ADS server and dump the results.\n" + "The expression is a standard LDAP search expression, and the\n" + "attributes are a list of LDAP fields to show in the results.\n\n" "Example: net ads search '(objectCategory=group)' sAMAccountName\n\n" - ); - net_common_flags_usage(argc, argv); + )); + net_common_flags_usage(c, argc, argv); return -1; } @@ -1775,7 +2020,7 @@ static int net_ads_search_usage(int argc, const char **argv) /* general ADS search function. Useful in diagnosing problems in ADS */ -static int net_ads_search(int argc, const char **argv) +static int net_ads_search(struct net_context *c, int argc, const char **argv) { ADS_STRUCT *ads; ADS_STATUS rc; @@ -1783,11 +2028,11 @@ static int net_ads_search(int argc, const char **argv) const char **attrs; LDAPMessage *res = NULL; - if (argc < 1) { - return net_ads_search_usage(argc, argv); + if (argc < 1 || c->display_usage) { + return net_ads_search_usage(c, argc, argv); } - if (!ADS_ERR_OK(ads_startup(False, &ads))) { + if (!ADS_ERR_OK(ads_startup(c, false, &ads))) { return -1; } @@ -1798,12 +2043,12 @@ static int net_ads_search(int argc, const char **argv) LDAP_SCOPE_SUBTREE, ldap_exp, attrs, &res); if (!ADS_ERR_OK(rc)) { - d_fprintf(stderr, "search failed: %s\n", ads_errstr(rc)); + d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(rc)); ads_destroy(&ads); return -1; } - d_printf("Got %d replies\n\n", ads_count_replies(ads, res)); + d_printf(_("Got %d replies\n\n"), ads_count_replies(ads, res)); /* dump the results */ ads_dump(ads, res); @@ -1818,17 +2063,17 @@ static int net_ads_search(int argc, const char **argv) /* help for net ads search */ -static int net_ads_dn_usage(int argc, const char **argv) +static int net_ads_dn_usage(struct net_context *c, int argc, const char **argv) { - d_printf( - "\nnet ads dn \n"\ - "\nperform a raw LDAP search on a ADS server and dump the results\n"\ - "The DN standard LDAP DN, and the attributes are a list of LDAP fields \n"\ - "to show in the results\n\n"\ + d_printf(_( + "\nnet ads dn \n" + "\nperform a raw LDAP search on a ADS server and dump the results\n" + "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); + )); + net_common_flags_usage(c, argc, argv); return -1; } @@ -1836,7 +2081,7 @@ static int net_ads_dn_usage(int argc, const char **argv) /* general ADS search function. Useful in diagnosing problems in ADS */ -static int net_ads_dn(int argc, const char **argv) +static int net_ads_dn(struct net_context *c, int argc, const char **argv) { ADS_STRUCT *ads; ADS_STATUS rc; @@ -1844,11 +2089,11 @@ static int net_ads_dn(int argc, const char **argv) const char **attrs; LDAPMessage *res = NULL; - if (argc < 1) { - return net_ads_dn_usage(argc, argv); + if (argc < 1 || c->display_usage) { + return net_ads_dn_usage(c, argc, argv); } - if (!ADS_ERR_OK(ads_startup(False, &ads))) { + if (!ADS_ERR_OK(ads_startup(c, false, &ads))) { return -1; } @@ -1859,7 +2104,7 @@ static int net_ads_dn(int argc, const char **argv) LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res); if (!ADS_ERR_OK(rc)) { - d_fprintf(stderr, "search failed: %s\n", ads_errstr(rc)); + d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(rc)); ads_destroy(&ads); return -1; } @@ -1878,16 +2123,16 @@ static int net_ads_dn(int argc, const char **argv) /* help for net ads sid search */ -static int net_ads_sid_usage(int argc, const char **argv) +static int net_ads_sid_usage(struct net_context *c, int argc, const char **argv) { - d_printf( - "\nnet ads sid \n"\ - "\nperform a raw LDAP search on a ADS server and dump the results\n"\ - "The SID is in string format, and the attributes are a list of LDAP fields \n"\ - "to show in the results\n\n"\ + d_printf(_( + "\nnet ads sid \n" + "\nperform a raw LDAP search on a ADS server and dump the results\n" + "The SID is in string format, and the attributes are a list of LDAP fields \n" + "to show in the results\n\n" "Example: net ads sid 'S-1-5-32' distinguishedName\n\n" - ); - net_common_flags_usage(argc, argv); + )); + net_common_flags_usage(c, argc, argv); return -1; } @@ -1895,7 +2140,7 @@ static int net_ads_sid_usage(int argc, const char **argv) /* general ADS search function. Useful in diagnosing problems in ADS */ -static int net_ads_sid(int argc, const char **argv) +static int net_ads_sid(struct net_context *c, int argc, const char **argv) { ADS_STRUCT *ads; ADS_STATUS rc; @@ -1904,11 +2149,11 @@ static int net_ads_sid(int argc, const char **argv) LDAPMessage *res = NULL; DOM_SID sid; - if (argc < 1) { - return net_ads_sid_usage(argc, argv); + if (argc < 1 || c->display_usage) { + return net_ads_sid_usage(c, argc, argv); } - if (!ADS_ERR_OK(ads_startup(False, &ads))) { + if (!ADS_ERR_OK(ads_startup(c, false, &ads))) { return -1; } @@ -1916,19 +2161,19 @@ static int net_ads_sid(int argc, const char **argv) attrs = (argv + 1); if (!string_to_sid(&sid, sid_string)) { - d_fprintf(stderr, "could not convert sid\n"); + d_fprintf(stderr, _("could not convert sid\n")); ads_destroy(&ads); return -1; } rc = ads_search_retry_sid(ads, &res, &sid, attrs); if (!ADS_ERR_OK(rc)) { - d_fprintf(stderr, "search failed: %s\n", ads_errstr(rc)); + d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(rc)); ads_destroy(&ads); return -1; } - d_printf("Got %d replies\n\n", ads_count_replies(ads, res)); + d_printf(_("Got %d replies\n\n"), ads_count_replies(ads, res)); /* dump the results */ ads_dump(ads, res); @@ -1939,35 +2184,19 @@ static int net_ads_sid(int argc, const char **argv) return 0; } - -static int net_ads_keytab_usage(int argc, const char **argv) -{ - d_printf( - "net ads keytab \n"\ -" can be either:\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"\ -" 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; -} - -static int net_ads_keytab_flush(int argc, const char **argv) +static int net_ads_keytab_flush(struct net_context *c, int argc, const char **argv) { int ret; ADS_STRUCT *ads; - if (!ADS_ERR_OK(ads_startup(True, &ads))) { + if (c->display_usage) { + d_printf(_("Usage:\n" + "net ads keytab flush\n" + " Delete the whole keytab\n")); + return 0; + } + + if (!ADS_ERR_OK(ads_startup(c, true, &ads))) { return -1; } ret = ads_keytab_flush(ads); @@ -1975,14 +2204,23 @@ static int net_ads_keytab_flush(int argc, const char **argv) return ret; } -static int net_ads_keytab_add(int argc, const char **argv) +static int net_ads_keytab_add(struct net_context *c, int argc, const char **argv) { int i; int ret = 0; ADS_STRUCT *ads; - d_printf("Processing principals to add...\n"); - if (!ADS_ERR_OK(ads_startup(True, &ads))) { + if (c->display_usage) { + d_printf(_("Usage:\n" + "net ads keytab add [principal ...]\n" + " Add principals to local keytab\n" + " principal\tKerberos principal to add to " + "keytab\n")); + return 0; + } + + d_printf(_("Processing principals to add...\n")); + if (!ADS_ERR_OK(ads_startup(c, true, &ads))) { return -1; } for (i = 0; i < argc; i++) { @@ -1992,12 +2230,19 @@ static int net_ads_keytab_add(int argc, const char **argv) return ret; } -static int net_ads_keytab_create(int argc, const char **argv) +static int net_ads_keytab_create(struct net_context *c, int argc, const char **argv) { ADS_STRUCT *ads; int ret; - if (!ADS_ERR_OK(ads_startup(True, &ads))) { + if (c->display_usage) { + d_printf(_("Usage:\n" + "net ads keytab create\n" + " Create new default keytab\n")); + return 0; + } + + if (!ADS_ERR_OK(ads_startup(c, true, &ads))) { return -1; } ret = ads_keytab_create_default(ads); @@ -2005,10 +2250,18 @@ static int net_ads_keytab_create(int argc, const char **argv) return ret; } -static int net_ads_keytab_list(int argc, const char **argv) +static int net_ads_keytab_list(struct net_context *c, int argc, const char **argv) { const char *keytab = NULL; + if (c->display_usage) { + d_printf(_("Usage:\n" + "net ads keytab list [keytab]\n" + " List a local keytab\n" + " keytab\tKeytab to list\n")); + return 0; + } + if (argc >= 1) { keytab = argv[0]; } @@ -2017,77 +2270,112 @@ static int net_ads_keytab_list(int argc, const char **argv) } -int net_ads_keytab(int argc, const char **argv) +int net_ads_keytab(struct net_context *c, int argc, const char **argv) { struct functable func[] = { - {"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} + { + "add", + net_ads_keytab_add, + NET_TRANSPORT_ADS, + N_("Add a service principal"), + N_("net ads keytab add\n" + " Add a service principal") + }, + { + "create", + net_ads_keytab_create, + NET_TRANSPORT_ADS, + N_("Create a fresh keytab"), + N_("net ads keytab create\n" + " Create a fresh keytab") + }, + { + "flush", + net_ads_keytab_flush, + NET_TRANSPORT_ADS, + N_("Remove all keytab entries"), + N_("net ads keytab flush\n" + " Remove all keytab entries") + }, + { + "list", + net_ads_keytab_list, + NET_TRANSPORT_ADS, + N_("List a keytab"), + N_("net ads keytab list\n" + " List a keytab") + }, + {NULL, NULL, 0, NULL, NULL} }; - if (!lp_use_kerberos_keytab()) { - d_printf("\nWarning: \"use kerberos keytab\" must be set to \"true\" in order to \ -use keytab functions.\n"); + if (!USE_KERBEROS_KEYTAB) { + d_printf(_("\nWarning: \"kerberos method\" must be set to a " + "keytab method to use keytab functions.\n")); } - return net_run_function(argc, argv, func, net_ads_keytab_usage); + return net_run_function(c, argc, argv, "net ads keytab", func); } -static int net_ads_kerberos_usage(int argc, const char **argv) +static int net_ads_kerberos_renew(struct net_context *c, int argc, const char **argv) { - d_printf( - "net ads kerberos \n"\ - " can be either:\n"\ - " RENEW Renew TGT from existing credential cache\n"\ - " PAC Dumps the Kerberos PAC\n"\ - " KINIT Retrieve Ticket Granting Ticket (TGT)\n"\ - "\n" - ); + int ret = -1; - return -1; -} + if (c->display_usage) { + d_printf(_("Usage:\n" + "net ads kerberos renew\n" + " Renew TGT from existing credential cache\n")); + return 0; + } -static int net_ads_kerberos_renew(int argc, const char **argv) -{ - int ret = smb_krb5_renew_ticket(NULL, NULL, NULL, NULL); + ret = smb_krb5_renew_ticket(NULL, NULL, NULL, NULL); if (ret) { - d_printf("failed to renew kerberos ticket: %s\n", + d_printf(_("failed to renew kerberos ticket: %s\n"), error_message(ret)); } return ret; } -static int net_ads_kerberos_pac(int argc, const char **argv) +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; int ret = -1; + const char *impersonate_princ_s = NULL; + + if (c->display_usage) { + d_printf(_("Usage:\n" + "net ads kerberos pac\n" + " Dump the Kerberos PAC\n")); + return 0; + } mem_ctx = talloc_init("net_ads_kerberos_pac"); if (!mem_ctx) { goto out; } - opt_password = net_prompt_pass(opt_user_name); + if (argc > 0) { + impersonate_princ_s = argv[0]; + } + + c->opt_password = net_prompt_pass(c, c->opt_user_name); status = kerberos_return_pac(mem_ctx, - opt_user_name, - opt_password, + c->opt_user_name, + c->opt_password, 0, NULL, NULL, NULL, - True, - True, + true, + true, 2592000, /* one month */ + impersonate_princ_s, &pac); if (!NT_STATUS_IS_OK(status)) { - d_printf("failed to query kerberos PAC: %s\n", + d_printf(_("failed to query kerberos PAC: %s\n"), nt_errstr(status)); goto out; } @@ -2096,7 +2384,7 @@ static int net_ads_kerberos_pac(int argc, const char **argv) if (info) { const char *s; s = NDR_PRINT_STRUCT_STRING(mem_ctx, PAC_LOGON_INFO, info); - d_printf("The Pac: %s\n", s); + d_printf(_("The Pac: %s\n"), s); } ret = 0; @@ -2105,162 +2393,291 @@ static int net_ads_kerberos_pac(int argc, const char **argv) return ret; } -static int net_ads_kerberos_kinit(int argc, const char **argv) +static int net_ads_kerberos_kinit(struct net_context *c, int argc, const char **argv) { TALLOC_CTX *mem_ctx = NULL; int ret = -1; NTSTATUS status; + if (c->display_usage) { + d_printf(_("Usage:\n" + "net ads kerberos kinit\n" + " Get Ticket Granting Ticket (TGT) for the user\n")); + return 0; + } + mem_ctx = talloc_init("net_ads_kerberos_kinit"); if (!mem_ctx) { goto out; } - opt_password = net_prompt_pass(opt_user_name); + c->opt_password = net_prompt_pass(c, c->opt_user_name); - ret = kerberos_kinit_password_ext(opt_user_name, - opt_password, + ret = kerberos_kinit_password_ext(c->opt_user_name, + c->opt_password, 0, NULL, NULL, NULL, - True, - True, + true, + true, 2592000, /* one month */ &status); if (ret) { - d_printf("failed to kinit password: %s\n", + d_printf(_("failed to kinit password: %s\n"), nt_errstr(status)); } out: return ret; } -int net_ads_kerberos(int argc, const char **argv) +int net_ads_kerberos(struct net_context *c, int argc, const char **argv) { struct functable func[] = { - {"KINIT", net_ads_kerberos_kinit}, - {"RENEW", net_ads_kerberos_renew}, - {"PAC", net_ads_kerberos_pac}, - {"HELP", net_ads_kerberos_usage}, - {NULL, NULL} + { + "kinit", + net_ads_kerberos_kinit, + NET_TRANSPORT_ADS, + N_("Retrieve Ticket Granting Ticket (TGT)"), + N_("net ads kerberos kinit\n" + " Receive Ticket Granting Ticket (TGT)") + }, + { + "renew", + net_ads_kerberos_renew, + NET_TRANSPORT_ADS, + N_("Renew Ticket Granting Ticket from credential cache"), + N_("net ads kerberos renew\n" + " Renew Ticket Granting Ticket (TGT) from " + "credential cache") + }, + { + "pac", + net_ads_kerberos_pac, + NET_TRANSPORT_ADS, + N_("Dump Kerberos PAC"), + N_("net ads kerberos pac\n" + " Dump Kerberos PAC") + }, + {NULL, NULL, 0, NULL, NULL} }; - return net_run_function(argc, argv, func, net_ads_kerberos_usage); + return net_run_function(c, argc, argv, "net ads kerberos", func); } - -int net_ads_help(int argc, const char **argv) +int net_ads(struct net_context *c, int argc, const char **argv) { struct functable func[] = { - {"USER", net_ads_user_usage}, - {"GROUP", net_ads_group_usage}, - {"PRINTER", net_ads_printer_usage}, - {"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}, - {"CHANGETRUSTPW", net_ads_changetrustpw}, - {NULL, NULL} + { + "info", + net_ads_info, + NET_TRANSPORT_ADS, + N_("Display details on remote ADS server"), + N_("net ads info\n" + " Display details on remote ADS server") + }, + { + "join", + net_ads_join, + NET_TRANSPORT_ADS, + N_("Join the local machine to ADS realm"), + N_("net ads join\n" + " Join the local machine to ADS realm") + }, + { + "testjoin", + net_ads_testjoin, + NET_TRANSPORT_ADS, + N_("Validate machine account"), + N_("net ads testjoin\n" + " Validate machine account") + }, + { + "leave", + net_ads_leave, + NET_TRANSPORT_ADS, + N_("Remove the local machine from ADS"), + N_("net ads leave\n" + " Remove the local machine from ADS") + }, + { + "status", + net_ads_status, + NET_TRANSPORT_ADS, + N_("Display machine account details"), + N_("net ads status\n" + " Display machine account details") + }, + { + "user", + net_ads_user, + NET_TRANSPORT_ADS, + N_("List/modify users"), + N_("net ads user\n" + " List/modify users") + }, + { + "group", + net_ads_group, + NET_TRANSPORT_ADS, + N_("List/modify groups"), + N_("net ads group\n" + " List/modify groups") + }, + { + "dns", + net_ads_dns, + NET_TRANSPORT_ADS, + N_("Issue dynamic DNS update"), + N_("net ads dns\n" + " Issue dynamic DNS update") + }, + { + "password", + net_ads_password, + NET_TRANSPORT_ADS, + N_("Change user passwords"), + N_("net ads password\n" + " Change user passwords") + }, + { + "changetrustpw", + net_ads_changetrustpw, + NET_TRANSPORT_ADS, + N_("Change trust account password"), + N_("net ads changetrustpw\n" + " Change trust account password") + }, + { + "printer", + net_ads_printer, + NET_TRANSPORT_ADS, + N_("List/modify printer entries"), + N_("net ads printer\n" + " List/modify printer entries") + }, + { + "search", + net_ads_search, + NET_TRANSPORT_ADS, + N_("Issue LDAP search using filter"), + N_("net ads search\n" + " Issue LDAP search using filter") + }, + { + "dn", + net_ads_dn, + NET_TRANSPORT_ADS, + N_("Issue LDAP search by DN"), + N_("net ads dn\n" + " Issue LDAP search by DN") + }, + { + "sid", + net_ads_sid, + NET_TRANSPORT_ADS, + N_("Issue LDAP search by SID"), + N_("net ads sid\n" + " Issue LDAP search by SID") + }, + { + "workgroup", + net_ads_workgroup, + NET_TRANSPORT_ADS, + N_("Display workgroup name"), + N_("net ads workgroup\n" + " Display the workgroup name") + }, + { + "lookup", + net_ads_lookup, + NET_TRANSPORT_ADS, + N_("Perfom CLDAP query on DC"), + N_("net ads lookup\n" + " Find the ADS DC using CLDAP lookups") + }, + { + "keytab", + net_ads_keytab, + NET_TRANSPORT_ADS, + N_("Manage local keytab file"), + N_("net ads keytab\n" + " Manage local keytab file") + }, + { + "gpo", + net_ads_gpo, + NET_TRANSPORT_ADS, + N_("Manage group policy objects"), + N_("net ads gpo\n" + " Manage group policy objects") + }, + { + "kerberos", + net_ads_kerberos, + NET_TRANSPORT_ADS, + N_("Manage kerberos keytab"), + N_("net ads kerberos\n" + " Manage kerberos keytab") + }, + {NULL, NULL, 0, NULL, NULL} }; - return net_run_function(argc, argv, func, net_ads_usage); -} - -int net_ads(int argc, const char **argv) -{ - struct functable func[] = { - {"INFO", net_ads_info}, - {"JOIN", net_ads_join}, - {"TESTJOIN", net_ads_testjoin}, - {"LEAVE", net_ads_leave}, - {"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}, - {"SEARCH", net_ads_search}, - {"DN", net_ads_dn}, - {"SID", net_ads_sid}, - {"WORKGROUP", net_ads_workgroup}, - {"LOOKUP", net_ads_lookup}, - {"KEYTAB", net_ads_keytab}, - {"GPO", net_ads_gpo}, - {"KERBEROS", net_ads_kerberos}, - {"HELP", net_ads_help}, - {NULL, NULL} - }; - - return net_run_function(argc, argv, func, net_ads_usage); + return net_run_function(c, argc, argv, "net ads", func); } #else static int net_ads_noads(void) { - d_fprintf(stderr, "ADS support not compiled in\n"); + d_fprintf(stderr, _("ADS support not compiled in\n")); return -1; } -int net_ads_keytab(int argc, const char **argv) -{ - return net_ads_noads(); -} - -int net_ads_kerberos(int argc, const char **argv) -{ - return net_ads_noads(); -} - -int net_ads_usage(int argc, const char **argv) +int net_ads_keytab(struct net_context *c, int argc, const char **argv) { return net_ads_noads(); } -int net_ads_help(int argc, const char **argv) +int net_ads_kerberos(struct net_context *c, int argc, const char **argv) { return net_ads_noads(); } -int net_ads_changetrustpw(int argc, const char **argv) +int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv) { return net_ads_noads(); } -int net_ads_join(int argc, const char **argv) +int net_ads_join(struct net_context *c, int argc, const char **argv) { return net_ads_noads(); } -int net_ads_user(int argc, const char **argv) +int net_ads_user(struct net_context *c, int argc, const char **argv) { return net_ads_noads(); } -int net_ads_group(int argc, const char **argv) +int net_ads_group(struct net_context *c, int argc, const char **argv) { return net_ads_noads(); } /* this one shouldn't display a message */ -int net_ads_check(void) +int net_ads_check(struct net_context *c) { return -1; } -int net_ads_check_our_domain(void) +int net_ads_check_our_domain(struct net_context *c) { return -1; } -int net_ads(int argc, const char **argv) +int net_ads(struct net_context *c, int argc, const char **argv) { - return net_ads_usage(argc, argv); + return net_ads_noads(); } #endif /* WITH_ADS */