r22412: Add a "deletelocalgroup" subcommand to net sam.
[sfrench/samba-autobuild/.git] / source / utils / net_sam.c
index 00289d3bd3c26d0f6ee0786e1dbb43b38f58833a..4d3102b51f4e3d218200338ecb1164b84118b09b 100644 (file)
@@ -206,23 +206,20 @@ static int net_sam_set_pwnoexp(int argc, const char **argv)
 }
 
 /*
- * Set a user's time field
+ * Set pass last change time, based on force pass change now
  */
 
-static int net_sam_set_time(int argc, const char **argv, const char *field,
-                           BOOL (*fn)(struct samu *, time_t,
-                                      enum pdb_value_state))
+static int net_sam_set_pwdmustchangenow(int argc, const char **argv)
 {
        struct samu *sam_acct = NULL;
        DOM_SID sid;
        enum lsa_SidType type;
        const char *dom, *name;
        NTSTATUS status;
-       time_t new_time;
 
-       if (argc != 2) {
-               d_fprintf(stderr, "usage: net sam set %s <user> "
-                         "[now|YYYY-MM-DD HH:MM]\n", field);
+       if ((argc != 2) || (!strequal(argv[1], "yes") &&
+                           !strequal(argv[1], "no"))) {
+               d_fprintf(stderr, "usage: net sam set pwdmustchangenow <user> [yes|no]\n");
                return -1;
        }
 
@@ -238,22 +235,6 @@ static int net_sam_set_time(int argc, const char **argv, const char *field,
                return -1;
        }
 
-       if (strequal(argv[1], "now")) {
-               new_time = time(NULL);
-       } else {
-               struct tm tm;
-               char *end;
-               ZERO_STRUCT(tm);
-               end = strptime(argv[1], "%Y-%m-%d %H:%M", &tm);
-               new_time = mktime(&tm);
-               if ((end == NULL) || (*end != '\0') || (new_time == -1)) {
-                       d_fprintf(stderr, "Could not parse time string %s\n",
-                                 argv[1]);
-                       return -1;
-               }
-       }
-
-
        if ( !(sam_acct = samu_new( NULL )) ) {
                d_fprintf(stderr, "Internal error\n");
                return -1;
@@ -264,9 +245,10 @@ static int net_sam_set_time(int argc, const char **argv, const char *field,
                return -1;
        }
 
-       if (!fn(sam_acct, new_time, PDB_CHANGED)) {
-               d_fprintf(stderr, "Internal error\n");
-               return -1;
+       if (strequal(argv[1], "yes")) {
+               pdb_set_pass_last_set_time(sam_acct, 0, PDB_CHANGED);
+       } else {
+               pdb_set_pass_last_set_time(sam_acct, time(NULL), PDB_CHANGED);
        }
 
        status = pdb_update_sam_account(sam_acct);
@@ -278,21 +260,11 @@ static int net_sam_set_time(int argc, const char **argv, const char *field,
 
        TALLOC_FREE(sam_acct);
 
-       d_printf("Updated %s for %s\\%s to %s\n", field, dom, name, argv[1]);
+       d_fprintf(stderr, "Updated 'user must change password at next logon' for %s\\%s to %s\n", dom,
+                 name, argv[1]);
        return 0;
 }
 
-static int net_sam_set_pwdmustchange(int argc, const char **argv)
-{
-       return net_sam_set_time(argc, argv, "pwdmustchange",
-                               pdb_set_pass_must_change_time);
-}
-
-static int net_sam_set_pwdcanchange(int argc, const char **argv)
-{
-       return net_sam_set_time(argc, argv, "pwdcanchange",
-                               pdb_set_pass_can_change_time);
-}
 
 /*
  * Set a user's or a group's comment
@@ -376,10 +348,8 @@ static int net_sam_set(int argc, const char **argv)
                  "Disable/Enable a user's lockout flag" },
                { "pwnoexp", net_sam_set_pwnoexp,
                  "Disable/Enable whether a user's pw does not expire" },
-               { "pwdmustchange", net_sam_set_pwdmustchange,
-                 "Set a users password must change time" },
-               { "pwdcanchange", net_sam_set_pwdcanchange,
-                 "Set a users password can change time" },
+               { "pwdmustchangenow", net_sam_set_pwdmustchangenow,
+                 "Force users password must change at next logon" },
                {NULL, NULL}
        };
 
@@ -387,78 +357,151 @@ static int net_sam_set(int argc, const char **argv)
 }
 
 /*
- * Change account policies
+ * Manage account policies
  */
 
-static int net_sam_policy(int argc, const char **argv)
+static int net_sam_policy_set(int argc, const char **argv)
 {
-       
        const char *account_policy = NULL;
        uint32 value, old_value;
        int field;
+       char *endptr;
 
-       if ((argc < 1) || (argc > 2)) {
-               d_fprintf(stderr, "usage: net sam policy \"<account policy>\" "
-                         "-> show current value\n");
-               d_fprintf(stderr, "usage: net sam policy \"<account policy>\" "
-                         "<value> -> set a new value\n");
-               return -1;
-       }
+        if (argc != 2) {
+                d_fprintf(stderr, "usage: net sam policy set " 
+                         "\"<account policy>\" <value> \n");
+                return -1;
+        }
 
        account_policy = argv[0];
        field = account_policy_name_to_fieldnum(account_policy);
 
+       if (strequal(argv[1], "forever") || strequal(argv[1], "never")
+           || strequal(argv[1], "off")) {
+               value = -1;
+       }
+       else {
+               value = strtoul(argv[1], &endptr, 10);
+
+               if ((endptr == argv[1]) || (endptr[0] != '\0')) {
+                       d_printf("Unable to set policy \"%s\"! Invalid value "
+                                "\"%s\".\n", 
+                                account_policy, argv[1]); 
+                       return -1;
+               }
+       }
+
        if (field == 0) {
-               char *apn = account_policy_names_list();
-               d_fprintf(stderr, "No account policy by that name!\n");
-               if (apn) {
-                       d_fprintf(stderr, "Valid account policies "
-                                 "are:\n%s\n", apn);
+               const char **names;
+                int i, count;
+
+                account_policy_names_list(&names, &count);
+               d_fprintf(stderr, "No account policy \"%s\"!\n\n", argv[0]);
+               d_fprintf(stderr, "Valid account policies are:\n");
+
+               for (i=0; i<count; i++) {
+                       d_fprintf(stderr, "%s\n", names[i]);
                }
-               SAFE_FREE(apn);
+
+               SAFE_FREE(names);
                return -1;
        }
 
        if (!pdb_get_account_policy(field, &old_value)) {
-               fprintf(stderr, "Valid account policy, but unable to "
-                       "fetch value!\n");
+               d_fprintf(stderr, "Valid account policy, but unable to fetch "
+                         "value!\n");
+       }
+
+       if (!pdb_set_account_policy(field, value)) {
+               d_fprintf(stderr, "Valid account policy, but unable to "
+                         "set value!\n");
                return -1;
        }
 
-       if (argc == 1) {
-               /*
-                * Just read the value
-                */
+       d_printf("Account policy \"%s\" value was: %d\n", account_policy,
+                old_value);
 
-               printf("Account policy \"%s\" description: %s\n",
-                      account_policy, account_policy_get_desc(field));
-               printf("Account policy \"%s\" value is: %d\n", account_policy,
-                      old_value);
-               return 0;
-       }
+       d_printf("Account policy \"%s\" value is now: %d\n", account_policy,
+                value);
+       return 0;
+}
 
-       /*
-        * Here we know we have 2 args, so set it
-        */
+static int net_sam_policy_show(int argc, const char **argv)
+{
+       const char *account_policy = NULL;
+        uint32 old_value;
+        int field;
+
+        if (argc != 1) {
+                d_fprintf(stderr, "usage: net sam policy show"
+                         " \"<account policy>\" \n");
+                return -1;
+        }
        
-       value = strtoul(argv[1], NULL, 10);
+       account_policy = argv[0];
+        field = account_policy_name_to_fieldnum(account_policy);
+
+        if (field == 0) {
+               const char **names;
+               int count;
+               int i;
+                account_policy_names_list(&names, &count);
+                d_fprintf(stderr, "No account policy by that name!\n");
+                if (count != 0) {
+                        d_fprintf(stderr, "Valid account policies "
+                                  "are:\n");
+                       for (i=0; i<count; i++) {
+                               d_fprintf(stderr, "%s\n", names[i]);
+                       }
+                }
+                SAFE_FREE(names);
+                return -1;
+        }
 
-       printf("Account policy \"%s\" description: %s\n", account_policy,
-              account_policy_get_desc(field));
-       printf("Account policy \"%s\" value was: %d\n", account_policy,
+       if (!pdb_get_account_policy(field, &old_value)) {
+                fprintf(stderr, "Valid account policy, but unable to "
+                        "fetch value!\n");
+                return -1;
+        }
+       
+       printf("Account policy \"%s\" description: %s\n",
+              account_policy, account_policy_get_desc(field));
+        printf("Account policy \"%s\" value is: %d\n", account_policy,
               old_value);
+        return 0;
+}
 
-       if (!pdb_set_account_policy(field, value)) {
-               d_fprintf(stderr, "Setting account policy %s to %u failed \n",
-                         account_policy, value);
+static int net_sam_policy_list(int argc, const char **argv)
+{
+       const char **names;
+       int count;
+       int i;
+       account_policy_names_list(&names, &count);
+        if (count != 0) {
+               d_fprintf(stderr, "Valid account policies "
+                         "are:\n");
+               for (i = 0; i < count ; i++) {
+                       d_fprintf(stderr, "%s\n", names[i]);
+               }
        }
-
-       printf("Account policy \"%s\" value is now: %d\n", account_policy,
-              value);
-
-       return 0;
+        SAFE_FREE(names);
+        return -1;
 }
 
+static int net_sam_policy(int argc, const char **argv)
+{
+        struct functable2 func[] = {
+               { "list", net_sam_policy_list,
+                  "List account policies" },
+                { "show", net_sam_policy_show,
+                  "Show account policies" },
+               { "set", net_sam_policy_set,
+                  "Change account policies" },
+                {NULL, NULL}
+        };
+
+        return net_run_function2(argc, argv, "net sam policy", func);
+}
 
 /*
  * Map a unix group to a domain group
@@ -528,6 +571,46 @@ static int net_sam_createlocalgroup(int argc, const char **argv)
        return 0;
 }
 
+/*
+ * Delete a local group
+ */
+
+static int net_sam_deletelocalgroup(int argc, const char **argv)
+{
+       DOM_SID sid;
+        enum lsa_SidType type;
+        const char *dom, *name;
+       int ret;
+
+       if (argc != 1) {
+               d_fprintf(stderr, "usage: net sam deletelocalgroup <name>\n");
+               return -1;
+       }
+
+       if (!lookup_name(tmp_talloc_ctx(), argv[0], LOOKUP_NAME_ISOLATED,
+                        &dom, &name, &sid, &type)) {
+               d_fprintf(stderr, "Could not find name %s.\n", argv[0]);
+               return -1;
+       }
+
+       if (type != SID_NAME_ALIAS) {
+               d_fprintf(stderr, "%s is a %s, not a local group.\n", argv[0],
+                         sid_type_lookup(type));
+               return -1;
+       }
+
+       ret = pdb_delete_alias(&sid);
+
+       if ( !ret ) {
+               d_fprintf(stderr, "Could not delete local group %s.\n", argv[0]);
+               return -1;
+       }
+
+       d_printf("Deleted local group %s.\n", argv[0]);
+
+       return 0;
+}
+
 /*
  * Create a local group
  */
@@ -947,7 +1030,7 @@ static int net_sam_provision(int argc, const char **argv)
                goto failed;
        }
 
-       if (!NT_STATUS_IS_OK(smbldap_init(tc, ldap_uri, &ls))) {
+       if (!NT_STATUS_IS_OK(smbldap_init(tc, NULL, ldap_uri, &ls))) {
                d_fprintf(stderr, "Unable to connect to the LDAP server.\n");
                goto failed;
        }
@@ -1000,6 +1083,7 @@ static int net_sam_provision(int argc, const char **argv)
                        d_fprintf(stderr, "Failed to add Domain Users group to ldap directory\n");
                }
        } else {
+               domusers_gid = gmap.gid;
                d_printf("found!\n");
        }       
 
@@ -1053,6 +1137,7 @@ domu_done:
                        d_fprintf(stderr, "Failed to add Domain Admins group to ldap directory\n");
                }
        } else {
+               domadmins_gid = gmap.gid;
                d_printf("found!\n");
        }
 
@@ -1081,7 +1166,7 @@ doma_done:
                d_printf("Adding the Administrator user.\n");
 
                if (domadmins_gid == -1) {
-                       d_fprintf(stderr, "Can't create Administrtor user, Domain Admins group not available!\n");
+                       d_fprintf(stderr, "Can't create Administrator user, Domain Admins group not available!\n");
                        goto done;
                }
                if (!winbind_allocate_uid(&uid)) {
@@ -1195,8 +1280,12 @@ doma_done:
                smbldap_set_mod(&mods, LDAP_MOD_ADD, "displayName", pwd->pw_name);
                smbldap_set_mod(&mods, LDAP_MOD_ADD, "uidNumber", uidstr);
                smbldap_set_mod(&mods, LDAP_MOD_ADD, "gidNumber", gidstr);
-               smbldap_set_mod(&mods, LDAP_MOD_ADD, "homeDirectory", pwd->pw_dir);
-               smbldap_set_mod(&mods, LDAP_MOD_ADD, "loginShell", pwd->pw_shell);
+               if ((pwd->pw_dir != NULL) && (pwd->pw_dir[0] != '\0')) {
+                       smbldap_set_mod(&mods, LDAP_MOD_ADD, "homeDirectory", pwd->pw_dir);
+               }
+               if ((pwd->pw_shell != NULL) && (pwd->pw_shell[0] != '\0')) {
+                       smbldap_set_mod(&mods, LDAP_MOD_ADD, "loginShell", pwd->pw_shell);
+               }
                smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaSID", sid_string_static(&sid));
                smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaAcctFlags",
                                pdb_encode_acct_ctrl(ACB_NORMAL|ACB_DISABLED,
@@ -1218,7 +1307,7 @@ doma_done:
        pwd = getpwnam_alloc(NULL, lp_guestaccount());
        if (!pwd) {
                d_fprintf(stderr, "Failed to find just created Guest account!\n"
-                                 "   Is nssswitch properly configured?!\n");
+                                 "   Is nss properly configured?!\n");
                goto failed;
        }
 
@@ -1292,6 +1381,8 @@ int net_sam(int argc, const char **argv)
                  "Create a new BUILTIN group" },
                { "createlocalgroup", net_sam_createlocalgroup,
                  "Create a new local group" },
+               { "deletelocalgroup", net_sam_deletelocalgroup,
+                 "Delete an existing local group" },
                { "mapunixgroup", net_sam_mapunixgroup,
                  "Map a unix group to a domain group" },
                { "addmem", net_sam_addmem,