00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "includes.h"
00025 #include "utils/net.h"
00026
00027 #ifdef HAVE_ADS
00028
00029 int net_ads_usage(int argc, const char **argv)
00030 {
00031 d_printf("join [createupn[=principal]] [createcomputer=<org_unit>]\n");
00032 d_printf(" Join the local machine to a ADS realm\n");
00033 d_printf("leave\n");
00034 d_printf(" Remove the local machine from a ADS realm\n");
00035 d_printf("testjoin\n");
00036 d_printf(" Validates the machine account in the domain\n");
00037 d_printf("user\n");
00038 d_printf(" List, add, or delete users in the realm\n");
00039 d_printf("group\n");
00040 d_printf(" List, add, or delete groups in the realm\n");
00041 d_printf("info\n");
00042 d_printf(" Displays details regarding a specific AD server\n");
00043 d_printf("status\n");
00044 d_printf(" Display details regarding the machine's account in AD\n");
00045 d_printf("lookup\n");
00046 d_printf(" Performs CLDAP query of AD domain controllers\n");
00047 d_printf("password <username@realm> <password> -Uadmin_username@realm%%admin_pass\n");
00048 d_printf(" Change a user's password using an admin account\n");
00049 d_printf(" (note: use realm in UPPERCASE, prompts if password is obmitted)\n");
00050 d_printf("changetrustpw\n");
00051 d_printf(" Change the trust account password of this machine in the AD tree\n");
00052 d_printf("printer [info | publish | remove] <printername> <servername>\n");
00053 d_printf(" Lookup, add, or remove directory entry for a printer\n");
00054 d_printf("{search,dn,sid}\n");
00055 d_printf(" Issue LDAP search queries using a general filter, by DN, or by SID\n");
00056 d_printf("keytab\n");
00057 d_printf(" Manage a local keytab file based on the machine account in AD\n");
00058 d_printf("dns\n");
00059 d_printf(" Issue a dynamic DNS update request the server's hostname\n");
00060 d_printf(" (using the machine credentials)\n");
00061
00062 return -1;
00063 }
00064
00065
00066
00067
00068 static const char *assume_own_realm(void)
00069 {
00070 if (!opt_host && strequal(lp_workgroup(), opt_target_workgroup)) {
00071 return lp_realm();
00072 }
00073
00074 return NULL;
00075 }
00076
00077
00078
00079
00080 static int net_ads_cldap_netlogon(ADS_STRUCT *ads)
00081 {
00082 struct cldap_netlogon_reply reply;
00083
00084 if ( !ads_cldap_netlogon( inet_ntoa(ads->ldap_ip), ads->server.realm, &reply ) ) {
00085 d_fprintf(stderr, "CLDAP query failed!\n");
00086 return -1;
00087 }
00088
00089 d_printf("Information for Domain Controller: %s\n\n",
00090 inet_ntoa(ads->ldap_ip));
00091
00092 d_printf("Response Type: ");
00093 switch (reply.type) {
00094 case SAMLOGON_AD_UNK_R:
00095 d_printf("SAMLOGON\n");
00096 break;
00097 case SAMLOGON_AD_R:
00098 d_printf("SAMLOGON_USER\n");
00099 break;
00100 default:
00101 d_printf("0x%x\n", reply.type);
00102 break;
00103 }
00104 d_printf("GUID: %s\n",
00105 smb_uuid_string_static(smb_uuid_unpack_static(reply.guid)));
00106 d_printf("Flags:\n"
00107 "\tIs a PDC: %s\n"
00108 "\tIs a GC of the forest: %s\n"
00109 "\tIs an LDAP server: %s\n"
00110 "\tSupports DS: %s\n"
00111 "\tIs running a KDC: %s\n"
00112 "\tIs running time services: %s\n"
00113 "\tIs the closest DC: %s\n"
00114 "\tIs writable: %s\n"
00115 "\tHas a hardware clock: %s\n"
00116 "\tIs a non-domain NC serviced by LDAP server: %s\n",
00117 (reply.flags & ADS_PDC) ? "yes" : "no",
00118 (reply.flags & ADS_GC) ? "yes" : "no",
00119 (reply.flags & ADS_LDAP) ? "yes" : "no",
00120 (reply.flags & ADS_DS) ? "yes" : "no",
00121 (reply.flags & ADS_KDC) ? "yes" : "no",
00122 (reply.flags & ADS_TIMESERV) ? "yes" : "no",
00123 (reply.flags & ADS_CLOSEST) ? "yes" : "no",
00124 (reply.flags & ADS_WRITABLE) ? "yes" : "no",
00125 (reply.flags & ADS_GOOD_TIMESERV) ? "yes" : "no",
00126 (reply.flags & ADS_NDNC) ? "yes" : "no");
00127
00128 printf("Forest:\t\t\t%s\n", reply.forest);
00129 printf("Domain:\t\t\t%s\n", reply.domain);
00130 printf("Domain Controller:\t%s\n", reply.hostname);
00131
00132 printf("Pre-Win2k Domain:\t%s\n", reply.netbios_domain);
00133 printf("Pre-Win2k Hostname:\t%s\n", reply.netbios_hostname);
00134
00135 if (*reply.unk) printf("Unk:\t\t\t%s\n", reply.unk);
00136 if (*reply.user_name) printf("User name:\t%s\n", reply.user_name);
00137
00138 printf("Server Site Name :\t\t%s\n", reply.server_site_name);
00139 printf("Client Site Name :\t\t%s\n", reply.client_site_name);
00140
00141 d_printf("NT Version: %d\n", reply.version);
00142 d_printf("LMNT Token: %.2x\n", reply.lmnt_token);
00143 d_printf("LM20 Token: %.2x\n", reply.lm20_token);
00144
00145 return 0;
00146 }
00147
00148
00149
00150
00151
00152
00153 static int net_ads_lookup(int argc, const char **argv)
00154 {
00155 ADS_STRUCT *ads;
00156
00157 if (!ADS_ERR_OK(ads_startup_nobind(False, &ads))) {
00158 d_fprintf(stderr, "Didn't find the cldap server!\n");
00159 return -1;
00160 }
00161
00162 if (!ads->config.realm) {
00163 ads->config.realm = CONST_DISCARD(char *, opt_target_workgroup);
00164 ads->ldap_port = 389;
00165 }
00166
00167 return net_ads_cldap_netlogon(ads);
00168 }
00169
00170
00171
00172 static int net_ads_info(int argc, const char **argv)
00173 {
00174 ADS_STRUCT *ads;
00175
00176 if (!ADS_ERR_OK(ads_startup_nobind(False, &ads))) {
00177 d_fprintf(stderr, "Didn't find the ldap server!\n");
00178 return -1;
00179 }
00180
00181 if (!ads || !ads->config.realm) {
00182 d_fprintf(stderr, "Didn't find the ldap server!\n");
00183 return -1;
00184 }
00185
00186
00187
00188
00189 if ( !ADS_ERR_OK(ads_current_time( ads )) ) {
00190 d_fprintf( stderr, "Failed to get server's current time!\n");
00191 }
00192
00193 d_printf("LDAP server: %s\n", inet_ntoa(ads->ldap_ip));
00194 d_printf("LDAP server name: %s\n", ads->config.ldap_server_name);
00195 d_printf("Realm: %s\n", ads->config.realm);
00196 d_printf("Bind Path: %s\n", ads->config.bind_path);
00197 d_printf("LDAP port: %d\n", ads->ldap_port);
00198 d_printf("Server time: %s\n", http_timestring(ads->config.current_time));
00199
00200 d_printf("KDC server: %s\n", ads->auth.kdc_server );
00201 d_printf("Server time offset: %d\n", ads->auth.time_offset );
00202
00203 return 0;
00204 }
00205
00206 static void use_in_memory_ccache(void) {
00207
00208
00209 setenv(KRB5_ENV_CCNAME, "MEMORY:net_ads", 1);
00210 }
00211
00212 static ADS_STATUS ads_startup_int(BOOL only_own_domain, uint32 auth_flags, ADS_STRUCT **ads_ret)
00213 {
00214 ADS_STRUCT *ads = NULL;
00215 ADS_STATUS status;
00216 BOOL need_password = False;
00217 BOOL second_time = False;
00218 char *cp;
00219 const char *realm = NULL;
00220 BOOL tried_closest_dc = False;
00221
00222
00223
00224
00225
00226
00227 *ads_ret = NULL;
00228
00229 retry_connect:
00230 if (only_own_domain) {
00231 realm = lp_realm();
00232 } else {
00233 realm = assume_own_realm();
00234 }
00235
00236 ads = ads_init(realm, opt_target_workgroup, opt_host);
00237
00238 if (!opt_user_name) {
00239 opt_user_name = "administrator";
00240 }
00241
00242 if (opt_user_specified) {
00243 need_password = True;
00244 }
00245
00246 retry:
00247 if (!opt_password && need_password && !opt_machine_pass) {
00248 char *prompt = NULL;
00249 asprintf(&prompt,"%s's password: ", opt_user_name);
00250 if (!prompt) {
00251 ads_destroy(&ads);
00252 return ADS_ERROR(LDAP_NO_MEMORY);
00253 }
00254 opt_password = getpass(prompt);
00255 free(prompt);
00256 }
00257
00258 if (opt_password) {
00259 use_in_memory_ccache();
00260 SAFE_FREE(ads->auth.password);
00261 ads->auth.password = smb_xstrdup(opt_password);
00262 }
00263
00264 ads->auth.flags |= auth_flags;
00265 SAFE_FREE(ads->auth.user_name);
00266 ads->auth.user_name = smb_xstrdup(opt_user_name);
00267
00268
00269
00270
00271
00272
00273 if ((cp = strchr_m(ads->auth.user_name, '@'))!=0) {
00274 *cp++ = '\0';
00275 SAFE_FREE(ads->auth.realm);
00276 ads->auth.realm = smb_xstrdup(cp);
00277 strupper_m(ads->auth.realm);
00278 }
00279
00280 status = ads_connect(ads);
00281
00282 if (!ADS_ERR_OK(status)) {
00283
00284 if (NT_STATUS_EQUAL(ads_ntstatus(status),
00285 NT_STATUS_NO_LOGON_SERVERS)) {
00286 DEBUG(0,("ads_connect: %s\n", ads_errstr(status)));
00287 ads_destroy(&ads);
00288 return status;
00289 }
00290
00291 if (!need_password && !second_time && !(auth_flags & ADS_AUTH_NO_BIND)) {
00292 need_password = True;
00293 second_time = True;
00294 goto retry;
00295 } else {
00296 ads_destroy(&ads);
00297 return status;
00298 }
00299 }
00300
00301
00302
00303
00304
00305 if ((only_own_domain || !opt_host) && !tried_closest_dc) {
00306
00307 tried_closest_dc = True;
00308
00309 if (!ads->config.tried_closest_dc) {
00310
00311 namecache_delete(ads->server.realm, 0x1C);
00312 namecache_delete(ads->server.workgroup, 0x1C);
00313
00314 ads_destroy(&ads);
00315 ads = NULL;
00316
00317 goto retry_connect;
00318 }
00319 }
00320
00321 *ads_ret = ads;
00322 return status;
00323 }
00324
00325 ADS_STATUS ads_startup(BOOL only_own_domain, ADS_STRUCT **ads)
00326 {
00327 return ads_startup_int(only_own_domain, 0, ads);
00328 }
00329
00330 ADS_STATUS ads_startup_nobind(BOOL only_own_domain, ADS_STRUCT **ads)
00331 {
00332 return ads_startup_int(only_own_domain, ADS_AUTH_NO_BIND, ads);
00333 }
00334
00335
00336
00337
00338
00339
00340 static int net_ads_check_int(const char *realm, const char *workgroup, const char *host)
00341 {
00342 ADS_STRUCT *ads;
00343 ADS_STATUS status;
00344
00345 if ( (ads = ads_init( realm, workgroup, host )) == NULL ) {
00346 return -1;
00347 }
00348
00349 ads->auth.flags |= ADS_AUTH_NO_BIND;
00350
00351 status = ads_connect(ads);
00352 if ( !ADS_ERR_OK(status) ) {
00353 return -1;
00354 }
00355
00356 ads_destroy(&ads);
00357 return 0;
00358 }
00359
00360 int net_ads_check_our_domain(void)
00361 {
00362 return net_ads_check_int(lp_realm(), lp_workgroup(), NULL);
00363 }
00364
00365 int net_ads_check(void)
00366 {
00367 return net_ads_check_int(NULL, opt_workgroup, opt_host);
00368 }
00369
00370
00371
00372 static int net_ads_workgroup(int argc, const char **argv)
00373 {
00374 ADS_STRUCT *ads;
00375 struct cldap_netlogon_reply reply;
00376
00377 if (!ADS_ERR_OK(ads_startup_nobind(False, &ads))) {
00378 d_fprintf(stderr, "Didn't find the cldap server!\n");
00379 return -1;
00380 }
00381
00382 if (!ads->config.realm) {
00383 ads->config.realm = CONST_DISCARD(char *, opt_target_workgroup);
00384 ads->ldap_port = 389;
00385 }
00386
00387 if ( !ads_cldap_netlogon( inet_ntoa(ads->ldap_ip), ads->server.realm, &reply ) ) {
00388 d_fprintf(stderr, "CLDAP query failed!\n");
00389 return -1;
00390 }
00391
00392 d_printf("Workgroup: %s\n", reply.netbios_domain);
00393
00394 ads_destroy(&ads);
00395
00396 return 0;
00397 }
00398
00399
00400
00401 static BOOL usergrp_display(char *field, void **values, void *data_area)
00402 {
00403 char **disp_fields = (char **) data_area;
00404
00405 if (!field) {
00406 if (disp_fields[0]) {
00407 if (!strchr_m(disp_fields[0], '$')) {
00408 if (disp_fields[1])
00409 d_printf("%-21.21s %s\n",
00410 disp_fields[0], disp_fields[1]);
00411 else
00412 d_printf("%s\n", disp_fields[0]);
00413 }
00414 }
00415 SAFE_FREE(disp_fields[0]);
00416 SAFE_FREE(disp_fields[1]);
00417 return True;
00418 }
00419 if (!values)
00420 return True;
00421 if (StrCaseCmp(field, "sAMAccountName") == 0) {
00422 disp_fields[0] = SMB_STRDUP((char *) values[0]);
00423 }
00424 if (StrCaseCmp(field, "description") == 0)
00425 disp_fields[1] = SMB_STRDUP((char *) values[0]);
00426 return True;
00427 }
00428
00429 static int net_ads_user_usage(int argc, const char **argv)
00430 {
00431 return net_help_user(argc, argv);
00432 }
00433
00434 static int ads_user_add(int argc, const char **argv)
00435 {
00436 ADS_STRUCT *ads;
00437 ADS_STATUS status;
00438 char *upn, *userdn;
00439 LDAPMessage *res=NULL;
00440 int rc = -1;
00441 char *ou_str = NULL;
00442
00443 if (argc < 1) return net_ads_user_usage(argc, argv);
00444
00445 if (!ADS_ERR_OK(ads_startup(False, &ads))) {
00446 return -1;
00447 }
00448
00449 status = ads_find_user_acct(ads, &res, argv[0]);
00450
00451 if (!ADS_ERR_OK(status)) {
00452 d_fprintf(stderr, "ads_user_add: %s\n", ads_errstr(status));
00453 goto done;
00454 }
00455
00456 if (ads_count_replies(ads, res)) {
00457 d_fprintf(stderr, "ads_user_add: User %s already exists\n", argv[0]);
00458 goto done;
00459 }
00460
00461 if (opt_container) {
00462 ou_str = SMB_STRDUP(opt_container);
00463 } else {
00464 ou_str = ads_default_ou_string(ads, WELL_KNOWN_GUID_USERS);
00465 }
00466
00467 status = ads_add_user_acct(ads, argv[0], ou_str, opt_comment);
00468
00469 if (!ADS_ERR_OK(status)) {
00470 d_fprintf(stderr, "Could not add user %s: %s\n", argv[0],
00471 ads_errstr(status));
00472 goto done;
00473 }
00474
00475
00476 if (argc == 1) {
00477 d_printf("User %s added\n", argv[0]);
00478 rc = 0;
00479 goto done;
00480 }
00481
00482
00483 asprintf(&upn, "%s@%s", argv[0], ads->config.realm);
00484 status = ads_krb5_set_password(ads->auth.kdc_server, upn, argv[1],
00485 ads->auth.time_offset);
00486 safe_free(upn);
00487 if (ADS_ERR_OK(status)) {
00488 d_printf("User %s added\n", argv[0]);
00489 rc = 0;
00490 goto done;
00491 }
00492
00493
00494 d_fprintf(stderr, "Could not add user %s. Error setting password %s\n",
00495 argv[0], ads_errstr(status));
00496 ads_msgfree(ads, res);
00497 status=ads_find_user_acct(ads, &res, argv[0]);
00498 if (ADS_ERR_OK(status)) {
00499 userdn = ads_get_dn(ads, res);
00500 ads_del_dn(ads, userdn);
00501 ads_memfree(ads, userdn);
00502 }
00503
00504 done:
00505 if (res)
00506 ads_msgfree(ads, res);
00507 ads_destroy(&ads);
00508 SAFE_FREE(ou_str);
00509 return rc;
00510 }
00511
00512 static int ads_user_info(int argc, const char **argv)
00513 {
00514 ADS_STRUCT *ads;
00515 ADS_STATUS rc;
00516 LDAPMessage *res;
00517 const char *attrs[] = {"memberOf", NULL};
00518 char *searchstring=NULL;
00519 char **grouplist;
00520 char *escaped_user;
00521
00522 if (argc < 1) {
00523 return net_ads_user_usage(argc, argv);
00524 }
00525
00526 escaped_user = escape_ldap_string_alloc(argv[0]);
00527
00528 if (!escaped_user) {
00529 d_fprintf(stderr, "ads_user_info: failed to escape user %s\n", argv[0]);
00530 return -1;
00531 }
00532
00533 if (!ADS_ERR_OK(ads_startup(False, &ads))) {
00534 SAFE_FREE(escaped_user);
00535 return -1;
00536 }
00537
00538 asprintf(&searchstring, "(sAMAccountName=%s)", escaped_user);
00539 rc = ads_search(ads, &res, searchstring, attrs);
00540 safe_free(searchstring);
00541
00542 if (!ADS_ERR_OK(rc)) {
00543 d_fprintf(stderr, "ads_search: %s\n", ads_errstr(rc));
00544 ads_destroy(&ads);
00545 SAFE_FREE(escaped_user);
00546 return -1;
00547 }
00548
00549 grouplist = ldap_get_values((LDAP *)ads->ld,
00550 (LDAPMessage *)res, "memberOf");
00551
00552 if (grouplist) {
00553 int i;
00554 char **groupname;
00555 for (i=0;grouplist[i];i++) {
00556 groupname = ldap_explode_dn(grouplist[i], 1);
00557 d_printf("%s\n", groupname[0]);
00558 ldap_value_free(groupname);
00559 }
00560 ldap_value_free(grouplist);
00561 }
00562
00563 ads_msgfree(ads, res);
00564 ads_destroy(&ads);
00565 SAFE_FREE(escaped_user);
00566 return 0;
00567 }
00568
00569 static int ads_user_delete(int argc, const char **argv)
00570 {
00571 ADS_STRUCT *ads;
00572 ADS_STATUS rc;
00573 LDAPMessage *res = NULL;
00574 char *userdn;
00575
00576 if (argc < 1) {
00577 return net_ads_user_usage(argc, argv);
00578 }
00579
00580 if (!ADS_ERR_OK(ads_startup(False, &ads))) {
00581 return -1;
00582 }
00583
00584 rc = ads_find_user_acct(ads, &res, argv[0]);
00585 if (!ADS_ERR_OK(rc) || ads_count_replies(ads, res) != 1) {
00586 d_printf("User %s does not exist.\n", argv[0]);
00587 ads_msgfree(ads, res);
00588 ads_destroy(&ads);
00589 return -1;
00590 }
00591 userdn = ads_get_dn(ads, res);
00592 ads_msgfree(ads, res);
00593 rc = ads_del_dn(ads, userdn);
00594 ads_memfree(ads, userdn);
00595 if (ADS_ERR_OK(rc)) {
00596 d_printf("User %s deleted\n", argv[0]);
00597 ads_destroy(&ads);
00598 return 0;
00599 }
00600 d_fprintf(stderr, "Error deleting user %s: %s\n", argv[0],
00601 ads_errstr(rc));
00602 ads_destroy(&ads);
00603 return -1;
00604 }
00605
00606 int net_ads_user(int argc, const char **argv)
00607 {
00608 struct functable func[] = {
00609 {"ADD", ads_user_add},
00610 {"INFO", ads_user_info},
00611 {"DELETE", ads_user_delete},
00612 {NULL, NULL}
00613 };
00614 ADS_STRUCT *ads;
00615 ADS_STATUS rc;
00616 const char *shortattrs[] = {"sAMAccountName", NULL};
00617 const char *longattrs[] = {"sAMAccountName", "description", NULL};
00618 char *disp_fields[2] = {NULL, NULL};
00619
00620 if (argc == 0) {
00621 if (!ADS_ERR_OK(ads_startup(False, &ads))) {
00622 return -1;
00623 }
00624
00625 if (opt_long_list_entries)
00626 d_printf("\nUser name Comment"\
00627 "\n-----------------------------\n");
00628
00629 rc = ads_do_search_all_fn(ads, ads->config.bind_path,
00630 LDAP_SCOPE_SUBTREE,
00631 "(objectCategory=user)",
00632 opt_long_list_entries ? longattrs :
00633 shortattrs, usergrp_display,
00634 disp_fields);
00635 ads_destroy(&ads);
00636 return ADS_ERR_OK(rc) ? 0 : -1;
00637 }
00638
00639 return net_run_function(argc, argv, func, net_ads_user_usage);
00640 }
00641
00642 static int net_ads_group_usage(int argc, const char **argv)
00643 {
00644 return net_help_group(argc, argv);
00645 }
00646
00647 static int ads_group_add(int argc, const char **argv)
00648 {
00649 ADS_STRUCT *ads;
00650 ADS_STATUS status;
00651 LDAPMessage *res=NULL;
00652 int rc = -1;
00653 char *ou_str = NULL;
00654
00655 if (argc < 1) {
00656 return net_ads_group_usage(argc, argv);
00657 }
00658
00659 if (!ADS_ERR_OK(ads_startup(False, &ads))) {
00660 return -1;
00661 }
00662
00663 status = ads_find_user_acct(ads, &res, argv[0]);
00664
00665 if (!ADS_ERR_OK(status)) {
00666 d_fprintf(stderr, "ads_group_add: %s\n", ads_errstr(status));
00667 goto done;
00668 }
00669
00670 if (ads_count_replies(ads, res)) {
00671 d_fprintf(stderr, "ads_group_add: Group %s already exists\n", argv[0]);
00672 goto done;
00673 }
00674
00675 if (opt_container) {
00676 ou_str = SMB_STRDUP(opt_container);
00677 } else {
00678 ou_str = ads_default_ou_string(ads, WELL_KNOWN_GUID_USERS);
00679 }
00680
00681 status = ads_add_group_acct(ads, argv[0], ou_str, opt_comment);
00682
00683 if (ADS_ERR_OK(status)) {
00684 d_printf("Group %s added\n", argv[0]);
00685 rc = 0;
00686 } else {
00687 d_fprintf(stderr, "Could not add group %s: %s\n", argv[0],
00688 ads_errstr(status));
00689 }
00690
00691 done:
00692 if (res)
00693 ads_msgfree(ads, res);
00694 ads_destroy(&ads);
00695 SAFE_FREE(ou_str);
00696 return rc;
00697 }
00698
00699 static int ads_group_delete(int argc, const char **argv)
00700 {
00701 ADS_STRUCT *ads;
00702 ADS_STATUS rc;
00703 LDAPMessage *res = NULL;
00704 char *groupdn;
00705
00706 if (argc < 1) {
00707 return net_ads_group_usage(argc, argv);
00708 }
00709
00710 if (!ADS_ERR_OK(ads_startup(False, &ads))) {
00711 return -1;
00712 }
00713
00714 rc = ads_find_user_acct(ads, &res, argv[0]);
00715 if (!ADS_ERR_OK(rc) || ads_count_replies(ads, res) != 1) {
00716 d_printf("Group %s does not exist.\n", argv[0]);
00717 ads_msgfree(ads, res);
00718 ads_destroy(&ads);
00719 return -1;
00720 }
00721 groupdn = ads_get_dn(ads, res);
00722 ads_msgfree(ads, res);
00723 rc = ads_del_dn(ads, groupdn);
00724 ads_memfree(ads, groupdn);
00725 if (ADS_ERR_OK(rc)) {
00726 d_printf("Group %s deleted\n", argv[0]);
00727 ads_destroy(&ads);
00728 return 0;
00729 }
00730 d_fprintf(stderr, "Error deleting group %s: %s\n", argv[0],
00731 ads_errstr(rc));
00732 ads_destroy(&ads);
00733 return -1;
00734 }
00735
00736 int net_ads_group(int argc, const char **argv)
00737 {
00738 struct functable func[] = {
00739 {"ADD", ads_group_add},
00740 {"DELETE", ads_group_delete},
00741 {NULL, NULL}
00742 };
00743 ADS_STRUCT *ads;
00744 ADS_STATUS rc;
00745 const char *shortattrs[] = {"sAMAccountName", NULL};
00746 const char *longattrs[] = {"sAMAccountName", "description", NULL};
00747 char *disp_fields[2] = {NULL, NULL};
00748
00749 if (argc == 0) {
00750 if (!ADS_ERR_OK(ads_startup(False, &ads))) {
00751 return -1;
00752 }
00753
00754 if (opt_long_list_entries)
00755 d_printf("\nGroup name Comment"\
00756 "\n-----------------------------\n");
00757 rc = ads_do_search_all_fn(ads, ads->config.bind_path,
00758 LDAP_SCOPE_SUBTREE,
00759 "(objectCategory=group)",
00760 opt_long_list_entries ? longattrs :
00761 shortattrs, usergrp_display,
00762 disp_fields);
00763
00764 ads_destroy(&ads);
00765 return ADS_ERR_OK(rc) ? 0 : -1;
00766 }
00767 return net_run_function(argc, argv, func, net_ads_group_usage);
00768 }
00769
00770 static int net_ads_status(int argc, const char **argv)
00771 {
00772 ADS_STRUCT *ads;
00773 ADS_STATUS rc;
00774 LDAPMessage *res;
00775
00776 if (!ADS_ERR_OK(ads_startup(True, &ads))) {
00777 return -1;
00778 }
00779
00780 rc = ads_find_machine_acct(ads, &res, global_myname());
00781 if (!ADS_ERR_OK(rc)) {
00782 d_fprintf(stderr, "ads_find_machine_acct: %s\n", ads_errstr(rc));
00783 ads_destroy(&ads);
00784 return -1;
00785 }
00786
00787 if (ads_count_replies(ads, res) == 0) {
00788 d_fprintf(stderr, "No machine account for '%s' found\n", global_myname());
00789 ads_destroy(&ads);
00790 return -1;
00791 }
00792
00793 ads_dump(ads, res);
00794 ads_destroy(&ads);
00795 return 0;
00796 }
00797
00798
00799
00800
00801
00802
00803
00804
00805 static int net_ads_leave(int argc, const char **argv)
00806 {
00807 ADS_STRUCT *ads = NULL;
00808 ADS_STATUS adsret;
00809 NTSTATUS status;
00810 int ret = -1;
00811 struct cli_state *cli = NULL;
00812 TALLOC_CTX *ctx;
00813 DOM_SID *dom_sid = NULL;
00814 char *short_domain_name = NULL;
00815
00816 if (!secrets_init()) {
00817 DEBUG(1,("Failed to initialise secrets database\n"));
00818 return -1;
00819 }
00820
00821 if (!(ctx = talloc_init("net_ads_leave"))) {
00822 d_fprintf(stderr, "Could not initialise talloc context.\n");
00823 return -1;
00824 }
00825
00826
00827
00828
00829 if (!ADS_ERR_OK(ads_startup(True, &ads))) {
00830 return -1;
00831 }
00832
00833
00834
00835 if ( !NT_STATUS_IS_OK(connect_to_ipc_krb5(&cli, &ads->ldap_ip,
00836 ads->config.ldap_server_name)) )
00837 {
00838 goto done;
00839 }
00840
00841 if ( !NT_STATUS_IS_OK(netdom_get_domain_sid( ctx, cli, &short_domain_name, &dom_sid )) ) {
00842 goto done;
00843 }
00844
00845 saf_delete( short_domain_name );
00846
00847 status = netdom_leave_domain(ctx, cli, dom_sid);
00848
00849
00850
00851 adsret = ads_leave_realm(ads, global_myname());
00852 if (ADS_ERR_OK(adsret)) {
00853 d_printf("Deleted account for '%s' in realm '%s'\n",
00854 global_myname(), ads->config.realm);
00855 ret = 0;
00856 } else {
00857
00858 if (NT_STATUS_IS_OK(status)) {
00859 d_printf("Disabled account for '%s' in realm '%s'\n",
00860 global_myname(), ads->config.realm);
00861 ret = 0;
00862 } else {
00863 d_fprintf(stderr, "Failed to disable machine account for '%s' in realm '%s'\n",
00864 global_myname(), ads->config.realm);
00865 }
00866 }
00867
00868 done:
00869
00870 if ( cli )
00871 cli_shutdown(cli);
00872
00873 ads_destroy(&ads);
00874 TALLOC_FREE( ctx );
00875
00876 return ret;
00877 }
00878
00879 static NTSTATUS net_ads_join_ok(void)
00880 {
00881 ADS_STRUCT *ads = NULL;
00882 ADS_STATUS status;
00883
00884 if (!secrets_init()) {
00885 DEBUG(1,("Failed to initialise secrets database\n"));
00886 return NT_STATUS_ACCESS_DENIED;
00887 }
00888
00889 net_use_krb_machine_account();
00890
00891 status = ads_startup(True, &ads);
00892 if (!ADS_ERR_OK(status)) {
00893 return ads_ntstatus(status);
00894 }
00895
00896 ads_destroy(&ads);
00897 return NT_STATUS_OK;
00898 }
00899
00900
00901
00902
00903 int net_ads_testjoin(int argc, const char **argv)
00904 {
00905 NTSTATUS status;
00906 use_in_memory_ccache();
00907
00908
00909 status = net_ads_join_ok();
00910 if (!NT_STATUS_IS_OK(status)) {
00911 fprintf(stderr,"Join to domain is not valid: %s\n",
00912 get_friendly_nt_error_msg(status));
00913 return -1;
00914 }
00915
00916 printf("Join is OK\n");
00917 return 0;
00918 }
00919
00920
00921
00922
00923
00924 static NTSTATUS check_ads_config( void )
00925 {
00926 if (lp_server_role() != ROLE_DOMAIN_MEMBER ) {
00927 d_printf("Host is not configured as a member server.\n");
00928 return NT_STATUS_INVALID_DOMAIN_ROLE;
00929 }
00930
00931 if (strlen(global_myname()) > 15) {
00932 d_printf("Our netbios name can be at most 15 chars long, "
00933 "\"%s\" is %u chars long\n", global_myname(),
00934 (unsigned int)strlen(global_myname()));
00935 return NT_STATUS_NAME_TOO_LONG;
00936 }
00937
00938 if ( lp_security() == SEC_ADS && !*lp_realm()) {
00939 d_fprintf(stderr, "realm must be set in in %s for ADS "
00940 "join to succeed.\n", dyn_CONFIGFILE);
00941 return NT_STATUS_INVALID_PARAMETER;
00942 }
00943
00944 if (!secrets_init()) {
00945 DEBUG(1,("Failed to initialise secrets database\n"));
00946
00947 return NT_STATUS_ACCESS_DENIED;
00948 }
00949
00950 return NT_STATUS_OK;
00951 }
00952
00953
00954
00955
00956
00957 static NTSTATUS net_join_domain(TALLOC_CTX *ctx, const char *servername,
00958 struct in_addr *ip, char **domain,
00959 DOM_SID **dom_sid,
00960 const char *password)
00961 {
00962 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
00963 struct cli_state *cli = NULL;
00964
00965 ret = connect_to_ipc_krb5(&cli, ip, servername);
00966 if ( !NT_STATUS_IS_OK(ret) ) {
00967 goto done;
00968 }
00969
00970 ret = netdom_get_domain_sid( ctx, cli, domain, dom_sid );
00971 if ( !NT_STATUS_IS_OK(ret) ) {
00972 goto done;
00973 }
00974
00975
00976
00977
00978 saf_store( *domain, cli->desthost );
00979
00980 ret = netdom_join_domain( ctx, cli, *dom_sid, password, ND_TYPE_AD );
00981
00982 done:
00983 if ( cli )
00984 cli_shutdown(cli);
00985
00986 return ret;
00987 }
00988
00989
00990
00991
00992
00993 static ADS_STATUS net_set_machine_spn(TALLOC_CTX *ctx, ADS_STRUCT *ads_s )
00994 {
00995 ADS_STATUS status = ADS_ERROR(LDAP_SERVER_DOWN);
00996 char *new_dn;
00997 ADS_MODLIST mods;
00998 const char *servicePrincipalName[3] = {NULL, NULL, NULL};
00999 char *psp;
01000 fstring my_fqdn;
01001 LDAPMessage *res = NULL;
01002 char *dn_string = NULL;
01003 const char *machine_name = global_myname();
01004 int count;
01005
01006 if ( !machine_name ) {
01007 return ADS_ERROR(LDAP_NO_MEMORY);
01008 }
01009
01010
01011
01012 status = ads_find_machine_acct(ads_s, &res, machine_name);
01013 if (!ADS_ERR_OK(status))
01014 return status;
01015
01016 if ( (count = ads_count_replies(ads_s, res)) != 1 ) {
01017 DEBUG(1,("net_set_machine_spn: %d entries returned!\n", count));
01018 return ADS_ERROR(LDAP_NO_MEMORY);
01019 }
01020
01021 if ( (dn_string = ads_get_dn(ads_s, res)) == NULL ) {
01022 DEBUG(1, ("ads_add_machine_acct: ads_get_dn returned NULL (malloc failure?)\n"));
01023 goto done;
01024 }
01025
01026 new_dn = talloc_strdup(ctx, dn_string);
01027 ads_memfree(ads_s, dn_string);
01028 if (!new_dn) {
01029 return ADS_ERROR(LDAP_NO_MEMORY);
01030 }
01031
01032
01033
01034 if ( !(psp = talloc_asprintf(ctx, "HOST/%s", machine_name)) )
01035 goto done;
01036 strupper_m(psp);
01037 servicePrincipalName[0] = psp;
01038
01039 name_to_fqdn(my_fqdn, machine_name);
01040 strlower_m(my_fqdn);
01041 if ( !(psp = talloc_asprintf(ctx, "HOST/%s", my_fqdn)) )
01042 goto done;
01043 servicePrincipalName[1] = psp;
01044
01045 if (!(mods = ads_init_mods(ctx))) {
01046 goto done;
01047 }
01048
01049
01050
01051 ads_mod_str(ctx, &mods, "dNSHostName", my_fqdn);
01052 ads_mod_strlist(ctx, &mods, "servicePrincipalName", servicePrincipalName);
01053
01054 status = ads_gen_mod(ads_s, new_dn, mods);
01055
01056 done:
01057 ads_msgfree(ads_s, res);
01058
01059 return status;
01060 }
01061
01062
01063
01064
01065
01066 static ADS_STATUS net_set_machine_upn(TALLOC_CTX *ctx, ADS_STRUCT *ads_s, const char *upn )
01067 {
01068 ADS_STATUS status = ADS_ERROR(LDAP_SERVER_DOWN);
01069 char *new_dn;
01070 ADS_MODLIST mods;
01071 LDAPMessage *res = NULL;
01072 char *dn_string = NULL;
01073 const char *machine_name = global_myname();
01074 int count;
01075
01076 if ( !machine_name ) {
01077 return ADS_ERROR(LDAP_NO_MEMORY);
01078 }
01079
01080
01081
01082 status = ads_find_machine_acct(ads_s, &res, machine_name);
01083 if (!ADS_ERR_OK(status))
01084 return status;
01085
01086 if ( (count = ads_count_replies(ads_s, res)) != 1 ) {
01087 DEBUG(1,("net_set_machine_spn: %d entries returned!\n", count));
01088 return ADS_ERROR(LDAP_NO_MEMORY);
01089 }
01090
01091 if ( (dn_string = ads_get_dn(ads_s, res)) == NULL ) {
01092 DEBUG(1, ("ads_add_machine_acct: ads_get_dn returned NULL (malloc failure?)\n"));
01093 goto done;
01094 }
01095
01096 new_dn = talloc_strdup(ctx, dn_string);
01097 ads_memfree(ads_s, dn_string);
01098 if (!new_dn) {
01099 return ADS_ERROR(LDAP_NO_MEMORY);
01100 }
01101
01102
01103
01104 if (!(mods = ads_init_mods(ctx))) {
01105 goto done;
01106 }
01107
01108
01109
01110 ads_mod_str(ctx, &mods, "userPrincipalName", upn);
01111
01112 status = ads_gen_mod(ads_s, new_dn, mods);
01113
01114 done:
01115 ads_msgfree(ads_s, res);
01116
01117 return status;
01118 }
01119
01120
01121
01122
01123
01124 static ADS_STATUS net_set_os_attributes(TALLOC_CTX *ctx, ADS_STRUCT *ads_s,
01125 const char *os_name, const char *os_version )
01126 {
01127 ADS_STATUS status = ADS_ERROR(LDAP_SERVER_DOWN);
01128 char *new_dn;
01129 ADS_MODLIST mods;
01130 LDAPMessage *res = NULL;
01131 char *dn_string = NULL;
01132 const char *machine_name = global_myname();
01133 int count;
01134 char *os_sp = NULL;
01135
01136 if ( !os_name || !os_version ) {
01137 return ADS_ERROR(LDAP_NO_MEMORY);
01138 }
01139
01140
01141
01142 status = ads_find_machine_acct(ads_s, &res, machine_name);
01143 if (!ADS_ERR_OK(status))
01144 return status;
01145
01146 if ( (count = ads_count_replies(ads_s, res)) != 1 ) {
01147 DEBUG(1,("net_set_machine_spn: %d entries returned!\n", count));
01148 return ADS_ERROR(LDAP_NO_MEMORY);
01149 }
01150
01151 if ( (dn_string = ads_get_dn(ads_s, res)) == NULL ) {
01152 DEBUG(1, ("ads_add_machine_acct: ads_get_dn returned NULL (malloc failure?)\n"));
01153 goto done;
01154 }
01155
01156 new_dn = talloc_strdup(ctx, dn_string);
01157 ads_memfree(ads_s, dn_string);
01158 if (!new_dn) {
01159 return ADS_ERROR(LDAP_NO_MEMORY);
01160 }
01161
01162
01163
01164 if (!(mods = ads_init_mods(ctx))) {
01165 goto done;
01166 }
01167
01168 os_sp = talloc_asprintf( ctx, "Samba %s", SAMBA_VERSION_STRING );
01169
01170
01171
01172 ads_mod_str(ctx, &mods, "operatingSystem", os_name);
01173 ads_mod_str(ctx, &mods, "operatingSystemVersion", os_version);
01174 if ( os_sp )
01175 ads_mod_str(ctx, &mods, "operatingSystemServicePack", os_sp);
01176
01177 status = ads_gen_mod(ads_s, new_dn, mods);
01178
01179 done:
01180 ads_msgfree(ads_s, res);
01181 TALLOC_FREE( os_sp );
01182
01183 return status;
01184 }
01185
01186
01187
01188
01189
01190 static ADS_STATUS net_precreate_machine_acct( ADS_STRUCT *ads, const char *ou )
01191 {
01192 ADS_STATUS rc = ADS_ERROR(LDAP_SERVER_DOWN);
01193 char *dn, *ou_str;
01194 LDAPMessage *res = NULL;
01195
01196 ou_str = ads_ou_string(ads, ou);
01197 if ((asprintf(&dn, "%s,%s", ou_str, ads->config.bind_path)) == -1) {
01198 SAFE_FREE(ou_str);
01199 return ADS_ERROR(LDAP_NO_MEMORY);
01200 }
01201
01202 rc = ads_search_dn(ads, &res, dn, NULL);
01203 ads_msgfree(ads, res);
01204
01205 if (ADS_ERR_OK(rc)) {
01206
01207
01208
01209 rc = ads_create_machine_acct( ads, global_myname(), dn );
01210 if ( rc.error_type == ENUM_ADS_ERROR_LDAP && rc.err.rc == LDAP_ALREADY_EXISTS ) {
01211 rc = ADS_SUCCESS;
01212 }
01213 }
01214
01215 SAFE_FREE( ou_str );
01216 SAFE_FREE( dn );
01217
01218 return rc;
01219 }
01220
01221
01222
01223
01224 static BOOL net_derive_salting_principal( TALLOC_CTX *ctx, ADS_STRUCT *ads )
01225 {
01226 uint32 domain_func;
01227 ADS_STATUS status;
01228 fstring salt;
01229 char *std_salt;
01230 LDAPMessage *res = NULL;
01231 const char *machine_name = global_myname();
01232
01233 status = ads_domain_func_level( ads, &domain_func );
01234 if ( !ADS_ERR_OK(status) ) {
01235 DEBUG(2,("Failed to determine domain functional level!\n"));
01236 return False;
01237 }
01238
01239
01240
01241 if ( (std_salt = kerberos_standard_des_salt()) == NULL ) {
01242 d_fprintf(stderr, "net_derive_salting_principal: failed to obtain stanard DES salt\n");
01243 return False;
01244 }
01245
01246 fstrcpy( salt, std_salt );
01247 SAFE_FREE( std_salt );
01248
01249
01250
01251 if ( domain_func == DS_DOMAIN_FUNCTION_2000 ) {
01252 char *upn;
01253 int count;
01254
01255 status = ads_find_machine_acct(ads, &res, machine_name);
01256 if (!ADS_ERR_OK(status)) {
01257 return False;
01258 }
01259
01260 if ( (count = ads_count_replies(ads, res)) != 1 ) {
01261 DEBUG(1,("net_set_machine_spn: %d entries returned!\n", count));
01262 return False;
01263 }
01264
01265 upn = ads_pull_string(ads, ctx, res, "userPrincipalName");
01266 if ( upn ) {
01267 fstrcpy( salt, upn );
01268 }
01269
01270 ads_msgfree(ads, res);
01271 }
01272
01273 return kerberos_secrets_store_des_salt( salt );
01274 }
01275
01276
01277
01278
01279
01280 #if defined(WITH_DNS_UPDATES)
01281 #include "dns.h"
01282 DNS_ERROR DoDNSUpdate(char *pszServerName,
01283 const char *pszDomainName,
01284 const char *pszHostName,
01285 const struct in_addr *iplist, int num_addrs );
01286
01287
01288 static NTSTATUS net_update_dns_internal(TALLOC_CTX *ctx, ADS_STRUCT *ads,
01289 const char *machine_name,
01290 const struct in_addr *addrs,
01291 int num_addrs)
01292 {
01293 struct dns_rr_ns *nameservers = NULL;
01294 int ns_count = 0;
01295 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
01296 DNS_ERROR dns_err;
01297 fstring dns_server;
01298 const char *dnsdomain = NULL;
01299 char *root_domain = NULL;
01300
01301 if ( (dnsdomain = strchr_m( machine_name, '.')) == NULL ) {
01302 d_printf("No DNS domain configured for %s. "
01303 "Unable to perform DNS Update.\n", machine_name);
01304 status = NT_STATUS_INVALID_PARAMETER;
01305 goto done;
01306 }
01307 dnsdomain++;
01308
01309 status = ads_dns_lookup_ns( ctx, dnsdomain, &nameservers, &ns_count );
01310 if ( !NT_STATUS_IS_OK(status) || (ns_count == 0)) {
01311
01312
01313
01314
01315 const char *rootname_attrs[] = { "rootDomainNamingContext", NULL };
01316 LDAPMessage *msg = NULL;
01317 char *root_dn;
01318 ADS_STATUS ads_status;
01319
01320 if ( !ads->ld ) {
01321 ads_status = ads_connect( ads );
01322 if ( !ADS_ERR_OK(ads_status) ) {
01323 DEBUG(0,("net_update_dns_internal: Failed to connect to our DC!\n"));
01324 goto done;
01325 }
01326 }
01327
01328 ads_status = ads_do_search(ads, "", LDAP_SCOPE_BASE,
01329 "(objectclass=*)", rootname_attrs, &msg);
01330 if (!ADS_ERR_OK(ads_status)) {
01331 goto done;
01332 }
01333
01334 root_dn = ads_pull_string(ads, ctx, msg, "rootDomainNamingContext");
01335 if ( !root_dn ) {
01336 ads_msgfree( ads, msg );
01337 goto done;
01338 }
01339
01340 root_domain = ads_build_domain( root_dn );
01341
01342
01343 ads_msgfree( ads, msg );
01344
01345
01346
01347 status = ads_dns_lookup_ns( ctx, root_domain, &nameservers, &ns_count );
01348
01349 if ( !NT_STATUS_IS_OK(status) || (ns_count == 0)) {
01350 DEBUG(3,("net_ads_join: Failed to find name server for the %s "
01351 "realm\n", ads->config.realm));
01352 goto done;
01353 }
01354
01355 dnsdomain = root_domain;
01356
01357 }
01358
01359
01360
01361
01362 fstrcpy( dns_server, nameservers[0].hostname );
01363
01364 dns_err = DoDNSUpdate(dns_server, dnsdomain, machine_name, addrs, num_addrs);
01365 if (!ERR_DNS_IS_OK(dns_err)) {
01366 status = NT_STATUS_UNSUCCESSFUL;
01367 }
01368
01369 done:
01370
01371 SAFE_FREE( root_domain );
01372
01373 return status;
01374 }
01375
01376 static NTSTATUS net_update_dns(TALLOC_CTX *mem_ctx, ADS_STRUCT *ads)
01377 {
01378 int num_addrs;
01379 struct in_addr *iplist = NULL;
01380 fstring machine_name;
01381 NTSTATUS status;
01382
01383 name_to_fqdn( machine_name, global_myname() );
01384 strlower_m( machine_name );
01385
01386
01387
01388
01389 num_addrs = get_my_ip_address( &iplist );
01390 if ( num_addrs <= 0 ) {
01391 DEBUG(4,("net_ads_join: Failed to find my non-loopback IP "
01392 "addresses!\n"));
01393 return NT_STATUS_INVALID_PARAMETER;
01394 }
01395
01396 status = net_update_dns_internal(mem_ctx, ads, machine_name,
01397 iplist, num_addrs);
01398 SAFE_FREE( iplist );
01399 return status;
01400 }
01401 #endif
01402
01403
01404
01405
01406
01407
01408 static char* get_string_param( const char* param )
01409 {
01410 char *p;
01411
01412 if ( (p = strchr( param, '=' )) == NULL )
01413 return NULL;
01414
01415 return (p+1);
01416 }
01417
01418
01419
01420
01421 static int net_ads_join_usage(int argc, const char **argv)
01422 {
01423 d_printf("net ads join [options]\n");
01424 d_printf("Valid options:\n");
01425 d_printf(" createupn[=UPN] Set the userPrincipalName attribute during the join.\n");
01426 d_printf(" The deault UPN is in the form host/netbiosname@REALM.\n");
01427 d_printf(" createcomputer=OU Precreate the computer account in a specific OU.\n");
01428 d_printf(" The OU string read from top to bottom without RDNs and delimited by a '/'.\n");
01429 d_printf(" E.g. \"createcomputer=Computers/Servers/Unix\"\n");
01430 d_printf(" NB: A backslash '\\' is used as escape at multiple levels and may\n");
01431 d_printf(" need to be doubled or even quadrupled. It is not used as a separator");
01432
01433 return -1;
01434 }
01435
01436
01437
01438
01439 int net_ads_join(int argc, const char **argv)
01440 {
01441 ADS_STRUCT *ads = NULL;
01442 ADS_STATUS status;
01443 NTSTATUS nt_status;
01444 char *machine_account = NULL;
01445 char *short_domain_name = NULL;
01446 char *tmp_password, *password;
01447 TALLOC_CTX *ctx = NULL;
01448 DOM_SID *domain_sid = NULL;
01449 BOOL createupn = False;
01450 const char *machineupn = NULL;
01451 const char *create_in_ou = NULL;
01452 int i;
01453 fstring dc_name;
01454 struct in_addr dcip;
01455 const char *os_name = NULL;
01456 const char *os_version = NULL;
01457
01458 nt_status = check_ads_config();
01459 if (!NT_STATUS_IS_OK(nt_status)) {
01460 d_fprintf(stderr, "Invalid configuration. Exiting....\n");
01461 goto fail;
01462 }
01463
01464
01465
01466 get_dc_name( lp_workgroup(), lp_realm(), dc_name, &dcip );
01467
01468 status = ads_startup(True, &ads);
01469 if (!ADS_ERR_OK(status)) {
01470 DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
01471 nt_status = ads_ntstatus(status);
01472 goto fail;
01473 }
01474
01475 if (strcmp(ads->config.realm, lp_realm()) != 0) {
01476 d_fprintf(stderr, "realm of remote server (%s) and realm in %s "
01477 "(%s) DO NOT match. Aborting join\n", ads->config.realm,
01478 dyn_CONFIGFILE, lp_realm());
01479 nt_status = NT_STATUS_INVALID_PARAMETER;
01480 goto fail;
01481 }
01482
01483 if (!(ctx = talloc_init("net_ads_join"))) {
01484 d_fprintf(stderr, "Could not initialise talloc context.\n");
01485 nt_status = NT_STATUS_NO_MEMORY;
01486 goto fail;
01487 }
01488
01489
01490
01491 for ( i=0; i<argc; i++ ) {
01492 if ( !StrnCaseCmp(argv[i], "createupn", strlen("createupn")) ) {
01493 createupn = True;
01494 machineupn = get_string_param(argv[i]);
01495 }
01496 else if ( !StrnCaseCmp(argv[i], "createcomputer", strlen("createcomputer")) ) {
01497 if ( (create_in_ou = get_string_param(argv[i])) == NULL ) {
01498 d_fprintf(stderr, "Please supply a valid OU path.\n");
01499 nt_status = NT_STATUS_INVALID_PARAMETER;
01500 goto fail;
01501 }
01502 }
01503 else if ( !StrnCaseCmp(argv[i], "osName", strlen("osName")) ) {
01504 if ( (os_name = get_string_param(argv[i])) == NULL ) {
01505 d_fprintf(stderr, "Please supply a operating system name.\n");
01506 nt_status = NT_STATUS_INVALID_PARAMETER;
01507 goto fail;
01508 }
01509 }
01510 else if ( !StrnCaseCmp(argv[i], "osVer", strlen("osVer")) ) {
01511 if ( (os_version = get_string_param(argv[i])) == NULL ) {
01512 d_fprintf(stderr, "Please supply a valid operating system version.\n");
01513 nt_status = NT_STATUS_INVALID_PARAMETER;
01514 goto fail;
01515 }
01516 }
01517 else {
01518 d_fprintf(stderr, "Bad option: %s\n", argv[i]);
01519 nt_status = NT_STATUS_INVALID_PARAMETER;
01520 goto fail;
01521 }
01522 }
01523
01524
01525
01526
01527 if ( create_in_ou ) {
01528 status = net_precreate_machine_acct( ads, create_in_ou );
01529 if ( !ADS_ERR_OK(status) ) {
01530 d_fprintf( stderr, "Failed to pre-create the machine object "
01531 "in OU %s.\n", argv[0]);
01532 DEBUG(1, ("error calling net_precreate_machine_acct: %s\n",
01533 ads_errstr(status)));
01534 nt_status = ads_ntstatus(status);
01535 goto fail;
01536 }
01537 }
01538
01539
01540
01541 tmp_password = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
01542 password = talloc_strdup(ctx, tmp_password);
01543
01544 nt_status = net_join_domain(ctx, ads->config.ldap_server_name,
01545 &ads->ldap_ip, &short_domain_name, &domain_sid, password);
01546 if ( !NT_STATUS_IS_OK(nt_status) ) {
01547 DEBUG(1, ("call of net_join_domain failed: %s\n",
01548 get_friendly_nt_error_msg(nt_status)));
01549 goto fail;
01550 }
01551
01552
01553
01554 if ( !strequal(lp_workgroup(), short_domain_name) ) {
01555 d_printf("The workgroup in %s does not match the short\n", dyn_CONFIGFILE);
01556 d_printf("domain name obtained from the server.\n");
01557 d_printf("Using the name [%s] from the server.\n", short_domain_name);
01558 d_printf("You should set \"workgroup = %s\" in %s.\n",
01559 short_domain_name, dyn_CONFIGFILE);
01560 }
01561
01562 d_printf("Using short domain name -- %s\n", short_domain_name);
01563
01564
01565
01566
01567
01568
01569 if ( (netdom_store_machine_account( lp_workgroup(), domain_sid, password ) == -1)
01570 || (netdom_store_machine_account( short_domain_name, domain_sid, password ) == -1) )
01571 {
01572
01573
01574 nt_status = NT_STATUS_INTERNAL_ERROR;
01575 goto fail;
01576 }
01577
01578
01579
01580 if ( net_rpc_join_ok(short_domain_name, ads->config.ldap_server_name, &ads->ldap_ip) != 0 ) {
01581 d_fprintf(stderr, "Failed to verify membership in domain!\n");
01582 goto fail;
01583 }
01584
01585
01586
01587 status = net_set_machine_spn( ctx, ads );
01588 if ( !ADS_ERR_OK(status) ) {
01589
01590 d_fprintf(stderr, "Failed to set servicePrincipalNames. Please ensure that\n");
01591 d_fprintf(stderr, "the DNS domain of this server matches the AD domain,\n");
01592 d_fprintf(stderr, "Or rejoin with using Domain Admin credentials.\n");
01593
01594
01595
01596
01597 if ( net_ads_leave( 0, NULL ) != 0 ) {
01598 d_fprintf( stderr, "Failed to disable machine account in AD. Please do so manually.\n");
01599 }
01600
01601
01602
01603 netdom_store_machine_account( lp_workgroup(), domain_sid, "" );
01604 netdom_store_machine_account( short_domain_name, domain_sid, "" );
01605
01606 nt_status = ads_ntstatus(status);
01607 goto fail;
01608 }
01609
01610 if ( !net_derive_salting_principal( ctx, ads ) ) {
01611 DEBUG(1,("Failed to determine salting principal\n"));
01612 goto fail;
01613 }
01614
01615 if ( createupn ) {
01616 pstring upn;
01617
01618
01619 if ( !machineupn ) {
01620 snprintf( upn, sizeof(upn), "host/%s@%s", global_myname(),
01621 ads->config.realm );
01622 machineupn = upn;
01623 }
01624
01625 status = net_set_machine_upn( ctx, ads, machineupn );
01626 if ( !ADS_ERR_OK(status) ) {
01627 d_fprintf(stderr, "Failed to set userPrincipalName. Are you a Domain Admin?\n");
01628 }
01629 }
01630
01631
01632
01633 if ( os_name && os_version ) {
01634 status = net_set_os_attributes( ctx, ads, os_name, os_version );
01635 if ( !ADS_ERR_OK(status) ) {
01636 d_fprintf(stderr, "Failed to set operatingSystem attributes. "
01637 "Are you a Domain Admin?\n");
01638 }
01639 }
01640
01641
01642
01643 if (lp_use_kerberos_keytab() && ads_keytab_create_default(ads)) {
01644 DEBUG(1,("Error creating host keytab!\n"));
01645 }
01646
01647 #if defined(WITH_DNS_UPDATES)
01648
01649 ads_kdestroy( NULL );
01650 ads_destroy(&ads);
01651 ads = NULL;
01652
01653 if ( (ads = ads_init( lp_realm(), NULL, NULL )) != NULL ) {
01654
01655
01656 use_in_memory_ccache();
01657 asprintf( &ads->auth.user_name, "%s$", global_myname() );
01658 ads->auth.password = secrets_fetch_machine_password(
01659 lp_workgroup(), NULL, NULL );
01660 ads->auth.realm = SMB_STRDUP( lp_realm() );
01661 ads_kinit_password( ads );
01662 }
01663
01664 if ( !ads || !NT_STATUS_IS_OK(net_update_dns( ctx, ads )) ) {
01665 d_fprintf( stderr, "DNS update failed!\n" );
01666 }
01667
01668
01669 #endif
01670
01671 d_printf("Joined '%s' to realm '%s'\n", global_myname(), ads->server.realm);
01672
01673 SAFE_FREE(machine_account);
01674 TALLOC_FREE( ctx );
01675 ads_destroy(&ads);
01676
01677 return 0;
01678
01679 fail:
01680
01681 d_printf("Failed to join domain: %s\n", get_friendly_nt_error_msg(nt_status));
01682
01683 SAFE_FREE(machine_account);
01684 TALLOC_FREE( ctx );
01685 ads_destroy(&ads);
01686
01687 return -1;
01688
01689 }
01690
01691
01692
01693
01694 static int net_ads_dns_usage(int argc, const char **argv)
01695 {
01696 #if defined(WITH_DNS_UPDATES)
01697 d_printf("net ads dns <command>\n");
01698 d_printf("Valid commands:\n");
01699 d_printf(" register Issue a dynamic DNS update request for our hostname\n");
01700
01701 return 0;
01702 #else
01703 d_fprintf(stderr, "DNS update support not enabled at compile time!\n");
01704 return -1;
01705 #endif
01706 }
01707
01708
01709
01710
01711 static int net_ads_dns_register(int argc, const char **argv)
01712 {
01713 #if defined(WITH_DNS_UPDATES)
01714 ADS_STRUCT *ads;
01715 ADS_STATUS status;
01716 TALLOC_CTX *ctx;
01717
01718 #ifdef DEVELOPER
01719 talloc_enable_leak_report();
01720 #endif
01721
01722 if (argc > 0) {
01723 d_fprintf(stderr, "net ads dns register\n");
01724 return -1;
01725 }
01726
01727 if (!(ctx = talloc_init("net_ads_dns"))) {
01728 d_fprintf(stderr, "Could not initialise talloc context\n");
01729 return -1;
01730 }
01731
01732 status = ads_startup(True, &ads);
01733 if ( !ADS_ERR_OK(status) ) {
01734 DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
01735 TALLOC_FREE(ctx);
01736 return -1;
01737 }
01738
01739 if ( !NT_STATUS_IS_OK(net_update_dns(ctx, ads)) ) {
01740 d_fprintf( stderr, "DNS update failed!\n" );
01741 ads_destroy( &ads );
01742 TALLOC_FREE( ctx );
01743 return -1;
01744 }
01745
01746 d_fprintf( stderr, "Successfully registered hostname with DNS\n" );
01747
01748 ads_destroy(&ads);
01749 TALLOC_FREE( ctx );
01750
01751 return 0;
01752 #else
01753 d_fprintf(stderr, "DNS update support not enabled at compile time!\n");
01754 return -1;
01755 #endif
01756 }
01757
01758 #if defined(WITH_DNS_UPDATES)
01759 DNS_ERROR do_gethostbyname(const char *server, const char *host);
01760 #endif
01761
01762 static int net_ads_dns_gethostbyname(int argc, const char **argv)
01763 {
01764 #if defined(WITH_DNS_UPDATES)
01765 DNS_ERROR err;
01766
01767 #ifdef DEVELOPER
01768 talloc_enable_leak_report();
01769 #endif
01770
01771 if (argc != 2) {
01772 d_fprintf(stderr, "net ads dns gethostbyname <server> "
01773 "<name>\n");
01774 return -1;
01775 }
01776
01777 err = do_gethostbyname(argv[0], argv[1]);
01778
01779 d_printf("do_gethostbyname returned %d\n", ERROR_DNS_V(err));
01780 #endif
01781 return 0;
01782 }
01783
01784 static int net_ads_dns(int argc, const char *argv[])
01785 {
01786 struct functable func[] = {
01787 {"REGISTER", net_ads_dns_register},
01788 {"GETHOSTBYNAME", net_ads_dns_gethostbyname},
01789 {NULL, NULL}
01790 };
01791
01792 return net_run_function(argc, argv, func, net_ads_dns_usage);
01793 }
01794
01795
01796
01797
01798 int net_ads_printer_usage(int argc, const char **argv)
01799 {
01800 d_printf(
01801 "\nnet ads printer search <printer>"
01802 "\n\tsearch for a printer in the directory\n"
01803 "\nnet ads printer info <printer> <server>"
01804 "\n\tlookup info in directory for printer on server"
01805 "\n\t(note: printer defaults to \"*\", server defaults to local)\n"
01806 "\nnet ads printer publish <printername>"
01807 "\n\tpublish printer in directory"
01808 "\n\t(note: printer name is required)\n"
01809 "\nnet ads printer remove <printername>"
01810 "\n\tremove printer from directory"
01811 "\n\t(note: printer name is required)\n");
01812 return -1;
01813 }
01814
01815
01816
01817
01818 static int net_ads_printer_search(int argc, const char **argv)
01819 {
01820 ADS_STRUCT *ads;
01821 ADS_STATUS rc;
01822 LDAPMessage *res = NULL;
01823
01824 if (!ADS_ERR_OK(ads_startup(False, &ads))) {
01825 return -1;
01826 }
01827
01828 rc = ads_find_printers(ads, &res);
01829
01830 if (!ADS_ERR_OK(rc)) {
01831 d_fprintf(stderr, "ads_find_printer: %s\n", ads_errstr(rc));
01832 ads_msgfree(ads, res);
01833 ads_destroy(&ads);
01834 return -1;
01835 }
01836
01837 if (ads_count_replies(ads, res) == 0) {
01838 d_fprintf(stderr, "No results found\n");
01839 ads_msgfree(ads, res);
01840 ads_destroy(&ads);
01841 return -1;
01842 }
01843
01844 ads_dump(ads, res);
01845 ads_msgfree(ads, res);
01846 ads_destroy(&ads);
01847 return 0;
01848 }
01849
01850 static int net_ads_printer_info(int argc, const char **argv)
01851 {
01852 ADS_STRUCT *ads;
01853 ADS_STATUS rc;
01854 const char *servername, *printername;
01855 LDAPMessage *res = NULL;
01856
01857 if (!ADS_ERR_OK(ads_startup(False, &ads))) {
01858 return -1;
01859 }
01860
01861 if (argc > 0) {
01862 printername = argv[0];
01863 } else {
01864 printername = "*";
01865 }
01866
01867 if (argc > 1) {
01868 servername = argv[1];
01869 } else {
01870 servername = global_myname();
01871 }
01872
01873 rc = ads_find_printer_on_server(ads, &res, printername, servername);
01874
01875 if (!ADS_ERR_OK(rc)) {
01876 d_fprintf(stderr, "Server '%s' not found: %s\n",
01877 servername, ads_errstr(rc));
01878 ads_msgfree(ads, res);
01879 ads_destroy(&ads);
01880 return -1;
01881 }
01882
01883 if (ads_count_replies(ads, res) == 0) {
01884 d_fprintf(stderr, "Printer '%s' not found\n", printername);
01885 ads_msgfree(ads, res);
01886 ads_destroy(&ads);
01887 return -1;
01888 }
01889
01890 ads_dump(ads, res);
01891 ads_msgfree(ads, res);
01892 ads_destroy(&ads);
01893
01894 return 0;
01895 }
01896
01897 void do_drv_upgrade_printer(int msg_type, struct process_id src,
01898 void *buf, size_t len, void *private_data)
01899 {
01900 return;
01901 }
01902
01903 static int net_ads_printer_publish(int argc, const char **argv)
01904 {
01905 ADS_STRUCT *ads;
01906 ADS_STATUS rc;
01907 const char *servername, *printername;
01908 struct cli_state *cli;
01909 struct rpc_pipe_client *pipe_hnd;
01910 struct in_addr server_ip;
01911 NTSTATUS nt_status;
01912 TALLOC_CTX *mem_ctx = talloc_init("net_ads_printer_publish");
01913 ADS_MODLIST mods = ads_init_mods(mem_ctx);
01914 char *prt_dn, *srv_dn, **srv_cn;
01915 char *srv_cn_escaped = NULL, *printername_escaped = NULL;
01916 LDAPMessage *res = NULL;
01917
01918 if (!ADS_ERR_OK(ads_startup(True, &ads))) {
01919 talloc_destroy(mem_ctx);
01920 return -1;
01921 }
01922
01923 if (argc < 1) {
01924 talloc_destroy(mem_ctx);
01925 return net_ads_printer_usage(argc, argv);
01926 }
01927
01928 printername = argv[0];
01929
01930 if (argc == 2) {
01931 servername = argv[1];
01932 } else {
01933 servername = global_myname();
01934 }
01935
01936
01937
01938 resolve_name(servername, &server_ip, 0x20);
01939
01940 nt_status = cli_full_connection(&cli, global_myname(), servername,
01941 &server_ip, 0,
01942 "IPC$", "IPC",
01943 opt_user_name, opt_workgroup,
01944 opt_password ? opt_password : "",
01945 CLI_FULL_CONNECTION_USE_KERBEROS,
01946 Undefined, NULL);
01947
01948 if (NT_STATUS_IS_ERR(nt_status)) {
01949 d_fprintf(stderr, "Unable to open a connnection to %s to obtain data "
01950 "for %s\n", servername, printername);
01951 ads_destroy(&ads);
01952 talloc_destroy(mem_ctx);
01953 return -1;
01954 }
01955
01956
01957
01958 ads_find_machine_acct(ads, &res, servername);
01959
01960 if (ads_count_replies(ads, res) == 0) {
01961 d_fprintf(stderr, "Could not find machine account for server %s\n",
01962 servername);
01963 ads_destroy(&ads);
01964 talloc_destroy(mem_ctx);
01965 return -1;
01966 }
01967
01968 srv_dn = ldap_get_dn((LDAP *)ads->ld, (LDAPMessage *)res);
01969 srv_cn = ldap_explode_dn(srv_dn, 1);
01970
01971 srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn[0]);
01972 printername_escaped = escape_rdn_val_string_alloc(printername);
01973 if (!srv_cn_escaped || !printername_escaped) {
01974 SAFE_FREE(srv_cn_escaped);
01975 SAFE_FREE(printername_escaped);
01976 d_fprintf(stderr, "Internal error, out of memory!");
01977 ads_destroy(&ads);
01978 talloc_destroy(mem_ctx);
01979 return -1;
01980 }
01981
01982 asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_escaped, printername_escaped, srv_dn);
01983
01984 SAFE_FREE(srv_cn_escaped);
01985 SAFE_FREE(printername_escaped);
01986
01987 pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SPOOLSS, &nt_status);
01988 if (!pipe_hnd) {
01989 d_fprintf(stderr, "Unable to open a connnection to the spoolss pipe on %s\n",
01990 servername);
01991 SAFE_FREE(prt_dn);
01992 ads_destroy(&ads);
01993 talloc_destroy(mem_ctx);
01994 return -1;
01995 }
01996
01997 if (!W_ERROR_IS_OK(get_remote_printer_publishing_data(pipe_hnd, mem_ctx, &mods,
01998 printername))) {
01999 SAFE_FREE(prt_dn);
02000 ads_destroy(&ads);
02001 talloc_destroy(mem_ctx);
02002 return -1;
02003 }
02004
02005 rc = ads_add_printer_entry(ads, prt_dn, mem_ctx, &mods);
02006 if (!ADS_ERR_OK(rc)) {
02007 d_fprintf(stderr, "ads_publish_printer: %s\n", ads_errstr(rc));
02008 SAFE_FREE(prt_dn);
02009 ads_destroy(&ads);
02010 talloc_destroy(mem_ctx);
02011 return -1;
02012 }
02013
02014 d_printf("published printer\n");
02015 SAFE_FREE(prt_dn);
02016 ads_destroy(&ads);
02017 talloc_destroy(mem_ctx);
02018
02019 return 0;
02020 }
02021
02022 static int net_ads_printer_remove(int argc, const char **argv)
02023 {
02024 ADS_STRUCT *ads;
02025 ADS_STATUS rc;
02026 const char *servername;
02027 char *prt_dn;
02028 LDAPMessage *res = NULL;
02029
02030 if (!ADS_ERR_OK(ads_startup(True, &ads))) {
02031 return -1;
02032 }
02033
02034 if (argc < 1) {
02035 return net_ads_printer_usage(argc, argv);
02036 }
02037
02038 if (argc > 1) {
02039 servername = argv[1];
02040 } else {
02041 servername = global_myname();
02042 }
02043
02044 rc = ads_find_printer_on_server(ads, &res, argv[0], servername);
02045
02046 if (!ADS_ERR_OK(rc)) {
02047 d_fprintf(stderr, "ads_find_printer_on_server: %s\n", ads_errstr(rc));
02048 ads_msgfree(ads, res);
02049 ads_destroy(&ads);
02050 return -1;
02051 }
02052
02053 if (ads_count_replies(ads, res) == 0) {
02054 d_fprintf(stderr, "Printer '%s' not found\n", argv[1]);
02055 ads_msgfree(ads, res);
02056 ads_destroy(&ads);
02057 return -1;
02058 }
02059
02060 prt_dn = ads_get_dn(ads, res);
02061 ads_msgfree(ads, res);
02062 rc = ads_del_dn(ads, prt_dn);
02063 ads_memfree(ads, prt_dn);
02064
02065 if (!ADS_ERR_OK(rc)) {
02066 d_fprintf(stderr, "ads_del_dn: %s\n", ads_errstr(rc));
02067 ads_destroy(&ads);
02068 return -1;
02069 }
02070
02071 ads_destroy(&ads);
02072 return 0;
02073 }
02074
02075 static int net_ads_printer(int argc, const char **argv)
02076 {
02077 struct functable func[] = {
02078 {"SEARCH", net_ads_printer_search},
02079 {"INFO", net_ads_printer_info},
02080 {"PUBLISH", net_ads_printer_publish},
02081 {"REMOVE", net_ads_printer_remove},
02082 {NULL, NULL}
02083 };
02084
02085 return net_run_function(argc, argv, func, net_ads_printer_usage);
02086 }
02087
02088
02089 static int net_ads_password(int argc, const char **argv)
02090 {
02091 ADS_STRUCT *ads;
02092 const char *auth_principal = opt_user_name;
02093 const char *auth_password = opt_password;
02094 char *realm = NULL;
02095 char *new_password = NULL;
02096 char *c, *prompt;
02097 const char *user;
02098 ADS_STATUS ret;
02099
02100 if (opt_user_name == NULL || opt_password == NULL) {
02101 d_fprintf(stderr, "You must supply an administrator username/password\n");
02102 return -1;
02103 }
02104
02105 if (argc < 1) {
02106 d_fprintf(stderr, "ERROR: You must say which username to change password for\n");
02107 return -1;
02108 }
02109
02110 user = argv[0];
02111 if (!strchr_m(user, '@')) {
02112 asprintf(&c, "%s@%s", argv[0], lp_realm());
02113 user = c;
02114 }
02115
02116 use_in_memory_ccache();
02117 c = strchr_m(auth_principal, '@');
02118 if (c) {
02119 realm = ++c;
02120 } else {
02121 realm = lp_realm();
02122 }
02123
02124
02125
02126 if (!(ads = ads_init(realm, opt_workgroup, opt_host))) {
02127 return -1;
02128 }
02129
02130
02131
02132 ads_connect(ads);
02133
02134 if (!ads || !ads->config.realm) {
02135 d_fprintf(stderr, "Didn't find the kerberos server!\n");
02136 return -1;
02137 }
02138
02139 if (argv[1]) {
02140 new_password = (char *)argv[1];
02141 } else {
02142 asprintf(&prompt, "Enter new password for %s:", user);
02143 new_password = getpass(prompt);
02144 free(prompt);
02145 }
02146
02147 ret = kerberos_set_password(ads->auth.kdc_server, auth_principal,
02148 auth_password, user, new_password, ads->auth.time_offset);
02149 if (!ADS_ERR_OK(ret)) {
02150 d_fprintf(stderr, "Password change failed: %s\n", ads_errstr(ret));
02151 ads_destroy(&ads);
02152 return -1;
02153 }
02154
02155 d_printf("Password change for %s completed.\n", user);
02156 ads_destroy(&ads);
02157
02158 return 0;
02159 }
02160
02161 int net_ads_changetrustpw(int argc, const char **argv)
02162 {
02163 ADS_STRUCT *ads;
02164 char *host_principal;
02165 fstring my_name;
02166 ADS_STATUS ret;
02167
02168 if (!secrets_init()) {
02169 DEBUG(1,("Failed to initialise secrets database\n"));
02170 return -1;
02171 }
02172
02173 net_use_krb_machine_account();
02174
02175 use_in_memory_ccache();
02176
02177 if (!ADS_ERR_OK(ads_startup(True, &ads))) {
02178 return -1;
02179 }
02180
02181 fstrcpy(my_name, global_myname());
02182 strlower_m(my_name);
02183 asprintf(&host_principal, "%s$@%s", my_name, ads->config.realm);
02184 d_printf("Changing password for principal: %s\n", host_principal);
02185
02186 ret = ads_change_trust_account_password(ads, host_principal);
02187
02188 if (!ADS_ERR_OK(ret)) {
02189 d_fprintf(stderr, "Password change failed: %s\n", ads_errstr(ret));
02190 ads_destroy(&ads);
02191 SAFE_FREE(host_principal);
02192 return -1;
02193 }
02194
02195 d_printf("Password change for principal %s succeeded.\n", host_principal);
02196
02197 if (lp_use_kerberos_keytab()) {
02198 d_printf("Attempting to update system keytab with new password.\n");
02199 if (ads_keytab_create_default(ads)) {
02200 d_printf("Failed to update system keytab.\n");
02201 }
02202 }
02203
02204 ads_destroy(&ads);
02205 SAFE_FREE(host_principal);
02206
02207 return 0;
02208 }
02209
02210
02211
02212
02213 static int net_ads_search_usage(int argc, const char **argv)
02214 {
02215 d_printf(
02216 "\nnet ads search <expression> <attributes...>\n"\
02217 "\nperform a raw LDAP search on a ADS server and dump the results\n"\
02218 "The expression is a standard LDAP search expression, and the\n"\
02219 "attributes are a list of LDAP fields to show in the results\n\n"\
02220 "Example: net ads search '(objectCategory=group)' sAMAccountName\n\n"
02221 );
02222 net_common_flags_usage(argc, argv);
02223 return -1;
02224 }
02225
02226
02227
02228
02229
02230 static int net_ads_search(int argc, const char **argv)
02231 {
02232 ADS_STRUCT *ads;
02233 ADS_STATUS rc;
02234 const char *ldap_exp;
02235 const char **attrs;
02236 LDAPMessage *res = NULL;
02237
02238 if (argc < 1) {
02239 return net_ads_search_usage(argc, argv);
02240 }
02241
02242 if (!ADS_ERR_OK(ads_startup(False, &ads))) {
02243 return -1;
02244 }
02245
02246 ldap_exp = argv[0];
02247 attrs = (argv + 1);
02248
02249 rc = ads_do_search_all(ads, ads->config.bind_path,
02250 LDAP_SCOPE_SUBTREE,
02251 ldap_exp, attrs, &res);
02252 if (!ADS_ERR_OK(rc)) {
02253 d_fprintf(stderr, "search failed: %s\n", ads_errstr(rc));
02254 ads_destroy(&ads);
02255 return -1;
02256 }
02257
02258 d_printf("Got %d replies\n\n", ads_count_replies(ads, res));
02259
02260
02261 ads_dump(ads, res);
02262
02263 ads_msgfree(ads, res);
02264 ads_destroy(&ads);
02265
02266 return 0;
02267 }
02268
02269
02270
02271
02272
02273 static int net_ads_dn_usage(int argc, const char **argv)
02274 {
02275 d_printf(
02276 "\nnet ads dn <dn> <attributes...>\n"\
02277 "\nperform a raw LDAP search on a ADS server and dump the results\n"\
02278 "The DN standard LDAP DN, and the attributes are a list of LDAP fields \n"\
02279 "to show in the results\n\n"\
02280 "Example: net ads dn 'CN=administrator,CN=Users,DC=my,DC=domain' sAMAccountName\n\n"
02281 "Note: the DN must be provided properly escaped. See RFC 4514 for details\n\n"
02282 );
02283 net_common_flags_usage(argc, argv);
02284 return -1;
02285 }
02286
02287
02288
02289
02290
02291 static int net_ads_dn(int argc, const char **argv)
02292 {
02293 ADS_STRUCT *ads;
02294 ADS_STATUS rc;
02295 const char *dn;
02296 const char **attrs;
02297 LDAPMessage *res = NULL;
02298
02299 if (argc < 1) {
02300 return net_ads_dn_usage(argc, argv);
02301 }
02302
02303 if (!ADS_ERR_OK(ads_startup(False, &ads))) {
02304 return -1;
02305 }
02306
02307 dn = argv[0];
02308 attrs = (argv + 1);
02309
02310 rc = ads_do_search_all(ads, dn,
02311 LDAP_SCOPE_BASE,
02312 "(objectclass=*)", attrs, &res);
02313 if (!ADS_ERR_OK(rc)) {
02314 d_fprintf(stderr, "search failed: %s\n", ads_errstr(rc));
02315 ads_destroy(&ads);
02316 return -1;
02317 }
02318
02319 d_printf("Got %d replies\n\n", ads_count_replies(ads, res));
02320
02321
02322 ads_dump(ads, res);
02323
02324 ads_msgfree(ads, res);
02325 ads_destroy(&ads);
02326
02327 return 0;
02328 }
02329
02330
02331
02332
02333 static int net_ads_sid_usage(int argc, const char **argv)
02334 {
02335 d_printf(
02336 "\nnet ads sid <sid> <attributes...>\n"\
02337 "\nperform a raw LDAP search on a ADS server and dump the results\n"\
02338 "The SID is in string format, and the attributes are a list of LDAP fields \n"\
02339 "to show in the results\n\n"\
02340 "Example: net ads sid 'S-1-5-32' distinguishedName\n\n"
02341 );
02342 net_common_flags_usage(argc, argv);
02343 return -1;
02344 }
02345
02346
02347
02348
02349
02350 static int net_ads_sid(int argc, const char **argv)
02351 {
02352 ADS_STRUCT *ads;
02353 ADS_STATUS rc;
02354 const char *sid_string;
02355 const char **attrs;
02356 LDAPMessage *res = NULL;
02357 DOM_SID sid;
02358
02359 if (argc < 1) {
02360 return net_ads_sid_usage(argc, argv);
02361 }
02362
02363 if (!ADS_ERR_OK(ads_startup(False, &ads))) {
02364 return -1;
02365 }
02366
02367 sid_string = argv[0];
02368 attrs = (argv + 1);
02369
02370 if (!string_to_sid(&sid, sid_string)) {
02371 d_fprintf(stderr, "could not convert sid\n");
02372 ads_destroy(&ads);
02373 return -1;
02374 }
02375
02376 rc = ads_search_retry_sid(ads, &res, &sid, attrs);
02377 if (!ADS_ERR_OK(rc)) {
02378 d_fprintf(stderr, "search failed: %s\n", ads_errstr(rc));
02379 ads_destroy(&ads);
02380 return -1;
02381 }
02382
02383 d_printf("Got %d replies\n\n", ads_count_replies(ads, res));
02384
02385
02386 ads_dump(ads, res);
02387
02388 ads_msgfree(ads, res);
02389 ads_destroy(&ads);
02390
02391 return 0;
02392 }
02393
02394
02395 static int net_ads_keytab_usage(int argc, const char **argv)
02396 {
02397 d_printf(
02398 "net ads keytab <COMMAND>\n"\
02399 "<COMMAND> can be either:\n"\
02400 " CREATE Creates a fresh keytab\n"\
02401 " ADD Adds new service principal\n"\
02402 " FLUSH Flushes out all keytab entries\n"\
02403 " HELP Prints this help message\n"\
02404 "The ADD command will take arguments, the other commands\n"\
02405 "will not take any arguments. The arguments given to ADD\n"\
02406 "should be a list of principals to add. For example, \n"\
02407 " net ads keytab add srv1 srv2\n"\
02408 "will add principals for the services srv1 and srv2 to the\n"\
02409 "system's keytab.\n"\
02410 "\n"
02411 );
02412 return -1;
02413 }
02414
02415 static int net_ads_keytab_flush(int argc, const char **argv)
02416 {
02417 int ret;
02418 ADS_STRUCT *ads;
02419
02420 if (!ADS_ERR_OK(ads_startup(True, &ads))) {
02421 return -1;
02422 }
02423 ret = ads_keytab_flush(ads);
02424 ads_destroy(&ads);
02425 return ret;
02426 }
02427
02428 static int net_ads_keytab_add(int argc, const char **argv)
02429 {
02430 int i;
02431 int ret = 0;
02432 ADS_STRUCT *ads;
02433
02434 d_printf("Processing principals to add...\n");
02435 if (!ADS_ERR_OK(ads_startup(True, &ads))) {
02436 return -1;
02437 }
02438 for (i = 0; i < argc; i++) {
02439 ret |= ads_keytab_add_entry(ads, argv[i]);
02440 }
02441 ads_destroy(&ads);
02442 return ret;
02443 }
02444
02445 static int net_ads_keytab_create(int argc, const char **argv)
02446 {
02447 ADS_STRUCT *ads;
02448 int ret;
02449
02450 if (!ADS_ERR_OK(ads_startup(True, &ads))) {
02451 return -1;
02452 }
02453 ret = ads_keytab_create_default(ads);
02454 ads_destroy(&ads);
02455 return ret;
02456 }
02457
02458 int net_ads_keytab(int argc, const char **argv)
02459 {
02460 struct functable func[] = {
02461 {"CREATE", net_ads_keytab_create},
02462 {"ADD", net_ads_keytab_add},
02463 {"FLUSH", net_ads_keytab_flush},
02464 {"HELP", net_ads_keytab_usage},
02465 {NULL, NULL}
02466 };
02467
02468 if (!lp_use_kerberos_keytab()) {
02469 d_printf("\nWarning: \"use kerberos keytab\" must be set to \"true\" in order to \
02470 use keytab functions.\n");
02471 }
02472
02473 return net_run_function(argc, argv, func, net_ads_keytab_usage);
02474 }
02475
02476 int net_ads_help(int argc, const char **argv)
02477 {
02478 struct functable func[] = {
02479 {"USER", net_ads_user_usage},
02480 {"GROUP", net_ads_group_usage},
02481 {"PRINTER", net_ads_printer_usage},
02482 {"SEARCH", net_ads_search_usage},
02483 {"INFO", net_ads_info},
02484 {"JOIN", net_ads_join_usage},
02485 {"DNS", net_ads_dns_usage},
02486 {"LEAVE", net_ads_leave},
02487 {"STATUS", net_ads_status},
02488 {"PASSWORD", net_ads_password},
02489 {"CHANGETRUSTPW", net_ads_changetrustpw},
02490 {NULL, NULL}
02491 };
02492
02493 return net_run_function(argc, argv, func, net_ads_usage);
02494 }
02495
02496 int net_ads(int argc, const char **argv)
02497 {
02498 struct functable func[] = {
02499 {"INFO", net_ads_info},
02500 {"JOIN", net_ads_join},
02501 {"TESTJOIN", net_ads_testjoin},
02502 {"LEAVE", net_ads_leave},
02503 {"STATUS", net_ads_status},
02504 {"USER", net_ads_user},
02505 {"GROUP", net_ads_group},
02506 {"DNS", net_ads_dns},
02507 {"PASSWORD", net_ads_password},
02508 {"CHANGETRUSTPW", net_ads_changetrustpw},
02509 {"PRINTER", net_ads_printer},
02510 {"SEARCH", net_ads_search},
02511 {"DN", net_ads_dn},
02512 {"SID", net_ads_sid},
02513 {"WORKGROUP", net_ads_workgroup},
02514 {"LOOKUP", net_ads_lookup},
02515 {"KEYTAB", net_ads_keytab},
02516 {"GPO", net_ads_gpo},
02517 {"HELP", net_ads_help},
02518 {NULL, NULL}
02519 };
02520
02521 return net_run_function(argc, argv, func, net_ads_usage);
02522 }
02523
02524 #else
02525
02526 static int net_ads_noads(void)
02527 {
02528 d_fprintf(stderr, "ADS support not compiled in\n");
02529 return -1;
02530 }
02531
02532 int net_ads_keytab(int argc, const char **argv)
02533 {
02534 return net_ads_noads();
02535 }
02536
02537 int net_ads_usage(int argc, const char **argv)
02538 {
02539 return net_ads_noads();
02540 }
02541
02542 int net_ads_help(int argc, const char **argv)
02543 {
02544 return net_ads_noads();
02545 }
02546
02547 int net_ads_changetrustpw(int argc, const char **argv)
02548 {
02549 return net_ads_noads();
02550 }
02551
02552 int net_ads_join(int argc, const char **argv)
02553 {
02554 return net_ads_noads();
02555 }
02556
02557 int net_ads_user(int argc, const char **argv)
02558 {
02559 return net_ads_noads();
02560 }
02561
02562 int net_ads_group(int argc, const char **argv)
02563 {
02564 return net_ads_noads();
02565 }
02566
02567
02568 int net_ads_check(void)
02569 {
02570 return -1;
02571 }
02572
02573 int net_ads_check_our_domain(void)
02574 {
02575 return -1;
02576 }
02577
02578 int net_ads(int argc, const char **argv)
02579 {
02580 return net_ads_usage(argc, argv);
02581 }
02582
02583 #endif