X-Git-Url: http://git.samba.org/samba.git/?p=kai%2Fsamba-autobuild%2F.git;a=blobdiff_plain;f=source3%2Futils%2Fnet_ads.c;h=627374cb96bb82162a7f31f01849479ad8fb52f3;hp=199804f3aaaa4d128f85a41d13d9b25c5502f402;hb=0fd0fc75c46b39a611c7f9a56081105714d73e36;hpb=c3ef76593b106e2c35c9c422cd9a216f0039ebf2 diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c index 199804f3aaa..627374cb96b 100644 --- a/source3/utils/net_ads.c +++ b/source3/utils/net_ads.c @@ -25,48 +25,12 @@ #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(); } @@ -76,14 +40,13 @@ 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 ) ) { + if ( !ads_cldap_netlogon_5(talloc_tos(), addr, ads->server.realm, &reply ) ) { d_fprintf(stderr, "CLDAP query failed!\n"); return -1; } @@ -92,20 +55,19 @@ static int net_ads_cldap_netlogon(ADS_STRUCT *ads) addr); d_printf("Response Type: "); - switch (reply.type) { - case SAMLOGON_AD_UNK_R: - d_printf("SAMLOGON\n"); + 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("GUID: %s\n", smb_uuid_string(talloc_tos(), reply.domain_uuid)); d_printf("Flags:\n" "\tIs a PDC: %s\n" @@ -117,32 +79,36 @@ static int net_ads_cldap_netlogon(ADS_STRUCT *ads) "\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"); + "\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.domain); - printf("Domain Controller:\t%s\n", reply.hostname); + 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.netbios_domain); - printf("Pre-Win2k Hostname:\t%s\n", reply.netbios_hostname); + printf("Pre-Win2k Domain:\t%s\n", reply.domain); + printf("Pre-Win2k Hostname:\t%s\n", reply.pdc_name); - 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); + 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.version); + 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); @@ -153,31 +119,46 @@ 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; - if (!ADS_ERR_OK(ads_startup_nobind(False, &ads))) { + 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"); 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); + return net_ads_cldap_netlogon(c, ads); } -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))) { + 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; } @@ -215,15 +196,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 @@ -236,37 +218,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", @@ -292,8 +274,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); @@ -305,9 +287,9 @@ 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) { @@ -325,14 +307,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); } /* @@ -360,42 +342,49 @@ 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))) { + 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 ) ) { + if ( !ads_cldap_netlogon_5(talloc_tos(), addr, ads->server.realm, &reply ) ) { d_fprintf(stderr, "CLDAP query failed!\n"); return -1; } - d_printf("Workgroup: %s\n", reply.netbios_domain); + d_printf("Workgroup: %s\n", reply.domain); ads_destroy(&ads); @@ -420,24 +409,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; @@ -446,9 +435,10 @@ 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; } @@ -464,13 +454,13 @@ static int ads_user_add(int argc, const char **argv) 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], @@ -515,7 +505,7 @@ 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_STATUS rc; @@ -525,8 +515,8 @@ static int ads_user_info(int argc, const char **argv) char **grouplist; char *escaped_user; - 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]); @@ -536,7 +526,7 @@ static int ads_user_info(int argc, const char **argv) return -1; } - if (!ADS_ERR_OK(ads_startup(False, &ads))) { + if (!ADS_ERR_OK(ads_startup(c, false, &ads))) { SAFE_FREE(escaped_user); return -1; } @@ -572,7 +562,7 @@ static int ads_user_info(int argc, const char **argv) return 0; } -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; @@ -580,10 +570,10 @@ 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; } @@ -609,13 +599,34 @@ static int ads_user_delete(int argc, const char **argv) 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, + "Add an AD user", + "net ads user add\n" + " Add an AD user" + }, + { + "info", + ads_user_info, + NET_TRANSPORT_ADS, + "Display information about an AD user", + "net ads user info\n" + " Display information about an AD user" + }, + { + "delete", + ads_user_delete, + NET_TRANSPORT_ADS, + "Delete an AD user", + "net ads user delete\n" + " Delete an AD user" + }, + {NULL, NULL, 0, NULL, NULL} }; ADS_STRUCT *ads; ADS_STATUS rc; @@ -624,33 +635,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"); + d_printf("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"\ + 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; @@ -658,11 +677,11 @@ 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; } @@ -678,13 +697,13 @@ static int ads_group_add(int argc, const char **argv) 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]); @@ -702,18 +721,18 @@ 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; } @@ -739,12 +758,26 @@ static int ads_group_delete(int argc, const char **argv) 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, + "Add an AD group", + "net ads group add\n" + " Add an AD group" + }, + { + "delete", + ads_group_delete, + NET_TRANSPORT_ADS, + "Delete an AD group", + "net ads group delete\n" + " Delete an AD group" + }, + {NULL, NULL, 0, NULL, NULL} }; ADS_STRUCT *ads; ADS_STATUS rc; @@ -753,33 +786,48 @@ 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"); + d_printf("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"\ + 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; } @@ -808,19 +856,21 @@ 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) { - ADS_STRUCT *ads = NULL; - ADS_STATUS adsret; - NTSTATUS status; - int ret = -1; - struct cli_state *cli = NULL; TALLOC_CTX *ctx; - DOM_SID *dom_sid = NULL; - const char *short_domain_name = NULL; + struct libnet_UnjoinCtx *r = NULL; + WERROR werr; - if (!secrets_init()) { - DEBUG(1,("Failed to initialise secrets database\n")); + 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; } @@ -829,60 +879,63 @@ static int net_ads_leave(int argc, const char **argv) return -1; } - /* The finds a DC and takes care of getting the - user creds if necessary */ + if (!c->opt_kerberos) { + use_in_memory_ccache(); + } - if (!ADS_ERR_OK(ads_startup(True, &ads))) { + werr = libnet_init_UnjoinCtx(ctx, &r); + if (!W_ERROR_IS_OK(werr)) { + d_fprintf(stderr, "Could not initialise unjoin context.\n"); return -1; } - /* make RPC calls here */ - - if ( !NT_STATUS_IS_OK(connect_to_ipc_krb5(&cli, &ads->ldap.ss, - ads->config.ldap_server_name)) ) - { + 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 = 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(); + r->in.unjoin_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE | + WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE; + + werr = libnet_Unjoin(ctx, r); + if (!W_ERROR_IS_OK(werr)) { + d_printf("Failed to leave domain: %s\n", + r->out.error_string ? r->out.error_string : + get_friendly_werror_msg(werr)); goto done; } - if ( !NT_STATUS_IS_OK(netdom_get_domain_sid( ctx, cli, &short_domain_name, &dom_sid )) ) { + if (W_ERROR_IS_OK(werr)) { + d_printf("Deleted account for '%s' in realm '%s'\n", + r->in.machine_name, r->out.dns_domain_name); goto done; } - saf_delete( short_domain_name ); - - status = netdom_leave_domain(ctx, cli, dom_sid); - - /* Try and delete it via LDAP - the old way we used to. */ - - adsret = ads_leave_realm(ads, global_myname()); - if (ADS_ERR_OK(adsret)) { - d_printf("Deleted account for '%s' in realm '%s'\n", - global_myname(), ads->config.realm); - ret = 0; - } else { - /* We couldn't delete it - see if the disable succeeded. */ - if (NT_STATUS_IS_OK(status)) { - d_printf("Disabled account for '%s' in realm '%s'\n", - global_myname(), ads->config.realm); - ret = 0; - } else { - d_fprintf(stderr, "Failed to disable machine account for '%s' in realm '%s'\n", - global_myname(), ads->config.realm); - } + /* 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", + r->in.machine_name, r->out.dns_domain_name); + werr = WERR_OK; + goto done; } -done: + d_fprintf(stderr, "Failed to disable machine account for '%s' in realm '%s'\n", + r->in.machine_name, r->out.dns_domain_name); - if ( cli ) - cli_shutdown(cli); + done: + TALLOC_FREE(r); + TALLOC_FREE(ctx); - ads_destroy(&ads); - TALLOC_FREE( ctx ); + if (W_ERROR_IS_OK(werr)) { + return 0; + } - return ret; + 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; @@ -892,9 +945,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); } @@ -906,13 +959,20 @@ 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", get_friendly_nt_error_msg(status)); @@ -927,363 +987,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; + 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(), (unsigned int)strlen(global_myname())); - return NT_STATUS_NAME_TOO_LONG; + return WERR_INVALID_COMPUTER_NAME; } 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; - } - - return NT_STATUS_OK; -} - -/******************************************************************* - Do the domain join - ********************************************************************/ - -static NTSTATUS net_join_domain(TALLOC_CTX *ctx, const char *servername, - struct sockaddr_storage *pss, - const char **domain, - DOM_SID **dom_sid, - const char *password) -{ - NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; - struct cli_state *cli = NULL; - - ret = connect_to_ipc_krb5(&cli, pss, servername); - if ( !NT_STATUS_IS_OK(ret) ) { - goto done; - } - - 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: - if ( cli ) - cli_shutdown(cli); - - return ret; -} - -/******************************************************************* - Set a machines dNSHostName and servicePrincipalName attributes - ********************************************************************/ - -static ADS_STATUS net_set_machine_spn(TALLOC_CTX *ctx, ADS_STRUCT *ads_s ) -{ - ADS_STATUS status = ADS_ERROR(LDAP_SERVER_DOWN); - char *new_dn; - ADS_MODLIST mods; - const char *servicePrincipalName[3] = {NULL, NULL, NULL}; - char *psp; - fstring my_fqdn; - LDAPMessage *res = NULL; - char *dn_string = NULL; - const char *machine_name = global_myname(); - int count; - - if ( !machine_name ) { - 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); + return WERR_INVALID_PARAM; } - 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); - } - - /* Windows only creates HOST/shortname & HOST/fqdn. */ - - if ( !(psp = talloc_asprintf(ctx, "HOST/%s", machine_name)) ) - goto done; - strupper_m(psp); - servicePrincipalName[0] = psp; - - name_to_fqdn(my_fqdn, machine_name); - strlower_m(my_fqdn); - if ( !(psp = talloc_asprintf(ctx, "HOST/%s", my_fqdn)) ) - goto done; - servicePrincipalName[1] = psp; - - if (!(mods = ads_init_mods(ctx))) { - goto done; - } - - /* fields of primary importance */ - - ads_mod_str(ctx, &mods, "dNSHostName", my_fqdn); - ads_mod_strlist(ctx, &mods, "servicePrincipalName", servicePrincipalName); - - status = ads_gen_mod(ads_s, new_dn, mods); - -done: - ads_msgfree(ads_s, res); - - return status; -} - -/******************************************************************* - Set a machines dNSHostName and servicePrincipalName attributes - ********************************************************************/ - -static ADS_STATUS net_set_machine_upn(TALLOC_CTX *ctx, ADS_STRUCT *ads_s, const char *upn ) -{ - 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; - - if ( !machine_name ) { - 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; - } - - /* fields of primary importance */ - - ads_mod_str(ctx, &mods, "userPrincipalName", upn); - - status = ads_gen_mod(ads_s, new_dn, mods); - -done: - ads_msgfree(ads_s, res); - - 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 *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) { - rc = ADS_ERROR(LDAP_NO_MEMORY); - goto done; - } - - rc = ads_search_dn(ads, &res, dn, NULL); - if (!ADS_ERR_OK(rc)) { - d_fprintf(stderr, "The specified OU does not exist.\n"); - goto done; - } - - /* 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 (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 ); - - return rc; -} - -/************************************************************************ - ************************************************************************/ - -static bool net_derive_salting_principal( TALLOC_CTX *ctx, ADS_STRUCT *ads ) -{ - uint32 domain_func; - ADS_STATUS status; - fstring salt; - char *std_salt; - const char *machine_name = global_myname(); - - status = ads_domain_func_level( ads, &domain_func ); - if ( !ADS_ERR_OK(status) ) { - DEBUG(2,("Failed to determine domain functional level!\n")); - return False; - } - - /* go ahead and setup the default salt */ - - if ( (std_salt = kerberos_standard_des_salt()) == NULL ) { - d_fprintf(stderr, "net_derive_salting_principal: failed to obtain stanard DES salt\n"); - return False; - } - - fstrcpy( salt, std_salt ); - SAFE_FREE( std_salt ); - - /* if it's a Windows functional domain, we have to look for the UPN */ - - if ( domain_func == DS_DOMAIN_FUNCTION_2000 ) { - char *upn = ads_get_upn(ads, ctx, machine_name); - if ( upn ) { - fstrcpy( salt, upn ); - } - } - - return kerberos_secrets_store_des_salt( salt ); + return WERR_OK; } /******************************************************************* @@ -1416,7 +1140,7 @@ static NTSTATUS net_update_dns(TALLOC_CTX *mem_ctx, ADS_STRUCT *ads) /******************************************************************* ********************************************************************/ -static int net_ads_join_usage(int argc, const char **argv) +static int net_ads_join_usage(struct net_context *c, int argc, const char **argv) { d_printf("net ads join [options]\n"); d_printf("Valid options:\n"); @@ -1439,52 +1163,44 @@ 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) { - ADS_STRUCT *ads = NULL; - ADS_STATUS status; - NTSTATUS nt_status; - const char *short_domain_name = NULL; - char *tmp_password, *password; TALLOC_CTX *ctx = NULL; - DOM_SID *domain_sid = NULL; - bool createupn = False; + struct libnet_JoinCtx *r = NULL; + const char *domain = lp_realm(); + WERROR werr = WERR_SETUP_NOT_JOINED; + bool createupn = false; const char *machineupn = NULL; const char *create_in_ou = NULL; int i; - fstring dc_name; - struct sockaddr_storage dcss; 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"); - goto fail; - } + if (c->display_usage) + return net_ads_join_usage(c, argc, argv); - /* find a DC to initialize the server affinity cache */ + if (!modify_config) { - get_dc_name( lp_workgroup(), lp_realm(), dc_name, &dcss ); + werr = check_ads_config(); + if (!W_ERROR_IS_OK(werr)) { + d_fprintf(stderr, "Invalid configuration. Exiting....\n"); + goto fail; + } + } - status = ads_startup(True, &ads); - if (!ADS_ERR_OK(status)) { - DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status))); - nt_status = ads_ntstatus(status); + if (!(ctx = talloc_init("net_ads_join"))) { + d_fprintf(stderr, "Could not initialise talloc context.\n"); + werr = WERR_NOMEM; goto fail; } - if (strcmp(ads->config.realm, lp_realm()) != 0) { - d_fprintf(stderr, "realm of remote server (%s) and realm in %s " - "(%s) DO NOT match. Aborting join\n", - ads->config.realm, get_dyn_CONFIGFILE(), lp_realm()); - nt_status = NT_STATUS_INVALID_PARAMETER; - goto fail; + if (!c->opt_kerberos) { + use_in_memory_ccache(); } - if (!(ctx = talloc_init("net_ads_join"))) { - d_fprintf(stderr, "Could not initialise talloc context.\n"); - nt_status = NT_STATUS_NO_MEMORY; + werr = libnet_init_JoinCtx(ctx, &r); + if (!W_ERROR_IS_OK(werr)) { goto fail; } @@ -1492,232 +1208,128 @@ int net_ads_join(int argc, const char **argv) for ( i=0; iconfig.ldap_server_name, - &ads->ldap.ss, &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))); + r->in.domain_name = domain; + r->in.create_upn = createupn; + r->in.upn = machineupn; + r->in.account_ou = create_in_ou; + r->in.os_name = os_name; + r->in.os_version = os_version; + 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; + + werr = libnet_Join(ctx, r); + if (!W_ERROR_IS_OK(werr)) { goto fail; } /* Check the short name of the domain */ - if ( !strequal(lp_workgroup(), short_domain_name) ) { + if (!modify_config && !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", short_domain_name); + 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", - short_domain_name, get_dyn_CONFIGFILE()); - } - - d_printf("Using short domain name -- %s\n", short_domain_name); - - /* HACK ALERT! Store the sid and password under both the lp_workgroup() - value from smb.conf and the string returned from the server. The former is - neede to bootstrap winbindd's first connection to the DC to get the real - short domain name --jerry */ - - if ( (netdom_store_machine_account( lp_workgroup(), domain_sid, password ) == -1) - || (netdom_store_machine_account( short_domain_name, domain_sid, password ) == -1) ) - { - /* issue an internal error here for now. - * everything else would mean changing tdb routines. */ - nt_status = NT_STATUS_INTERNAL_ERROR; - goto fail; - } - - /* Verify that everything is ok */ - - nt_status = net_rpc_join_ok(short_domain_name, - ads->config.ldap_server_name, &ads->ldap.ss); - if (!NT_STATUS_IS_OK(nt_status)) { - d_fprintf(stderr, - "Failed to verify membership in domain: %s!\n", - nt_errstr(nt_status)); - goto fail; + r->out.netbios_domain_name, get_dyn_CONFIGFILE()); } - /* create the dNSHostName & servicePrincipalName values */ - - status = net_set_machine_spn( ctx, ads ); - if ( !ADS_ERR_OK(status) ) { - - d_fprintf(stderr, "Failed to set servicePrincipalNames. Please ensure that\n"); - d_fprintf(stderr, "the DNS domain of this server matches the AD domain,\n"); - d_fprintf(stderr, "Or rejoin with using Domain Admin credentials.\n"); - - /* Disable the machine account in AD. Better to fail than to leave - a confused admin. */ - - if ( net_ads_leave( 0, NULL ) != 0 ) { - d_fprintf( stderr, "Failed to disable machine account in AD. Please do so manually.\n"); - } + d_printf("Using short domain name -- %s\n", r->out.netbios_domain_name); - /* clear out the machine password */ - - netdom_store_machine_account( lp_workgroup(), domain_sid, "" ); - netdom_store_machine_account( short_domain_name, domain_sid, "" ); - - nt_status = ads_ntstatus(status); - goto fail; - } - - if ( !net_derive_salting_principal( ctx, ads ) ) { - DEBUG(1,("Failed to determine salting principal\n")); - goto fail; + 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 ( createupn ) { - char *upn; - - /* default to using the short UPN name */ - if (!machineupn ) { - upn = talloc_asprintf(ctx, - "host/%s@%s", global_myname(), - ads->config.realm ); - if (!upn) { - nt_status = NT_STATUS_NO_MEMORY; - goto fail; - } - machineupn = upn; - } - - status = net_set_machine_upn( ctx, ads, machineupn ); - if ( !ADS_ERR_OK(status) ) { - d_fprintf(stderr, "Failed to set userPrincipalName. Are you a Domain Admin?\n"); +#if defined(WITH_DNS_UPDATES) + if (r->out.domain_is_ad) { + /* We enter this block with user creds */ + ADS_STRUCT *ads_dns = NULL; + + if ( (ads_dns = ads_init( lp_realm(), NULL, NULL )) != NULL ) { + /* kinit with the machine password */ + + use_in_memory_ccache(); + asprintf( &ads_dns->auth.user_name, "%s$", global_myname() ); + ads_dns->auth.password = secrets_fetch_machine_password( + 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 ); } - } - - /* 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"); + if ( !ads_dns || !NT_STATUS_IS_OK(net_update_dns( ctx, ads_dns )) ) { + d_fprintf( stderr, "DNS update failed!\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")); + /* exit from this block using machine creds */ + ads_destroy(&ads_dns); } - -#if defined(WITH_DNS_UPDATES) - /* We enter this block with user creds */ - ads_kdestroy( NULL ); - ads_destroy(&ads); - ads = NULL; - - if ( (ads = ads_init( lp_realm(), NULL, NULL )) != NULL ) { - /* kinit with the machine password */ - - use_in_memory_ccache(); - asprintf( &ads->auth.user_name, "%s$", global_myname() ); - ads->auth.password = secrets_fetch_machine_password( - lp_workgroup(), NULL, NULL ); - ads->auth.realm = SMB_STRDUP( lp_realm() ); - ads_kinit_password( ads ); - } - - if ( !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->server.realm); - + TALLOC_FREE(r); TALLOC_FREE( ctx ); - ads_destroy(&ads); return 0; fail: /* issue an overall failure message at the end. */ - d_printf("Failed to join domain: %s\n", get_friendly_nt_error_msg(nt_status)); - + d_printf("Failed to join domain: %s\n", + r && r->out.error_string ? r->out.error_string : + get_friendly_werror_msg(werr)); TALLOC_FREE( ctx ); - ads_destroy(&ads); return -1; - -} - -/******************************************************************* - ********************************************************************/ - -static int net_ads_dns_usage(int argc, const char **argv) -{ -#if defined(WITH_DNS_UPDATES) - d_printf("net ads dns \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; @@ -1728,8 +1340,10 @@ 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; } @@ -1738,7 +1352,7 @@ static int net_ads_dns_register(int argc, const char **argv) 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); @@ -1768,7 +1382,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; @@ -1777,9 +1391,12 @@ 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; } @@ -1790,21 +1407,35 @@ static int net_ads_dns_gethostbyname(int argc, const char **argv) 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, + "Add host dns entry to AD", + "net ads dns register\n" + " Add host dns entry to AD" + }, + { + "gethostbyname", + net_ads_dns_gethostbyname, + NET_TRANSPORT_ADS, + "Look up host", + "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( "\nnet ads printer search " @@ -1824,13 +1455,20 @@ int net_ads_printer_usage(int argc, const char **argv) /******************************************************************* ********************************************************************/ -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; } @@ -1856,14 +1494,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; } @@ -1903,7 +1550,7 @@ 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; @@ -1918,14 +1565,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]; @@ -1943,8 +1595,8 @@ static int net_ads_printer_publish(int argc, const char **argv) 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); @@ -1987,8 +1639,8 @@ static int net_ads_printer_publish(int argc, const char **argv) SAFE_FREE(srv_cn_escaped); SAFE_FREE(printername_escaped); - pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SPOOLSS, &nt_status); - if (!pipe_hnd) { + nt_status = cli_rpc_pipe_open_noauth(cli, &syntax_spoolss, &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); @@ -2022,7 +1674,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; @@ -2030,12 +1682,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) { @@ -2075,32 +1732,68 @@ 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, + "Search for a printer", + "net ads printer search\n" + " Search for a printer" + }, + { + "info", + net_ads_printer_info, + NET_TRANSPORT_ADS, + "Display printer information", + "net ads printer info\n" + " Display printer information" + }, + { + "publish", + net_ads_printer_publish, + NET_TRANSPORT_ADS, + "Publish a printer", + "net ads printer publish\n" + " Publish a printer" + }, + { + "remove", + net_ads_printer_remove, + NET_TRANSPORT_ADS, + "Delete a printer", + "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) { + 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; } @@ -2112,21 +1805,21 @@ static int net_ads_password(int argc, const char **argv) user = argv[0]; if (!strchr_m(user, '@')) { - asprintf(&c, "%s@%s", argv[0], lp_realm()); - user = c; + asprintf(&chr, "%s@%s", argv[0], lp_realm()); + 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; } @@ -2134,7 +1827,7 @@ static int net_ads_password(int argc, const char **argv) fill in the KDC's addresss */ ads_connect(ads); - if (!ads || !ads->config.realm) { + if (!ads->config.realm) { d_fprintf(stderr, "Didn't find the kerberos server!\n"); return -1; } @@ -2161,23 +1854,30 @@ static int net_ads_password(int argc, const char **argv) 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; } @@ -2213,16 +1913,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"\ + "\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; } @@ -2230,7 +1930,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; @@ -2238,11 +1938,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; } @@ -2273,17 +1973,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"\ + "\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; } @@ -2291,7 +1991,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; @@ -2299,11 +1999,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; } @@ -2333,16 +2033,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"\ + "\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; } @@ -2350,7 +2050,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; @@ -2359,11 +2059,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; } @@ -2394,35 +2094,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); @@ -2430,14 +2114,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; + 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(True, &ads))) { + if (!ADS_ERR_OK(ads_startup(c, true, &ads))) { return -1; } for (i = 0; i < argc; i++) { @@ -2447,12 +2140,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); @@ -2460,10 +2160,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]; } @@ -2472,15 +2180,42 @@ 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, + "Add a service principal", + "net ads keytab add\n" + " Add a service principal" + }, + { + "create", + net_ads_keytab_create, + NET_TRANSPORT_ADS, + "Create a fresh keytab", + "net ads keytab create\n" + " Create a fresh keytab" + }, + { + "flush", + net_ads_keytab_flush, + NET_TRANSPORT_ADS, + "Remove all keytab entries", + "net ads keytab flush\n" + " Remove all keytab entries" + }, + { + "list", + net_ads_keytab_list, + NET_TRANSPORT_ADS, + "List a keytab", + "net ads keytab list\n" + " List a keytab" + }, + {NULL, NULL, 0, NULL, NULL} }; if (!lp_use_kerberos_keytab()) { @@ -2488,26 +2223,21 @@ int net_ads_keytab(int argc, const char **argv) 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", error_message(ret)); @@ -2515,7 +2245,7 @@ static int net_ads_kerberos_renew(int argc, const char **argv) 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; @@ -2523,22 +2253,29 @@ static int net_ads_kerberos_pac(int argc, const char **argv) NTSTATUS status; int ret = -1; + 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); + 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 */ &pac); if (!NT_STATUS_IS_OK(status)) { @@ -2560,27 +2297,34 @@ 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) { @@ -2591,67 +2335,198 @@ static int net_ads_kerberos_kinit(int argc, const char **argv) 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, + "Retrieve Ticket Granting Ticket (TGT)", + "net ads kerberos kinit\n" + " Receive Ticket Granting Ticket (TGT)" + }, + { + "renew", + net_ads_kerberos_renew, + NET_TRANSPORT_ADS, + "Renew Ticket Granting Ticket from credential cache" + "net ads kerberos renew\n" + " Renew Ticket Granting Ticket from credential cache" + }, + { + "pac", + net_ads_kerberos_pac, + NET_TRANSPORT_ADS, + "Dump Kerberos PAC", + "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, + "Display details on remote ADS server", + "net ads info\n" + " Display details on remote ADS server" + }, + { + "join", + net_ads_join, + NET_TRANSPORT_ADS, + "Join the local machine to ADS realm", + "net ads join\n" + " Join the local machine to ADS realm" + }, + { + "testjoin", + net_ads_testjoin, + NET_TRANSPORT_ADS, + "Validate machine account", + "net ads testjoin\n" + " Validate machine account" + }, + { + "leave", + net_ads_leave, + NET_TRANSPORT_ADS, + "Remove the local machine from ADS", + "net ads leave\n" + " Remove the local machine from ADS" + }, + { + "status", + net_ads_status, + NET_TRANSPORT_ADS, + "Display machine account details", + "net ads status\n" + " Display machine account details" + }, + { + "user", + net_ads_user, + NET_TRANSPORT_ADS, + "List/modify users", + "net ads user\n" + " List/modify users" + }, + { + "group", + net_ads_group, + NET_TRANSPORT_ADS, + "List/modify groups", + "net ads group\n" + " List/modify groups" + }, + { + "dns", + net_ads_dns, + NET_TRANSPORT_ADS, + "Issue dynamic DNS update", + "net ads dns\n" + " Issue dynamic DNS update" + }, + { + "password", + net_ads_password, + NET_TRANSPORT_ADS, + "Change user passwords", + "net ads password\n" + " Change user passwords" + }, + { + "changetrustpw", + net_ads_changetrustpw, + NET_TRANSPORT_ADS, + "Change trust account password", + "net ads changetrustpw\n" + " Change trust account password" + }, + { + "printer", + net_ads_printer, + NET_TRANSPORT_ADS, + "List/modify printer entries", + "net ads printer\n" + " List/modify printer entries" + }, + { + "search", + net_ads_search, + NET_TRANSPORT_ADS, + "Issue LDAP search using filter", + "net ads search\n" + " Issue LDAP search using filter" + }, + { + "dn", + net_ads_dn, + NET_TRANSPORT_ADS, + "Issue LDAP search by DN", + "net ads dn\n" + " Issue LDAP search by DN" + }, + { + "sid", + net_ads_sid, + NET_TRANSPORT_ADS, + "Issue LDAP search by SID", + "net ads sid\n" + " Issue LDAP search by SID" + }, + { + "workgroup", + net_ads_workgroup, + NET_TRANSPORT_ADS, + "Display workgroup name", + "net ads workgroup\n" + " Display the workgroup name" + }, + { + "lookup", + net_ads_lookup, + NET_TRANSPORT_ADS, + "Perfom CLDAP query on DC", + "net ads lookup\n" + " Find the ADS DC using CLDAP lookups" + }, + { + "keytab", + net_ads_keytab, + NET_TRANSPORT_ADS, + "Manage local keytab file", + "net ads keytab\n" + " Manage local keytab file" + }, + { + "gpo", + net_ads_gpo, + NET_TRANSPORT_ADS, + "Manage group policy objects", + "net ads gpo\n" + " Manage group policy objects" + }, + { + "kerberos", + net_ads_kerberos, + NET_TRANSPORT_ADS, + "Manage kerberos keytab", + "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 @@ -2662,60 +2537,50 @@ static int net_ads_noads(void) return -1; } -int net_ads_keytab(int argc, const char **argv) -{ - return net_ads_noads(); -} - -int net_ads_kerberos(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_usage(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_help(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_changetrustpw(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_join(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_user(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 */