Removed version number from file header.
[ira/wip.git] / source3 / utils / net_ads.c
index 345fc5c3db332f3d9783a3e33d743f3669b14f2a..32cf1aafb889404b069d738907a22188cf5dd98c 100644 (file)
@@ -1,8 +1,8 @@
 /* 
    Samba Unix/Linux SMB client library 
-   Version 3.0
    net ads commands
    Copyright (C) 2001 Andrew Tridgell (tridge@samba.org)
+   Copyright (C) 2001 Remus Koos (remuskoos@yahoo.com)
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -26,7 +26,7 @@
 int net_ads_usage(int argc, const char **argv)
 {
        d_printf(
-"\nnet ads join"\
+"\nnet ads join <org_unit>"\
 "\n\tjoins the local machine to a ADS realm\n"\
 "\nnet ads leave"\
 "\n\tremoves the local machine from a ADS realm\n"\
@@ -34,22 +34,83 @@ int net_ads_usage(int argc, const char **argv)
 "\n\tlist users in the realm\n"\
 "\nnet ads group"\
 "\n\tlist groups in the realm\n"\
+"\nnet ads info"\
+"\n\tshows some info on the server\n"\
 "\nnet ads status"\
 "\n\tdump the machine account details to stdout\n"
+"\nnet ads password <username@realm> -Uadmin_username@realm%%admin_pass"\
+"\n\tchange a user's password using an admin account"
+"\n\t(note: use realm in UPPERCASE)\n"
+"\nnet ads chostpass"
+"\n\tchange the trust account password of this machine in the AD tree\n"
                );
        return -1;
 }
 
+
+static int net_ads_info(int argc, const char **argv)
+{
+       ADS_STRUCT *ads;
+
+       ads = ads_init(NULL, NULL, NULL, NULL);
+       ads_connect(ads);
+
+       if (!ads) {
+               d_printf("Didn't find the ldap server!\n");
+               return -1;
+       }
+
+       d_printf("LDAP server: %s\n", ads->ldap_server);
+       d_printf("LDAP server name: %s\n", ads->ldap_server_name);
+       d_printf("Realm: %s\n", ads->realm);
+       d_printf("Bind Path: %s\n", ads->bind_path);
+       d_printf("LDAP port: %d\n", ads->ldap_port);
+
+       return 0;
+}
+
+
 static ADS_STRUCT *ads_startup(void)
 {
        ADS_STRUCT *ads;
-       int rc;
-       ads = ads_init(NULL, NULL, NULL);
+       ADS_STATUS status;
+       BOOL need_password = False;
+       BOOL second_time = False;
+       extern char *opt_password;
+       extern char *opt_user_name;
+       extern BOOL opt_user_specified;
+
 
-       rc = ads_connect(ads);
-       if (rc) {
-               d_printf("ads_connect: %s\n", ads_errstr(rc));
-               return NULL;
+       ads = ads_init(NULL, NULL, NULL, NULL);
+
+       if (!opt_user_name) {
+               opt_user_name = "administrator";
+       }
+
+       if (opt_user_specified)
+               need_password = True;
+
+retry:
+       if (!opt_password && need_password) {
+               char *prompt;
+               asprintf(&prompt,"%s password: ", opt_user_name);
+               opt_password = getpass(prompt);
+               free(prompt);
+               ads->password = strdup(opt_password);
+       }
+
+       ads->user_name = strdup(opt_user_name);
+
+       status = ads_connect(ads);
+       if (!ADS_ERR_OK(status)) {
+               if (!need_password && !second_time) {
+                       need_password = True;
+                       second_time = True;
+                       goto retry;
+               } else {
+                       d_printf("ads_connect: %s\n", ads_errstr(status));
+                       return NULL;
+               }
        }
        return ads;
 }
@@ -57,13 +118,13 @@ static ADS_STRUCT *ads_startup(void)
 static int net_ads_user(int argc, const char **argv)
 {
        ADS_STRUCT *ads;
-       int rc;
+       ADS_STATUS rc;
        void *res;
        const char *attrs[] = {"sAMAccountName", "name", "objectSid", NULL};
 
        if (!(ads = ads_startup())) return -1;
        rc = ads_search(ads, &res, "(objectclass=user)", attrs);
-       if (rc) {
+       if (!ADS_ERR_OK(rc)) {
                d_printf("ads_search: %s\n", ads_errstr(rc));
                return -1;
        }
@@ -74,19 +135,20 @@ static int net_ads_user(int argc, const char **argv)
        }
 
        ads_dump(ads, res);
+       ads_destroy(&ads);
        return 0;
 }
 
 static int net_ads_group(int argc, const char **argv)
 {
        ADS_STRUCT *ads;
-       int rc;
+       ADS_STATUS rc;
        void *res;
        const char *attrs[] = {"sAMAccountName", "name", "objectSid", NULL};
 
        if (!(ads = ads_startup())) return -1;
        rc = ads_search(ads, &res, "(objectclass=group)", attrs);
-       if (rc) {
+       if (!ADS_ERR_OK(rc)) {
                d_printf("ads_search: %s\n", ads_errstr(rc));
                return -1;
        }
@@ -103,14 +165,14 @@ static int net_ads_group(int argc, const char **argv)
 static int net_ads_status(int argc, const char **argv)
 {
        ADS_STRUCT *ads;
-       int rc;
+       ADS_STATUS rc;
        extern pstring global_myname;
        void *res;
 
        if (!(ads = ads_startup())) return -1;
 
        rc = ads_find_machine_acct(ads, &res, global_myname);
-       if (rc) {
+       if (!ADS_ERR_OK(rc)) {
                d_printf("ads_find_machine_acct: %s\n", ads_errstr(rc));
                return -1;
        }
@@ -127,11 +189,13 @@ static int net_ads_status(int argc, const char **argv)
 
 static int net_ads_leave(int argc, const char **argv)
 {
-       ADS_STRUCT *ads;
-       int rc;
+       ADS_STRUCT *ads = NULL;
+       ADS_STATUS rc;
        extern pstring global_myname;
 
-       if (!(ads = ads_startup())) return -1;
+       if (!(ads = ads_startup())) {
+               return -1;
+       }
 
        if (!secrets_init()) {
                DEBUG(1,("Failed to initialise secrets database\n"));
@@ -139,7 +203,7 @@ static int net_ads_leave(int argc, const char **argv)
        }
 
        rc = ads_leave_realm(ads, global_myname);
-       if (rc) {
+       if (!ADS_ERR_OK(rc)) {
            d_printf("Failed to delete host '%s' from the '%s' realm.\n", 
                     global_myname, ads->realm);
            return -1;
@@ -153,30 +217,67 @@ static int net_ads_leave(int argc, const char **argv)
 static int net_ads_join(int argc, const char **argv)
 {
        ADS_STRUCT *ads;
-       int rc;
+       ADS_STATUS rc;
        char *password;
+       char *tmp_password;
        extern pstring global_myname;
-       NTSTATUS status;
+       const char *org_unit = "Computers";
+       char *dn;
+       void *res;
+       DOM_SID dom_sid;
+       char *ou_str;
+
+       if (argc > 0) org_unit = argv[0];
 
        if (!secrets_init()) {
                DEBUG(1,("Failed to initialise secrets database\n"));
                return -1;
        }
 
-       password = generate_random_str(15);
-       password = strdup(password);
+       tmp_password = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
+       password = strdup(tmp_password);
 
        if (!(ads = ads_startup())) return -1;
 
-       rc = ads_join_realm(ads, global_myname);
-       if (rc) {
+       ou_str = ads_ou_string(org_unit);
+       asprintf(&dn, "%s,%s", ou_str, ads->bind_path);
+       free(ou_str);
+
+       rc = ads_search_dn(ads, &res, dn, NULL);
+       ads_msgfree(ads, res);
+
+       if (rc.error_type == ADS_ERROR_LDAP && rc.rc == LDAP_NO_SUCH_OBJECT) {
+               d_printf("ads_join_realm: organisational unit %s does not exist (dn:%s)\n", 
+                        org_unit, dn);
+               return -1;
+       }
+       free(dn);
+
+       if (!ADS_ERR_OK(rc)) {
                d_printf("ads_join_realm: %s\n", ads_errstr(rc));
                return -1;
+       }       
+
+       rc = ads_join_realm(ads, global_myname, org_unit);
+       if (!ADS_ERR_OK(rc)) {
+               d_printf("ads_join_realm: %s\n", ads_errstr(rc));
+               return -1;
+       }
+
+       rc = ads_set_machine_password(ads, global_myname, password);
+       if (!ADS_ERR_OK(rc)) {
+               d_printf("ads_set_machine_password: %s\n", ads_errstr(rc));
+               return -1;
+       }
+
+       rc = ads_domain_sid(ads, &dom_sid);
+       if (!ADS_ERR_OK(rc)) {
+               d_printf("ads_domain_sid: %s\n", ads_errstr(rc));
+               return -1;
        }
 
-       status = ads_set_machine_password(ads, global_myname, password);
-       if (!NT_STATUS_IS_OK(status)) {
-               d_printf("ads_set_machine_password: %s\n", get_nt_error_msg(status));
+       if (!secrets_store_domain_sid(lp_workgroup(), &dom_sid)) {
+               DEBUG(1,("Failed to save domain sid\n"));
                return -1;
        }
 
@@ -192,14 +293,100 @@ static int net_ads_join(int argc, const char **argv)
        return 0;
 }
 
+
+static int net_ads_password(int argc, const char **argv)
+{
+    ADS_STRUCT *ads;
+    extern char *opt_user_name;
+    extern char *opt_password;
+    char *auth_principal = opt_user_name;
+    char *auth_password = opt_password;
+    char *realm = NULL;
+    char *new_password = NULL;
+    char *c;
+    char *prompt;
+    ADS_STATUS ret;
+
+    
+    if ((argc != 1) || (opt_user_name == NULL) || 
+       (opt_password == NULL) || (strchr(opt_user_name, '@') == NULL) ||
+       (strchr(argv[0], '@') == NULL)) {
+       return net_ads_usage(argc, argv);
+    }
+    
+    c = strchr(auth_principal, '@');
+    realm = ++c;
+
+    /* use the realm so we can eventually change passwords for users 
+    in realms other than default */
+    if (!(ads = ads_init(realm, NULL, NULL, NULL))) return -1;
+
+    asprintf(&prompt, "Enter new password for %s:", argv[0]);
+
+    new_password = getpass(prompt);
+
+    ret = kerberos_set_password(ads->kdc_server, auth_principal, 
+                               auth_password, argv[0], new_password);
+    if (!ADS_ERR_OK(ret)) {
+       d_printf("Password change failed :-( ...\n");
+       ads_destroy(&ads);
+       free(prompt);
+       return -1;
+    }
+
+    d_printf("Password change for %s completed.\n", argv[0]);
+    ads_destroy(&ads);
+    free(prompt);
+
+    return 0;
+}
+
+
+static int net_ads_change_localhost_pass(int argc, const char **argv)
+{    
+    ADS_STRUCT *ads;
+    extern pstring global_myname;
+    char *host_principal;
+    char *hostname;
+    ADS_STATUS ret;
+
+
+    if (!(ads = ads_init(NULL, NULL, NULL, NULL))) return -1;
+
+    hostname = strdup(global_myname);
+    strlower(hostname);
+    asprintf(&host_principal, "%s@%s", hostname, ads->realm);
+    SAFE_FREE(hostname);
+    d_printf("Changing password for principal: HOST/%s\n", host_principal);
+    
+    ret = ads_change_trust_account_password(ads, host_principal);
+
+    if (!ADS_ERR_OK(ret)) {
+       d_printf("Password change failed :-( ...\n");
+       ads_destroy(&ads);
+       SAFE_FREE(host_principal);
+       return -1;
+    }
+    
+    d_printf("Password change for principal HOST/%s succeeded.\n", host_principal);
+    ads_destroy(&ads);
+    SAFE_FREE(host_principal);
+
+    return 0;
+}
+
+
 int net_ads(int argc, const char **argv)
 {
        struct functable func[] = {
+               {"INFO", net_ads_info},
                {"JOIN", net_ads_join},
                {"LEAVE", net_ads_leave},
                {"STATUS", net_ads_status},
                {"USER", net_ads_user},
                {"GROUP", net_ads_group},
+               {"PASSWORD", net_ads_password},
+               {"CHOSTPASS", net_ads_change_localhost_pass},
                {NULL, NULL}
        };